From ef5201537238ce42232e783d91ef7c0815168e19 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Fri, 17 Feb 2023 14:47:56 +0100 Subject: [PATCH 1/5] refactor(ui): rework text gradient and text wrapper --- .../src/core/extensions/string_extension.dart | 9 +- .../lib/src/core/utils/text_wrapper.dart | 11 +- .../lib/buttons/flat_button/flat_buttons.dart | 8 +- .../information_card/information_cards.dart | 22 +-- .../cards/portfolio_card/portfolio_cards.dart | 4 +- .../lib/cards/quote_card/quote_cards.dart | 7 +- .../lib/cards/skill_card/skill_cards.dart | 11 +- .../example/lib/theme/card_theme.dart | 127 ++++++++++++++++++ .../example/lib/theme/themes.dart | 61 +-------- .../example/lib/theme_extension.dart | 54 -------- .../file_selection_button_screen.dart | 17 +-- .../flat_button/flat_button_screen.dart | 8 +- .../symbol_button/symbol_button_screen.dart | 8 +- .../information_card/information_card.dart | 2 +- .../widgets/information_card_titles.dart | 4 +- .../cards/portfolio_card/portfolio_card.dart | 4 +- .../widgets/portfolio_card_header.dart | 2 +- .../cards/quote_card/quote_card.dart | 25 ++-- .../cards/skill_card/skill_card.dart | 2 +- .../skill_card/widgets/skill_card_header.dart | 4 +- .../skill_card/widgets/skill_card_skills.dart | 2 +- .../components/cards/widgets/card_text.dart | 12 +- .../cards/widgets/card_wrapper.dart | 20 +-- .../components/gradients/gradient_text.dart | 53 +++++--- .../gradients/gradient_text_style.dart | 85 ++++++++++++ .../src/components/gradients/gradients.dart | 20 +++ .../lib/src/domain/card_theme_extension.dart | 11 +- 27 files changed, 367 insertions(+), 226 deletions(-) create mode 100644 packages/wyatt_ui_kit/example/lib/theme/card_theme.dart delete mode 100644 packages/wyatt_ui_kit/example/lib/theme_extension.dart create mode 100644 packages/wyatt_ui_kit/lib/src/components/gradients/gradient_text_style.dart create mode 100644 packages/wyatt_ui_kit/lib/src/components/gradients/gradients.dart diff --git a/packages/wyatt_ui_components/lib/src/core/extensions/string_extension.dart b/packages/wyatt_ui_components/lib/src/core/extensions/string_extension.dart index 886f51f9..04503d56 100644 --- a/packages/wyatt_ui_components/lib/src/core/extensions/string_extension.dart +++ b/packages/wyatt_ui_components/lib/src/core/extensions/string_extension.dart @@ -15,10 +15,11 @@ // along with this program. If not, see . import 'package:flutter/widgets.dart'; -import 'package:wyatt_ui_components/src/core/utils/text_wrapper.dart'; +import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; extension StringExtension on String? { - TextWrapper? wrap({TextStyle? style, List? gradient}) => this != null - ? TextWrapper(this!, style: style, gradient: gradient) - : null; + TextWrapper? wrap({TextStyle? style, MultiColor? gradientColors}) => + this != null + ? TextWrapper(this!, style: style, gradientColors: gradientColors) + : null; } diff --git a/packages/wyatt_ui_components/lib/src/core/utils/text_wrapper.dart b/packages/wyatt_ui_components/lib/src/core/utils/text_wrapper.dart index 176765bc..f690aa89 100644 --- a/packages/wyatt_ui_components/lib/src/core/utils/text_wrapper.dart +++ b/packages/wyatt_ui_components/lib/src/core/utils/text_wrapper.dart @@ -15,17 +15,22 @@ // along with this program. If not, see . import 'package:flutter/material.dart'; +import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; +/// Wraps [String] and [TextStyle] into one object that can be +/// a [Text] or a [RichText]. class TextWrapper { const TextWrapper( this.text, { this.style, - this.gradient, + this.gradientColors, }); - factory TextWrapper.text(String text) => TextWrapper(text); + const TextWrapper.text(this.text) + : style = null, + gradientColors = null; final String text; final TextStyle? style; - final List? gradient; + final MultiColor? gradientColors; } diff --git a/packages/wyatt_ui_kit/example/lib/buttons/flat_button/flat_buttons.dart b/packages/wyatt_ui_kit/example/lib/buttons/flat_button/flat_buttons.dart index 2a4d684f..4c1a6b1d 100644 --- a/packages/wyatt_ui_kit/example/lib/buttons/flat_button/flat_buttons.dart +++ b/packages/wyatt_ui_kit/example/lib/buttons/flat_button/flat_buttons.dart @@ -31,8 +31,14 @@ class FlatButtons extends StatelessWidget { ), const Gap(20), Center( + /// You can overwrite global textstyle of the label with [label], + /// but if you only want to override the color/gradient of the text + /// in a particular case you can override the style that will + /// be merge during the build. child: FlatButton( - label: const TextWrapper('Voir notre savoir faire'), + label: const TextWrapper( + 'Voir notre savoir faire', + ), ), ), const Gap(20), diff --git a/packages/wyatt_ui_kit/example/lib/cards/information_card/information_cards.dart b/packages/wyatt_ui_kit/example/lib/cards/information_card/information_cards.dart index 17cd4c98..a671cab1 100644 --- a/packages/wyatt_ui_kit/example/lib/cards/information_card/information_cards.dart +++ b/packages/wyatt_ui_kit/example/lib/cards/information_card/information_cards.dart @@ -18,13 +18,13 @@ class InformationCards extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ - InformationCard( - icons: const [ + const InformationCard( + icons: [ FlutterLogo(size: 60), FlutterLogo(size: 60), FlutterLogo(size: 60), ], - title: const TextWrapper('Flutter'), + title: TextWrapper('Flutter'), subtitle: TextWrapper.text('One single code base.'), body: TextWrapper.text( 'Cupidatat reprehenderit aliqua eiusmod Lorem. ' @@ -58,9 +58,9 @@ class InformationCards extends StatelessWidget { FlutterLogo(size: 60), ], title: 'Flutter'.wrap( - gradient: [Colors.blue, Colors.green], + gradientColors: const MultiColor([Colors.blue, Colors.green]), ), - subtitle: TextWrapper.text('One single code base.'), + subtitle: const TextWrapper.text('One single code base.'), body: 'Cupidatat reprehenderit aliqua eiusmod Lorem. ' 'Qui ipsum id ea ea nulla labore aute ullamco aute ' 'quis elit ut amet velit. Incididunt fugiat proident ' @@ -86,8 +86,8 @@ class InformationCards extends StatelessWidget { FlutterLogo(size: 60), ], axis: Axis.horizontal, - title: TextWrapper.text('Flutter'), - subtitle: TextWrapper.text('One single code base.'), + title: const TextWrapper.text('Flutter'), + subtitle: const TextWrapper.text('One single code base.'), body: 'Cupidatat reprehenderit aliqua eiusmod Lorem. ' 'Qui ipsum id ea ea nulla labore aute ullamco aute ' 'quis elit ut amet velit. Incididunt fugiat proident ' @@ -100,10 +100,10 @@ class InformationCards extends StatelessWidget { 'magna cupidatat Lorem nulla cupidatat voluptate ' 'irure ex reprehenderit.' .wrap( - gradient: [ + gradientColors: const MultiColor([ Colors.red, Colors.orange, - ], + ]), ), ), const Gap(20), @@ -123,14 +123,14 @@ class InformationCards extends StatelessWidget { FlutterLogo(size: 60), ], axis: Axis.horizontal, - title: TextWrapper.text('Flutter'), + title: const TextWrapper.text('Flutter'), subtitle: 'One single code base.'.wrap( // gradient: [Colors.blue, Colors.green], style: const TextStyle( fontWeight: FontWeight.bold, ), ), - body: TextWrapper.text( + body: const TextWrapper.text( 'Cupidatat reprehenderit aliqua eiusmod Lorem. ' 'Qui ipsum id ea ea nulla labore aute ullamco aute ' 'quis elit ut amet velit. Incididunt fugiat proident ' diff --git a/packages/wyatt_ui_kit/example/lib/cards/portfolio_card/portfolio_cards.dart b/packages/wyatt_ui_kit/example/lib/cards/portfolio_card/portfolio_cards.dart index 4d3a440a..509cb240 100644 --- a/packages/wyatt_ui_kit/example/lib/cards/portfolio_card/portfolio_cards.dart +++ b/packages/wyatt_ui_kit/example/lib/cards/portfolio_card/portfolio_cards.dart @@ -128,10 +128,10 @@ class PortfolioCards extends StatelessWidget { ), projectName: const TextWrapper( 'Flutter', - gradient: [ + gradientColors: MultiColor([ Colors.blue, Colors.green, - ], + ]), ), subtitle: const TextWrapper('Mobile / Web / Macos.'), description: const TextWrapper( diff --git a/packages/wyatt_ui_kit/example/lib/cards/quote_card/quote_cards.dart b/packages/wyatt_ui_kit/example/lib/cards/quote_card/quote_cards.dart index 91e52dd0..d5e76720 100644 --- a/packages/wyatt_ui_kit/example/lib/cards/quote_card/quote_cards.dart +++ b/packages/wyatt_ui_kit/example/lib/cards/quote_card/quote_cards.dart @@ -49,7 +49,12 @@ class QuoteCards extends StatelessWidget { 'quis elit ut amet velit. Incididunt fugiat proident ' 'proident deserunt tempor Lorem cillum qui do ' 'ullamco Lorem magna ipsum. Ullamco cupidatat velit ' - .wrap(gradient: [Colors.red, Colors.orange]), + .wrap( + gradientColors: const MultiColor([ + Colors.red, + Colors.orange, + ]), + ), avatar: const FlutterLogo( size: 40, ), diff --git a/packages/wyatt_ui_kit/example/lib/cards/skill_card/skill_cards.dart b/packages/wyatt_ui_kit/example/lib/cards/skill_card/skill_cards.dart index 54dafd90..d8b54077 100644 --- a/packages/wyatt_ui_kit/example/lib/cards/skill_card/skill_cards.dart +++ b/packages/wyatt_ui_kit/example/lib/cards/skill_card/skill_cards.dart @@ -44,7 +44,7 @@ class SkillCards extends StatelessWidget { 'proident deserunt tempor Lorem cillum qui do ' 'ullamco Lorem magna ipsum. Ullamco cupidatat velit ' .wrap(), - skills: [ + skills: const [ TextWrapper.text('Firebase'), TextWrapper.text( 'Qui ipsum id ea ea nulla labore aute ullamco aute ', @@ -62,11 +62,14 @@ class SkillCards extends StatelessWidget { 'proident deserunt tempor Lorem cillum qui do ' 'ullamco Lorem magna ipsum. Ullamco cupidatat velit ' .wrap(), - skills: [ + skills: const [ TextWrapper.text('Firebase'), - const TextWrapper( + TextWrapper( 'Qui ipsum id ea ea nulla labore aute ullamco aute ', - gradient: [Colors.red, Colors.orange], + gradientColors: MultiColor([ + Colors.red, + Colors.orange, + ]), ), TextWrapper.text('Firebase'), TextWrapper.text('Firebase'), diff --git a/packages/wyatt_ui_kit/example/lib/theme/card_theme.dart b/packages/wyatt_ui_kit/example/lib/theme/card_theme.dart new file mode 100644 index 00000000..f103c368 --- /dev/null +++ b/packages/wyatt_ui_kit/example/lib/theme/card_theme.dart @@ -0,0 +1,127 @@ +// 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_wyatt_ui_components.dart'; +import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; + +class CardTheme extends CardThemeExtension { + const CardTheme({ + super.backgroundColors, + super.body, + super.borderColors, + super.secondaryBackgroundColor, + super.shadowColor, + super.subtitle, + super.title, + }); + + factory CardTheme.light() => CardTheme( + backgroundColors: const MultiColor.single(Color(0xFFF6F6F6)), + secondaryBackgroundColor: Colors.white, + borderColors: const MultiColor([ + Color(0xFFDDE0E3), + Color(0xFFCACCD4), + ]), + title: GoogleFonts.montserrat( + fontSize: 24, + fontWeight: FontWeight.w500, + color: const Color(0xFF24262A), + ), + subtitle: GoogleFonts.montserrat( + fontSize: 15, + fontWeight: FontWeight.w300, + color: const Color(0xFF24262A), + ), + body: GoogleFonts.montserrat( + fontSize: 12, + fontWeight: FontWeight.w300, + height: 1.7, + color: const Color(0xFF24262A), + ), + ); + + factory CardTheme.dark() => CardTheme( + backgroundColors: + MultiColor.single(const Color(0xFFFFFFFF).withOpacity(0.04)), + secondaryBackgroundColor: const Color(0xFFFFFFFF).withOpacity(0.04), + borderColors: const MultiColor([ + Color(0xFF60656A), + Color(0xFF383C40), + ]), + title: GoogleFonts.montserrat( + fontSize: 24, + fontWeight: FontWeight.w500, + color: const Color(0xFFFFFFFF), + ), + subtitle: GoogleFonts.montserrat( + fontSize: 15, + fontWeight: FontWeight.w300, + color: const Color(0xFFFFFFFF), + ), + body: GoogleFonts.montserrat( + fontSize: 12, + fontWeight: FontWeight.w300, + height: 1.7, + color: const Color(0xFFFFFFFF), + ), + ); + + @override + ThemeExtension copyWith({ + MultiColor? backgroundColors, + Color? secondaryBackgroundColor, + MultiColor? borderColors, + BoxShadow? shadowColor, + TextStyle? body, + TextStyle? title, + TextStyle? subtitle, + }) => + CardTheme( + backgroundColors: backgroundColors ?? this.backgroundColors, + secondaryBackgroundColor: + secondaryBackgroundColor ?? this.secondaryBackgroundColor, + borderColors: borderColors ?? this.borderColors, + shadowColor: shadowColor ?? this.shadowColor, + body: body ?? this.body, + title: title ?? this.title, + subtitle: subtitle ?? this.subtitle, + ); + + @override + ThemeExtension lerp( + covariant ThemeExtension? other, + double t, + ) { + if (other is! CardTheme) { + return this; + } + return CardTheme( + backgroundColors: other.backgroundColors, + secondaryBackgroundColor: Color.lerp( + secondaryBackgroundColor, + other.secondaryBackgroundColor, + t, + ), + borderColors: other.borderColors, + shadowColor: BoxShadow.lerp(shadowColor, other.shadowColor, t), + body: TextStyle.lerp(body, other.body, t), + title: TextStyle.lerp(title, other.title, t), + subtitle: TextStyle.lerp(subtitle, other.subtitle, t), + ); + } +} diff --git a/packages/wyatt_ui_kit/example/lib/theme/themes.dart b/packages/wyatt_ui_kit/example/lib/theme/themes.dart index c298daf8..684270f8 100644 --- a/packages/wyatt_ui_kit/example/lib/theme/themes.dart +++ b/packages/wyatt_ui_kit/example/lib/theme/themes.dart @@ -15,14 +15,14 @@ // along with this program. If not, see . import 'package:adaptive_theme/adaptive_theme.dart'; -import 'package:flutter/material.dart'; +import 'package:flutter/material.dart' hide CardTheme; import 'package:google_fonts/google_fonts.dart'; +import 'package:wyatt_ui_kit_example/theme/card_theme.dart'; import 'package:wyatt_ui_kit_example/theme/file_selection_button_theme.dart'; import 'package:wyatt_ui_kit_example/theme/flat_button_theme.dart'; import 'package:wyatt_ui_kit_example/theme/loader_theme.dart'; import 'package:wyatt_ui_kit_example/theme/simple_icon_button_theme.dart'; import 'package:wyatt_ui_kit_example/theme/symbol_button_theme.dart'; -import 'package:wyatt_ui_kit_example/theme_extension.dart'; /// Easely switch between Material and Studio themes. abstract class Themes { @@ -78,32 +78,8 @@ abstract class Themes { ), scaffoldBackgroundColor: Colors.white, extensions: >[ - CustomCardColorExtension( - backgroundColors: const [ - Color(0xFFF6F6F6), - ], - secondaryBackgroundColors: Colors.white, - borderColor: const [ - Color(0xFFDDE0E3), - Color(0xFFCACCD4), - ], - title: GoogleFonts.montserrat( - fontSize: 24, - fontWeight: FontWeight.w500, - color: const Color(0xFF24262A), - ), - subtitle: GoogleFonts.montserrat( - fontSize: 15, - fontWeight: FontWeight.w300, - color: const Color(0xFF24262A), - ), - body: GoogleFonts.montserrat( - fontSize: 12, - fontWeight: FontWeight.w300, - height: 1.7, - color: const Color(0xFF24262A), - ), - ), + // Cards + CardTheme.light(), // Buttons FlatButtonTheme.light(), SymbolButtonTheme.light(), @@ -128,33 +104,8 @@ abstract class Themes { ), scaffoldBackgroundColor: const Color(0xFF383C40), extensions: >[ - CustomCardColorExtension( - secondaryBackgroundColors: - const Color(0xFFFFFFFF).withOpacity(0.04), - backgroundColors: [ - const Color(0xFFFFFFFF).withOpacity(0.04), - ], - borderColor: const [ - Color(0xFF60656A), - Color(0xFF383C40), - ], - title: GoogleFonts.montserrat( - fontSize: 24, - fontWeight: FontWeight.w500, - color: const Color(0xFFFFFFFF), - ), - subtitle: GoogleFonts.montserrat( - fontSize: 15, - fontWeight: FontWeight.w300, - color: const Color(0xFFFFFFFF), - ), - body: GoogleFonts.montserrat( - fontSize: 12, - fontWeight: FontWeight.w300, - height: 1.7, - color: const Color(0xFFFFFFFF), - ), - ), + // Cards + CardTheme.dark(), // Buttons FlatButtonTheme.dark(), SymbolButtonTheme.dark(), diff --git a/packages/wyatt_ui_kit/example/lib/theme_extension.dart b/packages/wyatt_ui_kit/example/lib/theme_extension.dart deleted file mode 100644 index 92abc0fb..00000000 --- a/packages/wyatt_ui_kit/example/lib/theme_extension.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:wyatt_ui_kit/wyatt_ui_kit.dart' as ui_kit; - -class CustomCardColorExtension extends ui_kit.CardThemeExtension { - const CustomCardColorExtension({ - super.backgroundColors, - super.secondaryBackgroundColors, - super.borderColor, - super.shadowColor, - super.body, - super.title, - super.subtitle, - }); - - @override - CustomCardColorExtension copyWith({ - List? backgroundColors, - Color? secondaryBackgroundColors, - List? borderColor, - BoxShadow? shadowColor, - TextStyle? body, - TextStyle? title, - TextStyle? subtitle, - }) => - CustomCardColorExtension( - backgroundColors: backgroundColors ?? this.backgroundColors, - secondaryBackgroundColors: - secondaryBackgroundColors ?? this.secondaryBackgroundColors, - borderColor: borderColor ?? this.borderColor, - body: body ?? this.body, - title: title ?? this.title, - subtitle: subtitle ?? this.subtitle, - ); - - @override - ThemeExtension lerp( - covariant ThemeExtension? other, - double t, - ) { - if (other is! CustomCardColorExtension) { - return this; - } - return CustomCardColorExtension( - secondaryBackgroundColors: Color.lerp( - secondaryBackgroundColors, - other.secondaryBackgroundColors, - t, - ), - body: TextStyle.lerp(body, other.body, t), - title: TextStyle.lerp(title, other.title, t), - subtitle: TextStyle.lerp(subtitle, other.subtitle, t), - ); - } -} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button_screen.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button_screen.dart index 8f884b51..bc45bec9 100644 --- a/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button_screen.dart +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button_screen.dart @@ -24,7 +24,6 @@ import 'package:wyatt_ui_kit/src/components/buttons/cubit/invalid_button_cubit.d import 'package:wyatt_ui_kit/src/components/buttons/file_selection_button/dotter_border_child.dart'; import 'package:wyatt_ui_kit/src/components/buttons/file_selection_button/file_selection_button_theme_resolver.dart'; import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart'; -import 'package:wyatt_ui_kit/src/core/helpers/linear_gradient_helper.dart'; class FileSelectionButtonScreen extends CubitScreen { @@ -220,13 +219,7 @@ class FileSelectionButtonScreen title!.text, style: title!.style ?? style.title, ).toGradient( - LinearGradientHelper.fromNullableColors( - title?.gradient ?? - ((style.foregroundColors?.isGradient ?? - false) - ? style.foregroundColors?.colors - : null), - ), + gradientColors: style.foregroundColors, ), ], @@ -247,13 +240,7 @@ class FileSelectionButtonScreen subTitle!.text, style: subTitle!.style ?? style.subTitle, ).toGradient( - LinearGradientHelper.fromNullableColors( - subTitle?.gradient ?? - ((style.foregroundColors?.isGradient ?? - false) - ? style.foregroundColors?.colors - : null), - ), + gradientColors: style.foregroundColors, ), ], ], diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button_screen.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button_screen.dart index 178cdb01..803c68cc 100644 --- a/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button_screen.dart +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button_screen.dart @@ -23,7 +23,6 @@ import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart'; import 'package:wyatt_ui_kit/src/components/buttons/flat_button/flat_button_theme_resolver.dart'; import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart'; import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart'; -import 'package:wyatt_ui_kit/src/core/helpers/linear_gradient_helper.dart'; class FlatButtonScreen extends CubitScreen { const FlatButtonScreen({ @@ -204,12 +203,7 @@ class FlatButtonScreen extends CubitScreen { label!.text, style: label!.style ?? style.label, ).toGradient( - LinearGradientHelper.fromNullableColors( - label?.gradient ?? - ((style.foregroundColors?.isGradient ?? false) - ? style.foregroundColors?.colors - : null), - ), + gradientColors: style.foregroundColors, ) ], Gap(style.padding?.vertical ?? 10), diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/symbol_button/symbol_button_screen.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/symbol_button/symbol_button_screen.dart index 547ebf64..b8c84633 100644 --- a/packages/wyatt_ui_kit/lib/src/components/buttons/symbol_button/symbol_button_screen.dart +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/symbol_button/symbol_button_screen.dart @@ -24,7 +24,6 @@ import 'package:wyatt_ui_kit/src/components/buttons/cubit/selectable_button_cubi import 'package:wyatt_ui_kit/src/components/buttons/symbol_button/symbol_button_theme_resolver.dart'; import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart'; import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart'; -import 'package:wyatt_ui_kit/src/core/helpers/linear_gradient_helper.dart'; class SymbolButtonScreen extends CubitScreen { @@ -228,12 +227,7 @@ class SymbolButtonScreen label!.text, style: label!.style ?? style.label, ).toGradient( - LinearGradientHelper.fromNullableColors( - label?.gradient ?? - ((style.foregroundColors?.isGradient ?? false) - ? style.foregroundColors?.colors - : null), - ), + gradientColors: style.foregroundColors, ), ], ], diff --git a/packages/wyatt_ui_kit/lib/src/components/cards/information_card/information_card.dart b/packages/wyatt_ui_kit/lib/src/components/cards/information_card/information_card.dart index 87cbba04..bcde0f56 100644 --- a/packages/wyatt_ui_kit/lib/src/components/cards/information_card/information_card.dart +++ b/packages/wyatt_ui_kit/lib/src/components/cards/information_card/information_card.dart @@ -80,7 +80,7 @@ class InformationCard extends InformationCardComponent body!.text, textType: TextType.body, style: body!.style, - gradient: body!.gradient, + gradientColors: body!.gradientColors, ), ], ], diff --git a/packages/wyatt_ui_kit/lib/src/components/cards/information_card/widgets/information_card_titles.dart b/packages/wyatt_ui_kit/lib/src/components/cards/information_card/widgets/information_card_titles.dart index 2b48a39d..969e1505 100644 --- a/packages/wyatt_ui_kit/lib/src/components/cards/information_card/widgets/information_card_titles.dart +++ b/packages/wyatt_ui_kit/lib/src/components/cards/information_card/widgets/information_card_titles.dart @@ -44,7 +44,7 @@ class InformationCardTitles extends StatelessWidget { title!.text, textType: TextType.title, style: title!.style, - gradient: title!.gradient, + gradientColors: title!.gradientColors, ), ], if (subtitle != null) ...[ @@ -53,7 +53,7 @@ class InformationCardTitles extends StatelessWidget { subtitle!.text, textType: TextType.subtitle, style: subtitle!.style, - gradient: subtitle!.gradient, + gradientColors: subtitle!.gradientColors, ), ], ], diff --git a/packages/wyatt_ui_kit/lib/src/components/cards/portfolio_card/portfolio_card.dart b/packages/wyatt_ui_kit/lib/src/components/cards/portfolio_card/portfolio_card.dart index 88529fb9..1226b2e6 100644 --- a/packages/wyatt_ui_kit/lib/src/components/cards/portfolio_card/portfolio_card.dart +++ b/packages/wyatt_ui_kit/lib/src/components/cards/portfolio_card/portfolio_card.dart @@ -73,7 +73,7 @@ class PortfolioCard extends PortfolioCardComponent with $PortfolioCardCWMixin { description!.text, textType: TextType.body, style: description!.style, - gradient: description!.gradient, + gradientColors: description!.gradientColors, ), const Gap(20), PortfolioCardHeader( @@ -108,7 +108,7 @@ class PortfolioCard extends PortfolioCardComponent with $PortfolioCardCWMixin { description!.text, textType: TextType.body, style: description!.style, - gradient: description!.gradient, + gradientColors: description!.gradientColors, ), ], if (ctas != null) ...[const Gap(20), ...ctas!], diff --git a/packages/wyatt_ui_kit/lib/src/components/cards/portfolio_card/widgets/portfolio_card_header.dart b/packages/wyatt_ui_kit/lib/src/components/cards/portfolio_card/widgets/portfolio_card_header.dart index 39998629..2a9620fe 100644 --- a/packages/wyatt_ui_kit/lib/src/components/cards/portfolio_card/widgets/portfolio_card_header.dart +++ b/packages/wyatt_ui_kit/lib/src/components/cards/portfolio_card/widgets/portfolio_card_header.dart @@ -71,7 +71,7 @@ class PortfolioCardHeader extends StatelessWidget { color: secondaryBackgroundColors ?? Theme.of(context) .extension() - ?.secondaryBackgroundColors, + ?.secondaryBackgroundColor, borderRadius: BorderRadius.circular(8), ), child: Text( diff --git a/packages/wyatt_ui_kit/lib/src/components/cards/quote_card/quote_card.dart b/packages/wyatt_ui_kit/lib/src/components/cards/quote_card/quote_card.dart index 358a3897..2363a5df 100644 --- a/packages/wyatt_ui_kit/lib/src/components/cards/quote_card/quote_card.dart +++ b/packages/wyatt_ui_kit/lib/src/components/cards/quote_card/quote_card.dart @@ -20,8 +20,7 @@ import 'package:wyatt_component_copy_with_extension/component_copy_with_extensio import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; import 'package:wyatt_ui_kit/src/components/cards/widgets/card_text.dart'; import 'package:wyatt_ui_kit/src/components/cards/widgets/card_wrapper.dart'; -import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart'; -import 'package:wyatt_ui_kit/src/core/extensions/theme_extensions.dart'; +import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; part 'quote_card.g.dart'; @@ -63,9 +62,11 @@ class QuoteCard extends QuoteCardComponent with $QuoteCardCWMixin { alignment: Alignment.topLeft, child: GradientText( '“', - gradient: gradient, - style: context.textTheme.titleLarge - ?.copyWith(fontWeight: FontWeight.bold), + style: GradientTextStyle.from( + context.textTheme.titleLarge + ?.copyWith(fontWeight: FontWeight.bold), + MultiColor(gradient?.colors), + ), ), ), if (quote != null) ...[ @@ -73,7 +74,7 @@ class QuoteCard extends QuoteCardComponent with $QuoteCardCWMixin { quote!.text, textType: TextType.body, style: quote!.style, - gradient: quote!.gradient, + gradientColors: quote!.gradientColors, ), ], const Gap(15), @@ -82,9 +83,11 @@ class QuoteCard extends QuoteCardComponent with $QuoteCardCWMixin { alignment: Alignment.bottomRight, child: GradientText( '”', - gradient: gradient, - style: context.textTheme.titleLarge - ?.copyWith(fontWeight: FontWeight.bold), + style: GradientTextStyle.from( + context.textTheme.titleLarge + ?.copyWith(fontWeight: FontWeight.bold), + MultiColor(gradient?.colors), + ), ), ), Row( @@ -102,7 +105,7 @@ class QuoteCard extends QuoteCardComponent with $QuoteCardCWMixin { name!.text, textType: TextType.body, style: name!.style, - gradient: name!.gradient, + gradientColors: name!.gradientColors, ), ], if (subtitle != null) ...[ @@ -110,7 +113,7 @@ class QuoteCard extends QuoteCardComponent with $QuoteCardCWMixin { subtitle!.text, textType: TextType.subtitle, style: subtitle!.style, - gradient: subtitle!.gradient, + gradientColors: subtitle!.gradientColors, ), ], ], diff --git a/packages/wyatt_ui_kit/lib/src/components/cards/skill_card/skill_card.dart b/packages/wyatt_ui_kit/lib/src/components/cards/skill_card/skill_card.dart index 357f8fcc..6285f0fa 100644 --- a/packages/wyatt_ui_kit/lib/src/components/cards/skill_card/skill_card.dart +++ b/packages/wyatt_ui_kit/lib/src/components/cards/skill_card/skill_card.dart @@ -70,7 +70,7 @@ class SkillCard extends SkillCardComponent with $SkillCardCWMixin { description!.text, textType: TextType.body, style: description!.style, - gradient: description!.gradient, + gradientColors: description!.gradientColors, ), const Gap(25), ], diff --git a/packages/wyatt_ui_kit/lib/src/components/cards/skill_card/widgets/skill_card_header.dart b/packages/wyatt_ui_kit/lib/src/components/cards/skill_card/widgets/skill_card_header.dart index cd4bbfee..bfd8af2d 100644 --- a/packages/wyatt_ui_kit/lib/src/components/cards/skill_card/widgets/skill_card_header.dart +++ b/packages/wyatt_ui_kit/lib/src/components/cards/skill_card/widgets/skill_card_header.dart @@ -46,7 +46,7 @@ class SkillCardHeader extends StatelessWidget { color: secondaryBackgroundColors ?? Theme.of(context) .extension() - ?.secondaryBackgroundColors, + ?.secondaryBackgroundColor, ), child: gradient != null ? GradientIcon( @@ -67,7 +67,7 @@ class SkillCardHeader extends StatelessWidget { title!.text, textType: TextType.title, style: title!.style, - gradient: title!.gradient, + gradientColors: title!.gradientColors, ), ], ], diff --git a/packages/wyatt_ui_kit/lib/src/components/cards/skill_card/widgets/skill_card_skills.dart b/packages/wyatt_ui_kit/lib/src/components/cards/skill_card/widgets/skill_card_skills.dart index 01e9c778..76059fa9 100644 --- a/packages/wyatt_ui_kit/lib/src/components/cards/skill_card/widgets/skill_card_skills.dart +++ b/packages/wyatt_ui_kit/lib/src/components/cards/skill_card/widgets/skill_card_skills.dart @@ -50,7 +50,7 @@ class SkillCardSkills extends StatelessWidget { e.text, textType: TextType.body, style: e.style, - gradient: e.gradient, + gradientColors: e.gradientColors, ), ), ], diff --git a/packages/wyatt_ui_kit/lib/src/components/cards/widgets/card_text.dart b/packages/wyatt_ui_kit/lib/src/components/cards/widgets/card_text.dart index 7f841274..87ae1880 100644 --- a/packages/wyatt_ui_kit/lib/src/components/cards/widgets/card_text.dart +++ b/packages/wyatt_ui_kit/lib/src/components/cards/widgets/card_text.dart @@ -15,7 +15,7 @@ // along with this program. If not, see . import 'package:flutter/material.dart'; -import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart'; +import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; enum TextType { @@ -28,13 +28,13 @@ class CardText extends StatelessWidget { const CardText( this.data, { required this.textType, - this.gradient, this.style, + this.gradientColors, super.key, }); final TextType textType; final TextStyle? style; - final List? gradient; + final MultiColor? gradientColors; final String data; TextStyle? _getStyle(BuildContext context) { @@ -58,9 +58,5 @@ class CardText extends StatelessWidget { Widget build(BuildContext context) => Text( data, style: _getStyle(context), - ).toGradient( - LinearGradientHelper.fromNullableColors( - gradient, - ), - ); + ).toGradient(gradientColors: gradientColors); } diff --git a/packages/wyatt_ui_kit/lib/src/components/cards/widgets/card_wrapper.dart b/packages/wyatt_ui_kit/lib/src/components/cards/widgets/card_wrapper.dart index fe2f1cb8..4c608380 100644 --- a/packages/wyatt_ui_kit/lib/src/components/cards/widgets/card_wrapper.dart +++ b/packages/wyatt_ui_kit/lib/src/components/cards/widgets/card_wrapper.dart @@ -110,8 +110,9 @@ class _CardWrapperState extends State { if (extensionCardColor != null && extensionCardColor.backgroundColors != null && - extensionCardColor.backgroundColors!.length >= 2) { - return LinearGradient(colors: extensionCardColor.backgroundColors!); + extensionCardColor.backgroundColors!.isGradient) { + return LinearGradient( + colors: extensionCardColor.backgroundColors!.colors,); } } return null; @@ -126,9 +127,8 @@ class _CardWrapperState extends State { Theme.of(context).extension(); if (extensionCardColor != null && - extensionCardColor.backgroundColors != null && - extensionCardColor.backgroundColors!.length == 1) { - return extensionCardColor.backgroundColors!.first; + extensionCardColor.backgroundColors != null) { + return extensionCardColor.backgroundColors!.color; } } return Theme.of(context).cardColor; @@ -151,16 +151,16 @@ class _CardWrapperState extends State { final extensionCardColor = Theme.of(context).extension(); if (extensionCardColor != null && - extensionCardColor.borderColor != null) { - if (extensionCardColor.borderColor!.length >= 2) { + extensionCardColor.borderColors != null) { + if (extensionCardColor.borderColors!.isGradient) { return GradientBoxBorder( gradient: LinearGradient( - colors: extensionCardColor.borderColor!, + colors: extensionCardColor.borderColors!.colors, ), ); - } else if (extensionCardColor.backgroundColors!.isNotEmpty) { + } else if (extensionCardColor.backgroundColors!.colors.isNotEmpty) { return Border.all( - color: extensionCardColor.backgroundColors!.first, + color: extensionCardColor.backgroundColors!.color, ); } } diff --git a/packages/wyatt_ui_kit/lib/src/components/gradients/gradient_text.dart b/packages/wyatt_ui_kit/lib/src/components/gradients/gradient_text.dart index 0bed20a9..cd6ae7fe 100644 --- a/packages/wyatt_ui_kit/lib/src/components/gradients/gradient_text.dart +++ b/packages/wyatt_ui_kit/lib/src/components/gradients/gradient_text.dart @@ -17,16 +17,29 @@ // along with this program. If not, see . import 'package:flutter/widgets.dart'; +import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; +import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; extension GradientTextExtension on Text { - GradientText toGradient(Gradient? gradient) => - GradientText.from(this, gradient); + /// If this text contains a [GradientTextStyle] it simply transforms it in + /// [GradientText], if not it needs a [MultiColor]. + GradientText toGradient({MultiColor? gradientColors}) { + if (style is GradientTextStyle?) { + // Gradient + final gradientStyle = (style as GradientTextStyle?)?.gradientColors; + return GradientText.from(this, gradientStyle ?? gradientColors); + } + + return GradientText.from(this, gradientColors); + } + + GradientText toFlutterGradient(Gradient? gradient) => + GradientText.from(this, MultiColor(gradient?.colors)); } class GradientText extends Text { const GradientText( super.data, { - this.gradient, super.style, super.strutStyle, super.textAlign, @@ -43,10 +56,10 @@ class GradientText extends Text { super.key, }); - factory GradientText.from(Text text, Gradient? gradient) => GradientText( + factory GradientText.from(Text text, MultiColor? gradientColors) => + GradientText( text.data ?? '', - style: text.style, - gradient: gradient, + style: GradientTextStyle.from(text.style, gradientColors), strutStyle: text.strutStyle, textAlign: text.textAlign, textDirection: text.textDirection, @@ -62,20 +75,24 @@ class GradientText extends Text { key: text.key, ); - final Gradient? gradient; - @override Widget build(BuildContext context) { - if (gradient != null) { - return ShaderMask( - blendMode: BlendMode.srcIn, - shaderCallback: (bounds) => gradient!.createShader( - Rect.fromLTWH(0, 0, bounds.width, bounds.height), - ), - child: super.build(context), - ); - } else { - return super.build(context); + if (style is GradientTextStyle?) { + // Gradient + final gradientStyle = (style as GradientTextStyle?)?.gradientColors; + final gradient = (gradientStyle?.isGradient ?? false) + ? LinearGradientHelper.fromMultiColor(gradientStyle!) + : null; + if (gradient != null) { + return ShaderMask( + blendMode: BlendMode.srcIn, + shaderCallback: (bounds) => gradient.createShader( + Rect.fromLTWH(0, 0, bounds.width, bounds.height), + ), + child: super.build(context), + ); + } } + return super.build(context); } } diff --git a/packages/wyatt_ui_kit/lib/src/components/gradients/gradient_text_style.dart b/packages/wyatt_ui_kit/lib/src/components/gradients/gradient_text_style.dart new file mode 100644 index 00000000..e737e9e4 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/gradients/gradient_text_style.dart @@ -0,0 +1,85 @@ +// 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/widgets.dart'; +import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; + +class GradientTextStyle extends TextStyle { + const GradientTextStyle({ + this.gradientColors, + super.inherit, + super.color, + super.backgroundColor, + super.fontSize, + super.fontWeight, + super.fontStyle, + super.letterSpacing, + super.wordSpacing, + super.textBaseline, + super.height, + super.leadingDistribution, + super.locale, + super.foreground, + super.background, + super.shadows, + super.fontFeatures, + super.fontVariations, + super.decoration, + super.decorationColor, + super.decorationStyle, + super.decorationThickness, + super.debugLabel, + super.fontFamily, + super.fontFamilyFallback, + super.package, + super.overflow, + }); + + factory GradientTextStyle.from( + TextStyle? textStyle, + MultiColor? gradientColors, + ) => + GradientTextStyle( + gradientColors: gradientColors, + inherit: textStyle?.inherit ?? true, + color: textStyle?.color, + backgroundColor: textStyle?.backgroundColor, + fontSize: textStyle?.fontSize, + fontWeight: textStyle?.fontWeight, + fontStyle: textStyle?.fontStyle, + letterSpacing: textStyle?.letterSpacing, + wordSpacing: textStyle?.wordSpacing, + textBaseline: textStyle?.textBaseline, + height: textStyle?.height, + leadingDistribution: textStyle?.leadingDistribution, + locale: textStyle?.locale, + foreground: textStyle?.foreground, + background: textStyle?.background, + shadows: textStyle?.shadows, + fontFeatures: textStyle?.fontFeatures, + fontVariations: textStyle?.fontVariations, + decoration: textStyle?.decoration, + decorationColor: textStyle?.decorationColor, + decorationStyle: textStyle?.decorationStyle, + decorationThickness: textStyle?.decorationThickness, + debugLabel: textStyle?.debugLabel, + fontFamily: textStyle?.fontFamily, + fontFamilyFallback: textStyle?.fontFamilyFallback, + overflow: textStyle?.overflow, + ); + + final MultiColor? gradientColors; +} diff --git a/packages/wyatt_ui_kit/lib/src/components/gradients/gradients.dart b/packages/wyatt_ui_kit/lib/src/components/gradients/gradients.dart new file mode 100644 index 00000000..e19e9d36 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/gradients/gradients.dart @@ -0,0 +1,20 @@ +// 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 'gradient_box_border.dart'; +export 'gradient_icon.dart'; +export 'gradient_text.dart'; +export 'gradient_text_style.dart'; diff --git a/packages/wyatt_ui_kit/lib/src/domain/card_theme_extension.dart b/packages/wyatt_ui_kit/lib/src/domain/card_theme_extension.dart index 63a0f8a6..1ac3c983 100644 --- a/packages/wyatt_ui_kit/lib/src/domain/card_theme_extension.dart +++ b/packages/wyatt_ui_kit/lib/src/domain/card_theme_extension.dart @@ -15,12 +15,13 @@ // along with this program. If not, see . import 'package:flutter/material.dart'; +import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; abstract class CardThemeExtension extends ThemeExtension { const CardThemeExtension({ this.backgroundColors, - this.secondaryBackgroundColors, - this.borderColor, + this.secondaryBackgroundColor, + this.borderColors, this.shadowColor, this.body, this.title, @@ -28,9 +29,9 @@ abstract class CardThemeExtension extends ThemeExtension { }); // Colors - final List? backgroundColors; - final Color? secondaryBackgroundColors; - final List? borderColor; + final MultiColor? backgroundColors; + final Color? secondaryBackgroundColor; + final MultiColor? borderColors; final BoxShadow? shadowColor; // TextStyles -- 2.47.2 From efeb3acff36fd0a8004dceb9afd5797b5f8fe865 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Fri, 17 Feb 2023 14:48:23 +0100 Subject: [PATCH 2/5] build(ui): optimize build runner --- packages/wyatt_ui_components/build.yaml | 9 +++++++++ packages/wyatt_ui_kit/build.yaml | 8 ++++++++ 2 files changed, 17 insertions(+) create mode 100644 packages/wyatt_ui_components/build.yaml create mode 100644 packages/wyatt_ui_kit/build.yaml diff --git a/packages/wyatt_ui_components/build.yaml b/packages/wyatt_ui_components/build.yaml new file mode 100644 index 00000000..2c112259 --- /dev/null +++ b/packages/wyatt_ui_components/build.yaml @@ -0,0 +1,9 @@ +targets: + $default: + builders: + # Typically the builder key is just the package name, run `pub run build_runner doctor` to check your config. + wyatt_component_copy_with_gen:component_copy_with_gen: + generate_for: + # Example glob for only the Dart files under `lib/models` + - lib/**/*.dart + - example/lib/**/*.dart \ No newline at end of file diff --git a/packages/wyatt_ui_kit/build.yaml b/packages/wyatt_ui_kit/build.yaml new file mode 100644 index 00000000..70c89a03 --- /dev/null +++ b/packages/wyatt_ui_kit/build.yaml @@ -0,0 +1,8 @@ +targets: + $default: + builders: + # Typically the builder key is just the package name, run `pub run build_runner doctor` to check your config. + wyatt_component_copy_with_gen:component_copy_with_gen: + generate_for: + # Example glob for only the Dart files under `lib/models` + - lib/**/*.dart \ No newline at end of file -- 2.47.2 From 25018dc78a66cf89f1cff1b641e673894821a083 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Fri, 17 Feb 2023 14:48:49 +0100 Subject: [PATCH 3/5] feat(ui_component): add rich text builder / parser --- .../lib/src/domain/entities/entities.dart | 1 + .../entities/rich_text_builder/parser.dart | 120 ++++++++++++++++++ .../rich_text_builder/rich_text_builder.dart | 19 +++ .../rich_text_builder_component.dart | 56 ++++++++ .../rich_text_builder_component.g.dart | 25 ++++ .../rich_text_builder_style.dart | 83 ++++++++++++ 6 files changed, 304 insertions(+) create mode 100644 packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/parser.dart create mode 100644 packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/rich_text_builder.dart create mode 100644 packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/rich_text_builder_component.dart create mode 100644 packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/rich_text_builder_component.g.dart create mode 100644 packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/rich_text_builder_style.dart diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/entities.dart b/packages/wyatt_ui_components/lib/src/domain/entities/entities.dart index f04375b8..85ce40c3 100644 --- a/packages/wyatt_ui_components/lib/src/domain/entities/entities.dart +++ b/packages/wyatt_ui_components/lib/src/domain/entities/entities.dart @@ -23,4 +23,5 @@ export './error_widget_component.dart'; export './loader_component.dart'; export './loader_style.dart'; export './loading_widget_component.dart'; +export './rich_text_builder/rich_text_builder.dart'; export './theme_style.dart'; diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/parser.dart b/packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/parser.dart new file mode 100644 index 00000000..bd92d252 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/parser.dart @@ -0,0 +1,120 @@ +// 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/widgets.dart'; + +class RichTextStyleParameter { + const RichTextStyleParameter( + this.defaultStyle, + this.definedStyle, + this.styleName, + ); + + final TextStyle defaultStyle; + final Map definedStyle; + final String? styleName; + + TextStyle get style { + if (definedStyle.containsKey(styleName)) { + return definedStyle[styleName]!; + } + return defaultStyle; + } + + RichTextStyleParameter copyWith({ + TextStyle? defaultStyle, + Map? definedStyle, + String? styleName, + }) => + RichTextStyleParameter( + defaultStyle ?? this.defaultStyle, + definedStyle ?? this.definedStyle, + styleName ?? this.styleName, + ); +} + +class RichTextNode { + RichTextNode(this.nodes); + + final List nodes; + + static RichTextNode from( + String content, + RegExp regex, + RichTextStyleParameter styleParameter, + ) { + final matches = regex.allMatches(content); + if (matches.isNotEmpty) { + // match found -> construct node with leaf/nodes + final List nodes = []; + for (var i = 0; i < matches.length; i++) { + final previousMatch = i > 0 ? matches.elementAt(i - 1) : null; + final currentMatch = matches.elementAt(i); + // non match before + final nonMatchBefore = (previousMatch != null) + ? content.substring(previousMatch.end, currentMatch.start) + : content.substring(0, currentMatch.start); + nodes + ..add(RichTextNode.from(nonMatchBefore, regex, styleParameter)) + // match + ..add( + RichTextNode.from( + currentMatch.group(2)!, + regex, + styleParameter.copyWith(styleName: currentMatch.group(1)), + ), + ); + } + // non match after + final nonMatchAfter = content.substring(matches.last.end); + nodes.add(RichTextNode.from(nonMatchAfter, regex, styleParameter)); + return RichTextNode(nodes); + } else { + // match not found -> construct leaf + return RichTextLeaf(styleParameter.style, content); + } + } + + InlineSpan toInlineSpan(RichTextParser parser) { + final children = []; + for (final node in nodes) { + children.add(node.toInlineSpan(parser)); + } + return TextSpan(children: children); + } +} + +class RichTextLeaf extends RichTextNode { + RichTextLeaf(this.style, this.content) : super([]); + + final TextStyle style; + final String content; + + @override + InlineSpan toInlineSpan(RichTextParser parser) => + parser.nodeBuilder.call(content, style); +} + +class RichTextParser { + const RichTextParser({required this.nodeBuilder}); + factory RichTextParser.defaultBuilder() => RichTextParser( + nodeBuilder: (content, style) => TextSpan( + text: content, + style: style, + ), + ); + final InlineSpan Function(String content, TextStyle style) nodeBuilder; +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/rich_text_builder.dart b/packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/rich_text_builder.dart new file mode 100644 index 00000000..1eae2365 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/rich_text_builder.dart @@ -0,0 +1,19 @@ +// 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 'parser.dart'; +export 'rich_text_builder_component.dart'; +export 'rich_text_builder_style.dart'; diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/rich_text_builder_component.dart b/packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/rich_text_builder_component.dart new file mode 100644 index 00000000..603aaa32 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/rich_text_builder_component.dart @@ -0,0 +1,56 @@ +// 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/widgets.dart'; +import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart'; +import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; + +part 'rich_text_builder_component.g.dart'; + +@ComponentProxyExtension() +abstract class RichTextBuilderComponent extends Component + with CopyWithMixin<$RichTextBuilderComponentCWProxy> { + const RichTextBuilderComponent({ + this.text, + this.parser, + this.defaultStyle, + this.styles, + super.themeResolver, + super.key, + }); + + /// Full text + final String? text; + + /// How to build InlineSpans + final RichTextParser? parser; + + /// Default TextStyle used in this rich text component. + final TextStyle? defaultStyle; + + /// Used styles in this rich text component. + /// + /// e.g. + /// ```dart + /// styles = {'red': TextStyle(color: Colors.red)}; + /// ``` + /// will transform: + /// ```text + /// This text is red? styles; +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/rich_text_builder_component.g.dart b/packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/rich_text_builder_component.g.dart new file mode 100644 index 00000000..9c5194e6 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/rich_text_builder_component.g.dart @@ -0,0 +1,25 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'rich_text_builder_component.dart'; + +// ************************************************************************** +// ComponentProxyGenerator +// ************************************************************************** + +abstract class $RichTextBuilderComponentCWProxy { + RichTextBuilderComponent text(String? text); + RichTextBuilderComponent parser(RichTextParser? parser); + RichTextBuilderComponent defaultStyle(TextStyle? defaultStyle); + RichTextBuilderComponent styles(Map? styles); + RichTextBuilderComponent themeResolver( + ThemeResolver? themeResolver); + RichTextBuilderComponent key(Key? key); + RichTextBuilderComponent call({ + String? text, + RichTextParser? parser, + TextStyle? defaultStyle, + Map? styles, + ThemeResolver? themeResolver, + Key? key, + }); +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/rich_text_builder_style.dart b/packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/rich_text_builder_style.dart new file mode 100644 index 00000000..43a03ff5 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/rich_text_builder/rich_text_builder_style.dart @@ -0,0 +1,83 @@ +// 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/widgets.dart'; +import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; + +class RichTextBuilderStyle extends ThemeStyle { + const RichTextBuilderStyle({ + this.defaultStyle, + this.styles, + }); + + /// Merges non-null `b` attributes in `a` + static RichTextBuilderStyle? merge( + RichTextBuilderStyle? a, + RichTextBuilderStyle? b, + ) { + if (b == null) { + return a?.copyWith(); + } + if (a == null) { + return b.copyWith(); + } + + return a.copyWith( + defaultStyle: b.defaultStyle, + styles: b.styles, + ); + } + + /// Used for interpolation. + static RichTextBuilderStyle? lerp( + RichTextBuilderStyle? a, + RichTextBuilderStyle? b, + double t, + ) { + if (a == null || b == null) { + return null; + } + // b.copyWith to return b attributes even if they are not lerped + return b.copyWith( + defaultStyle: TextStyle.lerp(a.defaultStyle, b.defaultStyle, t), + styles: b.styles, // TODO(wyatt): compute lerp value of each styles + ); + } + + /// Default TextStyle used in this rich text component. + final TextStyle? defaultStyle; + + /// Used styles in this rich text component. + final Map? styles; + + @override + RichTextBuilderStyle mergeWith(RichTextBuilderStyle? other) => + RichTextBuilderStyle.merge(this, other)!; + + @override + RichTextBuilderStyle? lerpWith(RichTextBuilderStyle? other, double t) => + RichTextBuilderStyle.lerp(this, other, t); + + @override + RichTextBuilderStyle copyWith({ + TextStyle? defaultStyle, + Map? styles, + }) => + RichTextBuilderStyle( + defaultStyle: defaultStyle ?? this.defaultStyle, + styles: styles ?? this.styles, + ); +} -- 2.47.2 From 66719732f73fbfe20b5edae76684078d79e407cb Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Fri, 17 Feb 2023 14:49:41 +0100 Subject: [PATCH 4/5] feat(ui_kit): implement rich text builder (closes #141) --- packages/wyatt_ui_kit/example/lib/home.dart | 8 +- .../rich_text_builders.dart | 70 ++++++++++++ .../lib/src/components/components.dart | 2 + .../rich_text_builder/rich_text_builder.dart | 101 ++++++++++++++++++ .../rich_text_builder.g.dart | 50 +++++++++ .../rich_text_builder_theme_resolver.dart | 50 +++++++++ .../rich_text_builder_theme_extension.dart | 31 ++++++ 7 files changed, 311 insertions(+), 1 deletion(-) create mode 100644 packages/wyatt_ui_kit/example/lib/rich_text_builders/rich_text_builders.dart create mode 100644 packages/wyatt_ui_kit/lib/src/components/rich_text_builder/rich_text_builder.dart create mode 100644 packages/wyatt_ui_kit/lib/src/components/rich_text_builder/rich_text_builder.g.dart create mode 100644 packages/wyatt_ui_kit/lib/src/components/rich_text_builder/rich_text_builder_theme_resolver.dart create mode 100644 packages/wyatt_ui_kit/lib/src/domain/rich_text_builder_theme_extension.dart diff --git a/packages/wyatt_ui_kit/example/lib/home.dart b/packages/wyatt_ui_kit/example/lib/home.dart index 72b3ce4a..cac6c236 100644 --- a/packages/wyatt_ui_kit/example/lib/home.dart +++ b/packages/wyatt_ui_kit/example/lib/home.dart @@ -5,6 +5,7 @@ import 'package:wyatt_ui_kit_example/buttons/buttons.dart'; import 'package:wyatt_ui_kit_example/cards/cards.dart'; import 'package:wyatt_ui_kit_example/demo_page.dart'; import 'package:wyatt_ui_kit_example/loaders/loaders.dart'; +import 'package:wyatt_ui_kit_example/rich_text_builders/rich_text_builders.dart'; import 'package:wyatt_ui_kit_example/theme/themes.dart'; const String title = 'Wyatt UIKit Example'; @@ -20,7 +21,12 @@ class Home extends StatefulWidget { class _HomeState extends State { // Simply add your demo page here. - final List pages = const [Cards(), Buttons(), Loaders()]; + final List pages = const [ + Cards(), + Buttons(), + Loaders(), + RichTextBuilders(), + ]; int currentIndex = 0; diff --git a/packages/wyatt_ui_kit/example/lib/rich_text_builders/rich_text_builders.dart b/packages/wyatt_ui_kit/example/lib/rich_text_builders/rich_text_builders.dart new file mode 100644 index 00000000..662a2b91 --- /dev/null +++ b/packages/wyatt_ui_kit/example/lib/rich_text_builders/rich_text_builders.dart @@ -0,0 +1,70 @@ +// 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:gap/gap.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; +import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; +import 'package:wyatt_ui_kit_example/demo_page.dart'; +import 'package:wyatt_ui_kit_example/theme/constants.dart'; + +class RichTextBuilders extends DemoPage { + const RichTextBuilders({super.key}); + + @override + String get title => 'RichTextBuilders'; + + @override + Widget build(BuildContext context) => ListView( + cacheExtent: 1000, + children: [ + const Gap(20), + Align( + child: Text( + title, + style: Theme.of(context).textTheme.titleLarge, + ), + ), + const Gap(20), + RichTextBuilder( + defaultStyle: GoogleFonts.montserrat( + fontSize: 18, + fontWeight: FontWeight.w500, + height: 1.8, + ), + styles: { + 'gradient-blue': GradientTextStyle.from( + GoogleFonts.montserrat( + fontSize: 20, + fontWeight: FontWeight.w600, + color: Constants.blue1, + height: 1.8, + ), + const MultiColor(Constants.blueGradient), + ) + }, + text: ''' +Innovation, Expertise et Accompagnement... +Notre agence de développement Wyatt Studio met tout en oeuvre pour vous aider à concrétiser vos idées de solutions informatiques et mobiles. + +Vous aussi, comme beaucoup d’autres agences ou startups, faites nous confiance pour la réalisation de votre projet dès maintenant ! +''', + ), + const Gap(20), + ], + ); +} diff --git a/packages/wyatt_ui_kit/lib/src/components/components.dart b/packages/wyatt_ui_kit/lib/src/components/components.dart index 191af8e8..e78cb40d 100644 --- a/packages/wyatt_ui_kit/lib/src/components/components.dart +++ b/packages/wyatt_ui_kit/lib/src/components/components.dart @@ -16,4 +16,6 @@ export './buttons/buttons.dart'; export './cards/cards.dart'; +export './gradients/gradients.dart'; export './loader/loader.dart'; +export './rich_text_builder/rich_text_builder.dart'; 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 new file mode 100644 index 00000000..8bf2017b --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/rich_text_builder/rich_text_builder.dart @@ -0,0 +1,101 @@ +// 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_component_copy_with_extension/component_copy_with_extension.dart'; +import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; +import 'package:wyatt_ui_kit/src/components/rich_text_builder/rich_text_builder_theme_resolver.dart'; +import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; + +part 'rich_text_builder.g.dart'; + +@ComponentCopyWithExtension() +class RichTextBuilder extends RichTextBuilderComponent + with $RichTextBuilderCWMixin { + const RichTextBuilder({ + super.text, + super.parser, + super.defaultStyle, + super.styles, + super.themeResolver, + super.key, + }); + + @override + RichTextBuilderThemeResolver? get themeResolver => + super.themeResolver as RichTextBuilderThemeResolver?; + + /// Negotiate the theme to get a complete style. + RichTextBuilderStyle _resolve(BuildContext context) { + final RichTextBuilderThemeResolver resolver = themeResolver ?? + RichTextBuilderThemeResolver( + computeExtensionValueFn: ( + context, + defaultValue, + themeExtension, { + extra, + }) => + RichTextBuilderStyle( + defaultStyle: themeExtension.defaultStyle, + ), + customStyleFn: (context, {extra}) => RichTextBuilderStyle( + defaultStyle: defaultStyle, + styles: styles, + ), + ); + + return resolver.negotiate(context); + } + + @override + Widget build(BuildContext context) { + final style = _resolve(context); + final RegExp regex = RegExp(r'<(.*?)>(.*?)<\/\1>'); + final root = RichTextNode.from( + text ?? '', + regex, + RichTextStyleParameter( + style.defaultStyle!, + style.styles ?? {}, + null, + ), + ); + + final customParser = parser ?? + RichTextParser( + nodeBuilder: (content, style) { + if (style is GradientTextStyle?) { + return WidgetSpan( + child: GradientText( + content, + style: style, + softWrap: true, + ), + style: style, + ); + } + return TextSpan( + text: content, + style: style, + ); + }, + ); + + return RichText( + text: root.toInlineSpan(customParser), + ); + } +} diff --git a/packages/wyatt_ui_kit/lib/src/components/rich_text_builder/rich_text_builder.g.dart b/packages/wyatt_ui_kit/lib/src/components/rich_text_builder/rich_text_builder.g.dart new file mode 100644 index 00000000..235c5f0f --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/rich_text_builder/rich_text_builder.g.dart @@ -0,0 +1,50 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'rich_text_builder.dart'; + +// ************************************************************************** +// ComponentCopyWithGenerator +// ************************************************************************** + +class $RichTextBuilderCWProxyImpl implements $RichTextBuilderComponentCWProxy { + const $RichTextBuilderCWProxyImpl(this._value); + final RichTextBuilder _value; + @override + RichTextBuilder text(String? text) => this(text: text); + @override + RichTextBuilder parser(RichTextParser? parser) => this(parser: parser); + @override + RichTextBuilder defaultStyle(TextStyle? defaultStyle) => + this(defaultStyle: defaultStyle); + @override + RichTextBuilder styles(Map? styles) => + this(styles: styles); + @override + RichTextBuilder themeResolver( + ThemeResolver? themeResolver) => + this(themeResolver: themeResolver); + @override + RichTextBuilder key(Key? key) => this(key: key); + @override + RichTextBuilder call({ + String? text, + RichTextParser? parser, + TextStyle? defaultStyle, + Map? styles, + ThemeResolver? themeResolver, + Key? key, + }) => + RichTextBuilder( + text: text ?? _value.text, + parser: parser ?? _value.parser, + defaultStyle: defaultStyle ?? _value.defaultStyle, + styles: styles ?? _value.styles, + themeResolver: themeResolver ?? _value.themeResolver, + key: key ?? _value.key, + ); +} + +mixin $RichTextBuilderCWMixin on Component { + $RichTextBuilderComponentCWProxy get copyWith => + $RichTextBuilderCWProxyImpl(this as RichTextBuilder); +} diff --git a/packages/wyatt_ui_kit/lib/src/components/rich_text_builder/rich_text_builder_theme_resolver.dart b/packages/wyatt_ui_kit/lib/src/components/rich_text_builder/rich_text_builder_theme_resolver.dart new file mode 100644 index 00000000..3ccf0112 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/rich_text_builder/rich_text_builder_theme_resolver.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_wyatt_ui_components.dart'; +import 'package:wyatt_ui_kit/src/domain/rich_text_builder_theme_extension.dart'; +import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; + +class RichTextBuilderThemeResolver extends ThemeResolver { + const RichTextBuilderThemeResolver({ + required this.computeExtensionValueFn, + required this.customStyleFn, + }); + + /// Values taken from + @override + RichTextBuilderStyle computeDefaultValue( + BuildContext context, { + void extra, + }) => + RichTextBuilderStyle( + defaultStyle: context.textTheme.bodyMedium, + ); + + @override + final RichTextBuilderStyle? Function( + BuildContext context, + RichTextBuilderStyle defaultValue, + RichTextBuilderThemeExtension themeExtension, { + void extra, + }) computeExtensionValueFn; + + @override + final RichTextBuilderStyle? Function(BuildContext context, {void extra}) + customStyleFn; +} diff --git a/packages/wyatt_ui_kit/lib/src/domain/rich_text_builder_theme_extension.dart b/packages/wyatt_ui_kit/lib/src/domain/rich_text_builder_theme_extension.dart new file mode 100644 index 00000000..e3ccd47e --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/domain/rich_text_builder_theme_extension.dart @@ -0,0 +1,31 @@ +// 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'; + +abstract class RichTextBuilderThemeExtension + extends ThemeExtension { + const RichTextBuilderThemeExtension({ + this.defaultStyle, + this.styles, + }); + + /// Default TextStyle used in this rich text component. + final TextStyle? defaultStyle; + + /// Used styles in this rich text component. + final Map? styles; +} -- 2.47.2 From 2769d45e201c649533efc935a68904293fc4c2d0 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Fri, 17 Feb 2023 15:57:54 +0100 Subject: [PATCH 5/5] fix(ui_kit): fix text align, add selection and update example for rich text builder --- .../rich_text_builders.dart | 37 +++--- .../lib/theme/rich_text_builder_theme.dart | 120 ++++++++++++++++++ .../example/lib/theme/themes.dart | 8 ++ .../rich_text_builder/rich_text_builder.dart | 13 +- .../rich_text_builder_theme_resolver.dart | 1 - .../wyatt_ui_kit/lib/src/domain/domain.dart | 3 +- 6 files changed, 155 insertions(+), 27 deletions(-) create mode 100644 packages/wyatt_ui_kit/example/lib/theme/rich_text_builder_theme.dart diff --git a/packages/wyatt_ui_kit/example/lib/rich_text_builders/rich_text_builders.dart b/packages/wyatt_ui_kit/example/lib/rich_text_builders/rich_text_builders.dart index 662a2b91..8d5316e4 100644 --- a/packages/wyatt_ui_kit/example/lib/rich_text_builders/rich_text_builders.dart +++ b/packages/wyatt_ui_kit/example/lib/rich_text_builders/rich_text_builders.dart @@ -16,11 +16,8 @@ import 'package:flutter/material.dart'; import 'package:gap/gap.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; import 'package:wyatt_ui_kit_example/demo_page.dart'; -import 'package:wyatt_ui_kit_example/theme/constants.dart'; class RichTextBuilders extends DemoPage { const RichTextBuilders({super.key}); @@ -40,29 +37,25 @@ class RichTextBuilders extends DemoPage { ), ), const Gap(20), - RichTextBuilder( - defaultStyle: GoogleFonts.montserrat( - fontSize: 18, - fontWeight: FontWeight.w500, - height: 1.8, - ), - styles: { - 'gradient-blue': GradientTextStyle.from( - GoogleFonts.montserrat( - fontSize: 20, - fontWeight: FontWeight.w600, - color: Constants.blue1, - height: 1.8, - ), - const MultiColor(Constants.blueGradient), - ) - }, - text: ''' + const Padding( + padding: EdgeInsets.all(8), + child: RichTextBuilder( + text: ''' Innovation, Expertise et Accompagnement... Notre agence de développement Wyatt Studio met tout en oeuvre pour vous aider à concrétiser vos idées de solutions informatiques et mobiles. Vous aussi, comme beaucoup d’autres agences ou startups, faites nous confiance pour la réalisation de votre projet dès maintenant ! -''', + ''', + ), + ), + const Gap(20), + const Padding( + padding: EdgeInsets.all(8), + child: RichTextBuilder( + text: ''' +Je peux être bleu, ou même rouge en dégradé. À vrai dire je peux être un peu n'importe quelle couleur. + ''', + ), ), const Gap(20), ], 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 new file mode 100644 index 00000000..2088f0fe --- /dev/null +++ b/packages/wyatt_ui_kit/example/lib/theme/rich_text_builder_theme.dart @@ -0,0 +1,120 @@ +// 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_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 684270f8..63ecea53 100644 --- a/packages/wyatt_ui_kit/example/lib/theme/themes.dart +++ b/packages/wyatt_ui_kit/example/lib/theme/themes.dart @@ -21,6 +21,7 @@ import 'package:wyatt_ui_kit_example/theme/card_theme.dart'; import 'package:wyatt_ui_kit_example/theme/file_selection_button_theme.dart'; import 'package:wyatt_ui_kit_example/theme/flat_button_theme.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/simple_icon_button_theme.dart'; import 'package:wyatt_ui_kit_example/theme/symbol_button_theme.dart'; @@ -87,6 +88,8 @@ abstract class Themes { FileSelectionButtonTheme.light(), // Loader LoaderTheme.light(), + // Rich Text + RichTextBuilderTheme.light(), ], ); @@ -102,6 +105,9 @@ abstract class Themes { color: const Color(0xFFFFFFFF), ), ), + drawerTheme: const DrawerThemeData( + backgroundColor: Color(0xFF383C40), + ), scaffoldBackgroundColor: const Color(0xFF383C40), extensions: >[ // Cards @@ -113,6 +119,8 @@ abstract class Themes { FileSelectionButtonTheme.dark(), // Loader LoaderTheme.dark(), + // Rich Text + RichTextBuilderTheme.dark(), ], ); } 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 8bf2017b..745d3462 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 @@ -50,6 +50,7 @@ class RichTextBuilder extends RichTextBuilderComponent }) => RichTextBuilderStyle( defaultStyle: themeExtension.defaultStyle, + styles: themeExtension.styles, ), customStyleFn: (context, {extra}) => RichTextBuilderStyle( defaultStyle: defaultStyle, @@ -73,7 +74,6 @@ class RichTextBuilder extends RichTextBuilderComponent null, ), ); - final customParser = parser ?? RichTextParser( nodeBuilder: (content, style) { @@ -83,6 +83,9 @@ class RichTextBuilder extends RichTextBuilderComponent content, style: style, softWrap: true, + textHeightBehavior: const TextHeightBehavior( + applyHeightToLastDescent: false, + ), ), style: style, ); @@ -94,8 +97,12 @@ class RichTextBuilder extends RichTextBuilderComponent }, ); - return RichText( - text: root.toInlineSpan(customParser), + return SelectionArea( + child: Text.rich( + TextSpan(children: [root.toInlineSpan(customParser)]), + textHeightBehavior: + const TextHeightBehavior(applyHeightToLastDescent: false), + ), ); } } diff --git a/packages/wyatt_ui_kit/lib/src/components/rich_text_builder/rich_text_builder_theme_resolver.dart b/packages/wyatt_ui_kit/lib/src/components/rich_text_builder/rich_text_builder_theme_resolver.dart index 3ccf0112..f619d0a0 100644 --- a/packages/wyatt_ui_kit/lib/src/components/rich_text_builder/rich_text_builder_theme_resolver.dart +++ b/packages/wyatt_ui_kit/lib/src/components/rich_text_builder/rich_text_builder_theme_resolver.dart @@ -16,7 +16,6 @@ import 'package:flutter/material.dart'; import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; -import 'package:wyatt_ui_kit/src/domain/rich_text_builder_theme_extension.dart'; import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; class RichTextBuilderThemeResolver extends ThemeResolver. export './button_theme_extension/button_theme_extension.dart'; +export './card_theme_extension.dart'; export './loader_theme_extension.dart'; -export 'card_theme_extension.dart'; +export './rich_text_builder_theme_extension.dart'; -- 2.47.2