Compare commits

...

8 Commits

42 changed files with 2562 additions and 188 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

@ -23,32 +23,54 @@ class MultiColor {
final List<Color>? _colors;
final Color? _color;
Color get color {
if (_color != null) {
return _color!;
}
if (_colors?.isNotEmpty ?? false) {
return _colors!.first;
}
throw IndexError.withLength(
0,
_colors?.length ?? 0,
message: '_color is not defined or _colors is empty.',
);
}
Color get color => _color != null
? _color!
: _colors?.isNotEmpty ?? false
? _colors!.first
: throw IndexError.withLength(
0,
_colors?.length ?? 0,
message: '_color is not defined or _colors is empty.',
);
List<Color> get colors => _colors ?? [];
bool get isGradient =>
(_colors?.isNotEmpty ?? false) && (_colors?.length ?? 0) > 1;
bool get isGradient => (_colors?.length ?? 0) > 1;
bool get isColor => _color != null || isGradient;
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

@ -34,24 +34,26 @@ abstract class ThemeResolver<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,
@ -64,25 +66,27 @@ abstract class ThemeResolver<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);
style = computeExtensionValue(context, style, extra: extra) ?? style;
style = computeCustomValue(context, style, extra: extra) ?? style;
style = _computeExtensionValue(context, style, extra: extra) ?? style;
style = _computeCustomValue(context, style, extra: extra) ?? style;
return style;
}
}

View File

