From fb6aa8c1ce64b14307d83ffba8cc853377800052 Mon Sep 17 00:00:00 2001 From: mikecoomber Date: Wed, 4 Sep 2024 17:23:33 +0100 Subject: [PATCH] added back color switching --- example/lib/utils/theme_color_switch.dart | 99 +++++++------- example/lib/widgets.dart | 3 +- lib/generated/tokens/primitives.g.dart | 128 +----------------- lib/generated/tokens/semantics.g.dart | 36 +++--- lib/src/theme/color_swatch.dart | 65 ++++++---- lib/src/utils/zeta_provider.dart | 150 ++++++++++++++++++---- 6 files changed, 241 insertions(+), 240 deletions(-) diff --git a/example/lib/utils/theme_color_switch.dart b/example/lib/utils/theme_color_switch.dart index f441fb90..16a92825 100644 --- a/example/lib/utils/theme_color_switch.dart +++ b/example/lib/utils/theme_color_switch.dart @@ -1,49 +1,58 @@ -// TODO(mikecoomber): Re implement this widget -// import 'package:flutter/material.dart'; -// import 'package:zeta_flutter/zeta_flutter.dart'; +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; -// class ZetaThemeColorSwitch extends StatelessWidget { -// ZetaThemeColorSwitch({super.key}); +class ZetaThemeColorSwitch extends StatefulWidget { + ZetaThemeColorSwitch({super.key}); -// @override -// Widget build(BuildContext context) { -// final zeta = Zeta.of(context); + @override + State createState() => _ZetaThemeColorSwitchState(); +} -// ZetaColors primary(ZetaThemeData data) { -// if (zeta.brightness == Brightness.light) { -// return data.colorsLight; -// } else { -// return data.colorsDark; -// } -// } +class _ZetaThemeColorSwitchState extends State { + String currentTheme = "default"; -// return DropdownButtonHideUnderline( -// child: DropdownButton( -// value: zeta.themeData?.identifier, -// elevation: 0, -// padding: EdgeInsets.all(8), -// icon: Nothing(), -// dropdownColor: zeta.colors.borderDisabled, -// items: appThemes.entries.map((e) { -// final zetaColors = primary(appThemes[e.key]!); -// final color = zetaColors.primary; -// return DropdownMenuItem( -// value: e.value.identifier, -// alignment: Alignment.center, -// child: ZetaAvatar( -// size: ZetaAvatarSize.xxs, -// backgroundColor: color.surface, -// image: ZetaIcon(Icons.color_lens, color: color), -// ), -// ); -// }).toList(), -// onChanged: (value) { -// final theme = appThemes[value]; -// if (theme != null) { -// ZetaProvider.of(context).updateThemeData(theme); -// } -// }, -// ), -// ); -// } -// } + final Map appThemes = { + "default": ZetaPrimitivesLight().blue, + "teal": ZetaPrimitivesLight().teal, + "yellow": ZetaPrimitivesLight().yellow, + "red": ZetaPrimitivesLight().red, + "purple": ZetaPrimitivesLight().purple, + }; + + @override + Widget build(BuildContext context) { + final zeta = Zeta.of(context); + + return DropdownButtonHideUnderline( + child: DropdownButton( + value: currentTheme, + elevation: 0, + padding: EdgeInsets.all(8), + icon: Nothing(), + dropdownColor: zeta.colors.borderDisabled, + items: appThemes.entries.map((e) { + final color = e.value; + final name = e.key; + return DropdownMenuItem( + value: name, + alignment: Alignment.center, + child: ZetaAvatar( + size: ZetaAvatarSize.xxs, + backgroundColor: color, + image: ZetaIcon(Icons.color_lens, color: color), + ), + ); + }).toList(), + onChanged: (value) { + final theme = appThemes[value]; + if (theme != null && value != null) { + ZetaProvider.of(context).updateThemeData(primary: theme); + setState(() { + currentTheme = value; + }); + } + }, + ), + ); + } +} diff --git a/example/lib/widgets.dart b/example/lib/widgets.dart index b32dd4ab..dcaa892b 100644 --- a/example/lib/widgets.dart +++ b/example/lib/widgets.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:zeta_example/utils/rounded_switch.dart'; +import 'package:zeta_example/utils/theme_color_switch.dart'; import 'package:zeta_example/utils/theme_constrast_switch.dart'; import 'package:zeta_example/utils/theme_mode_switch.dart'; @@ -36,7 +37,7 @@ class ExampleScaffold extends StatelessWidget { ZetaRoundedSwitch(), ZetaThemeModeSwitch(), ZetaThemeContrastSwitch(), - // ZetaThemeColorSwitch(), + ZetaThemeColorSwitch(), ], ), backgroundColor: colors.surface, diff --git a/lib/generated/tokens/primitives.g.dart b/lib/generated/tokens/primitives.g.dart index 57d31af3..aafdaeec 100644 --- a/lib/generated/tokens/primitives.g.dart +++ b/lib/generated/tokens/primitives.g.dart @@ -25,7 +25,7 @@ abstract interface class ZetaPrimitives { /// Secondary color ZetaColorSwatch get secondary => _secondary ?? yellow; - /// Brightness of primitives + /// The brightness of the primitives final Brightness brightness; /// Blue @@ -155,12 +155,8 @@ abstract interface class ZetaPrimitives { /// Light primitives final class ZetaPrimitivesLight extends ZetaPrimitives { - /// Constructor for light primitives + /// Constructs a new ZetaPrimitivesLight instance with the (optional) primary and secondary colors. const ZetaPrimitivesLight({super.primary, super.secondary}) : super(brightness: Brightness.light); - - /// Blue - /// - /// {@macro zeta-colors-swatch} @override ZetaColorSwatch get blue => const ZetaColorSwatch( swatch: { @@ -177,10 +173,6 @@ final class ZetaPrimitivesLight extends ZetaPrimitives { }, primary: 0xFF0073e6, ); - - /// Cool - /// - /// {@macro zeta-colors-swatch} @override ZetaColorSwatch get cool => const ZetaColorSwatch( swatch: { @@ -197,10 +189,6 @@ final class ZetaPrimitivesLight extends ZetaPrimitives { }, primary: 0xFF7a8190, ); - - /// Green - /// - /// {@macro zeta-colors-swatch} @override ZetaColorSwatch get green => const ZetaColorSwatch( swatch: { @@ -217,10 +205,6 @@ final class ZetaPrimitivesLight extends ZetaPrimitives { }, primary: 0xFF00864f, ); - - /// Orange - /// - /// {@macro zeta-colors-swatch} @override ZetaColorSwatch get orange => const ZetaColorSwatch( swatch: { @@ -237,10 +221,6 @@ final class ZetaPrimitivesLight extends ZetaPrimitives { }, primary: 0xFFae6500, ); - - /// Pink - /// - /// {@macro zeta-colors-swatch} @override ZetaColorSwatch get pink => const ZetaColorSwatch( swatch: { @@ -257,10 +237,6 @@ final class ZetaPrimitivesLight extends ZetaPrimitives { }, primary: 0xFFd30589, ); - - /// Pure - /// - /// {@macro zeta-colors-swatch} @override ZetaPureColorSwatch get pure => const ZetaPureColorSwatch( swatch: { @@ -270,10 +246,6 @@ final class ZetaPrimitivesLight extends ZetaPrimitives { }, primary: 0xFF151519, ); - - /// Purple - /// - /// {@macro zeta-colors-swatch} @override ZetaColorSwatch get purple => const ZetaColorSwatch( swatch: { @@ -290,10 +262,6 @@ final class ZetaPrimitivesLight extends ZetaPrimitives { }, primary: 0xFF7e0cff, ); - - /// Red - /// - /// {@macro zeta-colors-swatch} @override ZetaColorSwatch get red => const ZetaColorSwatch( swatch: { @@ -310,10 +278,6 @@ final class ZetaPrimitivesLight extends ZetaPrimitives { }, primary: 0xFFd70015, ); - - /// Teal - /// - /// {@macro zeta-colors-swatch} @override ZetaColorSwatch get teal => const ZetaColorSwatch( swatch: { @@ -330,10 +294,6 @@ final class ZetaPrimitivesLight extends ZetaPrimitives { }, primary: 0xFF1a8080, ); - - /// Warm - /// - /// {@macro zeta-colors-swatch} @override ZetaColorSwatch get warm => const ZetaColorSwatch( swatch: { @@ -350,10 +310,6 @@ final class ZetaPrimitivesLight extends ZetaPrimitives { }, primary: 0xFF858585, ); - - /// Yellow - /// - /// {@macro zeta-colors-swatch} @override ZetaColorSwatch get yellow => const ZetaColorSwatch( swatch: { @@ -370,68 +326,36 @@ final class ZetaPrimitivesLight extends ZetaPrimitives { }, primary: 0xFF8d7400, ); - - /// 0dp space @override double get x0 => 0; - - /// 4dp space @override double get x1 => 4; - - /// 8dp space @override double get x2 => 8; - - /// 12dp space @override double get x3 => 12; - - /// 16dp space @override double get x4 => 16; - - /// 20dp space @override double get x5 => 20; - - /// 24dp space @override double get x6 => 24; - - /// 28dp space @override double get x7 => 28; - - /// 32dp space @override double get x8 => 32; - - /// 36dp space @override double get x9 => 36; - - /// 40dp space @override double get x10 => 40; - - /// 44dp space @override double get x11 => 44; - - /// 48dp space @override double get x12 => 48; - - /// 64dp space @override double get x13 => 64; - - /// 80dp space @override double get x14 => 80; - - /// 96dp space @override double get x15 => 96; @override @@ -452,12 +376,8 @@ final class ZetaPrimitivesLight extends ZetaPrimitives { /// Dark primitives final class ZetaPrimitivesDark extends ZetaPrimitives { - /// Constructor for dark primitives + /// Constructs a new ZetaPrimitivesDark instance with the (optional) primary and secondary colors. const ZetaPrimitivesDark({super.primary, super.secondary}) : super(brightness: Brightness.dark); - - /// Blue - /// - /// {@macro zeta-colors-swatch} @override ZetaColorSwatch get blue => const ZetaColorSwatch( swatch: { @@ -474,7 +394,6 @@ final class ZetaPrimitivesDark extends ZetaPrimitives { }, primary: 0xFF599fe5, ); - @override ZetaColorSwatch get cool => const ZetaColorSwatch( swatch: { @@ -491,7 +410,6 @@ final class ZetaPrimitivesDark extends ZetaPrimitives { }, primary: 0xFF8d95a3, ); - @override ZetaColorSwatch get green => const ZetaColorSwatch( swatch: { @@ -508,7 +426,6 @@ final class ZetaPrimitivesDark extends ZetaPrimitives { }, primary: 0xFF67b796, ); - @override ZetaColorSwatch get orange => const ZetaColorSwatch( swatch: { @@ -525,7 +442,6 @@ final class ZetaPrimitivesDark extends ZetaPrimitives { }, primary: 0xFFd78d26, ); - @override ZetaColorSwatch get pink => const ZetaColorSwatch( swatch: { @@ -542,7 +458,6 @@ final class ZetaPrimitivesDark extends ZetaPrimitives { }, primary: 0xFFee78c3, ); - @override ZetaPureColorSwatch get pure => const ZetaPureColorSwatch( swatch: { @@ -552,7 +467,6 @@ final class ZetaPrimitivesDark extends ZetaPrimitives { }, primary: 0xFF1d1e23, ); - @override ZetaColorSwatch get purple => const ZetaColorSwatch( swatch: { @@ -569,7 +483,6 @@ final class ZetaPrimitivesDark extends ZetaPrimitives { }, primary: 0xFF9b71df, ); - @override ZetaColorSwatch get red => const ZetaColorSwatch( swatch: { @@ -586,7 +499,6 @@ final class ZetaPrimitivesDark extends ZetaPrimitives { }, primary: 0xFFf36170, ); - @override ZetaColorSwatch get teal => const ZetaColorSwatch( swatch: { @@ -603,7 +515,6 @@ final class ZetaPrimitivesDark extends ZetaPrimitives { }, primary: 0xFF65c4c4, ); - @override ZetaColorSwatch get warm => const ZetaColorSwatch( swatch: { @@ -620,7 +531,6 @@ final class ZetaPrimitivesDark extends ZetaPrimitives { }, primary: 0xFFb9b9b9, ); - @override ZetaColorSwatch get yellow => const ZetaColorSwatch( swatch: { @@ -637,68 +547,36 @@ final class ZetaPrimitivesDark extends ZetaPrimitives { }, primary: 0xFFc2a728, ); - - /// 0dp space @override double get x0 => 0; - - /// 4dp space @override double get x1 => 4; - - /// 8dp space @override double get x2 => 8; - - /// 12dp space @override double get x3 => 12; - - /// 16dp space @override double get x4 => 16; - - /// 20dp space @override double get x5 => 20; - - /// 24dp space @override double get x6 => 24; - - /// 28dp space @override double get x7 => 28; - - /// 32dp space @override double get x8 => 32; - - /// 36dp space @override double get x9 => 36; - - /// 40dp space @override double get x10 => 40; - - /// 44dp space @override double get x11 => 44; - - /// 48dp space @override double get x12 => 48; - - /// 64dp space @override double get x13 => 64; - - /// 80dp space @override double get x14 => 80; - - /// 96dp space @override double get x15 => 96; @override diff --git a/lib/generated/tokens/semantics.g.dart b/lib/generated/tokens/semantics.g.dart index 14e9f0a0..aa46e67f 100644 --- a/lib/generated/tokens/semantics.g.dart +++ b/lib/generated/tokens/semantics.g.dart @@ -339,7 +339,7 @@ class ZetaSemanticColorsAA implements ZetaSemanticColors { @override Color get mainSubtle => primitives.cool.shade70; @override - Color get mainPrimary => primitives.blue.shade60; + Color get mainPrimary => primitives.primary.shade60; @override Color get mainSecondary => primitives.yellow.shade60; @override @@ -369,9 +369,9 @@ class ZetaSemanticColorsAA implements ZetaSemanticColors { @override Color get borderPure => primitives.pure.shade0; @override - Color get borderPrimaryMain => primitives.blue.shade60; + Color get borderPrimaryMain => primitives.primary.shade60; @override - Color get borderPrimary => primitives.blue.shade50; + Color get borderPrimary => primitives.primary.shade50; @override Color get borderSecondary => primitives.yellow.shade50; @override @@ -399,9 +399,9 @@ class ZetaSemanticColorsAA implements ZetaSemanticColors { @override Color get surfaceWarm => primitives.warm.shade10; @override - Color get surfacePrimary => primitives.blue.shade60; + Color get surfacePrimary => primitives.primary.shade60; @override - Color get surfacePrimarySubtle => primitives.blue.shade10; + Color get surfacePrimarySubtle => primitives.primary.shade10; @override Color get surfaceSecondary => primitives.yellow.shade60; @override @@ -447,13 +447,13 @@ class ZetaSemanticColorsAA implements ZetaSemanticColors { @override Color get stateDefaultFocus => primitives.pure.shade0; @override - Color get statePrimaryEnabled => primitives.blue.shade60; + Color get statePrimaryEnabled => primitives.primary.shade60; @override - Color get statePrimaryHover => primitives.blue.shade50; + Color get statePrimaryHover => primitives.primary.shade50; @override - Color get statePrimarySelected => primitives.blue.shade70; + Color get statePrimarySelected => primitives.primary.shade70; @override - Color get statePrimaryFocus => primitives.blue.shade60; + Color get statePrimaryFocus => primitives.primary.shade60; @override Color get stateSecondaryEnabled => primitives.yellow.shade40; @override @@ -507,7 +507,7 @@ class ZetaSemanticColorsAAA implements ZetaSemanticColors { @override Color get mainSubtle => primitives.cool.shade90; @override - Color get mainPrimary => primitives.blue.shade80; + Color get mainPrimary => primitives.primary.shade80; @override Color get mainSecondary => primitives.yellow.shade80; @override @@ -537,9 +537,9 @@ class ZetaSemanticColorsAAA implements ZetaSemanticColors { @override Color get borderPure => primitives.pure.shade0; @override - Color get borderPrimaryMain => primitives.blue.shade80; + Color get borderPrimaryMain => primitives.primary.shade80; @override - Color get borderPrimary => primitives.blue.shade70; + Color get borderPrimary => primitives.primary.shade70; @override Color get borderSecondary => primitives.yellow.shade70; @override @@ -567,9 +567,9 @@ class ZetaSemanticColorsAAA implements ZetaSemanticColors { @override Color get surfaceWarm => primitives.warm.shade10; @override - Color get surfacePrimary => primitives.blue.shade80; + Color get surfacePrimary => primitives.primary.shade80; @override - Color get surfacePrimarySubtle => primitives.blue.shade10; + Color get surfacePrimarySubtle => primitives.primary.shade10; @override Color get surfaceSecondary => primitives.yellow.shade80; @override @@ -615,13 +615,13 @@ class ZetaSemanticColorsAAA implements ZetaSemanticColors { @override Color get stateDefaultFocus => primitives.pure.shade0; @override - Color get statePrimaryEnabled => primitives.blue.shade80; + Color get statePrimaryEnabled => primitives.primary.shade80; @override - Color get statePrimaryHover => primitives.blue.shade70; + Color get statePrimaryHover => primitives.primary.shade70; @override - Color get statePrimarySelected => primitives.blue.shade90; + Color get statePrimarySelected => primitives.primary.shade90; @override - Color get statePrimaryFocus => primitives.blue.shade80; + Color get statePrimaryFocus => primitives.primary.shade80; @override Color get stateSecondaryEnabled => primitives.yellow.shade80; @override diff --git a/lib/src/theme/color_swatch.dart b/lib/src/theme/color_swatch.dart index 0d4ce9aa..2c8442d3 100644 --- a/lib/src/theme/color_swatch.dart +++ b/lib/src/theme/color_swatch.dart @@ -13,8 +13,6 @@ class ZetaColorSwatch extends ColorSwatch with EquatableMixin { /// See also: /// * [MaterialColor]. const ZetaColorSwatch({ - this.brightness = Brightness.light, - this.contrast = ZetaContrast.aa, required int primary, required Map swatch, }) : super(primary, swatch); @@ -31,8 +29,6 @@ class ZetaColorSwatch extends ColorSwatch with EquatableMixin { // TODO(UX-1144): Find a way to make this better factory ZetaColorSwatch.fromColor( Color primary, { - Brightness brightness = Brightness.light, - ZetaContrast contrast = ZetaContrast.aa, Color background = Colors.white, }) { /// Returns a map of colors shades with their respective indexes. @@ -43,29 +39,48 @@ class ZetaColorSwatch extends ColorSwatch with EquatableMixin { /// - 60 is the primary color itself. /// - 50, 40, 30, 20, and 10 are progressively lighter shades of the primary color. return ZetaColorSwatch( - contrast: contrast, - brightness: brightness, primary: primary.value, swatch: primary.generateSwatch(background: background), - ).apply(brightness: brightness); + ); } - /// Selected contrast level of the system - final Brightness brightness; - - /// Selected contrast level of the system - final ZetaContrast contrast; + /// Creates a [ZetaColorSwatch] from a [MaterialColor] swatch. + factory ZetaColorSwatch.fromMaterialColor(MaterialColor swatch) { + return ZetaColorSwatch( + primary: swatch.value, + swatch: { + 10: swatch.shade50, + 20: swatch.shade100, + 30: swatch.shade200, + 40: swatch.shade300, + 50: swatch.shade400, + 60: swatch.shade500, + 70: swatch.shade600, + 80: swatch.shade700, + 90: swatch.shade800, + 100: swatch.shade900, + }, + ); + } - /// This method is an override of the index operator. - /// - /// If the requested index is not in the table (i.e., it results in `null`), the method returns `this`, - /// presumably the default color. - /// - /// [index] The index of the color swatch to return. Must be a non-negative integer. - /// - /// Returns the color at the specified swatch index, or the default color if the index is not in the table. - @override - Color? operator [](int index) => super[brightness == Brightness.dark ? 110 - index : index] ?? this; + /// Creates a [ZetaColorSwatch] from a [ZetaColorSwatch] with inverted shades. + factory ZetaColorSwatch.inverse(ZetaColorSwatch swatch) { + return ZetaColorSwatch( + primary: swatch.shade40.value, + swatch: { + 10: swatch.shade100, + 20: swatch.shade90, + 30: swatch.shade80, + 40: swatch.shade70, + 50: swatch.shade60, + 60: swatch.shade50, + 70: swatch.shade40, + 80: swatch.shade30, + 90: swatch.shade20, + 100: swatch.shade10, + }, + ); + } /// The lightest shade. Color get shade10 => this[10]!; @@ -119,8 +134,6 @@ class ZetaColorSwatch extends ColorSwatch with EquatableMixin { ZetaContrast contrast = ZetaContrast.aa, Brightness brightness = Brightness.light, }) { - if (this.contrast == contrast && this.brightness == brightness) return this; - // Generate a list of indices based on brightness level final indices = List.generate(10, (index) => (index + 1) * 10); @@ -132,8 +145,6 @@ class ZetaColorSwatch extends ColorSwatch with EquatableMixin { // Return a new ZetaColorSwatch object with the new primaryIndex color and swatch return ZetaColorSwatch( - contrast: contrast, - brightness: brightness, primary: swatch[primaryIndex]!.value, swatch: swatch, ); @@ -142,8 +153,6 @@ class ZetaColorSwatch extends ColorSwatch with EquatableMixin { @override List get props => [ super.value, - brightness, - contrast, shade10, shade20, shade30, diff --git a/lib/src/utils/zeta_provider.dart b/lib/src/utils/zeta_provider.dart index ca92a4bf..7dbd2e34 100644 --- a/lib/src/utils/zeta_provider.dart +++ b/lib/src/utils/zeta_provider.dart @@ -27,12 +27,11 @@ class ZetaProvider extends StatefulWidget with Diagnosticable { this.initialContrast, this.themeService = const ZetaDefaultThemeService(), this.initialRounded = true, - Color? primary, - Color? secondary, - }) : _primary = primary?.generateSwatch(), - _secondary = secondary?.generateSwatch(); - // TODO(mikecoomber): generateSwatch needs to return Map as its used in super constructor - // think about how to handle this + this.customPrimary, + this.customPrimaryDark, + this.customSecondary, + this.customSecondaryDark, + }); /// Specifies the initial theme mode for the app. /// @@ -56,8 +55,25 @@ class ZetaProvider extends StatefulWidget with Diagnosticable { /// Sets whether app should start with components in their rounded or sharp variants. final bool initialRounded; - final ZetaColorSwatch? _primary; - final ZetaColorSwatch? _secondary; + /// Custom primary color for the app. + /// {@template zeta-custom-color} + /// To define every shade of the color, provide a [ZetaColorSwatch] or a [MaterialColor]. + /// If only a [Color] is provided, a [ZetaColorSwatch] will be automatically generated. + /// {@endtemplate} + final Color? customPrimary; + + /// Custom primary color used for dark mode. + /// [customPrimary] must be provided for this to be applied. + /// If this is null, the [customPrimary] will be inverted to generate the dark variant. + final Color? customPrimaryDark; + + /// Custom secondary color for the app. + /// {@macro zeta-custom-color} + final Color? customSecondary; + + /// [customSecondary] must be provided for this to be applied. + /// If this is null, the [customSecondary] will be inverted to generate the dark variant. + final Color? customSecondaryDark; @override State createState() => ZetaProviderState(); @@ -70,7 +86,11 @@ class ZetaProvider extends StatefulWidget with Diagnosticable { ..add(EnumProperty('initialThemeMode', initialThemeMode)) ..add(EnumProperty('initialContrast', initialContrast)) ..add(DiagnosticsProperty('themeService', themeService)) - ..add(DiagnosticsProperty('initialRounded', initialRounded)); + ..add(DiagnosticsProperty('initialRounded', initialRounded)) + ..add(ColorProperty('primary', customPrimary)) + ..add(ColorProperty('primaryDark', customPrimaryDark)) + ..add(ColorProperty('secondary', customSecondary)) + ..add(ColorProperty('secondaryDark', customSecondaryDark)); } /// Retrieves the [ZetaProviderState] from the provided context. @@ -109,6 +129,14 @@ class ZetaProviderState extends State with Diagnosticable, Widgets /// Represents the late initialization of the ThemeMode value. late ThemeMode _themeMode; + ZetaColorSwatch? _customPrimary; + + ZetaColorSwatch? _customPrimaryDark; + + ZetaColorSwatch? _customSecondary; + + ZetaColorSwatch? _customSecondaryDark; + /// Represents the late initialization of the system's current brightness (dark or light mode). late Brightness _platformBrightness; @@ -139,6 +167,13 @@ class ZetaProviderState extends State with Diagnosticable, Widgets // Sets the initial rounded. _rounded = widget.initialRounded; + _setSwatches( + primary: widget.customPrimary, + primaryDark: widget.customPrimaryDark, + secondary: widget.customSecondary, + secondaryDark: widget.customSecondaryDark, + ); + if (widget.initialThemeMode != null) { _themeMode = widget.initialThemeMode!; } @@ -231,6 +266,10 @@ class ZetaProviderState extends State with Diagnosticable, Widgets rounded: _rounded, platformBrightness: _platformBrightness, widget: widget.builder, + customPrimary: _customPrimary, + customSecondary: _customSecondary, + customPrimaryDark: _customPrimaryDark, + customSecondaryDark: _customSecondaryDark, ); } @@ -256,6 +295,60 @@ class ZetaProviderState extends State with Diagnosticable, Widgets }); } + /// Generates and sets swatches with the provided colors. + void _setSwatches({ + Color? primary, + Color? primaryDark, + Color? secondary, + Color? secondaryDark, + }) { + if (primary != null) { + _customPrimary = _getSwatch(primary); + + if (primaryDark != null) { + _customPrimaryDark = _getSwatch(primaryDark); + } else { + _customPrimaryDark = ZetaColorSwatch.inverse(_customPrimary!); + } + } + if (secondary != null) { + _customSecondary = _getSwatch(secondary); + + if (secondaryDark != null) { + _customSecondaryDark = _getSwatch(secondaryDark); + } else { + _customSecondaryDark = ZetaColorSwatch.inverse(_customSecondary!); + } + } + } + + ZetaColorSwatch _getSwatch(Color color) { + if (color is ZetaColorSwatch) { + return color; + } else if (color is MaterialColor) { + return ZetaColorSwatch.fromMaterialColor(color); + } + return ZetaColorSwatch.fromColor(color); + } + + /// Updates the current theme data. + /// {@macro zeta-custom-color} + void updateThemeData({ + Color? primary, + Color? primaryDark, + Color? secondary, + Color? secondaryDark, + }) { + setState(() { + _setSwatches( + primary: primary, + primaryDark: primaryDark, + secondary: secondary, + secondaryDark: secondaryDark, + ); + }); + } + /// Updates the current contrast. void updateContrast(ZetaContrast contrast) { setState(() { @@ -298,8 +391,17 @@ class _InternalProvider extends StatefulWidget { required this.rounded, required this.platformBrightness, required this.widget, + required this.customPrimary, + required this.customSecondary, + required this.customPrimaryDark, + required this.customSecondaryDark, }); + final ZetaColorSwatch? customPrimary; + final ZetaColorSwatch? customSecondary; + final ZetaColorSwatch? customPrimaryDark; + final ZetaColorSwatch? customSecondaryDark; + /// Represents the late initialization of the ZetaContrast value. final ZetaContrast contrast; @@ -313,7 +415,7 @@ class _InternalProvider extends StatefulWidget { final ZetaAppBuilder widget; @override - State<_InternalProvider> createState() => __InternalProviderState(); + State<_InternalProvider> createState() => _InternalProviderState(); @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { @@ -323,28 +425,30 @@ class _InternalProvider extends StatefulWidget { ..add(EnumProperty('contrast', contrast)) ..add(EnumProperty('platformBrightness', platformBrightness)) ..add(DiagnosticsProperty('rounded', rounded)) - ..add(ObjectFlagProperty.has('widget', widget)); + ..add(ObjectFlagProperty.has('widget', widget)) + ..add(ColorProperty('customPrimary', customPrimary)) + ..add(ColorProperty('customSecondary', customSecondary)) + ..add(ColorProperty('customPrimaryDark', customPrimaryDark)) + ..add(ColorProperty('customSecondaryDark', customSecondaryDark)); } } -class __InternalProviderState extends State<_InternalProvider> { +class _InternalProviderState extends State<_InternalProvider> { @override Widget build(BuildContext context) { return Zeta( themeMode: widget.themeMode, contrast: widget.contrast, rounded: widget.rounded, - // customPrimitives: widget.themeMode.isLight - // ? ZetaLightPrimitives( - // primary: customPrimary, - // secondary: customSecondary, - // ) - // : ZetaDarkPrimitives( - // primary: customPrimary, - // secondary: customSecondary, - // ), - // customPrimitives: TODO: Add custom primitives based on theme mode, - // TODO: Add back into the example app + customPrimitives: widget.themeMode == ThemeMode.light + ? ZetaPrimitivesLight( + primary: widget.customPrimary, + secondary: widget.customSecondary, + ) + : ZetaPrimitivesDark( + primary: widget.customPrimaryDark, + secondary: widget.customSecondaryDark, + ), child: Builder( builder: (context) { return widget.widget(