ui/refactor/coherence-1 #187
@ -16,6 +16,5 @@
 | 
			
		||||
 | 
			
		||||
export 'enums/enums.dart';
 | 
			
		||||
export 'extensions/build_context_extensions.dart';
 | 
			
		||||
export 'extensions/string_extension.dart';
 | 
			
		||||
export 'mixins/copy_with_mixin.dart';
 | 
			
		||||
export 'utils/utils.dart';
 | 
			
		||||
 | 
			
		||||
@ -1,25 +0,0 @@
 | 
			
		||||
// Copyright (C) 2023 WYATT GROUP
 | 
			
		||||
// Please see the AUTHORS file for details.
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
import 'package:flutter/widgets.dart';
 | 
			
		||||
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
 | 
			
		||||
 | 
			
		||||
extension StringExtension on String? {
 | 
			
		||||
  TextWrapper? wrap({TextStyle? style, MultiColor? gradientColors}) =>
 | 
			
		||||
      this != null
 | 
			
		||||
          ? TextWrapper(this!, style: style, gradientColors: gradientColors)
 | 
			
		||||
          : null;
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,38 @@
 | 
			
		||||
// 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_ui_components.dart';
 | 
			
		||||
 | 
			
		||||
abstract class GradientHelper {
 | 
			
		||||
  static LinearGradient? linearFromNullableColors(List<Color>? colors) =>
 | 
			
		||||
      colors != null ? LinearGradient(colors: colors) : null;
 | 
			
		||||
 | 
			
		||||
  static LinearGradient? linearFromMultiColor(MultiColor multiColor) =>
 | 
			
		||||
      multiColor.isGradient ? LinearGradient(colors: multiColor.colors) : null;
 | 
			
		||||
 | 
			
		||||
  static RadialGradient? radialFromNullableColors(List<Color>? colors) =>
 | 
			
		||||
      colors != null ? RadialGradient(colors: colors) : null;
 | 
			
		||||
 | 
			
		||||
  static RadialGradient? radialFromMultiColor(MultiColor multiColor) =>
 | 
			
		||||
      multiColor.isGradient ? RadialGradient(colors: multiColor.colors) : null;
 | 
			
		||||
 | 
			
		||||
  static SweepGradient? sweepFromNullableColors(List<Color>? colors) =>
 | 
			
		||||
      colors != null ? SweepGradient(colors: colors) : null;
 | 
			
		||||
 | 
			
		||||
  static SweepGradient? sweepFromMultiColor(MultiColor multiColor) =>
 | 
			
		||||
      multiColor.isGradient ? SweepGradient(colors: multiColor.colors) : null;
 | 
			
		||||
}
 | 
			