@ -22,6 +22,8 @@ abstract class $FileSelectionButtonComponentCWProxy {
FileSelectionButtonComponent invalidStyle(ButtonStyle<dynamic>? invalidStyle);
FileSelectionButtonComponent onPressed(
void Function(ControlState)? onPressed);
FileSelectionButtonComponent themeResolver(
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver);
FileSelectionButtonComponent key(Key? key);
FileSelectionButtonComponent call({
MainAxisSize? mainAxisSize,
@ -36,6 +38,7 @@ abstract class $FileSelectionButtonComponentCWProxy {
ButtonStyle<dynamic>? selectedStyle,
ButtonStyle<dynamic>? invalidStyle,
void Function(ControlState)? onPressed,
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver,
Key? key,
});
}

View File

@ -17,6 +17,8 @@ abstract class $FlatButtonComponentCWProxy {
FlatButtonComponent focusedStyle(ButtonStyle<dynamic>? focusedStyle);
FlatButtonComponent tappedStyle(ButtonStyle<dynamic>? tappedStyle);
FlatButtonComponent onPressed(void Function(ControlState)? onPressed);
FlatButtonComponent themeResolver(
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver);
FlatButtonComponent key(Key? key);
FlatButtonComponent call({
MainAxisSize? mainAxisSize,
@ -29,6 +31,7 @@ abstract class $FlatButtonComponentCWProxy {
ButtonStyle<dynamic>? focusedStyle,
ButtonStyle<dynamic>? tappedStyle,
void Function(ControlState)? onPressed,
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver,
Key? key,
});
}

View File

@ -14,6 +14,8 @@ abstract class $SimpleIconButtonComponentCWProxy {
SimpleIconButtonComponent focusedStyle(ButtonStyle<dynamic>? focusedStyle);
SimpleIconButtonComponent tappedStyle(ButtonStyle<dynamic>? tappedStyle);
SimpleIconButtonComponent onPressed(void Function(ControlState)? onPressed);
SimpleIconButtonComponent themeResolver(
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver);
SimpleIconButtonComponent key(Key? key);
SimpleIconButtonComponent call({
Icon? icon,
@ -23,6 +25,7 @@ abstract class $SimpleIconButtonComponentCWProxy {
ButtonStyle<dynamic>? focusedStyle,
ButtonStyle<dynamic>? tappedStyle,
void Function(ControlState)? onPressed,
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver,
Key? key,
});
}

View File

@ -17,6 +17,8 @@ abstract class $SymbolButtonComponentCWProxy {
SymbolButtonComponent tappedStyle(ButtonStyle<dynamic>? tappedStyle);
SymbolButtonComponent selectedStyle(ButtonStyle<dynamic>? selectedStyle);
SymbolButtonComponent onPressed(void Function(ControlState)? onPressed);
SymbolButtonComponent themeResolver(
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver);
SymbolButtonComponent key(Key? key);
SymbolButtonComponent call({
MainAxisSize? mainAxisSize,
@ -29,6 +31,7 @@ abstract class $SymbolButtonComponentCWProxy {
ButtonStyle<dynamic>? tappedStyle,
ButtonStyle<dynamic>? selectedStyle,
void Function(ControlState)? onPressed,
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver,
Key? key,
});
}

View File

@ -21,3 +21,4 @@ export './cards/cards.dart';
export './component.dart';
export './error_widget_component.dart';
export './loading_widget_component.dart';
export './text_inputs/text_inputs.dart';

View File

@ -0,0 +1,173 @@
// 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 'dart:ui';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
part 'text_input_component.g.dart';
@ComponentProxyExtension()
abstract class TextInputComponent extends Component
with CopyWithMixin<$TextInputComponentCWProxy> {
const TextInputComponent({
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.keyboardType,
this.smartDashesType,
this.smartQuotesType,
this.enableInteractiveSelection,
this.textInputAction,
this.textCapitalization,
this.style,
this.strutStyle,
this.textAlign,
this.textAlignVertical,
this.textDirection,
this.readOnly,
this.showCursor,
this.autofocus,
this.obscuringCharacter,
this.obscureText,
this.autocorrect,
this.enableSuggestions,
this.maxLines,
this.minLines,
this.expands,
this.maxLength,
this.maxLengthEnforcement,
this.onChanged,
this.onEditingComplete,
this.onSubmitted,
this.onAppPrivateCommand,
this.inputFormatters,
this.enabled,
this.cursorWidth,
this.cursorHeight,
this.cursorRadius,
this.cursorColor,
this.selectionHeightStyle,
this.selectionWidthStyle,
this.keyboardAppearance,
this.scrollPadding,
this.dragStartBehavior,
this.selectionControls,
this.onTap,
this.onTapOutside,
this.mouseCursor,
this.scrollController,
this.scrollPhysics,
this.autofillHints,
this.clipBehavior,
this.restorationId,
this.scribbleEnabled,
this.enableIMEPersonalizedLearning,
this.contextMenuBuilder,
this.spellCheckConfiguration,
this.magnifierConfiguration,
super.key,
});
final TextMagnifierConfiguration? magnifierConfiguration;
final TextEditingController? controller;
final FocusNode? focusNode;
final TextInputType? keyboardType;
final TextInputAction? textInputAction;
final TextCapitalization? textCapitalization;
final TextStyle? style;
final StrutStyle? strutStyle;
final TextAlign? textAlign;
final TextAlignVertical? textAlignVertical;
final TextDirection? textDirection;
final bool? autofocus;
final String? obscuringCharacter;
final bool? obscureText;
final bool? autocorrect;
final SmartDashesType? smartDashesType;
final SmartQuotesType? smartQuotesType;
final bool? enableSuggestions;
final int? maxLines;
final int? minLines;
final bool? expands;
final bool? readOnly;
final bool? showCursor;
final int? maxLength;
final MaxLengthEnforcement? maxLengthEnforcement;
final ValueChanged<String>? onChanged;
final VoidCallback? onEditingComplete;
final ValueChanged<String>? onSubmitted;
final AppPrivateCommandCallback? onAppPrivateCommand;
final List<TextInputFormatter>? inputFormatters;
final ValueNotifier<bool>? enabled;
final double? cursorWidth;
final double? cursorHeight;
final Radius? cursorRadius;
final Color? cursorColor;
final BoxHeightStyle? selectionHeightStyle;
final BoxWidthStyle? selectionWidthStyle;
final Brightness? keyboardAppearance;
final EdgeInsets? scrollPadding;
final bool? enableInteractiveSelection;
final TextSelectionControls? selectionControls;
final DragStartBehavior? dragStartBehavior;
final GestureTapCallback? onTap;
final TapRegionCallback? onTapOutside;
final MouseCursor? mouseCursor;
final ScrollPhysics? scrollPhysics;
final ScrollController? scrollController;
final Iterable<String>? autofillHints;
final Clip? clipBehavior;
final String? restorationId;
final bool? scribbleEnabled;
final bool? enableIMEPersonalizedLearning;
final EditableTextContextMenuBuilder? contextMenuBuilder;
final SpellCheckConfiguration? spellCheckConfiguration;
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

@ -0,0 +1,157 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'text_input_component.dart';
// **************************************************************************
// ComponentProxyGenerator
// **************************************************************************
abstract class $TextInputComponentCWProxy {
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 keyboardType(TextInputType? keyboardType);
TextInputComponent smartDashesType(SmartDashesType? smartDashesType);
TextInputComponent smartQuotesType(SmartQuotesType? smartQuotesType);
TextInputComponent enableInteractiveSelection(
bool? enableInteractiveSelection);
TextInputComponent textInputAction(TextInputAction? textInputAction);
TextInputComponent textCapitalization(TextCapitalization? textCapitalization);
TextInputComponent style(TextStyle? style);
TextInputComponent strutStyle(StrutStyle? strutStyle);
TextInputComponent textAlign(TextAlign? textAlign);
TextInputComponent textAlignVertical(TextAlignVertical? textAlignVertical);
TextInputComponent textDirection(TextDirection? textDirection);
TextInputComponent readOnly(bool? readOnly);
TextInputComponent showCursor(bool? showCursor);
TextInputComponent autofocus(bool? autofocus);
TextInputComponent obscuringCharacter(String? obscuringCharacter);
TextInputComponent obscureText(bool? obscureText);
TextInputComponent autocorrect(bool? autocorrect);
TextInputComponent enableSuggestions(bool? enableSuggestions);
TextInputComponent maxLines(int? maxLines);
TextInputComponent minLines(int? minLines);
TextInputComponent expands(bool? expands);
TextInputComponent maxLength(int? maxLength);
TextInputComponent maxLengthEnforcement(
MaxLengthEnforcement? maxLengthEnforcement);
TextInputComponent onChanged(void Function(String)? onChanged);
TextInputComponent onEditingComplete(void Function()? onEditingComplete);
TextInputComponent onSubmitted(void Function(String)? onSubmitted);
TextInputComponent onAppPrivateCommand(
void Function(String, Map<String, dynamic>)? onAppPrivateCommand);
TextInputComponent inputFormatters(List<TextInputFormatter>? inputFormatters);
TextInputComponent enabled(ValueNotifier<bool>? enabled);
TextInputComponent cursorWidth(double? cursorWidth);
TextInputComponent cursorHeight(double? cursorHeight);
TextInputComponent cursorRadius(Radius? cursorRadius);
TextInputComponent cursorColor(Color? cursorColor);
TextInputComponent selectionHeightStyle(BoxHeightStyle? selectionHeightStyle);
TextInputComponent selectionWidthStyle(BoxWidthStyle? selectionWidthStyle);
TextInputComponent keyboardAppearance(Brightness? keyboardAppearance);
TextInputComponent scrollPadding(EdgeInsets? scrollPadding);
TextInputComponent dragStartBehavior(DragStartBehavior? dragStartBehavior);
TextInputComponent selectionControls(
TextSelectionControls? selectionControls);
TextInputComponent onTap(void Function()? onTap);
TextInputComponent onTapOutside(
void Function(PointerDownEvent)? onTapOutside);
TextInputComponent mouseCursor(MouseCursor? mouseCursor);
TextInputComponent scrollController(ScrollController? scrollController);
TextInputComponent scrollPhysics(ScrollPhysics? scrollPhysics);
TextInputComponent autofillHints(Iterable<String>? autofillHints);
TextInputComponent clipBehavior(Clip? clipBehavior);
TextInputComponent restorationId(String? restorationId);
TextInputComponent scribbleEnabled(bool? scribbleEnabled);
TextInputComponent enableIMEPersonalizedLearning(
bool? enableIMEPersonalizedLearning);
TextInputComponent contextMenuBuilder(
Widget Function(BuildContext, EditableTextState)? contextMenuBuilder);
TextInputComponent spellCheckConfiguration(
SpellCheckConfiguration? spellCheckConfiguration);
TextInputComponent magnifierConfiguration(
TextMagnifierConfiguration? magnifierConfiguration);
TextInputComponent key(Key? key);
TextInputComponent call({
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,
TextInputType? keyboardType,
SmartDashesType? smartDashesType,
SmartQuotesType? smartQuotesType,
bool? enableInteractiveSelection,
TextInputAction? textInputAction,
TextCapitalization? textCapitalization,
TextStyle? style,
StrutStyle? strutStyle,
TextAlign? textAlign,
TextAlignVertical? textAlignVertical,
TextDirection? textDirection,
bool? readOnly,
bool? showCursor,
bool? autofocus,
String? obscuringCharacter,
bool? obscureText,
bool? autocorrect,
bool? enableSuggestions,
int? maxLines,
int? minLines,
bool? expands,
int? maxLength,
MaxLengthEnforcement? maxLengthEnforcement,
void Function(String)? onChanged,
void Function()? onEditingComplete,
void Function(String)? onSubmitted,
void Function(String, Map<String, dynamic>)? onAppPrivateCommand,
List<TextInputFormatter>? inputFormatters,
ValueNotifier<bool>? enabled,
double? cursorWidth,
double? cursorHeight,
Radius? cursorRadius,
Color? cursorColor,
BoxHeightStyle? selectionHeightStyle,
BoxWidthStyle? selectionWidthStyle,
Brightness? keyboardAppearance,
EdgeInsets? scrollPadding,
DragStartBehavior? dragStartBehavior,
TextSelectionControls? selectionControls,
void Function()? onTap,
void Function(PointerDownEvent)? onTapOutside,
MouseCursor? mouseCursor,
ScrollController? scrollController,
ScrollPhysics? scrollPhysics,
Iterable<String>? autofillHints,
Clip? clipBehavior,
String? restorationId,
bool? scribbleEnabled,
bool? enableIMEPersonalizedLearning,
Widget Function(BuildContext, EditableTextState)? contextMenuBuilder,
SpellCheckConfiguration? spellCheckConfiguration,
TextMagnifierConfiguration? magnifierConfiguration,
Key? key,
});
}

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';

View File

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:wyatt_ui_kit_example/buttons/buttons.dart';
import 'package:wyatt_ui_kit_example/cards/cards.dart';
import 'package:wyatt_ui_kit_example/text_input/text_inputs.dart';
import 'package:wyatt_ui_kit_example/theme/themes.dart';
const String title = 'Wyatt UIKit Example';
@ -17,7 +18,11 @@ class Home extends StatefulWidget {
}
class _HomeState extends State<Home> {
final List<Widget> pages = const [Cards(), Buttons()];
final List<Widget> pages = [
const Cards(),
const Buttons(),
const TextInputs()
];
int currentIndex = 0;
@ -55,6 +60,17 @@ class _HomeState extends State<Home> {
}
},
),
ListTile(
title: const Text('Text inputs'),
onTap: () {
if (currentIndex != 2) {
setState(() {
currentIndex = 2;
});
Navigator.pop(context);
}
},
),
],
),
),

View File

@ -0,0 +1,129 @@
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
class TextInputs extends StatefulWidget {
const TextInputs({super.key});
@override
State<TextInputs> createState() => _TextInputsState();
}
class _TextInputsState extends State<TextInputs> {
final _formKey = GlobalKey<FormState>();
final _controller = TextEditingController();
final _focusNode = FocusNode();
final _formKey2 = GlobalKey<FormState>();
final _controller2 = TextEditingController();
final _focusNode2 = FocusNode();
final _formKey3 = GlobalKey<FormState>();
final _controller3 = TextEditingController();
final _focusNode3 = FocusNode();
final _formKey4 = GlobalKey<FormState>();
final _controller4 = TextEditingController();
final _focusNode4 = FocusNode();
final _formKey5 = GlobalKey<FormState>();
final _controller5 = TextEditingController();
final _focusNode5 = FocusNode();
final _formKey6 = GlobalKey<FormState>();
final _controller6 = TextEditingController();
final _focusNode6 = FocusNode();
final ValueNotifier<bool> _enable = ValueNotifier(true);
@override
void initState() {
super.initState();
Future.delayed(const Duration(milliseconds: 500), () {
setState(() {
_enable.value = false;
});
});
}
@override
Widget build(BuildContext context) => Form(
child: ListView(
cacheExtent: 1000,
children: [
const Gap(20),
Align(
child: Text(
'Text inputs',
style: Theme.of(context).textTheme.titleLarge,
),
),
const Gap(20),
TextInput(
key: _formKey6,
controller: _controller6,
focusNode: _focusNode6,
label: 'Nom / Prénom'.wrap(),
onError: (value) => 'Erreur : ${value.length} > 5.',
validator: (value) => value.length > 5,
),
const Gap(20),
TextInput(
key: _formKey,
enabled: _enable,
controller: _controller,
focusNode: _focusNode,
label: 'Nom / Prénom'.wrap(),
onError: (value) => 'Erreur : ${value.length} > 5.',
validator: (value) => value.length > 5,
),
const Gap(20),
TextInput(
key: _formKey2,
controller: _controller2,
focusNode: _focusNode2,
maxLines: 3,
onError: (value) => 'Erreur : ${value.length} > 5.',
validator: (value) => value.length > 5,
onChanged: (value) {},
),
const Gap(20),
TextInput(
key: _formKey3,
controller: _controller3,
focusNode: _focusNode3,
expand: false,
label: 'Nom / Prénom'.wrap(),
onError: (value) => 'Erreur : ${value.length} > 5.',
validator: (value) => value.length > 5,
onChanged: (value) {},
),
const Gap(20),
TextInput(
key: _formKey4,
expand: false,
controller: _controller4,
focusNode: _focusNode4,
label: 'Nom / Prénom'.wrap(),
maxLines: 3,
onError: (value) => 'Erreur : ${value.length} > 5.',
validator: (value) => value.length > 5,
onChanged: (value) {},
),
const Gap(20),
TextInput(
key: _formKey5,
prefixIcon: const Icon(Icons.architecture),
suffixIcon: const Icon(Icons.architecture),
controller: _controller5,
focusNode: _focusNode5,
label: 'Nom / Prénom'.wrap(),
onError: (value) => 'Erreur : ${value.length} > 5.',
validator: (value) => value.length > 5,
),
const Gap(20),
],
),
);
}

View File

@ -0,0 +1,181 @@
// 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: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 TextInputTheme extends TextInputThemeExtension {
const TextInputTheme({
super.normalStyle,
super.focusedStyle,
super.disableStyle,
super.errorStyle,
});
factory TextInputTheme.light() => TextInputTheme(
normalStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const MultiColor([
Color.fromRGBO(221, 224, 227, 1),
Color.fromRGBO(202, 204, 212, 1),
]),
labelStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(55, 65, 81, 1),
),
inputStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(55, 65, 81, 1),
),
),
focusedStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const MultiColor([
Color.fromRGBO(60, 125, 251, 1),
Color.fromRGBO(68, 109, 244, 1),
]),
labelStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(55, 65, 81, 1),
),
inputStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(55, 65, 81, 1),
),
),
errorStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const MultiColor([
Color.fromRGBO(251, 94, 60, 1),
Color.fromRGBO(244, 68, 100, 1),
]),
labelStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(244, 68, 100, 1),
),
inputStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(55, 65, 81, 1),
),
),
disableStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors:
const MultiColor.single(Color.fromRGBO(229, 231, 235, 1)),
labelStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(156, 163, 175, 1),
),
inputStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(156, 163, 175, 1),
),
),
);
factory TextInputTheme.dark() => TextInputTheme(
normalStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const MultiColor.single(
Color.fromRGBO(96, 101, 106, 1),
),
labelStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(204, 204, 204, 1),
),
inputStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(255, 255, 255, 1),
),
),
focusedStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const MultiColor([
Color.fromRGBO(60, 125, 251, 1),
Color.fromRGBO(68, 109, 244, 1),
]),
labelStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(204, 204, 204, 1),
),
inputStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(255, 255, 255, 1),
),
),
errorStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const MultiColor([
Color.fromRGBO(251, 94, 60, 1),
Color.fromRGBO(244, 68, 100, 1),
]),
labelStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(244, 68, 100, 1),
),
inputStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(255, 255, 255, 1),
),
),
disableStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const MultiColor.single(
Color.fromRGBO(96, 101, 106, 1),
),
labelStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(96, 101, 106, 1),
),
inputStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(255, 255, 255, 1),
),
),
);
@override
ThemeExtension<TextInputThemeExtension> lerp(
covariant ThemeExtension<TextInputThemeExtension>? other,
double t,
) {
if (other is! TextInputTheme) {
return this;
}
return TextInputTheme(
normalStyle: TextInputStyle.lerp(normalStyle, other.normalStyle, t),
focusedStyle: TextInputStyle.lerp(focusedStyle, other.focusedStyle, t),
disableStyle: TextInputStyle.lerp(disableStyle, other.disableStyle, t),
errorStyle: TextInputStyle.lerp(errorStyle, other.errorStyle, t),
);
}
@override
ThemeExtension<TextInputThemeExtension> copyWith({
TextInputStyle? normalStyle,
TextInputStyle? focusedStyle,
TextInputStyle? disableStyle,
TextInputStyle? errorStyle,
}) =>
TextInputTheme(
normalStyle: normalStyle ?? this.normalStyle,
focusedStyle: focusedStyle ?? this.focusedStyle,
disableStyle: disableStyle ?? this.disableStyle,
errorStyle: errorStyle ?? this.errorStyle,
);
}

