feat(ui_components):add text input components, theme extension and worked on utils (#138)

This commit is contained in:
Malo Léon 2023-02-21 08:20:37 +01:00
parent f6c16c5dc4
commit edf72cf4c2
11 changed files with 454 additions and 44 deletions

View File

@ -14,7 +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 'enums/control_state.dart';
export 'enums/enums.dart';
export 'extensions/build_context_extensions.dart';
export 'extensions/string_extension.dart';
export 'mixins/copy_with_mixin.dart';

View File

@ -0,0 +1,18 @@
// 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 './control_state.dart';
export './status_state.dart';

View File

@ -0,0 +1,22 @@
// 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/>.
enum StatusState {
initial,
success,
loading,
error;
}

View File

@ -41,10 +41,36 @@ class MultiColor {
static MultiColor? lerp(MultiColor? a, MultiColor? b, double t) {
if (a == null && b == null) {
return null;
}
if (b == null) {
} else if (a == null) {
return b;
} else if (b == null) {
return a;
}
if (a.isColor && b.isColor) {
return MultiColor.single(Color.lerp(a.color, b.color, t));
} else if (a.isColor && b.isGradient) {
return MultiColor(
b.colors
.map((e) => Color.lerp(a.color, e, t))
.whereType<Color>()
.toList(),
);
} else if (a.isGradient && b.isColor) {
return MultiColor(
a.colors
.map((e) => Color.lerp(b.color, e, t))
.whereType<Color>()
.toList(),
);
} else if (a.isGradient && b.isGradient) {
final colors = List<Color>.empty(growable: true);
for (int i = 0; i < a.colors.length; i++) {
final lerpColor = Color.lerp(a.colors[i], b.colors[i], t);
if (lerpColor != null) {
colors.add(lerpColor);
}
}
}
return b;
}

View File

@ -35,24 +35,26 @@ abstract class ThemeResolver<S extends ThemeStyle<S>, T, E> {
/// {@macro theme_resolver}
const ThemeResolver();
S? Function(
BuildContext context,
S defaultValue,
T themeExtension, {
E? extra,
}) get computeExtensionValueFn;
S? Function(BuildContext context, {E? extra}) get customStyleFn;
S? Function(BuildContext context, S extensionValue, {E? extra})
get customStyleFn;
/// Compute default value from Flutter Theme or with hardcoded values.
S computeDefaultValue(BuildContext context, {E? extra});
S? computeExtensionValueFn(
BuildContext context,
S defaultValue,
T themeExtension, {
E? extra,
});
/// Compute values from the extension if found
S? computeExtensionValue(
S? _computeExtensionValue(
BuildContext context,
S defaultValue, {
E? extra,
}) {
final themeExtension = findExtension(context);
final themeExtension = Theme.of(context).extension<T>();
if (themeExtension != null) {
return computeExtensionValueFn(
context,
@ -65,30 +67,27 @@ abstract class ThemeResolver<S extends ThemeStyle<S>, T, E> {
}
/// Compute custom value
S? computeCustomValue(
S? _computeCustomValue(
BuildContext context,
S previousPhaseValue, {
E? extra,
}) {
final customStyle = customStyleFn(context, extra: extra);
final customStyle = customStyleFn(
context,
previousPhaseValue,
extra: extra,
);
if (customStyle != null) {
return customStyle;
}
return previousPhaseValue;
}
T? findExtension(BuildContext context) => Theme.of(context).extension<T>();
/// Choose most suitable style for a given context.
S negotiate(BuildContext context, {E? extra}) {
S style = computeDefaultValue(context, extra: extra);
final S? extensionStyle =
computeExtensionValue(context, style, extra: extra);
style = style.mergeWith(extensionStyle);
final S? customStyle = computeCustomValue(context, style, extra: extra);
return style.mergeWith(customStyle);
style = _computeExtensionValue(context, style, extra: extra) ?? style;
style = _computeCustomValue(context, style, extra: extra) ?? style;
return style;
}
}

View File

@ -24,5 +24,5 @@ export './loader_component.dart';
export './loader_style.dart';
export './loading_widget_component.dart';
export './rich_text_builder/rich_text_builder.dart';
export './text_input_component.dart';
export './text_inputs/text_inputs.dart';
export './theme_style.dart';

View File

@ -28,12 +28,21 @@ part 'text_input_component.g.dart';
abstract class TextInputComponent extends Component
with CopyWithMixin<$TextInputComponentCWProxy> {
const TextInputComponent({
this.backgroundColors,
this.borderColors,
this.radius,
this.expand,
this.onError,
this.validator,
this.suffixText,
this.prefixText,
this.prefixIcon,
this.suffixIcon,
this.label,
this.hint,
this.normalStyle,
this.focusedStyle,
this.errorStyle,
this.disableStyle,
this.controller,
this.focusNode,
this.decoration,
this.keyboardType,
this.smartDashesType,
this.smartQuotesType,
@ -92,7 +101,6 @@ abstract class TextInputComponent extends Component
final TextMagnifierConfiguration? magnifierConfiguration;
final TextEditingController? controller;
final FocusNode? focusNode;
final InputDecoration? decoration;
final TextInputType? keyboardType;
final TextInputAction? textInputAction;
final TextCapitalization? textCapitalization;
@ -120,7 +128,7 @@ abstract class TextInputComponent extends Component
final ValueChanged<String>? onSubmitted;
final AppPrivateCommandCallback? onAppPrivateCommand;
final List<TextInputFormatter>? inputFormatters;
final bool? enabled;
final ValueNotifier<bool>? enabled;
final double? cursorWidth;
final double? cursorHeight;
final Radius? cursorRadius;
@ -145,7 +153,21 @@ abstract class TextInputComponent extends Component
final EditableTextContextMenuBuilder? contextMenuBuilder;
final SpellCheckConfiguration? spellCheckConfiguration;
final MultiColor? backgroundColors;
final MultiColor? borderColors;
final double? radius;
final bool Function(String)? validator;
final String? Function(String)? onError;
final TextInputStyle? normalStyle;
final TextInputStyle? focusedStyle;
final TextInputStyle? errorStyle;
final TextInputStyle? disableStyle;
final bool? expand;
final TextWrapper? label;
final TextWrapper? hint;
final TextWrapper? prefixText;
final TextWrapper? suffixText;
final Icon? prefixIcon;
final Icon? suffixIcon;
}

View File

@ -7,12 +7,21 @@ part of 'text_input_component.dart';
// **************************************************************************
abstract class $TextInputComponentCWProxy {
TextInputComponent backgroundColors(MultiColor? backgroundColors);
TextInputComponent borderColors(MultiColor? borderColors);
TextInputComponent radius(double? radius);
TextInputComponent expand(bool? expand);
TextInputComponent onError(String Function(String)? onError);
TextInputComponent validator(bool Function(String)? validator);
TextInputComponent suffixText(TextWrapper? suffixText);
TextInputComponent prefixText(TextWrapper? prefixText);
TextInputComponent prefixIcon(Icon? prefixIcon);
TextInputComponent suffixIcon(Icon? suffixIcon);
TextInputComponent label(TextWrapper? label);
TextInputComponent hint(TextWrapper? hint);
TextInputComponent normalStyle(TextInputStyle? normalStyle);
TextInputComponent focusedStyle(TextInputStyle? focusedStyle);
TextInputComponent errorStyle(TextInputStyle? errorStyle);
TextInputComponent disableStyle(TextInputStyle? disableStyle);
TextInputComponent controller(TextEditingController? controller);
TextInputComponent focusNode(FocusNode? focusNode);
TextInputComponent decoration(InputDecoration? decoration);
TextInputComponent keyboardType(TextInputType? keyboardType);
TextInputComponent smartDashesType(SmartDashesType? smartDashesType);
TextInputComponent smartQuotesType(SmartQuotesType? smartQuotesType);
@ -44,7 +53,7 @@ abstract class $TextInputComponentCWProxy {
TextInputComponent onAppPrivateCommand(
void Function(String, Map<String, dynamic>)? onAppPrivateCommand);
TextInputComponent inputFormatters(List<TextInputFormatter>? inputFormatters);
TextInputComponent enabled(bool? enabled);
TextInputComponent enabled(ValueNotifier<bool>? enabled);
TextInputComponent cursorWidth(double? cursorWidth);
TextInputComponent cursorHeight(double? cursorHeight);
TextInputComponent cursorRadius(Radius? cursorRadius);
@ -76,12 +85,21 @@ abstract class $TextInputComponentCWProxy {
TextMagnifierConfiguration? magnifierConfiguration);
TextInputComponent key(Key? key);
TextInputComponent call({
MultiColor? backgroundColors,
MultiColor? borderColors,
double? radius,
bool? expand,
String Function(String)? onError,
bool Function(String)? validator,
TextWrapper? suffixText,
TextWrapper? prefixText,
Icon? prefixIcon,
Icon? suffixIcon,
TextWrapper? label,
TextWrapper? hint,
TextInputStyle? normalStyle,
TextInputStyle? focusedStyle,
TextInputStyle? errorStyle,
TextInputStyle? disableStyle,
TextEditingController? controller,
FocusNode? focusNode,
InputDecoration? decoration,
TextInputType? keyboardType,
SmartDashesType? smartDashesType,
SmartQuotesType? smartQuotesType,
@ -110,7 +128,7 @@ abstract class $TextInputComponentCWProxy {
void Function(String)? onSubmitted,
void Function(String, Map<String, dynamic>)? onAppPrivateCommand,
List<TextInputFormatter>? inputFormatters,
bool? enabled,
ValueNotifier<bool>? enabled,
double? cursorWidth,
double? cursorHeight,
Radius? cursorRadius,

View File

@ -0,0 +1,102 @@
// 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:copy_with_extension/copy_with_extension.dart';
import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
part 'text_input_style.g.dart';
@CopyWith()
class TextInputStyle {
TextInputStyle({
this.labelStyle,
this.hintStyle,
this.backgroundColors,
this.borderColors,
this.boxShadow,
this.radius,
this.inputStyle,
this.iconColor,
this.prefixStyle,
this.prefixIconColor,
this.suffixStyle,
this.suffixIconColor,
});
final TextStyle? labelStyle;
final TextStyle? hintStyle;
final Color? iconColor;
final TextStyle? prefixStyle;
final Color? prefixIconColor;
final TextStyle? suffixStyle;
final Color? suffixIconColor;
final MultiColor? backgroundColors;
final MultiColor? borderColors;
final BoxShadow? boxShadow;
final BorderRadiusGeometry? radius;
final TextStyle? inputStyle;
static TextInputStyle? merge(TextInputStyle? a, TextInputStyle? b) {
if (b == null) {
return a?.copyWith();
}
if (a == null) {
return b.copyWith();
}
return a.copyWith(
labelStyle: b.labelStyle,
hintStyle: b.hintStyle,
backgroundColors: b.backgroundColors,
borderColors: b.borderColors,
boxShadow: b.boxShadow,
radius: b.radius,
inputStyle: b.inputStyle,
iconColor: b.iconColor,
prefixStyle: b.prefixStyle,
prefixIconColor: b.prefixIconColor,
suffixIconColor: b.suffixIconColor,
suffixStyle: b.suffixStyle,
);
}
static TextInputStyle? lerp(
TextInputStyle? a,
TextInputStyle? b,
double t,
) {
if (a == null || b == null) {
return null;
}
return b.copyWith(
labelStyle: TextStyle.lerp(a.labelStyle, b.labelStyle, t),
hintStyle: TextStyle.lerp(a.hintStyle, b.hintStyle, t),
backgroundColors:
MultiColor.lerp(a.backgroundColors, b.backgroundColors, t),
radius: BorderRadiusGeometry.lerp(a.radius, b.radius, t),
borderColors: MultiColor.lerp(a.borderColors, b.borderColors, t),
boxShadow: BoxShadow.lerp(a.boxShadow, b.boxShadow, t),
inputStyle: TextStyle.lerp(a.inputStyle, b.inputStyle, t),
prefixStyle: TextStyle.lerp(a.prefixStyle, b.prefixStyle, t),
suffixStyle: TextStyle.lerp(a.suffixStyle, b.suffixStyle, t),
prefixIconColor: Color.lerp(a.prefixIconColor, b.prefixIconColor, t),
suffixIconColor: Color.lerp(a.suffixIconColor, b.suffixIconColor, t),
iconColor: Color.lerp(a.iconColor, b.iconColor, t),
);
}
}

View File

@ -0,0 +1,185 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'text_input_style.dart';
// **************************************************************************
// CopyWithGenerator
// **************************************************************************
abstract class _$TextInputStyleCWProxy {
TextInputStyle labelStyle(TextStyle? labelStyle);
TextInputStyle hintStyle(TextStyle? hintStyle);
TextInputStyle backgroundColors(MultiColor? backgroundColors);
TextInputStyle borderColors(MultiColor? borderColors);
TextInputStyle boxShadow(BoxShadow? boxShadow);
TextInputStyle radius(BorderRadiusGeometry? radius);
TextInputStyle inputStyle(TextStyle? inputStyle);
TextInputStyle iconColor(Color? iconColor);
TextInputStyle prefixStyle(TextStyle? prefixStyle);
TextInputStyle prefixIconColor(Color? prefixIconColor);
TextInputStyle suffixStyle(TextStyle? suffixStyle);
TextInputStyle suffixIconColor(Color? suffixIconColor);
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `TextInputStyle(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
///
/// Usage
/// ```dart
/// TextInputStyle(...).copyWith(id: 12, name: "My name")
/// ````
TextInputStyle call({
TextStyle? labelStyle,
TextStyle? hintStyle,
MultiColor? backgroundColors,
MultiColor? borderColors,
BoxShadow? boxShadow,
BorderRadiusGeometry? radius,
TextStyle? inputStyle,
Color? iconColor,
TextStyle? prefixStyle,
Color? prefixIconColor,
TextStyle? suffixStyle,
Color? suffixIconColor,
});
}
/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfTextInputStyle.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfTextInputStyle.copyWith.fieldName(...)`
class _$TextInputStyleCWProxyImpl implements _$TextInputStyleCWProxy {
const _$TextInputStyleCWProxyImpl(this._value);
final TextInputStyle _value;
@override
TextInputStyle labelStyle(TextStyle? labelStyle) =>
this(labelStyle: labelStyle);
@override
TextInputStyle hintStyle(TextStyle? hintStyle) => this(hintStyle: hintStyle);
@override
TextInputStyle backgroundColors(MultiColor? backgroundColors) =>
this(backgroundColors: backgroundColors);
@override
TextInputStyle borderColors(MultiColor? borderColors) =>
this(borderColors: borderColors);
@override
TextInputStyle boxShadow(BoxShadow? boxShadow) => this(boxShadow: boxShadow);
@override
TextInputStyle radius(BorderRadiusGeometry? radius) => this(radius: radius);
@override
TextInputStyle inputStyle(TextStyle? inputStyle) =>
this(inputStyle: inputStyle);
@override
TextInputStyle iconColor(Color? iconColor) => this(iconColor: iconColor);
@override
TextInputStyle prefixStyle(TextStyle? prefixStyle) =>
this(prefixStyle: prefixStyle);
@override
TextInputStyle prefixIconColor(Color? prefixIconColor) =>
this(prefixIconColor: prefixIconColor);
@override
TextInputStyle suffixStyle(TextStyle? suffixStyle) =>
this(suffixStyle: suffixStyle);
@override
TextInputStyle suffixIconColor(Color? suffixIconColor) =>
this(suffixIconColor: suffixIconColor);
@override
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `TextInputStyle(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
///
/// Usage
/// ```dart
/// TextInputStyle(...).copyWith(id: 12, name: "My name")
/// ````
TextInputStyle call({
Object? labelStyle = const $CopyWithPlaceholder(),
Object? hintStyle = const $CopyWithPlaceholder(),
Object? backgroundColors = const $CopyWithPlaceholder(),
Object? borderColors = const $CopyWithPlaceholder(),
Object? boxShadow = const $CopyWithPlaceholder(),
Object? radius = const $CopyWithPlaceholder(),
Object? inputStyle = const $CopyWithPlaceholder(),
Object? iconColor = const $CopyWithPlaceholder(),
Object? prefixStyle = const $CopyWithPlaceholder(),
Object? prefixIconColor = const $CopyWithPlaceholder(),
Object? suffixStyle = const $CopyWithPlaceholder(),
Object? suffixIconColor = const $CopyWithPlaceholder(),
}) {
return TextInputStyle(
labelStyle: labelStyle == const $CopyWithPlaceholder()
? _value.labelStyle
// ignore: cast_nullable_to_non_nullable
: labelStyle as TextStyle?,
hintStyle: hintStyle == const $CopyWithPlaceholder()
? _value.hintStyle
// ignore: cast_nullable_to_non_nullable
: hintStyle as TextStyle?,
backgroundColors: backgroundColors == const $CopyWithPlaceholder()
? _value.backgroundColors
// ignore: cast_nullable_to_non_nullable
: backgroundColors as MultiColor?,
borderColors: borderColors == const $CopyWithPlaceholder()
? _value.borderColors
// ignore: cast_nullable_to_non_nullable
: borderColors as MultiColor?,
boxShadow: boxShadow == const $CopyWithPlaceholder()
? _value.boxShadow
// ignore: cast_nullable_to_non_nullable
: boxShadow as BoxShadow?,
radius: radius == const $CopyWithPlaceholder()
? _value.radius
// ignore: cast_nullable_to_non_nullable
: radius as BorderRadiusGeometry?,
inputStyle: inputStyle == const $CopyWithPlaceholder()
? _value.inputStyle
// ignore: cast_nullable_to_non_nullable
: inputStyle as TextStyle?,
iconColor: iconColor == const $CopyWithPlaceholder()
? _value.iconColor
// ignore: cast_nullable_to_non_nullable
: iconColor as Color?,
prefixStyle: prefixStyle == const $CopyWithPlaceholder()
? _value.prefixStyle
// ignore: cast_nullable_to_non_nullable
: prefixStyle as TextStyle?,
prefixIconColor: prefixIconColor == const $CopyWithPlaceholder()
? _value.prefixIconColor
// ignore: cast_nullable_to_non_nullable
: prefixIconColor as Color?,
suffixStyle: suffixStyle == const $CopyWithPlaceholder()
? _value.suffixStyle
// ignore: cast_nullable_to_non_nullable
: suffixStyle as TextStyle?,
suffixIconColor: suffixIconColor == const $CopyWithPlaceholder()
? _value.suffixIconColor
// ignore: cast_nullable_to_non_nullable
: suffixIconColor as Color?,
);
}
}
extension $TextInputStyleCopyWith on TextInputStyle {
/// Returns a callable class that can be used as follows: `instanceOfTextInputStyle.copyWith(...)` or like so:`instanceOfTextInputStyle.copyWith.fieldName(...)`.
// ignore: library_private_types_in_public_api
_$TextInputStyleCWProxy get copyWith => _$TextInputStyleCWProxyImpl(this);
}

View File

@ -0,0 +1,18 @@
// 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 './text_input_component.dart';
export './text_input_style.dart';