Skip to content

Commit

Permalink
Merge pull request #94 from pbissonho/main
Browse files Browse the repository at this point in the history
[Feature] InheritedAttribute -  Extend Mix functionality with custom attributes.
  • Loading branch information
leoafarias authored Sep 27, 2022
2 parents b58a230 + fb25631 commit 403902c
Show file tree
Hide file tree
Showing 8 changed files with 338 additions and 3 deletions.
2 changes: 2 additions & 0 deletions lib/mix.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,5 @@ export 'src/theme/mix_theme.dart';
export 'src/theme/refs/color_token.dart';
export 'src/theme/refs/text_style_token.dart';
export 'src/variants/variants.dart';


21 changes: 21 additions & 0 deletions lib/src/attributes/common/attribute.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,27 @@ abstract class Attribute {
const Attribute();
}

/// An interface that add support to custom attributes for [MixContext].
abstract class InheritedAttribute<T extends InheritedAttribute<T>>
extends Attribute {
const InheritedAttribute();

InheritedAttribute<T> merge(covariant InheritedAttribute<T>? other);

Object get type => T;
}

class InheritedAttributes {
final Map<Object, InheritedAttribute<dynamic>> attributes;

InheritedAttributes(this.attributes);

/// Used to obtain a [InheritedAttribute] from [MixContext].
///
/// Obtain with `mixContext.fromType<MyAttributeExtension>()`.
T? fromType<T>() => attributes[T] as T?;
}

/// Allows to pass down Mixes as attributes for use with helpers
class NestedAttribute<T extends Attribute> extends Attribute {
const NestedAttribute(this.attributes);
Expand Down
41 changes: 41 additions & 0 deletions lib/src/mixer/mix_context.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ extension DecoratorMapExtension on DecoratorMap {

class MixContext {
final BuildContext context;
final InheritedAttributes inheritedAttributes;
final Mix sourceMix;
final Mix originalMix;

Expand All @@ -42,6 +43,16 @@ class MixContext {
final FlexProps flexProps;
final ZBoxProps zBoxProps;

/// Used to obtain a [InheritedAttribute] from [InheritedAttributes].
///
/// Obtain with `mixContext.fromType<MyInheritedAttribute>()`.
T fromType<T extends InheritedAttribute<T>>() {
final attribute = inheritedAttributes.fromType<T>();
debugCheckInheritedAttribute<T>(attribute);

return attribute!;
}

MixContext._({
required this.context,
required this.sourceMix,
Expand All @@ -55,6 +66,7 @@ class MixContext {
required this.directives,
required this.variants,
required this.decorators,
required this.inheritedAttributes,
});

factory MixContext.create({
Expand Down Expand Up @@ -93,6 +105,7 @@ class MixContext {
required Mix<T> mix,
}) {
final _attributes = _expandAttributes(context, mix);

BoxAttributes? boxAttributes;
IconAttributes? iconAttributes;
FlexAttributes? flexAttributes;
Expand All @@ -105,7 +118,21 @@ class MixContext {
final variants = <VariantAttribute>[];
final decorators = <Decorator>[];

final Map<Object, InheritedAttribute> inheritedAttributesMap = {};

for (final attribute in _attributes) {
if (attribute is InheritedAttribute) {
var inheritedAttribute = inheritedAttributesMap[attribute.type];

if (inheritedAttribute == null) {
inheritedAttribute = attribute;
} else {
inheritedAttribute = inheritedAttribute.merge(attribute);
}

inheritedAttributesMap[attribute.type] = inheritedAttribute;
}

if (attribute is VariantAttribute) {
variants.add(attribute);
}
Expand Down Expand Up @@ -211,6 +238,7 @@ class MixContext {
directives: directives,
variants: variants,
decorators: decoratorMap,
inheritedAttributes: InheritedAttributes(inheritedAttributesMap),
);
}

Expand Down Expand Up @@ -335,3 +363,16 @@ class MixContext {
// );
// }
}

/// Asserts that the given mixContext has a [T] attribute.
void debugCheckInheritedAttribute<T extends InheritedAttribute<T>>(
InheritedAttribute? attribute,
) {
assert(() {
return attribute is T;
}(), '''
No $T could be found starting from the mixContext
when call mixContext.fromType<$T>(). This can happen because you
have not create a Mix with $T.
''');
}
1 change: 1 addition & 0 deletions lib/src/mixer/mix_factory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ class Mix<T extends Attribute> {
}

/// Merges many mixes into one
// ignore: long-parameter-list
static Mix<T> combine<T extends Attribute>([
Mix<T>? mix1,
Mix<T>? mix2,
Expand Down
1 change: 1 addition & 0 deletions lib/src/widgets/box.widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,4 @@ class BoxMixedWidget extends MixedWidget {
return current;
}
}

6 changes: 5 additions & 1 deletion lib/src/widgets/mix_context_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import 'package:mix/src/variants/variants.dart';
import 'package:mix/src/widgets/mixable.widget.dart';

typedef WidgetMixBuilder<T> = Widget Function(
BuildContext context, MixContext mixContext);
BuildContext context,
MixContext mixContext,
);

class MixContextBuilder extends MixableWidget {
const MixContextBuilder({
Expand All @@ -27,6 +29,7 @@ class MixContextBuilder extends MixableWidget {
@override
Widget build(BuildContext context) {
final mixContext = getMixContext(context);

return MixContextNotifier(
mixContext,
child: builder(
Expand All @@ -36,3 +39,4 @@ class MixContextBuilder extends MixableWidget {
);
}
}

7 changes: 5 additions & 2 deletions lib/src/widgets/mixable.widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,11 @@ abstract class MixableWidget extends StatelessWidget {
DiagnosticsProperty<Mix>('mix', _mix, defaultValue: null),
);
properties.add(
DiagnosticsProperty<List<Variant>>('variants', _variants,
defaultValue: null),
DiagnosticsProperty<List<Variant>>(
'variants',
_variants,
defaultValue: null,
),
);
properties.add(
DiagnosticsProperty<bool>('inherit', _inherit, defaultValue: true),
Expand Down
Loading

0 comments on commit 403902c

Please sign in to comment.