feat(ui_kit): implement rich text builder (closes #141)
This commit is contained in:
		
							parent
							
								
									25018dc78a
								
							
						
					
					
						commit
						66719732f7
					
				| @ -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<Home> { | ||||
|   // Simply add your demo page here. | ||||
|   final List<DemoPage> pages = const [Cards(), Buttons(), Loaders()]; | ||||
|   final List<DemoPage> pages = const [ | ||||
|     Cards(), | ||||
|     Buttons(), | ||||
|     Loaders(), | ||||
|     RichTextBuilders(), | ||||
|   ]; | ||||
| 
 | ||||
|   int currentIndex = 0; | ||||
| 
 | ||||
|  | ||||
| @ -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 <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| 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 à <gradient-blue>concrétiser vos idées</gradient-blue> de solutions informatiques et mobiles. | ||||
| 
 | ||||
| Vous aussi, comme beaucoup d’autres <gradient-blue>agences ou startups</gradient-blue>, faites nous confiance pour la réalisation de votre projet dès maintenant ! | ||||
| ''', | ||||
|           ), | ||||
|           const Gap(20), | ||||
|         ], | ||||
|       ); | ||||
| } | ||||
| @ -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'; | ||||
|  | ||||
| @ -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 <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| 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), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @ -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<String, TextStyle>? styles) => | ||||
|       this(styles: styles); | ||||
|   @override | ||||
|   RichTextBuilder themeResolver( | ||||
|           ThemeResolver<dynamic, dynamic, dynamic>? themeResolver) => | ||||
|       this(themeResolver: themeResolver); | ||||
|   @override | ||||
|   RichTextBuilder key(Key? key) => this(key: key); | ||||
|   @override | ||||
|   RichTextBuilder call({ | ||||
|     String? text, | ||||
|     RichTextParser? parser, | ||||
|     TextStyle? defaultStyle, | ||||
|     Map<String, TextStyle>? styles, | ||||
|     ThemeResolver<dynamic, dynamic, dynamic>? 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); | ||||
| } | ||||
| @ -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 <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| 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<RichTextBuilderStyle, | ||||
|     RichTextBuilderThemeExtension, void> { | ||||
|   const RichTextBuilderThemeResolver({ | ||||
|     required this.computeExtensionValueFn, | ||||
|     required this.customStyleFn, | ||||
|   }); | ||||
| 
 | ||||
|   /// Values taken from <https://api.flutter.dev/flutter/material/ElevatedButton/defaultStyleOf.html> | ||||
|   @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; | ||||
| } | ||||
| @ -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 <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| import 'package:flutter/material.dart'; | ||||
| 
 | ||||
| abstract class RichTextBuilderThemeExtension | ||||
|     extends ThemeExtension<RichTextBuilderThemeExtension> { | ||||
|   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<String, TextStyle>? styles; | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user