diff --git a/packages/mix/lib/src/animation/animation_config.dart b/packages/mix/lib/src/animation/animation_config.dart index a70f54e02..f18a9afba 100644 --- a/packages/mix/lib/src/animation/animation_config.dart +++ b/packages/mix/lib/src/animation/animation_config.dart @@ -427,6 +427,28 @@ sealed class AnimationConfig { ); } +/// Animation configuration that pairs a forward (enter) config with a reverse +/// (exit) config. +/// +/// This wrapper lets a single style own both its enter and exit transition +/// timing. When a style becomes active, Mix uses [forward]; when the style is +/// no longer active, Mix uses the leaving style's [reverse]. +/// +/// `reverse` is an exit transition config. It does not mean calling +/// `AnimationController.reverse()`. +final class ReversibleAnimationConfig extends AnimationConfig with Equatable { + final AnimationConfig forward; + final AnimationConfig reverse; + + const ReversibleAnimationConfig({ + required this.forward, + required this.reverse, + }); + + @override + List get props => [forward, reverse]; +} + /// Curve-based animation configuration with fixed duration. /// /// This configuration provides duration, curve, and optional completion callback diff --git a/packages/mix/lib/src/animation/style_animation_builder.dart b/packages/mix/lib/src/animation/style_animation_builder.dart index 5a833d5cc..f23dc92b7 100644 --- a/packages/mix/lib/src/animation/style_animation_builder.dart +++ b/packages/mix/lib/src/animation/style_animation_builder.dart @@ -34,12 +34,18 @@ class _StyleAnimationBuilderState> with TickerProviderStateMixin { late StyleAnimationDriver animationDriver; + /// The config currently driving the active driver. Tracked separately from + /// the spec's config because a reverse transition can leave the driver using + /// a different kind from the current spec's forward config. + AnimationConfig? _activeConfig; + @override void initState() { super.initState(); final spec = widget.spec; - final config = spec.animation; + final config = _forwardOf(spec.animation); animationDriver = _createAnimationDriver(config: config, initialSpec: spec); + _activeConfig = config; } StyleAnimationDriver _createAnimationDriver({ @@ -73,6 +79,11 @@ class _StyleAnimationBuilderState> initialSpec: initialSpec, context: context, ), + // A reversible config is unwrapped to its forward config for driving. + ReversibleAnimationConfig() => _createAnimationDriver( + config: config.forward, + initialSpec: initialSpec, + ), // ignore: avoid-undisposed-instances null => NoAnimationDriver(vsync: this, initialSpec: initialSpec), }; @@ -88,18 +99,26 @@ class _StyleAnimationBuilderState> void didUpdateWidget(StyleAnimationBuilder oldWidget) { super.didUpdateWidget(oldWidget); - final config = widget.spec.animation; + final newConfig = widget.spec.animation; final oldConfig = oldWidget.spec.animation; - if ((oldConfig.runtimeType == config.runtimeType) && config != null) { + // Select the effective transition config: the leaving style's reverse + // config when leaving it, otherwise the target style's forward config. + final config = + _transitionConfig(oldConfig, newConfig) ?? _forwardOf(oldConfig); + + // Compare against the active driver's config kind, not the spec's, because + // a reverse transition can leave the driver using a different kind. + if ((_activeConfig.runtimeType == config.runtimeType) && config != null) { animationDriver.updateDriver(config); } else { animationDriver.dispose(); animationDriver = _createAnimationDriver( - config: config ?? oldConfig, + config: config, initialSpec: oldWidget.spec, ); } + _activeConfig = config; if (oldWidget.spec != widget.spec) { animationDriver.didUpdateSpec(oldWidget.spec, widget.spec); @@ -118,3 +137,38 @@ class _StyleAnimationBuilderState> ); } } + +/// Unwraps the forward (enter) config from a [ReversibleAnimationConfig]. +AnimationConfig? _forwardOf(AnimationConfig? config) { + return switch (config) { + ReversibleAnimationConfig(:final forward) => forward, + _ => config, + }; +} + +/// Unwraps the reverse (exit) config from a [ReversibleAnimationConfig]. +AnimationConfig? _reverseOf(AnimationConfig? config) { + return switch (config) { + ReversibleAnimationConfig(:final reverse) => reverse, + _ => null, + }; +} + +/// Selects the effective transition config when moving from [oldConfig] to +/// [newConfig]. +/// +/// Uses the leaving style's reverse config only when the old and new configs +/// are distinct; otherwise uses the target style's forward config. This keeps +/// an inherited base reversible config from being mistaken for an exit +/// animation on enter. +AnimationConfig? _transitionConfig( + AnimationConfig? oldConfig, + AnimationConfig? newConfig, +) { + if (oldConfig != newConfig) { + final reverse = _reverseOf(oldConfig); + if (reverse != null) return reverse; + } + + return _forwardOf(newConfig); +} diff --git a/packages/mix/lib/src/specs/box/box_spec.g.dart b/packages/mix/lib/src/specs/box/box_spec.g.dart index 1b6c080de..601bcdcc4 100644 --- a/packages/mix/lib/src/specs/box/box_spec.g.dart +++ b/packages/mix/lib/src/specs/box/box_spec.g.dart @@ -379,8 +379,10 @@ class BoxStyler extends MixStyler ); factory BoxStyler.transform(Matrix4 value, {Alignment alignment = .center}) => BoxStyler().transform(value, alignment: alignment); - factory BoxStyler.animate(AnimationConfig value) => - BoxStyler().animate(value); + factory BoxStyler.animate( + AnimationConfig value, { + AnimationConfig? reverse, + }) => BoxStyler().animate(value, reverse: reverse); BoxStyler textStyle(TextStyler value) { return wrap(WidgetModifierConfig.defaultTextStyler(value)); @@ -432,9 +434,16 @@ class BoxStyler extends MixStyler } /// Sets the animation configuration. + /// + /// When [reverse] is provided, it is used as the exit transition + /// config when leaving this style. @override - BoxStyler animate(AnimationConfig value) { - return merge(BoxStyler(animation: value)); + BoxStyler animate(AnimationConfig value, {AnimationConfig? reverse}) { + final config = reverse == null + ? value + : ReversibleAnimationConfig(forward: value, reverse: reverse); + + return merge(BoxStyler(animation: config)); } /// Sets the style variants. diff --git a/packages/mix/lib/src/specs/flex/flex_spec.g.dart b/packages/mix/lib/src/specs/flex/flex_spec.g.dart index 19f9ee66c..ebd19613c 100644 --- a/packages/mix/lib/src/specs/flex/flex_spec.g.dart +++ b/packages/mix/lib/src/specs/flex/flex_spec.g.dart @@ -296,9 +296,16 @@ class FlexStyler extends MixStyler } /// Sets the animation configuration. + /// + /// When [reverse] is provided, it is used as the exit transition + /// config when leaving this style. @override - FlexStyler animate(AnimationConfig value) { - return merge(FlexStyler(animation: value)); + FlexStyler animate(AnimationConfig value, {AnimationConfig? reverse}) { + final config = reverse == null + ? value + : ReversibleAnimationConfig(forward: value, reverse: reverse); + + return merge(FlexStyler(animation: config)); } /// Sets the style variants. diff --git a/packages/mix/lib/src/specs/flexbox/flexbox_spec.g.dart b/packages/mix/lib/src/specs/flexbox/flexbox_spec.g.dart index a2ebedd9d..aa9659373 100644 --- a/packages/mix/lib/src/specs/flexbox/flexbox_spec.g.dart +++ b/packages/mix/lib/src/specs/flexbox/flexbox_spec.g.dart @@ -358,8 +358,10 @@ class FlexBoxStyler extends MixStyler Matrix4 value, { Alignment alignment = .center, }) => FlexBoxStyler().transform(value, alignment: alignment); - factory FlexBoxStyler.animate(AnimationConfig value) => - FlexBoxStyler().animate(value); + factory FlexBoxStyler.animate( + AnimationConfig value, { + AnimationConfig? reverse, + }) => FlexBoxStyler().animate(value, reverse: reverse); FlexBoxStyler textStyle(TextStyler value) { return wrap(WidgetModifierConfig.defaultTextStyler(value)); @@ -418,9 +420,16 @@ class FlexBoxStyler extends MixStyler } /// Sets the animation configuration. + /// + /// When [reverse] is provided, it is used as the exit transition + /// config when leaving this style. @override - FlexBoxStyler animate(AnimationConfig value) { - return merge(FlexBoxStyler(animation: value)); + FlexBoxStyler animate(AnimationConfig value, {AnimationConfig? reverse}) { + final config = reverse == null + ? value + : ReversibleAnimationConfig(forward: value, reverse: reverse); + + return merge(FlexBoxStyler(animation: config)); } /// Sets the style variants. diff --git a/packages/mix/lib/src/specs/icon/icon_spec.g.dart b/packages/mix/lib/src/specs/icon/icon_spec.g.dart index f6762df27..106610d19 100644 --- a/packages/mix/lib/src/specs/icon/icon_spec.g.dart +++ b/packages/mix/lib/src/specs/icon/icon_spec.g.dart @@ -339,9 +339,16 @@ class IconStyler extends MixStyler { } /// Sets the animation configuration. + /// + /// When [reverse] is provided, it is used as the exit transition + /// config when leaving this style. @override - IconStyler animate(AnimationConfig value) { - return merge(IconStyler(animation: value)); + IconStyler animate(AnimationConfig value, {AnimationConfig? reverse}) { + final config = reverse == null + ? value + : ReversibleAnimationConfig(forward: value, reverse: reverse); + + return merge(IconStyler(animation: config)); } /// Sets the style variants. diff --git a/packages/mix/lib/src/specs/image/image_spec.g.dart b/packages/mix/lib/src/specs/image/image_spec.g.dart index 7db71f5b8..65eecc243 100644 --- a/packages/mix/lib/src/specs/image/image_spec.g.dart +++ b/packages/mix/lib/src/specs/image/image_spec.g.dart @@ -392,9 +392,16 @@ class ImageStyler extends MixStyler { } /// Sets the animation configuration. + /// + /// When [reverse] is provided, it is used as the exit transition + /// config when leaving this style. @override - ImageStyler animate(AnimationConfig value) { - return merge(ImageStyler(animation: value)); + ImageStyler animate(AnimationConfig value, {AnimationConfig? reverse}) { + final config = reverse == null + ? value + : ReversibleAnimationConfig(forward: value, reverse: reverse); + + return merge(ImageStyler(animation: config)); } /// Sets the style variants. diff --git a/packages/mix/lib/src/specs/stack/stack_spec.g.dart b/packages/mix/lib/src/specs/stack/stack_spec.g.dart index 682cc88e6..7f03eb10d 100644 --- a/packages/mix/lib/src/specs/stack/stack_spec.g.dart +++ b/packages/mix/lib/src/specs/stack/stack_spec.g.dart @@ -165,9 +165,16 @@ class StackStyler extends MixStyler { } /// Sets the animation configuration. + /// + /// When [reverse] is provided, it is used as the exit transition + /// config when leaving this style. @override - StackStyler animate(AnimationConfig value) { - return merge(StackStyler(animation: value)); + StackStyler animate(AnimationConfig value, {AnimationConfig? reverse}) { + final config = reverse == null + ? value + : ReversibleAnimationConfig(forward: value, reverse: reverse); + + return merge(StackStyler(animation: config)); } /// Sets the style variants. diff --git a/packages/mix/lib/src/specs/stackbox/stackbox_spec.g.dart b/packages/mix/lib/src/specs/stackbox/stackbox_spec.g.dart index 5cb9f22b8..f073d5ece 100644 --- a/packages/mix/lib/src/specs/stackbox/stackbox_spec.g.dart +++ b/packages/mix/lib/src/specs/stackbox/stackbox_spec.g.dart @@ -340,8 +340,10 @@ class StackBoxStyler extends MixStyler Matrix4 value, { Alignment alignment = .center, }) => StackBoxStyler().transform(value, alignment: alignment); - factory StackBoxStyler.animate(AnimationConfig value) => - StackBoxStyler().animate(value); + factory StackBoxStyler.animate( + AnimationConfig value, { + AnimationConfig? reverse, + }) => StackBoxStyler().animate(value, reverse: reverse); StackBoxStyler textStyle(TextStyler value) { return wrap(WidgetModifierConfig.defaultTextStyler(value)); @@ -415,9 +417,16 @@ class StackBoxStyler extends MixStyler } /// Sets the animation configuration. + /// + /// When [reverse] is provided, it is used as the exit transition + /// config when leaving this style. @override - StackBoxStyler animate(AnimationConfig value) { - return merge(StackBoxStyler(animation: value)); + StackBoxStyler animate(AnimationConfig value, {AnimationConfig? reverse}) { + final config = reverse == null + ? value + : ReversibleAnimationConfig(forward: value, reverse: reverse); + + return merge(StackBoxStyler(animation: config)); } /// Sets the style variants. diff --git a/packages/mix/lib/src/specs/text/text_spec.g.dart b/packages/mix/lib/src/specs/text/text_spec.g.dart index a2d6293fd..a55c75b8e 100644 --- a/packages/mix/lib/src/specs/text/text_spec.g.dart +++ b/packages/mix/lib/src/specs/text/text_spec.g.dart @@ -432,9 +432,16 @@ class TextStyler extends MixStyler } /// Sets the animation configuration. + /// + /// When [reverse] is provided, it is used as the exit transition + /// config when leaving this style. @override - TextStyler animate(AnimationConfig value) { - return merge(TextStyler(animation: value)); + TextStyler animate(AnimationConfig value, {AnimationConfig? reverse}) { + final config = reverse == null + ? value + : ReversibleAnimationConfig(forward: value, reverse: reverse); + + return merge(TextStyler(animation: config)); } /// Sets the style variants. diff --git a/packages/mix/lib/src/style/mixins/animation_style_mixin.dart b/packages/mix/lib/src/style/mixins/animation_style_mixin.dart index 256d9f28d..4833bc8ce 100644 --- a/packages/mix/lib/src/style/mixins/animation_style_mixin.dart +++ b/packages/mix/lib/src/style/mixins/animation_style_mixin.dart @@ -6,7 +6,7 @@ import '../../core/style.dart'; mixin AnimationStyleMixin, S extends Spec> on Style { @protected - T animate(AnimationConfig config); + T animate(AnimationConfig config, {AnimationConfig? reverse}); /// Creates a keyframe animation. It will animate through the given timeline. T keyframeAnimation({ diff --git a/packages/mix/test/src/animation/animation_config_test.dart b/packages/mix/test/src/animation/animation_config_test.dart index d24b18c00..472c8ae05 100644 --- a/packages/mix/test/src/animation/animation_config_test.dart +++ b/packages/mix/test/src/animation/animation_config_test.dart @@ -655,4 +655,135 @@ void main() { trigger2.dispose(); }); }); + + group('ReversibleAnimationConfig', () { + test('exposes forward and reverse configs', () { + const forward = CurveAnimationConfig( + duration: Duration(milliseconds: 200), + curve: Curves.easeIn, + ); + const reverse = CurveAnimationConfig( + duration: Duration(milliseconds: 100), + curve: Curves.easeOut, + ); + + const config = ReversibleAnimationConfig( + forward: forward, + reverse: reverse, + ); + + expect(config.forward, forward); + expect(config.reverse, reverse); + expect(config, isA()); + }); + + test('supports equality on forward and reverse', () { + const forward = CurveAnimationConfig( + duration: Duration(milliseconds: 200), + curve: Curves.easeIn, + ); + const reverse = CurveAnimationConfig( + duration: Duration(milliseconds: 100), + curve: Curves.easeOut, + ); + + const config1 = ReversibleAnimationConfig( + forward: forward, + reverse: reverse, + ); + const config2 = ReversibleAnimationConfig( + forward: forward, + reverse: reverse, + ); + + expect(config1, equals(config2)); + }); + + test('differs when reverse config differs', () { + const forward = CurveAnimationConfig( + duration: Duration(milliseconds: 200), + curve: Curves.easeIn, + ); + + const config1 = ReversibleAnimationConfig( + forward: forward, + reverse: CurveAnimationConfig( + duration: Duration(milliseconds: 100), + curve: Curves.easeOut, + ), + ); + const config2 = ReversibleAnimationConfig( + forward: forward, + reverse: CurveAnimationConfig( + duration: Duration(milliseconds: 300), + curve: Curves.easeOut, + ), + ); + + expect(config1, isNot(equals(config2))); + }); + + test('allows forward and reverse with different driver kinds', () { + final config = ReversibleAnimationConfig( + forward: SpringAnimationConfig.standard(), + reverse: const CurveAnimationConfig( + duration: Duration(milliseconds: 100), + curve: Curves.easeOut, + ), + ); + + expect(config.forward, isA()); + expect(config.reverse, isA()); + }); + }); + + group('animate(reverse:)', () { + test('wraps in ReversibleAnimationConfig when reverse is provided', () { + const forward = CurveAnimationConfig( + duration: Duration(milliseconds: 200), + curve: Curves.easeIn, + ); + const reverse = CurveAnimationConfig( + duration: Duration(milliseconds: 100), + curve: Curves.easeOut, + ); + + final styler = BoxStyler().animate(forward, reverse: reverse); + + expect( + styler.$animation, + const ReversibleAnimationConfig(forward: forward, reverse: reverse), + ); + }); + + test('keeps the raw config when reverse is omitted', () { + const forward = CurveAnimationConfig( + duration: Duration(milliseconds: 200), + curve: Curves.easeIn, + ); + + final styler = BoxStyler().animate(forward); + + expect(styler.$animation, forward); + expect(styler.$animation, isNot(isA())); + }); + + test('static factory supports reverse', () { + const forward = CurveAnimationConfig( + duration: Duration(milliseconds: 200), + curve: Curves.easeIn, + ); + const reverse = CurveAnimationConfig( + duration: Duration(milliseconds: 100), + curve: Curves.easeOut, + ); + + final styler = BoxStyler.animate(forward, reverse: reverse); + + expect( + styler.$animation, + const ReversibleAnimationConfig(forward: forward, reverse: reverse), + ); + }); + }); } diff --git a/packages/mix/test/src/core/style_builder_hover_test.dart b/packages/mix/test/src/core/style_builder_hover_test.dart index 983c9cd11..9699ecda6 100644 --- a/packages/mix/test/src/core/style_builder_hover_test.dart +++ b/packages/mix/test/src/core/style_builder_hover_test.dart @@ -178,5 +178,99 @@ void main() { await gesture.removePointer(); }, ); + + testWidgets( + 'hover with animate(reverse:) uses forward on enter and reverse on exit', + (tester) async { + // Forward enter is slow (300ms), reverse exit is fast (60ms). We pump + // partway through each to assert the correct timing config drives the + // transition without throwing. + final style = BoxStyler() + .color(Colors.blue) + .width(100) + .height(100) + .animate(.linear(300.ms)) + .onHovered( + BoxStyler() + .color(Colors.red) + .scale(1.02) + .animate(.linear(300.ms), reverse: .linear(60.ms)), + ); + + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: Center( + child: Box(key: const Key('reverse_card'), style: style), + ), + ), + ), + ); + + final gesture = await tester.createGesture( + kind: PointerDeviceKind.mouse, + ); + await gesture.addPointer(location: Offset.zero); + + // Enter: forward (300ms) drives. Settle the animation fully. + await gesture.moveTo( + tester.getCenter(find.byKey(const Key('reverse_card'))), + ); + await tester.pump(); + await tester.pumpAndSettle(); + expect(tester.takeException(), isNull); + + // Exit: reverse (60ms) drives. Pump less than forward duration to make + // sure the fast exit config completed the transition. + await gesture.moveTo(const Offset(-100, -100)); + await tester.pump(); + await tester.pump(const Duration(milliseconds: 80)); + expect(tester.takeException(), isNull); + + await tester.pumpAndSettle(); + await gesture.removePointer(); + }, + ); + + testWidgets('inherited base reversible config does not break hover enter', ( + tester, + ) async { + // The base owns a reversible config and the hover style inherits it. + // Enter should use the forward config rather than the reverse one. + final style = BoxStyler() + .color(Colors.blue) + .width(100) + .height(100) + .animate(.linear(120.ms), reverse: .linear(60.ms)) + .onHovered(BoxStyler().color(Colors.red).scale(1.02)); + + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: Center( + child: Box(key: const Key('inherited_card'), style: style), + ), + ), + ), + ); + + final gesture = await tester.createGesture(kind: PointerDeviceKind.mouse); + await gesture.addPointer(location: Offset.zero); + + await gesture.moveTo( + tester.getCenter(find.byKey(const Key('inherited_card'))), + ); + await tester.pump(); + await tester.pump(const Duration(milliseconds: 70)); + expect(tester.takeException(), isNull); + + await tester.pumpAndSettle(); + await gesture.moveTo(const Offset(-100, -100)); + await tester.pump(); + await tester.pumpAndSettle(); + expect(tester.takeException(), isNull); + + await gesture.removePointer(); + }); }); } diff --git a/packages/mix_generator/lib/src/core/builders/styler_mixin_builder.dart b/packages/mix_generator/lib/src/core/builders/styler_mixin_builder.dart index 6d995d609..401bc8896 100644 --- a/packages/mix_generator/lib/src/core/builders/styler_mixin_builder.dart +++ b/packages/mix_generator/lib/src/core/builders/styler_mixin_builder.dart @@ -67,9 +67,22 @@ class StylerMixinBuilder { final buffer = StringBuffer(); buffer.writeln(' /// Sets the animation configuration.'); + buffer.writeln(' ///'); + buffer.writeln( + ' /// When [reverse] is provided, it is used as the exit transition', + ); + buffer.writeln(' /// config when leaving this style.'); _writeMethodOverride(buffer, 'animate', methodOverrides); - buffer.writeln(' $stylerName animate(AnimationConfig value) {'); - buffer.writeln(' return merge($stylerName(animation: value));'); + buffer.writeln( + ' $stylerName animate(AnimationConfig value, {AnimationConfig? reverse}) {', + ); + buffer.writeln(' final config = reverse == null'); + buffer.writeln(' ? value'); + buffer.writeln( + ' : ReversibleAnimationConfig(forward: value, reverse: reverse);', + ); + buffer.writeln(); + buffer.writeln(' return merge($stylerName(animation: config));'); buffer.writeln(' }'); buffer.writeln(); diff --git a/packages/mix_generator/lib/src/core/curated/styler_surface_metadata.dart b/packages/mix_generator/lib/src/core/curated/styler_surface_metadata.dart index 515f57435..47f29cf87 100644 --- a/packages/mix_generator/lib/src/core/curated/styler_surface_metadata.dart +++ b/packages/mix_generator/lib/src/core/curated/styler_surface_metadata.dart @@ -884,7 +884,7 @@ StylerMethodDescriptor transformAnchorMethodDescriptor() { StylerFactoryDescriptor animateFactoryDescriptor() { return const StylerFactoryDescriptor( name: 'animate', - signature: 'animate(AnimationConfig value)', - invocation: 'animate(value)', + signature: 'animate(AnimationConfig value, {AnimationConfig? reverse})', + invocation: 'animate(value, reverse: reverse)', ); } diff --git a/packages/mix_generator/test/core/builders/styler_mixin_builder_test.dart b/packages/mix_generator/test/core/builders/styler_mixin_builder_test.dart index 15a6e919d..1651b25ed 100644 --- a/packages/mix_generator/test/core/builders/styler_mixin_builder_test.dart +++ b/packages/mix_generator/test/core/builders/styler_mixin_builder_test.dart @@ -290,8 +290,19 @@ void main() { ); final code = builder.build(); - expect(code, contains('BoxStyler animate(AnimationConfig value)')); - expect(code, contains('return merge(BoxStyler(animation: value))')); + expect( + code, + contains( + 'BoxStyler animate(AnimationConfig value, {AnimationConfig? reverse})', + ), + ); + expect( + code, + contains( + 'ReversibleAnimationConfig(forward: value, reverse: reverse)', + ), + ); + expect(code, contains('return merge(BoxStyler(animation: config))')); }); test('generates variants method', () { diff --git a/packages/mix_generator/test/integration/spec_styler_generator_smoke_test.dart b/packages/mix_generator/test/integration/spec_styler_generator_smoke_test.dart index f3879d2ba..86b919c0d 100644 --- a/packages/mix_generator/test/integration/spec_styler_generator_smoke_test.dart +++ b/packages/mix_generator/test/integration/spec_styler_generator_smoke_test.dart @@ -60,6 +60,11 @@ const _mixStub = ''' } class AnimationConfig {} + class ReversibleAnimationConfig extends AnimationConfig { + final AnimationConfig forward; + final AnimationConfig reverse; + const ReversibleAnimationConfig({required this.forward, required this.reverse}); + } class WidgetModifierConfig { static WidgetModifierConfig defaultTextStyler(Object value) => WidgetModifierConfig(); Object? resolve(Object context) => null; @@ -943,7 +948,9 @@ void main() { contains('TrivialStyler({'), contains('EdgeInsetsGeometryMix? padding'), contains('Prop.maybeMix(padding)'), - contains('TrivialStyler animate(AnimationConfig value)'), + contains( + 'TrivialStyler animate(AnimationConfig value, {AnimationConfig? reverse})', + ), contains( 'TrivialStyler variants(List> value)', ), @@ -1300,7 +1307,7 @@ void main() { ), contains('factory BoxStyler.translate(double x, double y'), contains('factory BoxStyler.textStyle(TextStyler value)'), - contains('factory BoxStyler.animate(AnimationConfig value)'), + contains('factory BoxStyler.animate('), ]), ), }, @@ -1386,9 +1393,7 @@ void main() { isNot( contains('factory TextStyler.semanticsLabel(String value)'), ), - isNot( - contains('factory TextStyler.animate(AnimationConfig value)'), - ), + isNot(contains('factory TextStyler.animate(')), ]), ), }, @@ -1423,9 +1428,7 @@ void main() { isNot( contains('factory IconStyler.semanticsLabel(String value)'), ), - isNot( - contains('factory IconStyler.animate(AnimationConfig value)'), - ), + isNot(contains('factory IconStyler.animate(')), ]), ), }, @@ -1471,7 +1474,7 @@ void main() { 'mix|lib/box_spec.g.dart': decodedMatches( allOf([ contains('factory BoxStyler.clipBehavior(Clip value)'), - contains('factory BoxStyler.animate(AnimationConfig value)'), + contains('factory BoxStyler.animate('), isNot(contains('factory BoxStyler.color(Color value)')), isNot(contains('factory BoxStyler.width(double value)')), isNot(contains('factory BoxStyler.scale(double scale')),