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; +}