		||||
@ -36,15 +36,28 @@ class TextWrapper {
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  /// Creates a [TextWrapper] from a [Text] widget.
 | 
			
		||||
  const TextWrapper.text(this.data)
 | 
			
		||||
      : style = null,
 | 
			
		||||
  TextWrapper.text(Text text)
 | 
			
		||||
      : data = text.data!,
 | 
			
		||||
        style = text.style,
 | 
			
		||||
        gradientColors = null,
 | 
			
		||||
        textAlign = null,
 | 
			
		||||
        textDirection = null,
 | 
			
		||||
        softWrap = null,
 | 
			
		||||
        overflow = null,
 | 
			
		||||
        maxLines = null,
 | 
			
		||||
        selectionColor = null;
 | 
			
		||||
        textAlign = text.textAlign,
 | 
			
		||||
        textDirection = text.textDirection,
 | 
			
		||||
        softWrap = text.softWrap,
 | 
			
		||||
        overflow = text.overflow,
 | 
			
		||||
        maxLines = text.maxLines,
 | 
			
		||||
        selectionColor = text.selectionColor;
 | 
			
		||||
 | 
			
		||||
  /// Creates a [TextWrapper] from a [RichText] widget.
 | 
			
		||||
  TextWrapper.rich(RichText richText)
 | 
			
		||||
      : data = richText.text.toPlainText(),
 | 
			
		||||
        style = richText.text.style,
 | 
			
		||||
        gradientColors = null,
 | 
			
		||||
        textAlign = richText.textAlign,
 | 
			
		||||
        textDirection = richText.textDirection,
 | 
			
		||||
        softWrap = richText.softWrap,
 | 
			
		||||
        overflow = richText.overflow,
 | 
			
		||||
        maxLines = richText.maxLines,
 | 
			
		||||
        selectionColor = richText.selectionColor;
 | 
			
		||||
 | 
			
		||||
  /// Text to be displayed
 | 
			
		||||
  final String data;
 | 
			
		||||
 | 
			
		||||
@ -16,33 +16,76 @@
 | 
			
		||||
 | 
			
		||||
/// A helper class for getting theme elements.
 | 
			
		||||
abstract class ThemeHelper {
 | 
			
		||||
  /// Gets a theme element from a list of styles.
 | 
			
		||||
  /// Gets a nullable theme element from a list of styles.
 | 
			
		||||
  /// {@template getElement}
 | 
			
		||||
  /// Styles are checked in order, and the first one that passes the
 | 
			
		||||
  /// [valueValidator] is returned.
 | 
			
		||||
  /// Style elements are transformed using the [transform] function.
 | 
			
		||||
  ///
 | 
			
		||||
  /// [styles]: A list of styles that need to be checked.
 | 
			
		||||
  /// [transform]: A function that transforms each style element
 | 
			
		||||
  /// to a [T] type.
 | 
			
		||||
  /// [valueValidator]: An optional validation function that
 | 
			
		||||
  /// determines if a style element is valid.
 | 
			
		||||
  /// [combine]: A function that combines two [P] type objects to create
 | 
			
		||||
  /// a new object.
 | 
			
		||||
  static T? getThemeElement<P, T>(
 | 
			
		||||
  /// - [styles] : A list of styles that need to be checked.
 | 
			
		||||
  ///
 | 
			
		||||
  /// - [transform] : An optional function that transforms each style element
 | 
			
		||||
  /// to a [T] type after it passes the [valueValidator]. *(default: returns
 | 
			
		||||
  /// element as is)*
 | 
			
		||||
  ///
 | 
			
		||||
  /// - [valueValidator] : An optional validation function that
 | 
			
		||||
  /// determines if a style element is valid. *(default: checks if element
 | 
			
		||||
  /// is not null)*
 | 
			
		||||
  ///
 | 
			
		||||
  /// - [combine] : A function that combines two [P] type objects to create
 | 
			
		||||
  /// a new object. *(default: returns the first element)*
 | 
			
		||||
  ///
 | 
			
		||||
  /// So, if you only pass a [styles] list, the first valid style element
 | 
			
		||||
  /// will be returned as is.
 | 
			
		||||
  /// If you pass a [transform] function, the first valid style element
 | 
			
		||||
  /// will be transformed to a [T] type.
 | 
			
		||||
  /// {@endtemplate}
 | 
			
		||||
  static T? maybeGetElement<P, T>(
 | 
			
		||||
    List<P?>? styles, {
 | 
			
		||||
    required T? Function(P?)? transform,
 | 
			
		||||
    T? Function(P?)? transform,
 | 
			
		||||
    bool? Function(P?)? valueValidator,
 | 
			
		||||
    P? Function(P?, P?)? combine,
 | 
			
		||||
  }) {
 | 
			
		||||
    // List of valid styles
 | 
			
		||||
    final Iterable<P?>? validStyles = styles?.where(
 | 
			
		||||
      (element) => valueValidator?.call(element) ?? (element != null),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // tranformation function
 | 
			
		||||
    final transformation = transform ?? (element) => element as T?;
 | 
			
		||||
 | 
			
		||||
    return (validStyles?.isNotEmpty ?? false)
 | 
			
		||||
        ? transform?.call(
 | 
			
		||||
        ? transformation.call(
 | 
			
		||||
            validStyles?.reduce(
 | 
			
		||||
              (value, element) => combine?.call(value, element) ?? value,
 | 
			
		||||
            ),
 | 
			
		||||
          )
 | 
			
		||||
        : null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// Gets a theme element from a list of styles. Throws an exception if no
 | 
			
		||||
  /// valid style is found.
 | 
			
		||||
  ///
 | 
			
		||||
  /// See [maybeGetElement] for more details.
 | 
			
		||||
  ///
 | 
			
		||||
  /// {@macro getElement}
 | 
			
		||||
  static T getElement<P, T>(
 | 
			
		||||
    List<P?>? styles, {
 | 
			
		||||
    T? Function(P?)? transform,
 | 
			
		||||
    bool? Function(P?)? valueValidator,
 | 
			
		||||
    P? Function(P?, P?)? combine,
 | 
			
		||||
  }) {
 | 
			
		||||
    final result = maybeGetElement<P, T>(
 | 
			
		||||
      styles,
 | 
			
		||||
      transform: transform,
 | 
			
		||||
      valueValidator: valueValidator,
 | 
			
		||||
      combine: combine,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    if (result == null) {
 | 
			
		||||
      throw Exception('No valid style found');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -15,12 +15,25 @@
 | 
			
		||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
 | 
			
		||||
 | 
			
		||||
class LinearGradientHelper {
 | 
			
		||||
  static LinearGradient? fromNullableColors(List<Color>? colors) =>
 | 
			
		||||
      colors != null ? LinearGradient(colors: colors) : null;
 | 
			
		||||
abstract class ThemeImporter {
 | 
			
		||||
  /// Imports a [ThemeData] from either a [BuildContext] or a [ThemeData].
 | 
			
		||||
  ///
 | 
			
		||||
  /// Throws an [ArgumentError] if the type of [from] is not a [BuildContext]
 | 
			
		||||
  /// or a [ThemeData].
 | 
			
		||||
  static ThemeData importFrom<T>(T from) {
 | 
			
		||||
    ThemeData theme;
 | 
			
		||||
 | 
			
		||||
  static LinearGradient? fromMultiColor(MultiColor multiColor) =>
 | 
			
		||||
      multiColor.isGradient ? LinearGradient(colors: multiColor.colors) : null;
 | 
			
		||||
    if (from is BuildContext) {
 | 
			
		||||
      theme = Theme.of(from);
 | 
			
		||||
    } else if (from is ThemeData) {
 | 
			
		||||
      theme = from;
 | 
			
		||||
    } else {
 | 
			
		||||
      throw ArgumentError(
 | 
			
		||||
        'from must be either a BuildContext or a ThemeData',
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return theme;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -26,47 +26,52 @@ import 'package:wyatt_ui_components/src/domain/entities/theme_style.dart';
 | 
			
		||||
/// 1) Pass the "radius" into the constructor, `Component(radius: 12)`.
 | 
			
		||||
/// 2) Set up a theme extension `ComponentThemeExtension(radius: 15)`.
 | 
			
		||||
/// 3) Let `wyatt_ui_kit` "negotiate" and try to find a suitable style in the
 | 
			
		||||
/// flutter theme.
 | 
			
		||||
/// flutter theme, or use a hardcoded value.
 | 
			
		||||
///
 | 
			
		||||
/// If this negotiation phase fails, then:
 | 
			
		||||
/// - If the value is mandatory: a hardcoded value in "wyatt_ui_kit" is chosen.
 | 
			
		||||
/// - If not, the style is simply not applied.
 | 
			
		||||
/// If a negotiation phase fails, it will fallback to the next one.
 | 
			
		||||
///
 | 
			
		||||
/// This resolver uses [ThemeHelper] to negotiate and merge styles.
 | 
			
		||||
/// {@endtemplate}
 | 
			
		||||
abstract class ThemeResolver<S extends ThemeStyle<S>, T, E> {
 | 
			
		||||
abstract class ThemeResolver<Style extends ThemeStyle<Style>, Extension,
 | 
			
		||||
    Extra> {
 | 
			
		||||
  /// {@macro theme_resolver}
 | 
			
		||||
  const ThemeResolver();
 | 
			
		||||
 | 
			
		||||
  S? Function(BuildContext context, {E? extra}) get customStyleFn;
 | 
			
		||||
 | 
			
		||||
  /// Compute default value from Flutter Theme or with hardcoded values.
 | 
			
		||||
  S computeDefaultValue(
 | 
			
		||||
  Style computeDefaultValue(
 | 
			
		||||
    BuildContext context, {
 | 
			
		||||
    E? extra,
 | 
			
		||||
    Extra? extra,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  /// Compute custom style from context.
 | 
			
		||||
  Style? Function(BuildContext context, {Extra? extra}) get customStyleFn;
 | 
			
		||||
 | 
			
		||||
  /// Compute extension value from custom component extension.
 | 
			
		||||
  S? computeExtensionValueFn(
 | 
			
		||||
  Style? computeExtensionValueFn(
 | 
			
		||||
    BuildContext context,
 | 
			
		||||
    T? themeExtension, {
 | 
			
		||||
    E? extra,
 | 
			
		||||
    Extension? themeExtension, {
 | 
			
		||||
    Extra? extra,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  /// Choose most suitable style for a given context.
 | 
			
		||||
  S negotiate(BuildContext context, {E? extra}) {
 | 
			
		||||
  Style negotiate(BuildContext context, {Extra? extra}) {
 | 
			
		||||
    // 1) Custom style passed in constructor (cannot be null)
 | 
			
		||||
    final style = computeDefaultValue(context, extra: extra);
 | 
			
		||||
    return ThemeHelper.getThemeElement<S, S>(
 | 
			
		||||
          [
 | 
			
		||||
            style,
 | 
			
		||||
            computeExtensionValueFn(
 | 
			
		||||
              context,
 | 
			
		||||
              Theme.of(context).extension<T>(),
 | 
			
		||||
              extra: extra,
 | 
			
		||||
            ),
 | 
			
		||||
            customStyleFn(context, extra: extra)
 | 
			
		||||
          ],
 | 
			
		||||
          transform: (value) => value,
 | 
			
		||||
          combine: (value, element) => value?.mergeWith(element),
 | 
			
		||||
        ) ??
 | 
			
		||||
        style;
 | 
			
		||||
    return ThemeHelper.getElement<Style, Style>(
 | 
			
		||||
      [
 | 
			
		||||
        // 1) Custom style passed in constructor
 | 
			
		||||
        customStyleFn(context, extra: extra),
 | 
			
		||||
        // 2) Theme extension
 | 
			
		||||
        computeExtensionValueFn(
 | 
			
		||||
          context,
 | 
			
		||||
          Theme.of(context).extension<Extension>(),
 | 
			
		||||
          extra: extra,
 | 
			
		||||
        ),
 | 
			
		||||
        // 3) Default
 | 
			
		||||
        style,
 | 
			
		||||
      ],
 | 
			
		||||
      transform: (value) => value,
 | 
			
		||||
      combine: (value, element) => value?.mergeWith(element),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,7 @@
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
export 'gradient_helper.dart';
 | 
			
		||||
export 'multi_color.dart';
 | 
			
		||||
export 'text_wrapper.dart';
 | 
			
		||||
export 'theme_helper.dart';
 | 
			
		||||
 | 
			
		||||
@ -15,4 +15,3 @@
 | 
			
		||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
export './extensions/extensions.dart';
 | 
			
		||||
export './helpers/helpers.dart';
 | 
			
		||||
 | 
			
		||||
@ -1,17 +0,0 @@
 | 
			
		||||
// Copyright (C) 2023 WYATT GROUP
 | 
			
		||||
// Please see the AUTHORS file for details.
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
export './linear_gradient_helper.dart';
 | 
			
		||||
@ -17,7 +17,11 @@
 | 
			
		||||
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
 | 
			
		||||
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
 | 
			
		||||
 | 
			
		||||
/// {@template wyatt_component_theme_data}
 | 
			
		||||
/// A class that holds the theme data for the Wyatt UI Kit.
 | 
			
		||||
/// {@endtemplate}
 | 
			
		||||
class WyattComponentThemeData {
 | 
			
		||||
  /// {@macro wyatt_component_theme_data}
 | 
			
		||||
  static ComponentThemeData get wyattComponentThemeData => ComponentThemeData(
 | 
			
		||||
        appBar: const TopAppBar(),
 | 
			
		||||
        topNavigationBarComponent: const TopNavigationBar(),
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user