-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1ce3ccb
commit edb3542
Showing
14 changed files
with
352 additions
and
119 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,71 +1,304 @@ | ||
## widget_wrapper | ||
|
||
![coverage][coverage_badge] | ||
[![style: very good analysis][very_good_analysis_badge]][very_good_analysis_link] | ||
[![License: MIT][license_badge]][license_link] | ||
## Table of Contents | ||
|
||
Generated by the [Very Good CLI][very_good_cli_link] 🤖 | ||
- [Rabbit 🐰](#rabbit-) | ||
- [Features](#features) | ||
- [Requirements](#requirements) | ||
- [Installation](#installation) | ||
- [Getting Started](#getting-started) | ||
- [Configuration Options](#configuration-options) | ||
- [Example Configuration](#example-configuration) | ||
- [`widgets`](#widgets) | ||
- [`output_dir`](#output_dir) | ||
- [`add_imports`](#add_imports) | ||
- [`prefix`](#prefix) | ||
- [`docs`](#docs) | ||
- [Multiple Constructors](#multiple-constructors) | ||
- [Maintaining Generated Code](#maintaining-generated-code) | ||
- [Common Use Cases](#common-use-cases) | ||
- [Theming Widgets](#theming-widgets) | ||
- [Adding Default Behaviors](#adding-default-behaviors) | ||
- [Best Practices](#best-practices) | ||
- [When to Use Wrappers](#when-to-use-wrappers) | ||
- [When Not to Use Wrappers](#when-not-to-use-wrappers) | ||
- [Naming Conventions](#naming-conventions) | ||
|
||
Customize you favorite widgets by wrapping them.. | ||
|
||
--- | ||
# Rabbit 🐰 | ||
|
||
## Getting Started 🚀 | ||
A Dart CLI tool that generates wrapper widgets to help reduce boilerplate code and create reusable widget variations. Instead of manually writing wrapper widgets for customized versions of existing widgets, Rabbit generates the boilerplate code for you, allowing you to focus on the customization. | ||
|
||
If the CLI application is available on [pub](https://pub.dev), activate globally via: | ||
For example, if you need a red container in multiple places in your app, instead of writing: | ||
```dart | ||
Container( | ||
color: Colors.red, | ||
child: child, | ||
) | ||
``` | ||
You can generate a `RedContainer` widget that encapsulates this styling: | ||
```dart | ||
RedContainer( | ||
child: child, | ||
) | ||
``` | ||
|
||
Rabbit helps you create these wrapper widgets quickly and consistently, maintaining all the original widget's parameters while allowing you to customize what you need. | ||
|
||
## Features | ||
|
||
- **Easy Widget Wrapping**: Generate wrapper widgets from any existing widget with a single command | ||
- **Type Safety**: Preserves generic types and constructor parameters from the original widget | ||
- **Customizable Output**: | ||
- Choose your output directory | ||
- Customize widget name prefixes | ||
- Control import statement generation | ||
- **Documentation Support**: Option to include original widget's documentation comments | ||
- **Bulk Generation**: Generate multiple wrappers at once, even for entire packages | ||
- **Non-Destructive**: Never overwrites existing files, allowing safe regeneration | ||
- **Flutter Compatible**: Works with any Flutter widget, including third-party packages | ||
|
||
## Requirements | ||
|
||
- Flutter SDK: >=3.19.0 | ||
- Dart SDK: >=3.19.0 | ||
|
||
## Installation | ||
|
||
Add Rabbit to your project's dev dependencies: | ||
|
||
```sh | ||
dart pub global activate widget_wrapper | ||
flutter pub add dev:rabbit | ||
``` | ||
|
||
Or locally via: | ||
Or manually add it to your `pubspec.yaml`: | ||
|
||
```yaml | ||
dev_dependencies: | ||
rabbit: ^latest_version | ||
``` | ||
Then run: | ||
```sh | ||
dart pub global activate --source=path <path to this package> | ||
flutter pub get | ||
``` | ||
|
||
## Usage | ||
## Getting Started | ||
|
||
```sh | ||
# Sample command | ||
$ widget_wrapper sample | ||
In this example we will generate a `RedContainer` widget that is identical to a `Container` widget but with a red background color. | ||
|
||
# Sample command option | ||
$ widget_wrapper sample --cyan | ||
1. Configure your widget wrappers in `pubspec.yaml`: | ||
|
||
# Show CLI version | ||
$ widget_wrapper --version | ||
```yaml | ||
widget_wrapper: | ||
widgets: | ||
package:flutter/material.dart: | ||
- Container | ||
``` | ||
For a complete list of configuration options, see the [Configuration](#configuration) section. | ||
# Show usage help | ||
$ widget_wrapper --help | ||
2. Run the generation command: | ||
```bash | ||
dart run rabbit generate | ||
``` | ||
This will generate a `$Container` widget in the default output directory. | ||
3. Locate the generated widget and customize it as needed. | ||
```dart | ||
class RedContainer extends StatelessWidget { | ||
final AlignmentGeometry alignment; | ||
final EdgeInsetsGeometry padding; | ||
// ... and the rest of the Container properties | ||
const RedContainer({ | ||
super.key, | ||
this.alignment, | ||
this.padding, | ||
// ... and the rest of the Container properties | ||
}); | ||
@override | ||
Widget build(BuildContext context) { | ||
return Container( | ||
color: Colors.red, | ||
alignment: alignment, | ||
padding: padding, | ||
// ... and the rest of the Container properties | ||
); | ||
} | ||
} | ||
``` | ||
You can now use the `RedContainer` widget in your app as you would a `Container` widget. | ||
4. (Optional) Rename the generated file: | ||
Rename the generated file to `red_container.dart` for better readability and import statements. | ||
|
||
Now you can use the `RedContainer` widget in your app as you would a `Container` widget. | ||
```dart | ||
RedContainer( | ||
child: Text('Hello, World!'), | ||
) | ||
``` | ||
|
||
## Running Tests with coverage 🧪 | ||
## Configuration Options | ||
|
||
To run all unit tests use the following command: | ||
The following options can be configured in your `pubspec.yaml` under the `widget_wrapper` key: | ||
|
||
```sh | ||
$ dart pub global activate coverage 1.2.0 | ||
$ dart test --coverage=coverage | ||
$ dart pub global run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info | ||
| Option | Default | Description | | ||
| ------------- | ----------------- | ---------------------------------------------------- | | ||
| `widgets` | Required | Map of package imports and widget names | | ||
| `output_dir` | `lib/src/wrapped` | Directory where generated files will be placed | | ||
| `add_imports` | `false` | Create the import statements for the generated files | | ||
| `prefix` | `$` | Prefix for generated widget names | | ||
| `docs` | `false` | Include documentation comments from original widget | | ||
|
||
### Example Configuration | ||
|
||
```yaml | ||
widget_wrapper: | ||
output_dir: lib/src/widgets | ||
add_imports: true | ||
prefix: My | ||
docs: true | ||
widgets: | ||
package:flutter/material.dart: | ||
- Container | ||
- ElevatedButton | ||
package:shadcn_ui/shadcn_ui.dart: | ||
Check warning on line 166 in README.md GitHub Actions / spell-check / build
|
||
- ShadButton | ||
``` | ||
|
||
### `widgets` | ||
|
||
To view the generated coverage report you can use [lcov](https://github.com/linux-test-project/lcov) | ||
. | ||
The `widgets` option is a map where: | ||
- Keys are package import statements | ||
- Values are lists of widget names to generate wrappers for | ||
|
||
```sh | ||
# Generate Coverage Report | ||
$ genhtml coverage/lcov.info -o coverage/ | ||
You can use the special value `all` to generate wrappers for all widgets in a package: | ||
```yaml | ||
widget_wrapper: | ||
widgets: | ||
package:flutter/material.dart: | ||
- all # Will generate wrappers for all Material widgets | ||
``` | ||
⚠️ **Warning**: Using `all` will generate a large number of files and is not recommended for most use cases. | ||
|
||
### `output_dir` | ||
The directory where generated files will be placed. | ||
```yaml | ||
widget_wrapper: | ||
output_dir: lib/src/widgets # Your custom path | ||
``` | ||
- Default: `lib/src/wrapped` | ||
- The directory will be created if it doesn't exist | ||
- Relative paths are resolved from your project root | ||
- The generate widgets will match the package structure of the original widgets | ||
|
||
# Open Coverage Report | ||
$ open coverage/index.html | ||
### `add_imports` | ||
`rabbit` *can* generate import statements for the generated files, however they look very ugly so it's disabled by default. | ||
|
||
If you want to use this feature, you can enable it like this: | ||
|
||
```yaml | ||
widget_wrapper: | ||
add_imports: true | ||
``` | ||
- Default: `false` | ||
- When `true`, adds imports with package prefixes to avoid naming conflicts | ||
|
||
### `prefix` | ||
The prefix added to generated widget names to avoid naming conflicts. | ||
```yaml | ||
widget_wrapper: | ||
prefix: My # Will generate MyContainer, MyButton, etc. | ||
``` | ||
- Default: `$` | ||
- Can be set to an empty string (`''`) if you want no prefix | ||
- If using no prefix, consider setting `add_imports: true` to avoid naming conflicts | ||
|
||
### `docs` | ||
Controls whether documentation comments from the original widget are included. | ||
```yaml | ||
widget_wrapper: | ||
docs: true | ||
``` | ||
- Default: `false` | ||
- Includes parameter descriptions, examples, and other documentation | ||
- Can significantly increase the size of generated files | ||
- Useful when creating public packages or maintaining API documentation | ||
- | ||
## Multiple Constructors | ||
|
||
When a widget has multiple constructors, Rabbit generates a separate wrapper for each constructor. For example, with `ListView`: | ||
|
||
```dart | ||
// Original ListView has multiple constructors: | ||
// ListView() | ||
// ListView.builder() | ||
// ListView.separated() | ||
// ListView.custom() | ||
// Rabbit will generate: | ||
class $ListView extends StatelessWidget { ... } | ||
class $ListViewBuilder extends StatelessWidget { ... } | ||
class $ListViewSeparated extends StatelessWidget { ... } | ||
class $ListViewCustom extends StatelessWidget { ... } | ||
``` | ||
|
||
Each generated wrapper maintains the exact signature and functionality of its corresponding constructor. | ||
|
||
## Maintaining Generated Code | ||
|
||
If a Flutter update changes the API of wrapped widgets: | ||
|
||
1. Backup your customized wrappers | ||
2. Regenerate the wrappers with the latest Flutter version: | ||
```bash | ||
dart run rabbit generate | ||
``` | ||
3. Copy your customizations from the backup to the newly generated files | ||
|
||
This ensures your wrappers stay in sync with Flutter's API changes while preserving your modifications. | ||
|
||
|
||
## Common Use Cases | ||
|
||
### Theming Widgets | ||
Create consistent themed versions of widgets across your app: | ||
```dart | ||
class PrimaryButton extends StatelessWidget { | ||
// Generated from ElevatedButton | ||
// Customized with your theme's primary color | ||
} | ||
### Platform-Specific Variants | ||
```dart | ||
class AdaptiveContainer extends StatelessWidget { | ||
// Generated from Container | ||
// Customized with platform-specific styling | ||
} | ||
``` | ||
|
||
### Adding Default Behaviors | ||
```dart | ||
class LoadingButton extends StatelessWidget { | ||
// Generated from ElevatedButton | ||
// Adds loading state handling | ||
} | ||
``` | ||
|
||
## Best Practices | ||
|
||
### When to Use Wrappers | ||
- For consistent styling across your app | ||
- When you need multiple variants of a widget | ||
- To encapsulate complex behavior | ||
|
||
--- | ||
### When Not to Use Wrappers | ||
- For one-off customizations | ||
- When composition would be clearer | ||
- For very simple modifications | ||
|
||
[coverage_badge]: coverage_badge.svg | ||
[license_badge]: https://img.shields.io/badge/license-MIT-blue.svg | ||
[license_link]: https://opensource.org/licenses/MIT | ||
[very_good_analysis_badge]: https://img.shields.io/badge/style-very_good_analysis-B22C89.svg | ||
[very_good_analysis_link]: https://pub.dev/packages/very_good_analysis | ||
[very_good_cli_link]: https://github.com/VeryGoodOpenSource/very_good_cli | ||
### Naming Conventions | ||
- Use descriptive names that indicate the purpose | ||
- Follow Flutter's widget naming conventions | ||
- Consider grouping related wrappers | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.