mix_annotations 2.2.0-beta.1
mix_annotations: ^2.2.0-beta.1 copied to clipboard
Annotations for mix and mix_generator
mix_annotations #
Annotations used by mix_generator to generate boilerplate code for the Mix styling framework.
Installation #
flutter pub add mix_annotations
This package is typically used alongside mix and mix_generator:
dependencies:
mix: ^2.0.0
mix_annotations: ^2.0.0
dev_dependencies:
build_runner: ^2.4.0
mix_generator: ^2.0.0
Annotations #
@MixableSpec #
Generates a self-contained _$<Name> mixin for Spec classes (immutable style data). The mixin declares implements Spec<T>, Diagnosticable and inlines type, copyWith, lerp, generated props by default, ==, hashCode, toString, toDiagnosticsNode, and debugFillProperties — so the user class needs a single with to be a fully-formed Spec.
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:mix/mix.dart';
import 'package:mix_annotations/mix_annotations.dart';
part 'box_spec.g.dart';
@MixableSpec()
@immutable
final class BoxSpec with _$BoxSpec {
@override
final Color? color;
@override
final double? width;
const BoxSpec({this.color, this.width});
}
The generated mixin _$BoxSpec is the only thing the user class mixes in — Equatable-style equality (via propsEquals / propsHash helpers) and Diagnosticable's concrete surface are inlined by the generator, not pushed onto the user.
Control which methods are generated via GeneratedSpecMethods flags:
@MixableSpec(methods: GeneratedSpecMethods.skipLerp)
GeneratedSpecMethods.skipEquals suppresses generated props so the class can
author custom equality inputs while still using the generated equality surface.
@MixableStyler legacy marker #
Retained for compatibility with older code and shared generated styler method flags. New Mix stylers are generated from @MixableSpec(target: Widget.new).
@MixableStyler()
class BoxStyler extends Style<BoxSpec>
with Diagnosticable, ..., _$BoxStylerMixin {
final Prop<AlignmentGeometry>? $alignment;
final Prop<Color>? $color;
// ...
}
GeneratedStylerMethods flags remain available for generator internals and compatibility.
@Mixable #
Generates a mixin for Mix classes (compound property types) with merge(), resolve(), props, and debugFillProperties().
@Mixable()
final class BoxConstraintsMix extends ConstraintsMix<BoxConstraints>
with DefaultValue<BoxConstraints>, Diagnosticable, _$BoxConstraintsMixMixin {
final Prop<double>? $minWidth;
final Prop<double>? $maxWidth;
// ...
}
@MixableField #
Configures code generation for individual fields in Styler classes.
// Skip setter generation for this field
@MixableField(ignoreSetter: true)
final Prop<Matrix4>? $transform;
// Override the setter parameter type
@MixableField(setterType: List<Shadow>)
final Prop<List<Shadow>>? $shadows;
// Forward canonical factories from a nested generated Styler.
@MixableField(forwardStyler: true)
final StyleSpec<BoxSpec>? container;
// Restrict a FlexBox-backed field to the Box-generated Styler surface.
@MixableField(forwardStyler: true, stylerSurface: BoxSpec)
final StyleSpec<FlexBoxSpec>? restrictedContainer;
stylerSurface references the source @MixableSpec type, not its generated
Styler, so same-package clean builds do not depend on resolving generated code.
Forwarding preserves the canonical named-factory allowlist and does not promote
fluent-only helpers such as paddingAll.
When setterType and forwardStyler are combined, the custom setter type must
be a concrete class with an accessible unnamed constructor callable without
arguments. It must implement every forwarded fluent method with the canonical
generated signature and return a type assignable to itself.
@MixWidget #
Generates a StatelessWidget wrapper around a top-level styler variable or
styler-returning function. By default, the wrapper exposes every non-key
value parameter from the styler's call() method:
@MixWidget() // Equivalent to widgetParameters: .all()
final cardStyle = BoxStyler();
Use widgetParameters: .only(...) to keep the generated widget's value-
parameter API limited to a deliberate subset. This prevents newly added styler
value parameters from becoming public widget parameters automatically:
@MixWidget(
widgetParameters: .only({'controller', 'focusNode'}),
)
final editorStyle = EditorStyler();
An empty .only({}) exposes no selectable styler value parameters. A valid
Key? key and method-level call<T>() type parameters remain automatic;
required styler value parameters must be selected. Excluded optional
parameters are not forwarded, so the styler method's defaults apply.
Use target to wrap a plain widget constructor directly and
factoryParameters to curate recipe controls independently:
@MixWidget(
name: 'FortalButton',
target: RemixButton.new,
factoryParameters: .only({'variant', 'size'}),
)
ButtonStyler fortalButtonStyler({
ButtonVariant variant = .solid,
ButtonSize size = .medium,
bool highContrast = false,
});
The target must be a Widget constructor with a compatible named style
parameter. Its style and styleSpec parameters never surface on the
generated wrapper. Required factory parameters must be selected; omitted
optional parameters use the recipe's defaults.
Generators that also support older mix_annotations releases interpret an
annotation without widgetParameters as .all(). Using .only(...) requires
an annotations release that defines MixWidgetParameterSelection.
Generator Flags #
Each annotation accepts bitwise flags to control which methods or components are generated:
| Class | Available Flags |
|---|---|
GeneratedSpecMethods |
copyWith, equals, lerp |
GeneratedStylerMethods |
setters, merge, resolve, debugFillProperties, props |
GeneratedMixMethods |
merge, resolve, props, debugFillProperties |
Use all (default) to generate everything, or skip* helpers to exclude specific methods:
GeneratedSpecMethods.skipLerp // all except lerp
GeneratedSpecMethods.skipEquals // user authors props; equality surface still emits
GeneratedMixMethods.skipResolve // all except resolve
GeneratedStylerMethods.call / skipCall are retained for source
compatibility, but call generation is no longer supported.
Code Generation #
After annotating your classes, run build_runner to generate code:
dart run build_runner build --delete-conflicting-outputs
Or within the Mix monorepo:
melos run gen:build
Learn More #
- Mix documentation
- mix — Core framework
- mix_generator — Code generator
- GitHub repository