View File

@ -21,6 +21,7 @@ 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/simple_icon_button_theme.dart';
import 'package:wyatt_ui_kit_example/theme/symbol_button_theme.dart';
import 'package:wyatt_ui_kit_example/theme/text_input_theme.dart';
import 'package:wyatt_ui_kit_example/theme_extension.dart';
/// Easely switch between Material and Studio themes.
@ -107,6 +108,7 @@ abstract class Themes {
SymbolButtonTheme.light(),
SimpleIconButtonTheme.light(),
FileSelectionButtonTheme.light(),
TextInputTheme.light(),
],
);
@ -154,6 +156,7 @@ abstract class Themes {
SymbolButtonTheme.dark(),
SimpleIconButtonTheme.dark(),
FileSelectionButtonTheme.dark(),
TextInputTheme.dark(),
],
);
}

View File

@ -68,41 +68,7 @@ class FileSelectionButtonScreen
FileSelectionButtonStyle resolve(BuildContext context, ButtonState state) {
final FileSelectionButtonThemeResolver resolver = themeResolver ??
FileSelectionButtonThemeResolver(
computeExtensionValueFn: (
context,
defaultValue,
themeExtension, {
extra,
}) {
FileSelectionButtonStyle? style = defaultValue;
switch (extra?.state) {
case ControlState.disabled:
style = themeExtension.disabledStyle;
break;
case ControlState.focused:
style = themeExtension.focusedStyle;
break;
case ControlState.hovered:
style = themeExtension.hoveredStyle;
break;
case ControlState.tapped:
style = themeExtension.tappedStyle;
break;
case ControlState.normal:
case null:
style = themeExtension.normalStyle;
break;
}
if (extra?.isSelected ?? false) {
style = themeExtension.selectedStyle;
}
if (extra?.isInvalid ?? false) {
style = themeExtension.invalidStyle;
}
return style;
},
customStyleFn: (context, {extra}) {
customStyleFn: (context, extensionValue, {extra}) {
FileSelectionButtonStyle? style;
switch (extra?.state) {
case ControlState.disabled:
@ -221,7 +187,7 @@ class FileSelectionButtonScreen
children: [
if (leading != null) ...[
leading ?? const SizedBox.shrink(),
Gap((style.padding?.horizontal ?? 10)/2),
Gap((style.padding?.horizontal ?? 10) / 2),
],
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,

View File

@ -22,7 +22,6 @@ import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
class FileSelectionButtonThemeResolver extends ThemeResolver<
FileSelectionButtonStyle, FileSelectionButtonThemeExtension, ButtonState> {
const FileSelectionButtonThemeResolver({
required this.computeExtensionValueFn,
required this.customStyleFn,
});
@ -57,8 +56,7 @@ class FileSelectionButtonThemeResolver extends ThemeResolver<
}
if (extra?.isInvalid ?? false) {
backgroundColor =
MultiColor.single(context.colorScheme.error);
backgroundColor = MultiColor.single(context.colorScheme.error);
}
return FileSelectionButtonStyle(
@ -75,15 +73,43 @@ class FileSelectionButtonThemeResolver extends ThemeResolver<
@override
final FileSelectionButtonStyle? Function(
BuildContext context,
FileSelectionButtonStyle? extensionValue, {
ButtonState? extra,
}) customStyleFn;
@override
FileSelectionButtonStyle? computeExtensionValueFn(
BuildContext context,
FileSelectionButtonStyle defaultValue,
FileSelectionButtonThemeExtension themeExtension, {
ButtonState? extra,
}) computeExtensionValueFn;
@override
final FileSelectionButtonStyle? Function(
BuildContext context, {
ButtonState? extra,
}) customStyleFn;
}) {
FileSelectionButtonStyle? style = defaultValue;
switch (extra?.state) {
case ControlState.disabled:
style = themeExtension.disabledStyle;
break;
case ControlState.focused:
style = themeExtension.focusedStyle;
break;
case ControlState.hovered:
style = themeExtension.hoveredStyle;
break;
case ControlState.tapped:
style = themeExtension.tappedStyle;
break;
case ControlState.normal:
case null:
style = themeExtension.normalStyle;
break;
}
if (extra?.isSelected ?? false) {
style = themeExtension.selectedStyle;
}
if (extra?.isInvalid ?? false) {
style = themeExtension.invalidStyle;
}
return style;
}
}

View File

@ -62,27 +62,7 @@ class FlatButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
FlatButtonStyle resolve(BuildContext context, ControlState state) {
final FlatButtonThemeResolver resolver = themeResolver ??
FlatButtonThemeResolver(
computeExtensionValueFn: (
context,
defaultValue,
themeExtension, {
extra,
}) {
switch (extra) {
case ControlState.disabled:
return themeExtension.disabledStyle;
case ControlState.focused:
return themeExtension.focusedStyle;
case ControlState.hovered:
return themeExtension.hoveredStyle;
case ControlState.tapped:
return themeExtension.tappedStyle;
case ControlState.normal:
case null:
return themeExtension.normalStyle;
}
},
customStyleFn: (context, {extra}) {
customStyleFn: (context, extensionValue, {extra}) {
switch (extra) {
case ControlState.disabled:
return disabledStyle;
@ -142,7 +122,7 @@ class FlatButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
// If no border color => no default value
border: (style.borderColors != null && style.stroke != null)
? (style.borderColors?.isGradient ?? false)
? GradientBoxBorder(
? CustomGradientBoxBorder(
gradient: LinearGradient(
colors: style.borderColors!.colors,
),

View File

@ -21,7 +21,6 @@ import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
class FlatButtonThemeResolver extends ThemeResolver<FlatButtonStyle,
FlatButtonThemeExtension, ControlState> {
const FlatButtonThemeResolver({
required this.computeExtensionValueFn,
required this.customStyleFn,
});
@ -70,13 +69,30 @@ class FlatButtonThemeResolver extends ThemeResolver<FlatButtonStyle,
@override
final FlatButtonStyle? Function(
BuildContext context,
FlatButtonStyle? extensionValue, {
ControlState? extra,
}) customStyleFn;
@override
FlatButtonStyle? computeExtensionValueFn(
BuildContext context,
FlatButtonStyle defaultValue,
FlatButtonThemeExtension themeExtension, {
ControlState? extra,
}) computeExtensionValueFn;
@override
final FlatButtonStyle? Function(BuildContext context, {ControlState? extra})
customStyleFn;
}) {
switch (extra) {
case ControlState.disabled:
return themeExtension.disabledStyle;
case ControlState.focused:
return themeExtension.focusedStyle;
case ControlState.hovered:
return themeExtension.hoveredStyle;
case ControlState.tapped:
return themeExtension.tappedStyle;
case ControlState.normal:
case null:
return themeExtension.normalStyle;
}
}
}

View File

@ -21,7 +21,6 @@ import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
class SimpleIconButtonThemeResolver extends ThemeResolver<SimpleIconButtonStyle,
SimpleIconButtonThemeExtension, ControlState> {
const SimpleIconButtonThemeResolver({
required this.computeExtensionValueFn,
required this.customStyleFn,
});
@ -68,15 +67,30 @@ class SimpleIconButtonThemeResolver extends ThemeResolver<SimpleIconButtonStyle,
@override
final SimpleIconButtonStyle? Function(
BuildContext context,
SimpleIconButtonStyle? extensionValue, {
ControlState? extra,
}) customStyleFn;
@override
SimpleIconButtonStyle? computeExtensionValueFn(
BuildContext context,
SimpleIconButtonStyle defaultValue,
SimpleIconButtonThemeExtension themeExtension, {
ControlState? extra,
}) computeExtensionValueFn;
@override
final SimpleIconButtonStyle? Function(
BuildContext context, {
ControlState? extra,
}) customStyleFn;
}) {
switch (extra) {
case ControlState.disabled:
return themeExtension.disabledStyle;
case ControlState.focused:
return themeExtension.focusedStyle;
case ControlState.hovered:
return themeExtension.hoveredStyle;
case ControlState.tapped:
return themeExtension.tappedStyle;
case ControlState.normal:
case null:
return themeExtension.normalStyle;
}
}
}

View File

@ -55,27 +55,7 @@ class SimpleIconButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
SimpleIconButtonStyle resolve(BuildContext context, ControlState state) {
final SimpleIconButtonThemeResolver resolver = themeResolver ??
SimpleIconButtonThemeResolver(
computeExtensionValueFn: (
context,
defaultValue,
themeExtension, {
extra,
}) {
switch (extra) {
case ControlState.disabled:
return themeExtension.disabledStyle;
case ControlState.focused:
return themeExtension.focusedStyle;
case ControlState.hovered:
return themeExtension.hoveredStyle;
case ControlState.tapped:
return themeExtension.tappedStyle;
case ControlState.normal:
case null:
return themeExtension.normalStyle;
}
},
customStyleFn: (context, {extra}) {
customStyleFn: (context, extensionValue, {extra}) {
switch (extra) {
case ControlState.disabled:
return disabledStyle;
@ -140,7 +120,7 @@ class SimpleIconButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
// If no border color => no default value
border: (style.borderColors != null && style.stroke != null)
? (style.borderColors?.isGradient ?? false)
? GradientBoxBorder(
? CustomGradientBoxBorder(
gradient: LinearGradient(
colors: style.borderColors!.colors,
),

View File

@ -64,38 +64,7 @@ class SymbolButtonScreen
SymbolButtonStyle resolve(BuildContext context, ButtonState state) {
final SymbolButtonThemeResolver resolver = themeResolver ??
SymbolButtonThemeResolver(
computeExtensionValueFn: (
context,
defaultValue,
themeExtension, {
extra,
}) {
SymbolButtonStyle? style = defaultValue;
switch (extra?.state) {
case ControlState.disabled:
style = themeExtension.disabledStyle;
break;
case ControlState.focused:
style = themeExtension.focusedStyle;
break;
case ControlState.hovered:
style = themeExtension.hoveredStyle;
break;
case ControlState.tapped:
style = themeExtension.tappedStyle;
break;
case ControlState.normal:
case null:
style = themeExtension.normalStyle;
break;
}
if (extra?.isSelected ?? false) {
style = themeExtension.selectedStyle;
}
return style;
},
customStyleFn: (context, {extra}) {
customStyleFn: (context, extensionValue, {extra}) {
SymbolButtonStyle? style;
switch (extra?.state) {
case ControlState.disabled:
@ -176,7 +145,7 @@ class SymbolButtonScreen
border:
(style.borderColors != null && style.stroke != null)
? (style.borderColors?.isGradient ?? false)
? GradientBoxBorder(
? CustomGradientBoxBorder(
gradient: LinearGradient(
colors: style.borderColors!.colors,
),

View File

@ -22,7 +22,6 @@ import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
class SymbolButtonThemeResolver extends ThemeResolver<SymbolButtonStyle,
SymbolButtonThemeExtension, ButtonState> {
const SymbolButtonThemeResolver({
required this.computeExtensionValueFn,
required this.customStyleFn,
});
@ -58,7 +57,7 @@ class SymbolButtonThemeResolver extends ThemeResolver<SymbolButtonStyle,
return SymbolButtonStyle(
label: context.textTheme.labelLarge,
dimension: context.buttonTheme.height*1.5,
dimension: context.buttonTheme.height * 1.5,
radius: (context.buttonTheme.shape is RoundedRectangleBorder)
? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius
: null,
@ -70,15 +69,41 @@ class SymbolButtonThemeResolver extends ThemeResolver<SymbolButtonStyle,
@override
final SymbolButtonStyle? Function(
BuildContext context,
SymbolButtonStyle? extensionValue, {
ButtonState? extra,
}) customStyleFn;
@override
SymbolButtonStyle? computeExtensionValueFn(
BuildContext context,
SymbolButtonStyle defaultValue,
SymbolButtonThemeExtension themeExtension, {
ButtonState? extra,
}) computeExtensionValueFn;
}) {
SymbolButtonStyle? style = defaultValue;
switch (extra?.state) {
case ControlState.disabled:
style = themeExtension.disabledStyle;
break;
case ControlState.focused:
style = themeExtension.focusedStyle;
break;
case ControlState.hovered:
style = themeExtension.hoveredStyle;
break;
case ControlState.tapped:
style = themeExtension.tappedStyle;
break;
case ControlState.normal:
case null:
style = themeExtension.normalStyle;
break;
}
if (extra?.isSelected ?? false) {
style = themeExtension.selectedStyle;
}
@override
final SymbolButtonStyle? Function(
BuildContext context, {
ButtonState? extra,
}) customStyleFn;
return style;
}
}

View File

@ -137,7 +137,7 @@ class _CardWrapperState extends State<CardWrapper> {
BoxBorder? _boxBorder(BuildContext context) {
if (widget.borderColors != null) {
if (widget.borderColors!.length >= 2) {
return GradientBoxBorder(
return CustomGradientBoxBorder(
gradient: LinearGradient(
colors: widget.borderColors!,
),
@ -153,7 +153,7 @@ class _CardWrapperState extends State<CardWrapper> {
if (extensionCardColor != null &&
extensionCardColor.borderColor != null) {
if (extensionCardColor.borderColor!.length >= 2) {
return GradientBoxBorder(
return CustomGradientBoxBorder(
gradient: LinearGradient(
colors: extensionCardColor.borderColor!,
),

View File

@ -16,3 +16,4 @@
export './buttons/buttons.dart';
export './cards/cards.dart';
export './text_inputs/text_input.dart';

View File

@ -14,10 +14,11 @@
// 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:flutter/painting.dart';
class GradientBoxBorder extends BoxBorder {
const GradientBoxBorder({this.gradient, this.width = 1});
class CustomGradientBoxBorder extends Border {
const CustomGradientBoxBorder({this.gradient, this.width = 1});
final Gradient? gradient;
final double width;
@ -34,9 +35,6 @@ class GradientBoxBorder extends BoxBorder {
@override
bool get isUniform => true;
@override
ShapeBorder scale(double t) => this;
@override
void paint(
Canvas canvas,

View File

@ -0,0 +1,57 @@
// 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 'dart:async';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
part 'text_input_state.dart';
class TextInputCubit extends Cubit<TextInputState> {
TextInputCubit() : super(const TextInputState.initial());
// ControlState logic
FutureOr<void> onFocus() async {
if (state.controlState != ControlState.disabled) {
emit(state.copyWith(controlState: ControlState.focused));
}
}
FutureOr<void> onUnfocus() async {
if (state.controlState != ControlState.disabled) {
emit(state.copyWith(controlState: ControlState.normal));
}
}
Future<void> disable() async {
emit(state.copyWith(controlState: ControlState.disabled));
}
Future<void> enable() async {
emit(state.copyWith(controlState: ControlState.normal));
}
// StatusState logic
FutureOr<void> onInvalid(String? error) async {
emit(state.copyWith(statusState: StatusState.error, statusMessage: error));
}
FutureOr<void> onSuccess() async {
emit(state.copyWith(statusState: StatusState.initial, statusMessage: ''));
}
}

View File

@ -0,0 +1,49 @@
// 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/>.
part of 'text_input_cubit.dart';
class TextInputState extends Equatable {
const TextInputState({
required this.controlState,
required this.statusState,
this.statusMessage,
});
const TextInputState.initial()
: controlState = ControlState.normal,
statusState = StatusState.initial,
statusMessage = null;
final ControlState controlState;
final StatusState statusState;
final String? statusMessage;
@override
List<Object?> get props => [controlState, statusState, statusMessage];
TextInputState copyWith({
ControlState? controlState,
StatusState? statusState,
String? statusMessage,
}) =>
TextInputState(
controlState: controlState ?? this.controlState,
statusState: statusState ?? this.statusState,
statusMessage: statusMessage ?? this.statusMessage,
);
}

View File

@ -0,0 +1,168 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// super 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.
//
// super 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 super program. If not, see <https://www.gnu.org/licenses/>.
import 'dart:ui';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.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/text_inputs/text_input_screen.dart';
part 'text_input.g.dart';
@ComponentCopyWithExtension()
class TextInput extends TextInputComponent with $TextInputCWMixin {
TextInput({
super.expand,
super.validator,
super.key,
super.prefixIcon,
super.prefixText,
super.suffixIcon,
super.suffixText,
super.label,
super.onError,
super.hint,
super.normalStyle,
super.focusedStyle,
super.errorStyle,
super.disableStyle,
super.controller,
super.focusNode,
super.keyboardType,
super.smartDashesType,
super.smartQuotesType,
super.enableInteractiveSelection,
super.textInputAction,
super.textCapitalization,
super.style,
super.strutStyle,
super.textAlign,
super.textAlignVertical,
super.textDirection,
super.readOnly,
super.showCursor,
super.autofocus,
super.obscuringCharacter,
super.obscureText,
super.autocorrect,
super.enableSuggestions,
super.maxLines,
super.minLines,
super.expands,
super.maxLength,
super.maxLengthEnforcement,
super.onChanged,
super.onEditingComplete,
super.onSubmitted,
super.onAppPrivateCommand,
super.inputFormatters,
super.enabled,
super.cursorWidth,
super.cursorHeight,
super.cursorRadius,
super.cursorColor,
super.selectionHeightStyle,
super.selectionWidthStyle,
super.keyboardAppearance,
super.scrollPadding,
super.dragStartBehavior,
super.selectionControls,
super.onTap,
super.onTapOutside,
super.mouseCursor,
super.scrollController,
super.scrollPhysics,
super.autofillHints,
super.clipBehavior,
super.restorationId,
super.scribbleEnabled,
super.enableIMEPersonalizedLearning,
super.contextMenuBuilder,
super.spellCheckConfiguration,
super.magnifierConfiguration,
});
@override
Widget build(BuildContext context) => TextInputScreen(
expand: expand,
validator: validator,
label: label,
onError: onError,
hint: hint,
focusedStyle: focusedStyle,
normalStyle: normalStyle,
errorStyle: errorStyle,
disableStyle: disableStyle,
prefixIcon: prefixIcon,
prefixText: prefixText,
suffixIcon: suffixIcon,
magnifierConfiguration: magnifierConfiguration,
controller: controller,
focusNode: focusNode,
keyboardType: keyboardType,
textInputAction: textInputAction,
textCapitalization: textCapitalization,
style: style,
strutStyle: strutStyle,
textAlign: textAlign,
textAlignVertical: textAlignVertical,
textDirection: textDirection,
autofocus: autofocus,
obscuringCharacter: obscuringCharacter,
obscureText: obscureText,
autocorrect: autocorrect,
smartDashesType: smartDashesType,
smartQuotesType: smartQuotesType,
enableSuggestions: enableSuggestions,
maxLines: maxLines,
minLines: minLines,
expands: expands,
readOnly: readOnly,
showCursor: showCursor,
maxLength: maxLength,
maxLengthEnforcement: maxLengthEnforcement,
onChanged: onChanged,
onEditingComplete: onEditingComplete,
onSubmitted: onSubmitted,
onAppPrivateCommand: onAppPrivateCommand,
inputFormatters: inputFormatters,
enabled: enabled,
cursorWidth: cursorWidth,
cursorHeight: cursorHeight,
cursorRadius: cursorRadius,
cursorColor: cursorColor,
selectionHeightStyle: selectionHeightStyle,
selectionWidthStyle: selectionWidthStyle,
keyboardAppearance: keyboardAppearance,
scrollPadding: scrollPadding,
enableInteractiveSelection: enableInteractiveSelection,
selectionControls: selectionControls,
dragStartBehavior: dragStartBehavior,
onTap: onTap,
onTapOutside: onTapOutside,
mouseCursor: mouseCursor,
scrollPhysics: scrollPhysics,
scrollController: scrollController,
autofillHints: autofillHints,
clipBehavior: clipBehavior,
restorationId: restorationId,
scribbleEnabled: scribbleEnabled,
enableIMEPersonalizedLearning: enableIMEPersonalizedLearning,
contextMenuBuilder: contextMenuBuilder,
spellCheckConfiguration: spellCheckConfiguration,
);
}

View File

@ -0,0 +1,348 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'text_input.dart';
// **************************************************************************
// ComponentCopyWithGenerator
// **************************************************************************
class $TextInputCWProxyImpl implements $TextInputComponentCWProxy {
const $TextInputCWProxyImpl(this._value);
final TextInput _value;
@override
TextInput expand(bool? expand) => this(expand: expand);
@override
TextInput onError(String Function(String)? onError) => this(onError: onError);
@override
TextInput validator(bool Function(String)? validator) =>
this(validator: validator);
@override
TextInput suffixText(TextWrapper? suffixText) => this(suffixText: suffixText);
@override
TextInput prefixText(TextWrapper? prefixText) => this(prefixText: prefixText);
@override
TextInput prefixIcon(Icon? prefixIcon) => this(prefixIcon: prefixIcon);
@override
TextInput suffixIcon(Icon? suffixIcon) => this(suffixIcon: suffixIcon);
@override
TextInput label(TextWrapper? label) => this(label: label);
@override
TextInput hint(TextWrapper? hint) => this(hint: hint);
@override
TextInput normalStyle(TextInputStyle? normalStyle) =>
this(normalStyle: normalStyle);
@override
TextInput focusedStyle(TextInputStyle? focusedStyle) =>
this(focusedStyle: focusedStyle);
@override
TextInput errorStyle(TextInputStyle? errorStyle) =>
this(errorStyle: errorStyle);
@override
TextInput disableStyle(TextInputStyle? disableStyle) =>
this(disableStyle: disableStyle);
@override
TextInput controller(TextEditingController? controller) =>
this(controller: controller);
@override
TextInput focusNode(FocusNode? focusNode) => this(focusNode: focusNode);
@override
TextInput keyboardType(TextInputType? keyboardType) =>
this(keyboardType: keyboardType);
@override
TextInput smartDashesType(SmartDashesType? smartDashesType) =>
this(smartDashesType: smartDashesType);
@override
TextInput smartQuotesType(SmartQuotesType? smartQuotesType) =>
this(smartQuotesType: smartQuotesType);
@override
TextInput enableInteractiveSelection(bool? enableInteractiveSelection) =>
this(enableInteractiveSelection: enableInteractiveSelection);
@override
TextInput textInputAction(TextInputAction? textInputAction) =>
this(textInputAction: textInputAction);
@override
TextInput textCapitalization(TextCapitalization? textCapitalization) =>
this(textCapitalization: textCapitalization);
@override
TextInput style(TextStyle? style) => this(style: style);
@override
TextInput strutStyle(StrutStyle? strutStyle) => this(strutStyle: strutStyle);
@override
TextInput textAlign(TextAlign? textAlign) => this(textAlign: textAlign);
@override
TextInput textAlignVertical(TextAlignVertical? textAlignVertical) =>
this(textAlignVertical: textAlignVertical);
@override
TextInput textDirection(TextDirection? textDirection) =>
this(textDirection: textDirection);
@override
TextInput readOnly(bool? readOnly) => this(readOnly: readOnly);
@override
TextInput showCursor(bool? showCursor) => this(showCursor: showCursor);
@override
TextInput autofocus(bool? autofocus) => this(autofocus: autofocus);
@override
TextInput obscuringCharacter(String? obscuringCharacter) =>
this(obscuringCharacter: obscuringCharacter);
@override
TextInput obscureText(bool? obscureText) => this(obscureText: obscureText);
@override
TextInput autocorrect(bool? autocorrect) => this(autocorrect: autocorrect);
@override
TextInput enableSuggestions(bool? enableSuggestions) =>
this(enableSuggestions: enableSuggestions);
@override
TextInput maxLines(int? maxLines) => this(maxLines: maxLines);
@override
TextInput minLines(int? minLines) => this(minLines: minLines);
@override
TextInput expands(bool? expands) => this(expands: expands);
@override
TextInput maxLength(int? maxLength) => this(maxLength: maxLength);
@override
TextInput maxLengthEnforcement(MaxLengthEnforcement? maxLengthEnforcement) =>
this(maxLengthEnforcement: maxLengthEnforcement);
@override
TextInput onChanged(void Function(String)? onChanged) =>
this(onChanged: onChanged);
@override
TextInput onEditingComplete(void Function()? onEditingComplete) =>
this(onEditingComplete: onEditingComplete);
@override
TextInput onSubmitted(void Function(String)? onSubmitted) =>
this(onSubmitted: onSubmitted);
@override
TextInput onAppPrivateCommand(
void Function(String, Map<String, dynamic>)? onAppPrivateCommand) =>
this(onAppPrivateCommand: onAppPrivateCommand);
@override
TextInput inputFormatters(List<TextInputFormatter>? inputFormatters) =>
this(inputFormatters: inputFormatters);
@override
TextInput enabled(ValueNotifier<bool>? enabled) => this(enabled: enabled);
@override
TextInput cursorWidth(double? cursorWidth) => this(cursorWidth: cursorWidth);
@override
TextInput cursorHeight(double? cursorHeight) =>
this(cursorHeight: cursorHeight);
@override
TextInput cursorRadius(Radius? cursorRadius) =>
this(cursorRadius: cursorRadius);
@override
TextInput cursorColor(Color? cursorColor) => this(cursorColor: cursorColor);
@override
TextInput selectionHeightStyle(BoxHeightStyle? selectionHeightStyle) =>
this(selectionHeightStyle: selectionHeightStyle);
@override
TextInput selectionWidthStyle(BoxWidthStyle? selectionWidthStyle) =>
this(selectionWidthStyle: selectionWidthStyle);
@override
TextInput keyboardAppearance(Brightness? keyboardAppearance) =>
this(keyboardAppearance: keyboardAppearance);
@override
TextInput scrollPadding(EdgeInsets? scrollPadding) =>
this(scrollPadding: scrollPadding);
@override
TextInput dragStartBehavior(DragStartBehavior? dragStartBehavior) =>
this(dragStartBehavior: dragStartBehavior);
@override
TextInput selectionControls(TextSelectionControls? selectionControls) =>
this(selectionControls: selectionControls);
@override
TextInput onTap(void Function()? onTap) => this(onTap: onTap);
@override
TextInput onTapOutside(void Function(PointerDownEvent)? onTapOutside) =>
this(onTapOutside: onTapOutside);
@override
TextInput mouseCursor(MouseCursor? mouseCursor) =>
this(mouseCursor: mouseCursor);
@override
TextInput scrollController(ScrollController? scrollController) =>
this(scrollController: scrollController);
@override
TextInput scrollPhysics(ScrollPhysics? scrollPhysics) =>
this(scrollPhysics: scrollPhysics);
@override
TextInput autofillHints(Iterable<String>? autofillHints) =>
this(autofillHints: autofillHints);
@override
TextInput clipBehavior(Clip? clipBehavior) =>
this(clipBehavior: clipBehavior);
@override
TextInput restorationId(String? restorationId) =>
this(restorationId: restorationId);
@override
TextInput scribbleEnabled(bool? scribbleEnabled) =>
this(scribbleEnabled: scribbleEnabled);
@override
TextInput enableIMEPersonalizedLearning(
bool? enableIMEPersonalizedLearning) =>
this(enableIMEPersonalizedLearning: enableIMEPersonalizedLearning);
@override
TextInput contextMenuBuilder(
Widget Function(BuildContext, EditableTextState)?
contextMenuBuilder) =>
this(contextMenuBuilder: contextMenuBuilder);
@override
TextInput spellCheckConfiguration(
SpellCheckConfiguration? spellCheckConfiguration) =>
this(spellCheckConfiguration: spellCheckConfiguration);
@override
TextInput magnifierConfiguration(
TextMagnifierConfiguration? magnifierConfiguration) =>
this(magnifierConfiguration: magnifierConfiguration);
@override
TextInput key(Key? key) => this(key: key);
@override
TextInput call({
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,
TextInputType? keyboardType,
SmartDashesType? smartDashesType,
SmartQuotesType? smartQuotesType,
bool? enableInteractiveSelection,
TextInputAction? textInputAction,
TextCapitalization? textCapitalization,
TextStyle? style,
StrutStyle? strutStyle,
TextAlign? textAlign,
TextAlignVertical? textAlignVertical,
TextDirection? textDirection,
bool? readOnly,
bool? showCursor,
bool? autofocus,
String? obscuringCharacter,
bool? obscureText,
bool? autocorrect,
bool? enableSuggestions,
int? maxLines,
int? minLines,
bool? expands,
int? maxLength,
MaxLengthEnforcement? maxLengthEnforcement,
void Function(String)? onChanged,
void Function()? onEditingComplete,
void Function(String)? onSubmitted,
void Function(String, Map<String, dynamic>)? onAppPrivateCommand,
List<TextInputFormatter>? inputFormatters,
ValueNotifier<bool>? enabled,
double? cursorWidth,
double? cursorHeight,
Radius? cursorRadius,
Color? cursorColor,
BoxHeightStyle? selectionHeightStyle,
BoxWidthStyle? selectionWidthStyle,
Brightness? keyboardAppearance,
EdgeInsets? scrollPadding,
DragStartBehavior? dragStartBehavior,
TextSelectionControls? selectionControls,
void Function()? onTap,
void Function(PointerDownEvent)? onTapOutside,
MouseCursor? mouseCursor,
ScrollController? scrollController,
ScrollPhysics? scrollPhysics,
Iterable<String>? autofillHints,
Clip? clipBehavior,
String? restorationId,
bool? scribbleEnabled,
bool? enableIMEPersonalizedLearning,
Widget Function(BuildContext, EditableTextState)? contextMenuBuilder,
SpellCheckConfiguration? spellCheckConfiguration,
TextMagnifierConfiguration? magnifierConfiguration,
Key? key,
}) =>
TextInput(
expand: expand ?? _value.expand,
validator: validator ?? _value.validator,
key: key ?? _value.key,
prefixIcon: prefixIcon ?? _value.prefixIcon,
prefixText: prefixText ?? _value.prefixText,
suffixIcon: suffixIcon ?? _value.suffixIcon,
suffixText: suffixText ?? _value.suffixText,
label: label ?? _value.label,
onError: onError ?? _value.onError,
hint: hint ?? _value.hint,
normalStyle: normalStyle ?? _value.normalStyle,
focusedStyle: focusedStyle ?? _value.focusedStyle,
errorStyle: errorStyle ?? _value.errorStyle,
disableStyle: disableStyle ?? _value.disableStyle,
controller: controller ?? _value.controller,
focusNode: focusNode ?? _value.focusNode,
keyboardType: keyboardType ?? _value.keyboardType,
smartDashesType: smartDashesType ?? _value.smartDashesType,
smartQuotesType: smartQuotesType ?? _value.smartQuotesType,
enableInteractiveSelection:
enableInteractiveSelection ?? _value.enableInteractiveSelection,
textInputAction: textInputAction ?? _value.textInputAction,
textCapitalization: textCapitalization ?? _value.textCapitalization,
style: style ?? _value.style,
strutStyle: strutStyle ?? _value.strutStyle,
textAlign: textAlign ?? _value.textAlign,
textAlignVertical: textAlignVertical ?? _value.textAlignVertical,
textDirection: textDirection ?? _value.textDirection,
readOnly: readOnly ?? _value.readOnly,
showCursor: showCursor ?? _value.showCursor,
autofocus: autofocus ?? _value.autofocus,
obscuringCharacter: obscuringCharacter ?? _value.obscuringCharacter,
obscureText: obscureText ?? _value.obscureText,
autocorrect: autocorrect ?? _value.autocorrect,
enableSuggestions: enableSuggestions ?? _value.enableSuggestions,
maxLines: maxLines ?? _value.maxLines,
minLines: minLines ?? _value.minLines,
expands: expands ?? _value.expands,
maxLength: maxLength ?? _value.maxLength,
maxLengthEnforcement:
maxLengthEnforcement ?? _value.maxLengthEnforcement,
onChanged: onChanged ?? _value.onChanged,
onEditingComplete: onEditingComplete ?? _value.onEditingComplete,
onSubmitted: onSubmitted ?? _value.onSubmitted,
onAppPrivateCommand: onAppPrivateCommand ?? _value.onAppPrivateCommand,
inputFormatters: inputFormatters ?? _value.inputFormatters,
enabled: enabled ?? _value.enabled,
cursorWidth: cursorWidth ?? _value.cursorWidth,
cursorHeight: cursorHeight ?? _value.cursorHeight,
cursorRadius: cursorRadius ?? _value.cursorRadius,
cursorColor: cursorColor ?? _value.cursorColor,
selectionHeightStyle:
selectionHeightStyle ?? _value.selectionHeightStyle,
selectionWidthStyle: selectionWidthStyle ?? _value.selectionWidthStyle,
keyboardAppearance: keyboardAppearance ?? _value.keyboardAppearance,
scrollPadding: scrollPadding ?? _value.scrollPadding,
dragStartBehavior: dragStartBehavior ?? _value.dragStartBehavior,
selectionControls: selectionControls ?? _value.selectionControls,
onTap: onTap ?? _value.onTap,
onTapOutside: onTapOutside ?? _value.onTapOutside,
mouseCursor: mouseCursor ?? _value.mouseCursor,
scrollController: scrollController ?? _value.scrollController,
scrollPhysics: scrollPhysics ?? _value.scrollPhysics,
autofillHints: autofillHints ?? _value.autofillHints,
clipBehavior: clipBehavior ?? _value.clipBehavior,
restorationId: restorationId ?? _value.restorationId,
scribbleEnabled: scribbleEnabled ?? _value.scribbleEnabled,
enableIMEPersonalizedLearning: enableIMEPersonalizedLearning ??
_value.enableIMEPersonalizedLearning,
contextMenuBuilder: contextMenuBuilder ?? _value.contextMenuBuilder,
spellCheckConfiguration:
spellCheckConfiguration ?? _value.spellCheckConfiguration,
magnifierConfiguration:
magnifierConfiguration ?? _value.magnifierConfiguration,
);
}
mixin $TextInputCWMixin on Component {
$TextInputComponentCWProxy get copyWith =>
$TextInputCWProxyImpl(this as TextInput);
}

View File

@ -0,0 +1,396 @@
// 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 'dart:ui';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/text_inputs/cubit/text_input_cubit.dart';
import 'package:wyatt_ui_kit/src/components/text_inputs/text_input_theme_resolver.dart';
import 'package:wyatt_ui_kit/src/components/text_inputs/widgets/label_widget.dart';
import 'package:wyatt_ui_kit/src/components/text_inputs/widgets/text_input_wrapper.dart';
class TextInputScreen extends CubitScreen<TextInputCubit, TextInputState> {
TextInputScreen({
this.expand,
this.onError,
this.validator,
super.key,
this.suffixText,
this.prefixText,
this.prefixIcon,
this.suffixIcon,
this.label,
this.hint,
this.normalStyle,
this.focusedStyle,
this.errorStyle,
this.disableStyle,
this.magnifierConfiguration,
this.controller,
this.focusNode,
this.keyboardType,
this.textInputAction,
this.textCapitalization,
this.style,
this.strutStyle,
this.textAlign,
this.textAlignVertical,
this.textDirection,
this.autofocus,
this.obscuringCharacter,
this.obscureText,
this.autocorrect,
this.smartDashesType,
this.smartQuotesType,
this.enableSuggestions,
this.maxLines,
this.minLines,
this.expands,
this.readOnly,
this.showCursor,
this.maxLength,
this.maxLengthEnforcement,
this.onChanged,
this.onEditingComplete,
this.onSubmitted,
this.onAppPrivateCommand,
this.inputFormatters,
this.enabled,
this.cursorWidth,
this.cursorHeight,
this.cursorRadius,
this.cursorColor,
this.selectionHeightStyle,
this.selectionWidthStyle,
this.keyboardAppearance,
this.scrollPadding,
this.enableInteractiveSelection,
this.selectionControls,
this.dragStartBehavior,
this.onTap,
this.onTapOutside,
this.mouseCursor,
this.scrollPhysics,
this.scrollController,
this.autofillHints,
this.clipBehavior,
this.restorationId,
this.scribbleEnabled,
this.enableIMEPersonalizedLearning,
this.contextMenuBuilder,
this.spellCheckConfiguration,
});
final TextMagnifierConfiguration? magnifierConfiguration;
final TextEditingController? controller;
final FocusNode? focusNode;
final TextInputType? keyboardType;
final TextInputAction? textInputAction;
final TextCapitalization? textCapitalization;
final TextStyle? style;
final StrutStyle? strutStyle;
final TextAlign? textAlign;
final TextAlignVertical? textAlignVertical;
final TextDirection? textDirection;
final bool? autofocus;
final String? obscuringCharacter;
final bool? obscureText;
final bool? autocorrect;
final SmartDashesType? smartDashesType;
final SmartQuotesType? smartQuotesType;
final bool? enableSuggestions;
final int? maxLines;
final int? minLines;
final bool? expands;
final bool? readOnly;
final bool? showCursor;
final int? maxLength;
final MaxLengthEnforcement? maxLengthEnforcement;
final ValueChanged<String>? onChanged;
final VoidCallback? onEditingComplete;
final ValueChanged<String>? onSubmitted;
final AppPrivateCommandCallback? onAppPrivateCommand;
final List<TextInputFormatter>? inputFormatters;
final double? cursorWidth;
final double? cursorHeight;
final Radius? cursorRadius;
final Color? cursorColor;
final BoxHeightStyle? selectionHeightStyle;
final BoxWidthStyle? selectionWidthStyle;
final Brightness? keyboardAppearance;
final EdgeInsets? scrollPadding;
final bool? enableInteractiveSelection;
final TextSelectionControls? selectionControls;
final DragStartBehavior? dragStartBehavior;
final GestureTapCallback? onTap;
final TapRegionCallback? onTapOutside;
final MouseCursor? mouseCursor;
final ScrollPhysics? scrollPhysics;
final ScrollController? scrollController;
final Iterable<String>? autofillHints;
final Clip? clipBehavior;
final String? restorationId;
final bool? scribbleEnabled;
final bool? enableIMEPersonalizedLearning;
final EditableTextContextMenuBuilder? contextMenuBuilder;
final SpellCheckConfiguration? spellCheckConfiguration;
final bool Function(String)? validator;
final String? Function(String)? onError;
final TextInputStyle? normalStyle;
final TextInputStyle? focusedStyle;
final TextInputStyle? errorStyle;
final TextInputStyle? disableStyle;
final TextWrapper? label;
final TextWrapper? hint;
final ValueNotifier<bool>? enabled;
final bool? expand;
final TextWrapper? prefixText;
final Icon? prefixIcon;
final Icon? suffixIcon;
final TextWrapper? suffixText;
@override
TextInputCubit create(BuildContext context) => TextInputCubit();
@override
TextInputCubit init(BuildContext context, TextInputCubit bloc) {
enabled?.addListener(() {
if (enabled?.value ?? false) {
bloc.enable();
} else {
bloc.disable();
}
});
return bloc;
}
final _focusNode = FocusNode();
final _controller = TextEditingController();
final _notOutilinedBorder = const OutlineInputBorder(
borderSide: BorderSide(color: Colors.transparent),
);
TextInputStyle _resolve(BuildContext context, TextInputState state) {
final resolver = TextInputThemeResolver(
customStyleFn: (context, extensionValue, {extra}) {
TextInputStyle? textInputStyle;
switch (extra?.controlState) {
case ControlState.focused:
textInputStyle = focusedStyle;
break;
case ControlState.disabled:
textInputStyle = disableStyle;
break;
case ControlState.normal:
textInputStyle = normalStyle;
break;
case ControlState.hovered:
break;
case ControlState.tapped:
break;
case null:
break;
}
TextInputStyle? style;
switch (extra?.statusState) {
case StatusState.error:
style = errorStyle;
break;
case StatusState.initial:
break;
case StatusState.success:
break;
case StatusState.loading:
break;
case null:
break;
}
return TextInputStyle.merge(
extensionValue,
TextInputStyle.merge(textInputStyle, style),
);
},
);
return resolver.negotiate(context, extra: state);
}
bool _wrapperExpanded(TextInputState state) {
final fn = focusNode ?? _focusNode;
final tec = controller ?? _controller;
if (fn.hasFocus && label != null) {
return true;
} else if (tec.value.text.isNotEmpty && label != null) {
return true;
} else if (state.statusState == StatusState.error &&
(state.statusMessage?.isNotEmpty ?? false)) {
return true;
}
return false;
}
@override
Widget onBuild(BuildContext context, TextInputState state) {
final style = _resolve(context, state);
return Focus(
onFocusChange: (hasFocus) {
if (hasFocus) {
bloc(context).onFocus();
} else {
bloc(context).onUnfocus();
}
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 600),
decoration: BoxDecoration(
boxShadow: style.boxShadow != null ? [style.boxShadow!] : null,
gradient: style.backgroundColors?.isGradient ?? false
? LinearGradient(colors: style.backgroundColors!.colors)
: null,
color: style.backgroundColors?.isColor ?? false
? style.backgroundColors?.color
: null,
borderRadius: style.radius ?? BorderRadius.circular(4),
border: (style.borderColors?.isGradient ?? false) ||
(style.borderColors?.isColor ?? false)
? Border.all(
width: 1.5,
color: (style.borderColors?.isGradient ?? false)
? style.borderColors!.colors.first
: (style.borderColors?.isColor ?? false)
? style.borderColors!.color
: Colors.transparent,
)
: null,
),
child: TextInputWrapper(
expand: expand ?? true,
expanded: _wrapperExpanded(state),
child: TextField(
onTap: onTap,
onChanged: (value) {
onChanged?.call(value);
if (validator?.call(value) ?? false) {
bloc(context).onInvalid(onError?.call(value));
} else {
bloc(context).onSuccess();
}
},
onTapOutside: onTapOutside,
controller: controller ?? _controller,
focusNode: focusNode ?? _focusNode,
textAlignVertical: textAlignVertical ?? TextAlignVertical.top,
style: style.inputStyle ?? this.style,
decoration: InputDecoration(
focusedErrorBorder: _notOutilinedBorder,
focusedBorder: _notOutilinedBorder,
errorBorder: _notOutilinedBorder,
disabledBorder: _notOutilinedBorder,
enabledBorder: _notOutilinedBorder,
border: _notOutilinedBorder,
isDense: true,
iconColor: style.iconColor,
alignLabelWithHint: true,
label: (state.statusState == StatusState.error &&
(state.statusMessage?.isNotEmpty ?? false)) ||
label != null
? LabelWidget(
focusNode: focusNode ?? _focusNode,
label: (state.statusState == StatusState.error &&
(state.statusMessage?.isNotEmpty ?? false))
? state.statusMessage?.wrap()
: label,
labelStyle: style.labelStyle,
)
: null,
hintText: hint?.text,
hintStyle: hint?.style,
prefixIcon: prefixIcon,
prefixText: prefixText?.text,
prefixStyle: prefixText?.style,
prefixIconColor: style.prefixIconColor,
suffixIcon: suffixIcon,
suffixText: suffixText?.text,
suffixStyle: suffixText?.style,
suffixIconColor: style.suffixIconColor,
enabled: state.controlState != ControlState.disabled,
),
keyboardType: keyboardType,
smartDashesType: smartDashesType,
smartQuotesType: smartQuotesType,
enableInteractiveSelection: enableInteractiveSelection,
textInputAction: textInputAction,
textCapitalization: textCapitalization ?? TextCapitalization.none,
strutStyle: strutStyle,
textAlign: textAlign ?? TextAlign.start,
textDirection: textDirection,
readOnly: readOnly ?? false,
showCursor: showCursor,
autofocus: autofocus ?? false,
obscuringCharacter: obscuringCharacter ?? '*',
obscureText: obscureText ?? false,
autocorrect: autocorrect ?? true,
enableSuggestions: enableSuggestions ?? true,
maxLines: maxLines ?? 1,
minLines: minLines,
expands: expands ?? false,
maxLength: maxLength,
maxLengthEnforcement: maxLengthEnforcement,
onEditingComplete: onEditingComplete,
onSubmitted: onSubmitted,
onAppPrivateCommand: onAppPrivateCommand,
inputFormatters: inputFormatters,
enabled: state.controlState != ControlState.disabled,
cursorWidth: cursorWidth ?? 2.0,
cursorHeight: cursorHeight,
cursorRadius: cursorRadius,
cursorColor: cursorColor,
selectionHeightStyle: selectionHeightStyle ?? BoxHeightStyle.tight,
selectionWidthStyle: selectionWidthStyle ?? BoxWidthStyle.tight,
keyboardAppearance: keyboardAppearance,
scrollPadding: scrollPadding ?? const EdgeInsets.all(20),
dragStartBehavior: dragStartBehavior ?? DragStartBehavior.start,
selectionControls: selectionControls,
mouseCursor: mouseCursor,
scrollController: scrollController,
scrollPhysics: scrollPhysics,
autofillHints: autofillHints,
clipBehavior: clipBehavior ?? Clip.hardEdge,
restorationId: restorationId,
scribbleEnabled: scribbleEnabled ?? true,
enableIMEPersonalizedLearning:
enableIMEPersonalizedLearning ?? true,
contextMenuBuilder: contextMenuBuilder,
spellCheckConfiguration: spellCheckConfiguration,
magnifierConfiguration: magnifierConfiguration,
),
),
),
);
}
}

View File

@ -0,0 +1,172 @@
// 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/components/text_inputs/cubit/text_input_cubit.dart';
import 'package:wyatt_ui_kit/src/core/core.dart';
import 'package:wyatt_ui_kit/src/domain/text_input_theme_extension.dart';
class TextInputThemeResolver extends ThemeResolver<TextInputStyle,
TextInputThemeExtension, TextInputState> {
const TextInputThemeResolver({
required this.customStyleFn,
});
@override
final TextInputStyle? Function(
BuildContext context,
TextInputStyle extensionValue, {
TextInputState? extra,
}) customStyleFn;
@override
TextInputStyle computeDefaultValue(
BuildContext context, {
TextInputState? extra,
}) {
TextStyle? labelStyle = context.textTheme.labelLarge
?.copyWith(color: Theme.of(context).unselectedWidgetColor);
TextStyle? hintStyle = context.textTheme.labelLarge;
TextStyle? prefixStyle = context.textTheme.bodyMedium;
TextStyle? suffixStyle = context.textTheme.bodyMedium;
TextStyle? inputStyle = context.textTheme.bodyMedium;
Color? iconColor = context.colorScheme.inversePrimary;
Color? prefixIconColor = Theme.of(context).unselectedWidgetColor;
Color? suffixIconColor = Theme.of(context).unselectedWidgetColor;
MultiColor? borderColors =
MultiColor.single(Theme.of(context).unselectedWidgetColor);
MultiColor? backgroundColors;
BoxShadow? boxShadow;
final BorderRadiusGeometry radius = BorderRadius.circular(4);
switch (extra?.controlState) {
case ControlState.disabled:
labelStyle =
labelStyle?.copyWith(color: Theme.of(context).disabledColor);
hintStyle = hintStyle?.copyWith(color: Theme.of(context).disabledColor);
prefixStyle =
prefixStyle?.copyWith(color: Theme.of(context).disabledColor);
suffixStyle =
suffixStyle?.copyWith(color: Theme.of(context).disabledColor);
inputStyle =
inputStyle?.copyWith(color: Theme.of(context).disabledColor);
borderColors = MultiColor.single(Theme.of(context).disabledColor);
prefixIconColor = Theme.of(context).disabledColor;
suffixIconColor = Theme.of(context).disabledColor;
break;
case ControlState.focused:
prefixIconColor = context.colorScheme.primary;
suffixIconColor = context.colorScheme.primary;
iconColor = context.colorScheme.primary;
borderColors = MultiColor.single(context.colorScheme.primary);
labelStyle = labelStyle?.copyWith(color: context.colorScheme.primary);
break;
case ControlState.hovered:
break;
case ControlState.tapped:
break;
case ControlState.normal:
break;
case null:
break;
}
switch (extra?.statusState) {
case StatusState.error:
labelStyle = context.textTheme.labelLarge
?.copyWith(color: context.colorScheme.error);
borderColors = MultiColor.single(context.colorScheme.error);
break;
case StatusState.initial:
break;
case StatusState.success:
break;
case StatusState.loading:
break;
case null:
break;
}
return TextInputStyle(
labelStyle: labelStyle,
hintStyle: hintStyle,
iconColor: iconColor,
prefixIconColor: prefixIconColor,
prefixStyle: prefixStyle,
suffixStyle: suffixStyle,
suffixIconColor: suffixIconColor,
backgroundColors: backgroundColors,
borderColors: borderColors,
boxShadow: boxShadow,
radius: radius,
inputStyle: inputStyle,
);
}
@override
TextInputStyle? computeExtensionValueFn(
BuildContext context,
TextInputStyle defaultValue,
TextInputThemeExtension themeExtension, {
TextInputState? extra,
}) {
TextInputStyle? textInputStyle;
switch (extra?.controlState) {
case ControlState.focused:
textInputStyle = themeExtension.focusedStyle;
break;
case ControlState.disabled:
textInputStyle = themeExtension.disableStyle;
break;
case ControlState.normal:
textInputStyle = themeExtension.normalStyle;
break;
case ControlState.hovered:
break;
case ControlState.tapped:
break;
case null:
break;
}
TextInputStyle? style;
switch (extra?.statusState) {
case StatusState.error:
style = themeExtension.errorStyle;
break;
case StatusState.initial:
break;
case StatusState.success:
break;
case StatusState.loading:
break;
case null:
break;
}
return TextInputStyle.merge(
defaultValue,
TextInputStyle.merge(textInputStyle, style),
);
}
}

View File

@ -0,0 +1,37 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// super 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.
//
// super 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 super program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
class LabelWidget extends StatelessWidget {
const LabelWidget({
required this.label,
required this.focusNode,
required this.labelStyle,
super.key,
});
final TextWrapper? label;
final FocusNode focusNode;
final TextStyle? labelStyle;
@override
Widget build(BuildContext context) => Text(
label?.text ?? '',
style: labelStyle,
);
}

View File

@ -0,0 +1,60 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// super 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.
//
// super 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 super program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
const _defaultPadding = 7.5;
const _paddingAnimationDuration = Duration(milliseconds: 200);
class TextInputWrapper extends StatelessWidget {
const TextInputWrapper({
required this.expand,
required this.expanded,
required this.child,
super.key,
});
final bool expand;
final bool expanded;
final Widget child;
double _top() {
if (expanded) {
return 2 * _defaultPadding;
} else if (!expand) {
return _defaultPadding;
}
return 0;
}
double _bottom() {
if (expanded) {
return 0;
} else if (!expand) {
return _defaultPadding;
}
return 0;
}
@override
Widget build(BuildContext context) => AnimatedPadding(
duration: _paddingAnimationDuration,
padding: EdgeInsets.only(
top: _top(),
bottom: _bottom(),
),
child: child,
);
}

View File

@ -21,4 +21,6 @@ extension BuildContextThemeExtension on BuildContext {
TextTheme get textTheme => Theme.of(this).textTheme;
ColorScheme get colorScheme => Theme.of(this).colorScheme;
ButtonThemeData get buttonTheme => Theme.of(this).buttonTheme;
InputDecorationTheme get inputDecorationTheme =>
Theme.of(this).inputDecorationTheme;
}

View File

@ -0,0 +1,33 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// super 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.
//
// super 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 super program. If not, see <https://www.gnu.org/licenses/>.
class ThemeHelper {
static T? getThemeElement<P, T>(
List<P?>? styles, {
required T? Function(P?)? transform,
required T? defaultValue,
bool? Function(P?)? valueValidator,
}) {
if (styles?.isNotEmpty ?? false) {
for (final element in styles!) {
if (valueValidator?.call(element) ?? false) {
return transform?.call(element);
}
}
}
return defaultValue;
}
}

View File

@ -14,5 +14,6 @@
// 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 'button_theme_extension/button_theme_extension.dart';
export 'card_theme_extension.dart';
export './button_theme_extension/button_theme_extension.dart';
export './card_theme_extension.dart';
export 'text_input_theme_extension.dart';

View File

@ -0,0 +1,33 @@
// 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';
abstract class TextInputThemeExtension
extends ThemeExtension<TextInputThemeExtension> {
const TextInputThemeExtension({
this.normalStyle,
this.focusedStyle,
this.errorStyle,
this.disableStyle,
});
final TextInputStyle? normalStyle;
final TextInputStyle? focusedStyle;
final TextInputStyle? errorStyle;
final TextInputStyle? disableStyle;
}