diff --git a/packages/wyatt_ui_components/example/lib/main.dart b/packages/wyatt_ui_components/example/lib/main.dart index 690322d8..051f5f76 100644 --- a/packages/wyatt_ui_components/example/lib/main.dart +++ b/packages/wyatt_ui_components/example/lib/main.dart @@ -28,7 +28,7 @@ class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) => ComponentTheme( - componentThemeWidget: AppThemeComponent.components, + data: AppThemeComponent.components, child: MaterialApp( title: 'Wyatt Ui Components Example', theme: ThemeData( diff --git a/packages/wyatt_ui_components/lib/src/core/utils/theme_helper.dart b/packages/wyatt_ui_components/lib/src/core/utils/theme_helper.dart index f376b5c9..5db92be8 100644 --- a/packages/wyatt_ui_components/lib/src/core/utils/theme_helper.dart +++ b/packages/wyatt_ui_components/lib/src/core/utils/theme_helper.dart @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with super program. If not, see . +import 'package:flutter/material.dart'; + /// A helper class for getting theme elements. abstract class ThemeHelper { /// Gets a nullable theme element from a list of styles. @@ -83,7 +85,11 @@ abstract class ThemeHelper { ); if (result == null) { - throw Exception('No valid style found'); + throw FlutterError( + 'No valid style found.\nPlease check your theme configuration.\n' + 'Searching for: $P in $styles (transform to $T)\n' + 'If this value can be null, use maybeGetElement instead.', + ); } return result; diff --git a/packages/wyatt_ui_components/lib/src/data/theme_extensions/card_theme_extension_default.dart b/packages/wyatt_ui_components/lib/src/data/theme_extensions/card_theme_extension_default.dart index 06856317..f2c4cab0 100644 --- a/packages/wyatt_ui_components/lib/src/data/theme_extensions/card_theme_extension_default.dart +++ b/packages/wyatt_ui_components/lib/src/data/theme_extensions/card_theme_extension_default.dart @@ -45,7 +45,7 @@ class CardThemeExtensionDefault extends CardThemeExtension { factory CardThemeExtensionDefault.from(ThemeData theme) => CardThemeExtensionDefault( radius: const BorderRadius.all(Radius.circular(12)), - padding: theme.cardTheme.margin, + padding: theme.cardTheme.margin ?? const EdgeInsets.all(4), backgroundColors: MultiColor.single(theme.cardTheme.color), borderColors: MultiColor.single(theme.cardTheme.color), minSize: const Size(330, 0), diff --git a/packages/wyatt_ui_components/lib/src/data/theme_extensions/loader_theme_extension_default.dart b/packages/wyatt_ui_components/lib/src/data/theme_extensions/loader_theme_extension_default.dart new file mode 100644 index 00000000..a962121c --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/data/theme_extensions/loader_theme_extension_default.dart @@ -0,0 +1,50 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/material.dart'; +import 'package:wyatt_ui_components/wyatt_ui_components.dart'; + +/// {@template loader_theme_extension_default} +/// The default [LoaderThemeExtension]. +/// {@endtemplate} +class LoaderThemeExtensionDefault extends LoaderThemeExtension { + /// {@macro loader_theme_extension_default} + const LoaderThemeExtensionDefault({ + required super.colors, + required super.stroke, + }); + + /// Creates a [LoaderThemeExtensionDefault] from a [ThemeData] + /// and opinionated defaults. + /// + /// {@macro card_theme_extension_default} + factory LoaderThemeExtensionDefault.from(ThemeData theme) => + LoaderThemeExtensionDefault( + colors: MultiColor([ + theme.progressIndicatorTheme.color ?? theme.colorScheme.primary, + Colors.transparent, + ]), + stroke: 4, + ); + + /// Creates a [LoaderThemeExtensionDefault] from a dark [ThemeData] + factory LoaderThemeExtensionDefault.dark() => + LoaderThemeExtensionDefault.from(ThemeData.dark()); + + /// Creates a [LoaderThemeExtensionDefault] from a light [ThemeData] + factory LoaderThemeExtensionDefault.light() => + LoaderThemeExtensionDefault.from(ThemeData.light()); +} diff --git a/packages/wyatt_ui_components/lib/src/data/theme_extensions/rich_text_builder_theme_extension_default.dart b/packages/wyatt_ui_components/lib/src/data/theme_extensions/rich_text_builder_theme_extension_default.dart new file mode 100644 index 00000000..2401c2f9 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/data/theme_extensions/rich_text_builder_theme_extension_default.dart @@ -0,0 +1,73 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/material.dart'; +import 'package:wyatt_ui_components/src/domain/theme_extensions/rich_text_builder_theme_extension.dart'; + +class RichTextBuilderThemeExtensionDefault + extends RichTextBuilderThemeExtension { + const RichTextBuilderThemeExtensionDefault({ + required super.defaultStyle, + required super.styles, + }); + + /// Creates a [RichTextBuilderThemeExtensionDefault] from a [ThemeData] + /// and opinionated defaults. + /// + /// {@macro card_theme_extension_default} + factory RichTextBuilderThemeExtensionDefault.from(ThemeData theme) => + RichTextBuilderThemeExtensionDefault( + defaultStyle: theme.textTheme.bodyMedium, + styles: { + 'blue': theme.textTheme.bodyMedium?.copyWith( + color: Colors.blue, + ) ?? + const TextStyle( + color: Colors.blue, + ), + 'red': theme.textTheme.bodyMedium?.copyWith( + color: Colors.red, + ) ?? + const TextStyle( + color: Colors.red, + ), + 'green': theme.textTheme.bodyMedium?.copyWith( + color: Colors.green, + ) ?? + const TextStyle( + color: Colors.green, + ), + 'bold': theme.textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.bold, + ) ?? + const TextStyle( + fontWeight: FontWeight.bold, + ), + 'italic': theme.textTheme.bodyMedium?.copyWith( + fontStyle: FontStyle.italic, + ) ?? + const TextStyle(fontStyle: FontStyle.italic), + }, + ); + + /// Creates a [RichTextBuilderThemeExtensionDefault] from a dark [ThemeData] + factory RichTextBuilderThemeExtensionDefault.dark() => + RichTextBuilderThemeExtensionDefault.from(ThemeData.dark()); + + /// Creates a [RichTextBuilderThemeExtensionDefault] from a light [ThemeData] + factory RichTextBuilderThemeExtensionDefault.light() => + RichTextBuilderThemeExtensionDefault.from(ThemeData.light()); +} diff --git a/packages/wyatt_ui_components/lib/src/data/theme_extensions/theme_extensions.dart b/packages/wyatt_ui_components/lib/src/data/theme_extensions/theme_extensions.dart index 8ba6db44..93ca0a86 100644 --- a/packages/wyatt_ui_components/lib/src/data/theme_extensions/theme_extensions.dart +++ b/packages/wyatt_ui_components/lib/src/data/theme_extensions/theme_extensions.dart @@ -16,4 +16,7 @@ export 'button_theme_extension/button_theme_extension.dart'; export 'card_theme_extension_default.dart'; +export 'loader_theme_extension_default.dart'; +export 'rich_text_builder_theme_extension_default.dart'; export 'text_input_theme_extension_default.dart'; +export 'top_bar_theme_extension_default.dart'; diff --git a/packages/wyatt_ui_components/lib/src/data/theme_extensions/top_bar_theme_extension_default.dart b/packages/wyatt_ui_components/lib/src/data/theme_extensions/top_bar_theme_extension_default.dart new file mode 100644 index 00000000..fbeb5b52 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/data/theme_extensions/top_bar_theme_extension_default.dart @@ -0,0 +1,54 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/material.dart'; +import 'package:wyatt_ui_components/wyatt_ui_components.dart'; + +class TopBarThemeExtensionDefault extends TopBarThemeExtension { + const TopBarThemeExtensionDefault({ + required super.iconTheme, + required super.backgroundColors, + required super.titleStyle, + required super.subtitleStyle, + required super.selectedIndicatorColors, + required super.selectedIndicatorSize, + required super.dividerColor, + }); + + /// Creates a [TopBarThemeExtensionDefault] from a [ThemeData] + /// and opinionated defaults. + /// + /// {@macro card_theme_extension_default} + factory TopBarThemeExtensionDefault.from(ThemeData theme) => + TopBarThemeExtensionDefault( + backgroundColors: MultiColor.single(theme.appBarTheme.backgroundColor), + titleStyle: + theme.appBarTheme.titleTextStyle ?? theme.textTheme.titleMedium, + subtitleStyle: theme.textTheme.bodyMedium, + selectedIndicatorColors: MultiColor.single(theme.colorScheme.primary), + selectedIndicatorSize: const Size(70, 5), + iconTheme: theme.iconTheme, + dividerColor: theme.colorScheme.onSurface.withOpacity(0.12), + ); + + /// Creates a [TopBarThemeExtensionDefault] from a dark [ThemeData] + factory TopBarThemeExtensionDefault.dark() => + TopBarThemeExtensionDefault.from(ThemeData.dark()); + + /// Creates a [TopBarThemeExtensionDefault] from a light [ThemeData] + factory TopBarThemeExtensionDefault.light() => + TopBarThemeExtensionDefault.from(ThemeData.light()); +} diff --git a/packages/wyatt_ui_kit/example/lib/theme/loader_theme.dart b/packages/wyatt_ui_components/lib/src/domain/theme_extensions/loader_theme_extension.dart similarity index 69% rename from packages/wyatt_ui_kit/example/lib/theme/loader_theme.dart rename to packages/wyatt_ui_components/lib/src/domain/theme_extensions/loader_theme_extension.dart index 7933c451..19773054 100644 --- a/packages/wyatt_ui_kit/example/lib/theme/loader_theme.dart +++ b/packages/wyatt_ui_components/lib/src/domain/theme_extensions/loader_theme_extension.dart @@ -18,31 +18,25 @@ import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:wyatt_ui_components/wyatt_ui_components.dart'; -import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; -import 'package:wyatt_ui_kit_example/theme/constants.dart'; -class LoaderTheme extends LoaderThemeExtension { - const LoaderTheme({ - super.colors, - super.stroke, +class LoaderThemeExtension extends ThemeExtension { + const LoaderThemeExtension({ + this.colors, + this.stroke, }); - factory LoaderTheme.light() => const LoaderTheme( - colors: MultiColor([Constants.blue1, Constants.white]), - stroke: 15, - ); + /// Gradient colors from start to end. + final MultiColor? colors; - factory LoaderTheme.dark() => const LoaderTheme( - colors: MultiColor([Constants.blue2, Constants.grey2]), - stroke: 15, - ); + /// Loader stroke width + final double? stroke; @override ThemeExtension copyWith({ MultiColor? colors, double? stroke, }) => - LoaderTheme( + LoaderThemeExtension( colors: colors ?? this.colors, stroke: stroke ?? this.stroke, ); @@ -52,10 +46,10 @@ class LoaderTheme extends LoaderThemeExtension { covariant ThemeExtension? other, double t, ) { - if (other is! LoaderTheme) { + if (other is! LoaderThemeExtension) { return this; } - return LoaderTheme( + return LoaderThemeExtension( colors: MultiColor.lerp(colors, other.colors, t), stroke: lerpDouble(stroke, other.stroke, t), ); diff --git a/packages/wyatt_ui_kit/lib/src/domain/rich_text_builder_theme_extension.dart b/packages/wyatt_ui_components/lib/src/domain/theme_extensions/rich_text_builder_theme_extension.dart similarity index 60% rename from packages/wyatt_ui_kit/lib/src/domain/rich_text_builder_theme_extension.dart rename to packages/wyatt_ui_components/lib/src/domain/theme_extensions/rich_text_builder_theme_extension.dart index e3ccd47e..97b0c2c1 100644 --- a/packages/wyatt_ui_kit/lib/src/domain/rich_text_builder_theme_extension.dart +++ b/packages/wyatt_ui_components/lib/src/domain/theme_extensions/rich_text_builder_theme_extension.dart @@ -16,7 +16,7 @@ import 'package:flutter/material.dart'; -abstract class RichTextBuilderThemeExtension +class RichTextBuilderThemeExtension extends ThemeExtension { const RichTextBuilderThemeExtension({ this.defaultStyle, @@ -28,4 +28,28 @@ abstract class RichTextBuilderThemeExtension /// Used styles in this rich text component. final Map? styles; + + @override + ThemeExtension copyWith({ + TextStyle? defaultStyle, + Map? styles, + }) => + RichTextBuilderThemeExtension( + defaultStyle: defaultStyle ?? this.defaultStyle, + styles: styles ?? this.styles, + ); + + @override + ThemeExtension lerp( + covariant ThemeExtension? other, + double t, + ) { + if (other is! RichTextBuilderThemeExtension) { + return this; + } + return RichTextBuilderThemeExtension( + defaultStyle: TextStyle.lerp(defaultStyle, other.defaultStyle, t), + styles: styles, + ); + } } diff --git a/packages/wyatt_ui_components/lib/src/domain/theme_extensions/theme_extensions.dart b/packages/wyatt_ui_components/lib/src/domain/theme_extensions/theme_extensions.dart index 86fd7252..2ee56ddc 100644 --- a/packages/wyatt_ui_components/lib/src/domain/theme_extensions/theme_extensions.dart +++ b/packages/wyatt_ui_components/lib/src/domain/theme_extensions/theme_extensions.dart @@ -16,4 +16,7 @@ export 'button_theme_extension/button_theme_extension.dart'; export 'card_theme_extension.dart'; +export 'loader_theme_extension.dart'; +export 'rich_text_builder_theme_extension.dart'; export 'text_input_theme_extension.dart'; +export 'top_bar_theme_extension.dart'; diff --git a/packages/wyatt_ui_components/lib/src/domain/theme_extensions/top_bar_theme_extension.dart b/packages/wyatt_ui_components/lib/src/domain/theme_extensions/top_bar_theme_extension.dart new file mode 100644 index 00000000..22d07c41 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/theme_extensions/top_bar_theme_extension.dart @@ -0,0 +1,95 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/material.dart'; +import 'package:wyatt_ui_components/wyatt_ui_components.dart'; + +class TopBarThemeExtension extends ThemeExtension { + const TopBarThemeExtension({ + this.iconTheme, + this.backgroundColors, + this.titleStyle, + this.subtitleStyle, + this.selectedIndicatorColors, + this.selectedIndicatorSize, + this.dividerColor, + }); + + /// Background colors from start to end of the top bar. + final MultiColor? backgroundColors; + + /// Icon theme used in this top bar. + final IconThemeData? iconTheme; + + /// Selected indicator colors used in this top bar. + final MultiColor? selectedIndicatorColors; + + /// Divider color used in this top bar. + final Color? dividerColor; + + /// Title style used in this top bar. + final TextStyle? titleStyle; + + /// Subtitle style used in this top bar. + final TextStyle? subtitleStyle; + + /// Selected indicator size used in this top bar. + final Size? selectedIndicatorSize; + + @override + ThemeExtension copyWith({ + MultiColor? backgroundColors, + IconThemeData? iconTheme, + MultiColor? selectedIndicatorColors, + Color? dividerColor, + TextStyle? titleStyle, + TextStyle? subtitleStyle, + Size? selectedIndicatorSize, + }) => + TopBarThemeExtension( + iconTheme: iconTheme ?? this.iconTheme, + backgroundColors: backgroundColors ?? this.backgroundColors, + selectedIndicatorColors: + selectedIndicatorColors ?? this.selectedIndicatorColors, + dividerColor: dividerColor ?? this.dividerColor, + titleStyle: titleStyle ?? this.titleStyle, + subtitleStyle: subtitleStyle ?? this.subtitleStyle, + selectedIndicatorSize: + selectedIndicatorSize ?? this.selectedIndicatorSize, + ); + + @override + ThemeExtension lerp( + covariant ThemeExtension? other, + double t, + ) { + if (other is! TopBarThemeExtension) { + return this; + } + return TopBarThemeExtension( + iconTheme: IconThemeData.lerp(iconTheme, other.iconTheme, t), + backgroundColors: + MultiColor.lerp(backgroundColors, other.backgroundColors, t), + selectedIndicatorColors: MultiColor.lerp( + selectedIndicatorColors, other.selectedIndicatorColors, t,), + dividerColor: Color.lerp(dividerColor, other.dividerColor, t), + titleStyle: TextStyle.lerp(titleStyle, other.titleStyle, t), + subtitleStyle: TextStyle.lerp(subtitleStyle, other.subtitleStyle, t), + selectedIndicatorSize: + Size.lerp(selectedIndicatorSize, other.selectedIndicatorSize, t), + ); + } +} diff --git a/packages/wyatt_ui_components/lib/src/features/component_theme.dart b/packages/wyatt_ui_components/lib/src/features/component_theme.dart index c7dc79d3..47649a69 100644 --- a/packages/wyatt_ui_components/lib/src/features/component_theme.dart +++ b/packages/wyatt_ui_components/lib/src/features/component_theme.dart @@ -15,7 +15,7 @@ // along with this program. If not, see . import 'package:flutter/material.dart'; -import 'package:wyatt_ui_components/src/features/features.dart'; +import 'package:wyatt_ui_components/wyatt_ui_components.dart'; /// {@template component_theme} /// A [ComponentTheme] widget that provides a [ComponentThemeData] to its @@ -25,11 +25,22 @@ class ComponentTheme extends StatelessWidget { /// {@macro component_theme} const ComponentTheme({ required this.child, - required this.componentThemeWidget, + required this.data, + this.themeExtensionProvider = const DefaultThemeExtensionProvider(), super.key, }); + + /// The [ComponentThemeData] of this widget. + /// + /// This contains all components instances of the theme. + final ComponentThemeData data; + + /// The [ThemeExtensionProvider] that provides the extensions for the + /// current theme. + final ThemeExtensionProvider themeExtensionProvider; + + /// The widget below this widget in the tree. final Widget child; - final ComponentThemeData componentThemeWidget; /// Returns the [ComponentThemeData] of the closest ancestor [ComponentTheme] /// widget. If there is no ancestor [ComponentTheme] widget, it throws an @@ -42,7 +53,7 @@ class ComponentTheme extends StatelessWidget { inheritedThemeComponent != null, 'Theme component not find in tree', ); - return inheritedThemeComponent!.themeWidget.componentThemeWidget; + return inheritedThemeComponent!.themeWidget.data; } /// Returns the [ComponentThemeData] of the closest ancestor [ComponentTheme] @@ -51,13 +62,17 @@ class ComponentTheme extends StatelessWidget { final _InheritedComponentTheme? inheritedThemeComponent = context.dependOnInheritedWidgetOfExactType<_InheritedComponentTheme>(); - return inheritedThemeComponent?.themeWidget.componentThemeWidget; + return inheritedThemeComponent?.themeWidget.data; } @override - Widget build(BuildContext context) => _InheritedComponentTheme( - this, - child: child, + Widget build(BuildContext context) => Theme( + // Injections of the default extensions for the current brightness + data: themeExtensionProvider.applyExtensionsTo(Theme.of(context)), + child: _InheritedComponentTheme( + this, + child: child, + ), ); } diff --git a/packages/wyatt_ui_components/lib/src/features/features.dart b/packages/wyatt_ui_components/lib/src/features/features.dart index 6c0f1b4a..584f8990 100644 --- a/packages/wyatt_ui_components/lib/src/features/features.dart +++ b/packages/wyatt_ui_components/lib/src/features/features.dart @@ -16,3 +16,4 @@ export 'component_theme.dart'; export 'component_theme_data.dart'; +export 'theme_extension_provider.dart'; diff --git a/packages/wyatt_ui_components/lib/src/features/theme_extension_provider.dart b/packages/wyatt_ui_components/lib/src/features/theme_extension_provider.dart new file mode 100644 index 00000000..3b7fd736 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/features/theme_extension_provider.dart @@ -0,0 +1,107 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/material.dart'; +import 'package:wyatt_ui_components/wyatt_ui_components.dart'; + +/// {@template theme_extension_provider} +/// A provider of [ThemeExtension]s to automatically apply to a [Theme]. +/// {@endtemplate} +abstract class ThemeExtensionProvider { + /// {@macro theme_extension_provider} + const ThemeExtensionProvider(); + + /// Returns the [ThemeExtension]s to apply to the current [ThemeData]. + List> getThemeExtensionsFor(ThemeData theme); + + /// Returns a [ThemeData] with the [ThemeExtension]s applied. + ThemeData applyExtensionsTo( + ThemeData theme, + ) => + theme.copyWith( + extensions: [ + ...theme.extensions.values, + ...getThemeExtensionsFor(theme), + ], + ); +} + +/// {@template default_theme_extension_provider} +/// A [ThemeExtensionProvider] that provides the default [ThemeExtension]s +/// for the current [ThemeData.brightness]. +/// {@endtemplate} +class DefaultThemeExtensionProvider extends ThemeExtensionProvider { + /// {@macro default_theme_extension_provider} + const DefaultThemeExtensionProvider(); + + /// Default light theme extensions form Wyatt UI Components + /// + /// This needs to be added to the [ThemeData] in order to use the + /// Wyatt UI Components widgets. + /// + /// Those extensions are the default ones used in fallback mode + /// when no custom theme is provided. + /// + /// See `wyatt_ui_kit` for a custom theme example. + static List> get defaultLight => [ + // Cards + CardThemeExtensionDefault.light(), + // Loader + LoaderThemeExtensionDefault.light(), + // RichText + RichTextBuilderThemeExtensionDefault.light(), + // Buttons + FileSelectionButtonThemeExtensionDefault.light(), + FlatButtonThemeExtensionDefault.light(), + SimpleIconButtonThemeExtensionDefault.light(), + SymbolButtonThemeExtensionDefault.light(), + // TextInput + TextInputThemeExtensionDefault.light(), + // TopBar + TopBarThemeExtensionDefault.light(), + ]; + + /// Default dark theme extensions form Wyatt UI Components + /// + /// This needs to be added to the [ThemeData] in order to use the + /// Wyatt UI Components widgets. + /// + /// Those extensions are the default ones used in fallback mode + /// when no custom theme is provided. + /// + /// See `wyatt_ui_kit` for a custom theme example. + static List> get defaultDark => [ + // Cards + CardThemeExtensionDefault.dark(), + // Loader + LoaderThemeExtensionDefault.dark(), + // RichText + RichTextBuilderThemeExtensionDefault.dark(), + // Buttons + FileSelectionButtonThemeExtensionDefault.dark(), + FlatButtonThemeExtensionDefault.dark(), + SimpleIconButtonThemeExtensionDefault.dark(), + SymbolButtonThemeExtensionDefault.dark(), + // TextInput + TextInputThemeExtensionDefault.dark(), + // TopBar + TopBarThemeExtensionDefault.dark(), + ]; + + @override + List> getThemeExtensionsFor(ThemeData theme) => + theme.brightness == Brightness.light ? defaultLight : defaultDark; +} diff --git a/packages/wyatt_ui_kit/example/lib/main.dart b/packages/wyatt_ui_kit/example/lib/main.dart index 12d39646..a9de8a29 100644 --- a/packages/wyatt_ui_kit/example/lib/main.dart +++ b/packages/wyatt_ui_kit/example/lib/main.dart @@ -17,6 +17,8 @@ import 'package:adaptive_theme/adaptive_theme.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:wyatt_ui_components/wyatt_ui_components.dart'; +import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; import 'package:wyatt_ui_kit_example/home.dart'; import 'package:wyatt_ui_kit_example/theme/themes.dart'; @@ -43,20 +45,23 @@ class App extends StatelessWidget { initial: AdaptiveThemeMode.light, light: Themes.lightFromTheme(defaultTheme), dark: Themes.darkFromTheme(defaultTheme), - builder: (light, dark) => MaterialApp( - localizationsDelegates: const [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - ], - theme: light, - darkTheme: dark, - supportedLocales: const [ - Locale('fr', ''), - ], - title: title, - home: Home( - forceIndex: defaultPage, + builder: (light, dark) => ComponentTheme( + data: WyattComponentThemeData.wyattComponentThemeData, + child: MaterialApp( + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + ], + theme: light, + darkTheme: dark, + supportedLocales: const [ + Locale('fr', ''), + ], + title: title, + home: Home( + forceIndex: defaultPage, + ), ), ), ); diff --git a/packages/wyatt_ui_kit/example/lib/theme/rich_text_builder_theme.dart b/packages/wyatt_ui_kit/example/lib/theme/rich_text_builder_theme.dart deleted file mode 100644 index dc5d4cac..00000000 --- a/packages/wyatt_ui_kit/example/lib/theme/rich_text_builder_theme.dart +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (C) 2023 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:wyatt_ui_components/wyatt_ui_components.dart'; -import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; -import 'package:wyatt_ui_kit_example/theme/constants.dart'; - -final Map _styles = { - 'gradient-blue': GradientTextStyle.from( - GoogleFonts.montserrat( - fontSize: 20, - fontWeight: FontWeight.w600, - color: Constants.blue1, - height: 1.8, - ), - const MultiColor(Constants.blueGradient), - ), - 'gradient-red': GradientTextStyle.from( - GoogleFonts.montserrat( - fontSize: 20, - fontWeight: FontWeight.w600, - color: Constants.red1, - height: 1.8, - ), - const MultiColor(Constants.redGradient), - ), - 'gradient-green': GradientTextStyle.from( - GoogleFonts.montserrat( - fontSize: 20, - fontWeight: FontWeight.w600, - color: Constants.green1, - height: 1.8, - ), - const MultiColor(Constants.greenGradient), - ), - 'blue': GoogleFonts.montserrat( - fontSize: 20, - fontWeight: FontWeight.w600, - color: Constants.blue1, - height: 1.8, - ), - 'red': GoogleFonts.montserrat( - fontSize: 20, - fontWeight: FontWeight.w600, - color: Constants.red1, - height: 1.8, - ), - 'green': GoogleFonts.montserrat( - fontSize: 20, - fontWeight: FontWeight.w600, - color: Constants.green1, - height: 1.8, - ), -}; - -class RichTextBuilderTheme extends RichTextBuilderThemeExtension { - const RichTextBuilderTheme({ - super.defaultStyle, - super.styles, - }); - - factory RichTextBuilderTheme.light() => RichTextBuilderTheme( - defaultStyle: GoogleFonts.montserrat( - fontSize: 18, - fontWeight: FontWeight.w500, - color: Constants.grey3, - height: 1.8, - ), - styles: _styles, - ); - - factory RichTextBuilderTheme.dark() => RichTextBuilderTheme( - defaultStyle: GoogleFonts.montserrat( - fontSize: 18, - fontWeight: FontWeight.w500, - color: Constants.white, - height: 1.8, - ), - styles: _styles, - ); - - @override - ThemeExtension copyWith({ - TextStyle? defaultStyle, - Map? styles, - }) => - RichTextBuilderTheme( - defaultStyle: defaultStyle ?? this.defaultStyle, - styles: styles ?? this.styles, - ); - - @override - ThemeExtension lerp( - covariant ThemeExtension? other, - double t, - ) { - if (other is! RichTextBuilderTheme) { - return this; - } - return RichTextBuilderTheme( - defaultStyle: TextStyle.lerp(defaultStyle, other.defaultStyle, t), - styles: styles, - ); - } -} diff --git a/packages/wyatt_ui_kit/example/lib/theme/themes.dart b/packages/wyatt_ui_kit/example/lib/theme/themes.dart index 57252b6e..4a8ad422 100644 --- a/packages/wyatt_ui_kit/example/lib/theme/themes.dart +++ b/packages/wyatt_ui_kit/example/lib/theme/themes.dart @@ -17,11 +17,7 @@ import 'package:adaptive_theme/adaptive_theme.dart'; import 'package:flutter/material.dart' hide CardTheme; import 'package:google_fonts/google_fonts.dart'; -import 'package:wyatt_ui_components/wyatt_ui_components.dart'; import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; -import 'package:wyatt_ui_kit_example/theme/loader_theme.dart'; -import 'package:wyatt_ui_kit_example/theme/rich_text_builder_theme.dart'; -import 'package:wyatt_ui_kit_example/theme/top_bar_theme.dart'; /// Easely switch between Material and Studio themes. abstract class Themes { @@ -67,17 +63,6 @@ abstract class Themes { textTheme: GoogleFonts.robotoTextTheme( ThemeData.light().textTheme, ), - extensions: >[ - // Cards - CardThemeExtensionDefault.light(), - // Buttons - FileSelectionButtonThemeExtensionDefault.light(), - FlatButtonThemeExtensionDefault.light(), - SimpleIconButtonThemeExtensionDefault.light(), - SymbolButtonThemeExtensionDefault.light(), - // TextInput - TextInputThemeExtensionDefault.light(), - ], ); static ThemeData get studioLight { @@ -97,41 +82,13 @@ abstract class Themes { ), ); - return theme.copyWith( - extensions: >[ - // Cards - CardThemeExtensionImpl.light(theme: theme), - // Buttons - FileSelectionButtonThemeExtensionImpl.light(theme: theme), - FlatButtonThemeExtensionImpl.light(theme: theme), - SimpleIconButtonThemeExtensionImpl.light(theme: theme), - SymbolButtonThemeExtensionImpl.light(theme: theme), - // Loader - LoaderTheme.light(), - // Rich Text - RichTextBuilderTheme.light(), - // TextInput - TextInputThemeExtensionImpl.light(theme: theme), - TopAppBarTheme.light(), - ], - ); + return const WyattThemeExtensions().applyExtensionsTo(theme); } static ThemeData get materialDark => ThemeData.dark().copyWith( textTheme: GoogleFonts.robotoTextTheme( ThemeData.dark().textTheme, ), - extensions: >[ - // Cards - CardThemeExtensionDefault.dark(), - // Buttons - FileSelectionButtonThemeExtensionDefault.dark(), - FlatButtonThemeExtensionDefault.dark(), - SimpleIconButtonThemeExtensionDefault.dark(), - SymbolButtonThemeExtensionDefault.dark(), - // TextInput - TextInputThemeExtensionDefault.dark(), - ], ); static ThemeData get studioDark { @@ -154,23 +111,6 @@ abstract class Themes { ), ); - return theme.copyWith( - extensions: >[ - // Cards - CardThemeExtensionImpl.dark(theme: theme), - // Buttons - FileSelectionButtonThemeExtensionImpl.dark(theme: theme), - FlatButtonThemeExtensionImpl.dark(theme: theme), - SimpleIconButtonThemeExtensionImpl.dark(theme: theme), - SymbolButtonThemeExtensionImpl.dark(theme: theme), - // Loader - LoaderTheme.dark(), - // Rich Text - RichTextBuilderTheme.dark(), - // TextInput - TextInputThemeExtensionImpl.dark(theme: theme), - TopAppBarTheme.dark(), - ], - ); + return const WyattThemeExtensions().applyExtensionsTo(theme); } } diff --git a/packages/wyatt_ui_kit/example/lib/theme/top_bar_theme.dart b/packages/wyatt_ui_kit/example/lib/theme/top_bar_theme.dart deleted file mode 100644 index 8c3f0772..00000000 --- a/packages/wyatt_ui_kit/example/lib/theme/top_bar_theme.dart +++ /dev/null @@ -1,81 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:wyatt_ui_components/wyatt_ui_components.dart'; -import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; - -class TopAppBarTheme extends TopBarThemeExtension { - const TopAppBarTheme({ - super.iconTheme, - super.backgroundColors, - super.secondaryColor, - super.titleStyle, - super.subTitleStyle, - }); - - factory TopAppBarTheme.light() => TopAppBarTheme( - backgroundColors: const MultiColor.single( - Color.fromRGBO(246, 246, 246, 1), - ), - secondaryColor: const Color.fromRGBO(36, 38, 42, 1), - titleStyle: GoogleFonts.montserrat( - fontWeight: FontWeight.bold, - color: const Color.fromRGBO(36, 38, 42, 1), - fontSize: 18, - ), - subTitleStyle: GoogleFonts.montserrat( - fontWeight: FontWeight.w400, - color: const Color.fromRGBO(36, 38, 42, 1), - fontSize: 18, - ), - iconTheme: const IconThemeData(color: Color.fromRGBO(36, 38, 42, 1)), - ); - - factory TopAppBarTheme.dark() => TopAppBarTheme( - backgroundColors: const MultiColor([ - Color.fromRGBO(44, 50, 56, 1), - Color.fromRGBO(39, 47, 61, 1), - Color.fromRGBO(44, 50, 56, 1), - ]), - secondaryColor: Colors.white, - titleStyle: GoogleFonts.montserrat( - fontWeight: FontWeight.bold, - fontSize: 18, - ), - subTitleStyle: GoogleFonts.montserrat( - fontWeight: FontWeight.w400, - fontSize: 18, - ), - iconTheme: const IconThemeData(color: Colors.white), - ); - - @override - ThemeExtension copyWith({ - IconThemeData? iconTheme, - MultiColor? backgroundColors, - Color? secondaryColor, - TextStyle? titleStyle, - }) => - TopAppBarTheme( - iconTheme: iconTheme ?? this.iconTheme, - backgroundColors: backgroundColors ?? this.backgroundColors, - secondaryColor: secondaryColor ?? this.secondaryColor, - titleStyle: titleStyle ?? this.titleStyle, - ); - - @override - ThemeExtension lerp( - covariant ThemeExtension? other, - double t, - ) { - if (other is! TopAppBarTheme) { - return this; - } - return TopAppBarTheme( - iconTheme: IconThemeData.lerp(iconTheme, other.iconTheme, t), - backgroundColors: - MultiColor.lerp(backgroundColors, other.backgroundColors, t), - secondaryColor: Color.lerp(secondaryColor, other.secondaryColor, t), - titleStyle: TextStyle.lerp(titleStyle, other.titleStyle, t), - ); - } -} diff --git a/packages/wyatt_ui_kit/lib/src/components/bars/top_app_bar.dart b/packages/wyatt_ui_kit/lib/src/components/bars/top_app_bar.dart index da1795a9..a9dac898 100644 --- a/packages/wyatt_ui_kit/lib/src/components/bars/top_app_bar.dart +++ b/packages/wyatt_ui_kit/lib/src/components/bars/top_app_bar.dart @@ -54,6 +54,8 @@ class TopAppBar extends TopAppBarComponent with $TopAppBarCWMixin { [ backgroundColor, context.themeExtension()?.backgroundColors, + TopBarThemeExtensionDefault.from(Theme.of(context)) + .backgroundColors, ], valueValidator: (value) => value?.isGradient, transform: (value) => @@ -63,7 +65,8 @@ class TopAppBar extends TopAppBarComponent with $TopAppBarCWMixin { [ backgroundColor, context.themeExtension()?.backgroundColors, - MultiColor.single(Theme.of(context).appBarTheme.backgroundColor), + TopBarThemeExtensionDefault.from(Theme.of(context)) + .backgroundColors, ], valueValidator: (value) => value?.isColor, transform: (value) => value?.color, @@ -86,10 +89,8 @@ class TopAppBar extends TopAppBarComponent with $TopAppBarCWMixin { [ iconTheme, context.themeExtension()?.iconTheme, - Theme.of(context).iconTheme, + TopBarThemeExtensionDefault.from(Theme.of(context)).iconTheme, ], - valueValidator: (value) => value != null, - transform: (value) => value, ), primary: primary ?? true, excludeHeaderSemantics: excludeHeaderSemantics ?? false, @@ -98,13 +99,12 @@ class TopAppBar extends TopAppBarComponent with $TopAppBarCWMixin { data: title?.data ?? '', style: ThemeHelper.getElement( [ - context.textTheme.titleLarge, + TopBarThemeExtensionDefault.from(Theme.of(context)) + .titleStyle, context.themeExtension()?.titleStyle, title?.style, ], - valueValidator: (value) => value != null, - combine: (p0, p1) => p0?.merge(p1), - transform: (value) => value, + combine: (value, element) => value?.merge(element), ), gradientColors: const MultiColor([]), ), @@ -118,12 +118,10 @@ class TopAppBar extends TopAppBarComponent with $TopAppBarCWMixin { [ context .themeExtension() - ?.secondaryColor - ?.withOpacity(0.1), - Theme.of(context).dividerColor, + ?.dividerColor, + TopBarThemeExtensionDefault.from(Theme.of(context)) + .dividerColor, ], - valueValidator: (value) => value != null, - transform: (value) => value, ), context: context, tiles: expandedWidget!, diff --git a/packages/wyatt_ui_kit/lib/src/components/bars/top_navigation_bar.dart b/packages/wyatt_ui_kit/lib/src/components/bars/top_navigation_bar.dart index 7497e61b..aaba2096 100644 --- a/packages/wyatt_ui_kit/lib/src/components/bars/top_navigation_bar.dart +++ b/packages/wyatt_ui_kit/lib/src/components/bars/top_navigation_bar.dart @@ -58,6 +58,8 @@ class TopNavigationBar extends TopNavigationBarComponent [ backgroundColor, context.themeExtension()?.backgroundColors, + TopBarThemeExtensionDefault.from(Theme.of(context)) + .backgroundColors, ], valueValidator: (value) => value?.isGradient, transform: (value) => @@ -67,7 +69,8 @@ class TopNavigationBar extends TopNavigationBarComponent [ backgroundColor, context.themeExtension()?.backgroundColors, - MultiColor.single(Theme.of(context).appBarTheme.backgroundColor), + TopBarThemeExtensionDefault.from(Theme.of(context)) + .backgroundColors, ], valueValidator: (value) => value?.isColor, transform: (value) => value?.color, @@ -89,10 +92,8 @@ class TopNavigationBar extends TopNavigationBarComponent [ iconTheme, context.themeExtension()?.iconTheme, - Theme.of(context).iconTheme, + TopBarThemeExtensionDefault.from(Theme.of(context)).iconTheme, ], - valueValidator: (value) => value != null, - transform: (value) => value, ), primary: primary ?? true, excludeHeaderSemantics: excludeHeaderSemantics ?? false, diff --git a/packages/wyatt_ui_kit/lib/src/components/bars/widgets/navigation_item.dart b/packages/wyatt_ui_kit/lib/src/components/bars/widgets/navigation_item.dart index cd9c8690..a89c9f1e 100644 --- a/packages/wyatt_ui_kit/lib/src/components/bars/widgets/navigation_item.dart +++ b/packages/wyatt_ui_kit/lib/src/components/bars/widgets/navigation_item.dart @@ -37,35 +37,48 @@ class NavigationItem extends StatelessWidget { [ context .themeExtension() - ?.selectedIndicatorHeight, - // TODO(wyatt): move default value - 5, + ?.selectedIndicatorSize + ?.height, + TopBarThemeExtensionDefault.from(Theme.of(context)) + .selectedIndicatorSize + ?.height, ], - valueValidator: (value) => value != null, - transform: (value) => value, ), width: ThemeHelper.getElement( [ context .themeExtension() - ?.selectedIndicatorWidth, - // TODO(wyatt): move default value - 70, + ?.selectedIndicatorSize + ?.width, + TopBarThemeExtensionDefault.from(Theme.of(context)) + .selectedIndicatorSize + ?.width, ], - valueValidator: (value) => value != null, - transform: (value) => value, ), decoration: BoxDecoration( borderRadius: BorderRadius.circular(100), - color: ThemeHelper.getElement( + gradient: ThemeHelper.maybeGetElement( [ context .themeExtension() - ?.secondaryColor, - context.colorScheme.primary + ?.selectedIndicatorColors, + TopBarThemeExtensionDefault.from(Theme.of(context)) + .selectedIndicatorColors ], - valueValidator: (value) => value != null, - transform: (value) => value, + valueValidator: (value) => value?.isGradient, + transform: (value) => + GradientHelper.linearFromNullableColors(value?.colors), + ), + color: ThemeHelper.getElement( + [ + context + .themeExtension() + ?.selectedIndicatorColors, + TopBarThemeExtensionDefault.from(Theme.of(context)) + .selectedIndicatorColors + ], + valueValidator: (value) => value?.isColor, + transform: (value) => value?.color, ), ), ), @@ -75,12 +88,12 @@ class NavigationItem extends StatelessWidget { [ context .themeExtension() - ?.selectedIndicatorWidth, - // TODO(wyatt): move default value - 70, + ?.selectedIndicatorSize + ?.width, + TopBarThemeExtensionDefault.from(Theme.of(context)) + .selectedIndicatorSize + ?.width, ], - valueValidator: (value) => value != null, - transform: (value) => value, ), ), child: SizedBox( @@ -90,15 +103,14 @@ class NavigationItem extends StatelessWidget { item.data, style: ThemeHelper.getElement( [ - context.textTheme.titleMedium, + TopBarThemeExtensionDefault.from(Theme.of(context)) + .subtitleStyle, context .themeExtension() - ?.subTitleStyle, + ?.subtitleStyle, item.style, ], combine: (value, element) => value?.merge(element), - valueValidator: (value) => value != null, - transform: (value) => value, ), ), ), diff --git a/packages/wyatt_ui_kit/lib/src/components/loader/loader.dart b/packages/wyatt_ui_kit/lib/src/components/loader/loader.dart index ec801221..ff9ff42e 100644 --- a/packages/wyatt_ui_kit/lib/src/components/loader/loader.dart +++ b/packages/wyatt_ui_kit/lib/src/components/loader/loader.dart @@ -48,29 +48,18 @@ class Loader extends LoaderComponent with $LoaderCWMixin { [ colors, Theme.of(context).extension()?.colors, - MultiColor([ - Theme.of(context).progressIndicatorTheme.color ?? - context.colorScheme.primary, - context.colorScheme.onPrimary, - ]), - - /// This is the default value. So the final - /// value cannot be null. - const MultiColor([]) + LoaderThemeExtensionDefault.from(Theme.of(context)).colors, ], valueValidator: (multiColor) => multiColor != null && multiColor.isColor, - transform: (multiColor) => multiColor, ), dimension / 2, ThemeHelper.getElement( [ stroke, Theme.of(context).extension()?.stroke, - 4, + LoaderThemeExtensionDefault.from(Theme.of(context)).stroke, ], - valueValidator: (stroke) => stroke != null, - transform: (stroke) => stroke, ), flip: flip ?? false, ), diff --git a/packages/wyatt_ui_kit/lib/src/components/rich_text_builder/rich_text_builder.dart b/packages/wyatt_ui_kit/lib/src/components/rich_text_builder/rich_text_builder.dart index 38c5aa7c..7ddacada 100644 --- a/packages/wyatt_ui_kit/lib/src/components/rich_text_builder/rich_text_builder.dart +++ b/packages/wyatt_ui_kit/lib/src/components/rich_text_builder/rich_text_builder.dart @@ -45,21 +45,19 @@ class RichTextBuilder extends RichTextBuilderComponent Theme.of(context) .extension() ?.defaultStyle, - context.textTheme.bodyMedium, + RichTextBuilderThemeExtensionDefault.from(Theme.of(context)) + .defaultStyle, ], - valueValidator: (style) => style != null, - transform: (style) => style, ), ThemeHelper.getElement, Map>( [ - styles, + RichTextBuilderThemeExtensionDefault.from(Theme.of(context)).styles, Theme.of(context) .extension() ?.styles, - const {}, + styles, ], - valueValidator: (styles) => styles != null, - transform: (styles) => styles, + combine: (value, element) => value?..addAll(element ?? {}), ), null, ), diff --git a/packages/wyatt_ui_kit/lib/src/domain/loader_theme_extension.dart b/packages/wyatt_ui_kit/lib/src/data/theme_extensions/loader_theme_extension_impl.dart similarity index 53% rename from packages/wyatt_ui_kit/lib/src/domain/loader_theme_extension.dart rename to packages/wyatt_ui_kit/lib/src/data/theme_extensions/loader_theme_extension_impl.dart index 727ea82f..0cc6e43f 100644 --- a/packages/wyatt_ui_kit/lib/src/domain/loader_theme_extension.dart +++ b/packages/wyatt_ui_kit/lib/src/data/theme_extensions/loader_theme_extension_impl.dart @@ -17,16 +17,33 @@ import 'package:flutter/material.dart'; import 'package:wyatt_ui_components/wyatt_ui_components.dart'; -abstract class LoaderThemeExtension - extends ThemeExtension { - const LoaderThemeExtension({ - this.colors, - this.stroke, +class LoaderThemeExtensionImpl extends LoaderThemeExtension { + const LoaderThemeExtensionImpl({ + super.colors, + super.stroke, }); - /// Gradient colors from start to end. - final MultiColor? colors; + factory LoaderThemeExtensionImpl.light({ThemeData? theme}) { + theme ??= ThemeData.light(); + return const LoaderThemeExtensionImpl( + colors: MultiColor([ + Color(0xFF436EF4), + Color(0xFF3C97FB), + Colors.transparent, + ]), + stroke: 15, + ); + } - /// Loader stroke width - final double? stroke; + factory LoaderThemeExtensionImpl.dark({ThemeData? theme}) { + theme ??= ThemeData.dark(); + return const LoaderThemeExtensionImpl( + colors: MultiColor([ + Color(0xFF3C97FB), + Color(0xFF436EF4), + Colors.transparent, + ]), + stroke: 15, + ); + } } diff --git a/packages/wyatt_ui_kit/lib/src/data/theme_extensions/rich_text_builder_theme_extension_impl.dart b/packages/wyatt_ui_kit/lib/src/data/theme_extensions/rich_text_builder_theme_extension_impl.dart new file mode 100644 index 00000000..34e30cc2 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/data/theme_extensions/rich_text_builder_theme_extension_impl.dart @@ -0,0 +1,111 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/material.dart'; +import 'package:wyatt_ui_components/wyatt_ui_components.dart'; +import 'package:wyatt_ui_kit/src/components/gradients/gradient_text_style.dart'; + +class RichTextBuilderThemeExtensionImpl extends RichTextBuilderThemeExtension { + const RichTextBuilderThemeExtensionImpl({ + super.defaultStyle, + super.styles, + }); + + factory RichTextBuilderThemeExtensionImpl.dark({ThemeData? theme}) { + theme ??= ThemeData.dark(); + + return RichTextBuilderThemeExtensionImpl( + defaultStyle: theme.textTheme.bodyMedium?.copyWith( + height: 1.8, + ), + styles: stylesFor(theme), + ); + } + + factory RichTextBuilderThemeExtensionImpl.light({ThemeData? theme}) { + theme ??= ThemeData.light(); + + return RichTextBuilderThemeExtensionImpl( + defaultStyle: theme.textTheme.bodyMedium?.copyWith( + height: 1.8, + ), + styles: stylesFor(theme), + ); + } + + static Map stylesFor(ThemeData theme) => { + 'gradient-blue': GradientTextStyle.from( + theme.textTheme.bodyMedium?.copyWith( + fontSize: 20, + fontWeight: FontWeight.w600, + height: 1.8, + ), + const MultiColor([ + Color(0xFF3C97FB), + Color(0xFF436EF4), + ]), + ), + 'gradient-red': GradientTextStyle.from( + theme.textTheme.bodyMedium?.copyWith( + fontSize: 20, + fontWeight: FontWeight.w600, + height: 1.8, + ), + const MultiColor([ + Color(0xFFF44464), + Color(0xFFF44464), + ]), + ), + 'gradient-green': GradientTextStyle.from( + theme.textTheme.bodyMedium?.copyWith( + fontSize: 20, + fontWeight: FontWeight.w600, + height: 1.8, + ), + const MultiColor([ + Color(0xFF00D16C), + Color(0xFF00D16C), + ]), + ), + 'blue': theme.textTheme.bodyMedium?.copyWith( + fontSize: 20, + fontWeight: FontWeight.w600, + color: const Color(0xFF3C97FB), + height: 1.8, + ) ?? + const TextStyle( + color: Color(0xFF3C97FB), + ), + 'red': theme.textTheme.bodyMedium?.copyWith( + fontSize: 20, + fontWeight: FontWeight.w600, + color: const Color(0xFFF44464), + height: 1.8, + ) ?? + const TextStyle( + color: Color(0xFFF44464), + ), + 'green': theme.textTheme.bodyMedium?.copyWith( + fontSize: 20, + fontWeight: FontWeight.w600, + color: const Color(0xFF00D16C), + height: 1.8, + ) ?? + const TextStyle( + color: Color(0xFF00D16C), + ), + }; +} diff --git a/packages/wyatt_ui_kit/lib/src/data/theme_extensions/theme_extensions.dart b/packages/wyatt_ui_kit/lib/src/data/theme_extensions/theme_extensions.dart index 4e97ef04..e028db1b 100644 --- a/packages/wyatt_ui_kit/lib/src/data/theme_extensions/theme_extensions.dart +++ b/packages/wyatt_ui_kit/lib/src/data/theme_extensions/theme_extensions.dart @@ -16,4 +16,7 @@ export 'button_theme_extensions/button_theme_extensions.dart'; export 'card_theme_extension_impl.dart'; +export 'loader_theme_extension_impl.dart'; +export 'rich_text_builder_theme_extension_impl.dart'; export 'text_input_theme_extension_impl.dart'; +export 'top_bar_theme_extension_impl.dart'; diff --git a/packages/wyatt_ui_kit/lib/src/data/theme_extensions/top_bar_theme_extension_impl.dart b/packages/wyatt_ui_kit/lib/src/data/theme_extensions/top_bar_theme_extension_impl.dart new file mode 100644 index 00000000..1695c158 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/data/theme_extensions/top_bar_theme_extension_impl.dart @@ -0,0 +1,75 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/material.dart'; +import 'package:wyatt_ui_components/wyatt_ui_components.dart'; + +class TopBarThemeExtensionImpl extends TopBarThemeExtension { + const TopBarThemeExtensionImpl({ + super.iconTheme, + super.backgroundColors, + super.selectedIndicatorColors, + super.selectedIndicatorSize, + super.dividerColor, + super.titleStyle, + super.subtitleStyle, + }); + + factory TopBarThemeExtensionImpl.light({ThemeData? theme}) { + theme ??= ThemeData.light(); + return TopBarThemeExtensionImpl( + backgroundColors: const MultiColor.single( + Color.fromRGBO(246, 246, 246, 1), + ), + dividerColor: const Color.fromRGBO(36, 38, 42, 0.1), + selectedIndicatorColors: + const MultiColor.single(Color.fromRGBO(36, 38, 42, 1)), + titleStyle: theme.textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.bold, + color: const Color.fromRGBO(36, 38, 42, 1), + fontSize: 18, + ), + subtitleStyle: theme.textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w400, + color: const Color.fromRGBO(36, 38, 42, 1), + fontSize: 18, + ), + iconTheme: const IconThemeData(color: Color.fromRGBO(36, 38, 42, 1)), + ); + } + + factory TopBarThemeExtensionImpl.dark({ThemeData? theme}) { + theme ??= ThemeData.dark(); + return TopBarThemeExtensionImpl( + backgroundColors: const MultiColor([ + Color.fromRGBO(44, 50, 56, 1), + Color.fromRGBO(39, 47, 61, 1), + Color.fromRGBO(44, 50, 56, 1), + ]), + dividerColor: const Color.fromRGBO(255, 255, 255, 0.1), + selectedIndicatorColors: const MultiColor.single(Colors.white), + titleStyle: theme.textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.bold, + fontSize: 18, + ), + subtitleStyle: theme.textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w400, + fontSize: 18, + ), + iconTheme: const IconThemeData(color: Colors.white), + ); + } +} diff --git a/packages/wyatt_ui_kit/lib/src/domain/domain.dart b/packages/wyatt_ui_kit/lib/src/domain/domain.dart deleted file mode 100644 index 9614891b..00000000 --- a/packages/wyatt_ui_kit/lib/src/domain/domain.dart +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (C) 2023 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -export './loader_theme_extension.dart'; -export './rich_text_builder_theme_extension.dart'; -export './text_input_theme_extension.dart'; -export 'top_bar_theme_extension.dart'; diff --git a/packages/wyatt_ui_kit/lib/src/domain/text_input_theme_extension.dart b/packages/wyatt_ui_kit/lib/src/domain/text_input_theme_extension.dart deleted file mode 100644 index 25ee1d2f..00000000 --- a/packages/wyatt_ui_kit/lib/src/domain/text_input_theme_extension.dart +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (C) 2023 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:flutter/material.dart'; -import 'package:wyatt_ui_components/wyatt_ui_components.dart'; - -abstract class TextInputThemeExtension - extends ThemeExtension { - const TextInputThemeExtension({ - this.normalStyle, - this.focusedStyle, - this.errorStyle, - this.disableStyle, - }); - - final TextInputStyle? normalStyle; - final TextInputStyle? focusedStyle; - final TextInputStyle? errorStyle; - final TextInputStyle? disableStyle; -} diff --git a/packages/wyatt_ui_kit/lib/src/domain/top_bar_theme_extension.dart b/packages/wyatt_ui_kit/lib/src/domain/top_bar_theme_extension.dart deleted file mode 100644 index 42a34410..00000000 --- a/packages/wyatt_ui_kit/lib/src/domain/top_bar_theme_extension.dart +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (C) 2023 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:flutter/material.dart'; -import 'package:wyatt_ui_components/wyatt_ui_components.dart'; - -abstract class TopBarThemeExtension - extends ThemeExtension { - const TopBarThemeExtension({ - this.iconTheme, - this.backgroundColors, - this.secondaryColor, - this.titleStyle, - this.subTitleStyle, - this.selectedIndicatorHeight, - this.selectedIndicatorWidth, - }); - - final MultiColor? backgroundColors; - final IconThemeData? iconTheme; - final Color? secondaryColor; - - final TextStyle? titleStyle; - final TextStyle? subTitleStyle; - - final double? selectedIndicatorHeight; - final double? selectedIndicatorWidth; -} diff --git a/packages/wyatt_ui_kit/lib/src/features/wyatt_component_theme_data.dart b/packages/wyatt_ui_kit/lib/src/features/wyatt_component_theme_data.dart index 3579428f..8003b1f4 100644 --- a/packages/wyatt_ui_kit/lib/src/features/wyatt_component_theme_data.dart +++ b/packages/wyatt_ui_kit/lib/src/features/wyatt_component_theme_data.dart @@ -20,7 +20,7 @@ import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; /// {@template wyatt_component_theme_data} /// A class that holds the theme data for the Wyatt UI Kit. /// {@endtemplate} -class WyattComponentThemeData { +abstract class WyattComponentThemeData { /// {@macro wyatt_component_theme_data} static ComponentThemeData get wyattComponentThemeData => ComponentThemeData( appBar: const TopAppBar(), diff --git a/packages/wyatt_ui_kit/lib/src/features/wyatt_theme_extensions.dart b/packages/wyatt_ui_kit/lib/src/features/wyatt_theme_extensions.dart new file mode 100644 index 00000000..25c19c03 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/features/wyatt_theme_extensions.dart @@ -0,0 +1,73 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/material.dart'; +import 'package:wyatt_ui_components/wyatt_ui_components.dart'; +import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; + +/// {@template wyatt_theme_extensions} +/// Wyatt UI Kit theme extensions +/// +/// This class is used to provide the theme extensions for the Wyatt UI Kit. +/// {@endtemplate} +class WyattThemeExtensions extends ThemeExtensionProvider { + /// {@macro wyatt_theme_extensions} + const WyattThemeExtensions() : super(); + + /// Wyatt UI Kit, light theme extensions + static List> light({ThemeData? theme}) => [ + // Cards + CardThemeExtensionImpl.light(theme: theme), + // Loader + LoaderThemeExtensionImpl.light(theme: theme), + // RichTextBuilder + RichTextBuilderThemeExtensionImpl.light(theme: theme), + // Buttons + FileSelectionButtonThemeExtensionImpl.light(theme: theme), + FlatButtonThemeExtensionImpl.light(theme: theme), + SimpleIconButtonThemeExtensionImpl.light(theme: theme), + SymbolButtonThemeExtensionImpl.light(theme: theme), + // TextInput + TextInputThemeExtensionImpl.light(theme: theme), + // TopBar + TopBarThemeExtensionImpl.light(theme: theme), + ]; + + /// Wyatt UI Kit, dark theme extensions + static List> dark({ThemeData? theme}) => [ + // Cards + CardThemeExtensionImpl.dark(theme: theme), + // Loader + LoaderThemeExtensionImpl.dark(theme: theme), + // RichTextBuilder + RichTextBuilderThemeExtensionImpl.dark(theme: theme), + // Buttons + FileSelectionButtonThemeExtensionImpl.dark(theme: theme), + FlatButtonThemeExtensionImpl.dark(theme: theme), + SimpleIconButtonThemeExtensionImpl.dark(theme: theme), + SymbolButtonThemeExtensionImpl.dark(theme: theme), + // TextInput + TextInputThemeExtensionImpl.dark(theme: theme), + // TopBar + TopBarThemeExtensionImpl.dark(theme: theme), + ]; + + @override + List> getThemeExtensionsFor(ThemeData theme) => + theme.brightness == Brightness.light + ? light(theme: theme) + : dark(theme: theme); +} diff --git a/packages/wyatt_ui_kit/lib/src/src.dart b/packages/wyatt_ui_kit/lib/src/src.dart index 58c053b4..5732be97 100644 --- a/packages/wyatt_ui_kit/lib/src/src.dart +++ b/packages/wyatt_ui_kit/lib/src/src.dart @@ -17,5 +17,5 @@ export 'components/components.dart'; export 'core/core.dart'; export 'data/data.dart'; -export 'domain/domain.dart'; export 'features/wyatt_component_theme_data.dart'; +export 'features/wyatt_theme_extensions.dart';