ui_kit/feat/button-components #134

Merged
hugo merged 35 commits from ui_kit/feat/button-components into master 2023-02-16 08:58:03 +00:00
114 changed files with 5734 additions and 182 deletions

View File

@ -1 +1 @@
{"bricks":{"wyatt_clean_code":{"git":{"url":"ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-bricks.git","path":"bricks/wyatt_clean_code","ref":"5009f1ef21d8531b773298c0fc08704d8f69afd1"}},"wyatt_feature_brick":{"git":{"url":"ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-bricks.git","path":"bricks/wyatt_feature_brick","ref":"5009f1ef21d8531b773298c0fc08704d8f69afd1"}},"wyatt_package_template":{"git":{"url":"ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-bricks.git","path":"bricks/wyatt_package_template","ref":"5009f1ef21d8531b773298c0fc08704d8f69afd1"}}}}
{"bricks":{"wyatt_component_template":{"git":{"url":"ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-bricks.git","path":"bricks/wyatt_component_template","ref":"7cea909470ce75b91840f479649b93f953ded596"}}}}

View File

@ -1,13 +1,25 @@
# 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/>.
bricks:
wyatt_clean_code:
git:
url: "ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-bricks.git"
path: bricks/wyatt_clean_code
wyatt_feature_brick:
git:
url: "ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-bricks.git"
path: bricks/wyatt_feature_brick
wyatt_package_template:
git:
url: "ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-bricks.git"
path: bricks/wyatt_package_template
path: bricks/wyatt_package_template
wyatt_component_template:
git:
url: "ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-bricks.git"
path: bricks/wyatt_component_template

View File

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

View File

@ -0,0 +1,38 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
enum ControlState {
/// When the control is disabled and un-clickable
disabled,
/// Default state of a control
normal,
/// When the mouse cursor is hover the control
hovered,
/// When the control is clicked
tapped,
/// When the control is focused (like pressing tab)
focused;
bool isDisabled() => this == ControlState.disabled;
bool isEnabled() => this != ControlState.disabled;
bool isHovered() => this == ControlState.hovered;
bool isTapped() => this == ControlState.tapped;
bool isFocused() => this == ControlState.focused;
}

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 'package:flutter/widgets.dart';
class MultiColor {
const MultiColor(this._colors) : _color = null;
const MultiColor.single(this._color) : _colors = null;
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.',
);
}
List<Color> get colors => _colors ?? [];
bool get isGradient =>
(_colors?.isNotEmpty ?? false) && (_colors?.length ?? 0) > 1;
static MultiColor? lerp(MultiColor? a, MultiColor? b, double t) {
if (a == null && b == null) {
return null;
}
if (b == null) {
return a;
}
return b;
}
@override
String toString() => 'MultiColor(_colors: $_colors, _color: $_color)';
}

View File

@ -0,0 +1,88 @@
// 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';
/// {@template theme_resolver}
/// In charge of theme negotiation and merge.
///
/// When you build a component `Component({double? radius})`.
/// You have several possibilities:
/// 1) Pass the "radius" into the constructor, `Component(radius: 12)`.
/// 2) Set up a theme extension `ComponentThemeExtension(radius: 15)`.
/// 3) Let `wyatt_ui_kit` "negotiate" and try to find a suitable style in the
/// flutter theme.
///
/// If this negotiation phase fails, then:
/// - If the value is mandatory: a hardcoded value in "wyatt_ui_kit" is chosen.
/// - If not, the style is simply not applied.
/// {@endtemplate}
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;
/// Compute default value from Flutter Theme or with hardcoded values.
S computeDefaultValue(BuildContext context, {E? extra});
/// Compute values from the extension if found
S? computeExtensionValue(
BuildContext context,
S defaultValue, {
E? extra,
}) {
final themeExtension = findExtension(context);
if (themeExtension != null) {
return computeExtensionValueFn(
context,
defaultValue,
themeExtension,
extra: extra,
);
}
return defaultValue;
}
/// Compute custom value
S? computeCustomValue(
BuildContext context,
S previousPhaseValue, {
E? extra,
}) {
final customStyle = customStyleFn(context, 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;
return style;
}
}

View File

@ -0,0 +1,19 @@
// 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 'multi_color.dart';
export 'text_wrapper.dart';
export 'theme_resolver.dart';

View File

@ -0,0 +1,59 @@
// 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:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
abstract class ButtonComponent extends Component {
const ButtonComponent({
this.disabledStyle,
this.normalStyle,
this.hoveredStyle,
this.focusedStyle,
this.tappedStyle,
this.selectedStyle,
this.invalidStyle,
this.onPressed,
this.themeResolver,
super.key,
});
/// Style of this button in disabled state
final ButtonStyle<dynamic>? disabledStyle;
/// Style of this button in normal state
final ButtonStyle<dynamic>? normalStyle;
/// Style of this button in hovered state
final ButtonStyle<dynamic>? hoveredStyle;
/// Style of this button in focused state
final ButtonStyle<dynamic>? focusedStyle;
/// Style of this button in tapped state
final ButtonStyle<dynamic>? tappedStyle;
/// Style of this button in selected state
final ButtonStyle<dynamic>? selectedStyle;
/// Style of this button in invalid state
final ButtonStyle<dynamic>? invalidStyle;
/// Callback on button press
final void Function(ControlState state)? onPressed;
/// Theme Resolver for this component
final ThemeResolver<dynamic, dynamic, dynamic>? themeResolver;
}

View File

@ -0,0 +1,71 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/widgets.dart';
import 'package:wyatt_ui_components/src/core/utils/multi_color.dart';
abstract class ButtonStyle<T> {
const ButtonStyle({
this.radius,
this.padding,
this.foregroundColors,
this.backgroundColors,
this.borderColors,
this.stroke,
this.shadow,
});
/// Button radius
///
/// Default to `BorderRadius.all(Radius.circular(4.0))`
final BorderRadiusGeometry? radius;
/// Padding and gaps of this button
///
/// Default to `ButtonTheme.padding`
final EdgeInsetsGeometry? padding;
/// Button foreground gradient colors (from left to right)
///
/// Default to `Theme.colorScheme.onPrimary`
final MultiColor? foregroundColors;
/// Button background gradient colors (from left to right)
///
/// Default to `Theme.colorScheme.primary`
final MultiColor? backgroundColors;
/// Border colors (from left to right).
///
/// Default to `null`
final MultiColor? borderColors;
/// Stroke of the border
///
/// Default to `null`
final double? stroke;
/// Drop shadow
///
/// Default to `null`
final BoxShadow? shadow;
@override
String toString() =>
'ButtonStyle(radius: $radius, padding: $padding, foregroundColors: '
'$foregroundColors, backgroundColors: $backgroundColors, borderColors: '
'$borderColors, stroke: $stroke, shadow: $shadow)';
}

View File

@ -0,0 +1,26 @@
// 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 './button_component.dart';
export './button_style.dart';
export './file_selection_button_component.dart';
export './file_selection_button_style.dart';
export './flat_button_component.dart';
export './flat_button_style.dart';
export './simple_icon_button_component.dart';
export './simple_icon_button_style.dart';
export './symbol_button_component.dart';
export './symbol_button_style.dart';

View File

@ -0,0 +1,70 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/widgets.dart';
import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
part 'file_selection_button_component.g.dart';
@ComponentProxyExtension()
abstract class FileSelectionButtonComponent extends ButtonComponent
with CopyWithMixin<$FileSelectionButtonComponentCWProxy> {
const FileSelectionButtonComponent({
this.mainAxisSize = MainAxisSize.min,
this.leading,
this.title,
this.subTitle,
super.disabledStyle,
super.normalStyle,
super.hoveredStyle,
super.focusedStyle,
super.tappedStyle,
super.selectedStyle,
super.invalidStyle,
super.onPressed,
super.themeResolver,
super.key,
});
@override
FileSelectionButtonStyle? get disabledStyle;
@override
FileSelectionButtonStyle? get normalStyle;
@override
FileSelectionButtonStyle? get hoveredStyle;
@override
FileSelectionButtonStyle? get focusedStyle;
@override
FileSelectionButtonStyle? get tappedStyle;
// When a file is selected
@override
FileSelectionButtonStyle? get selectedStyle;
// When the input file is invalid (too large, not supported format... etc)
@override
FileSelectionButtonStyle? get invalidStyle;
final MainAxisSize? mainAxisSize;
final Widget? leading;
final TextWrapper? title;
final TextWrapper? subTitle;
}

View File

@ -0,0 +1,41 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'file_selection_button_component.dart';
// **************************************************************************
// ComponentProxyGenerator
// **************************************************************************
abstract class $FileSelectionButtonComponentCWProxy {
FileSelectionButtonComponent mainAxisSize(MainAxisSize? mainAxisSize);
FileSelectionButtonComponent leading(Widget? leading);
FileSelectionButtonComponent title(TextWrapper? title);
FileSelectionButtonComponent subTitle(TextWrapper? subTitle);
FileSelectionButtonComponent disabledStyle(
ButtonStyle<dynamic>? disabledStyle);
FileSelectionButtonComponent normalStyle(ButtonStyle<dynamic>? normalStyle);
FileSelectionButtonComponent hoveredStyle(ButtonStyle<dynamic>? hoveredStyle);
FileSelectionButtonComponent focusedStyle(ButtonStyle<dynamic>? focusedStyle);
FileSelectionButtonComponent tappedStyle(ButtonStyle<dynamic>? tappedStyle);
FileSelectionButtonComponent selectedStyle(
ButtonStyle<dynamic>? selectedStyle);
FileSelectionButtonComponent invalidStyle(ButtonStyle<dynamic>? invalidStyle);
FileSelectionButtonComponent onPressed(
void Function(ControlState)? onPressed);
FileSelectionButtonComponent key(Key? key);
FileSelectionButtonComponent call({
MainAxisSize? mainAxisSize,
Widget? leading,
TextWrapper? title,
TextWrapper? subTitle,
ButtonStyle<dynamic>? disabledStyle,
ButtonStyle<dynamic>? normalStyle,
ButtonStyle<dynamic>? hoveredStyle,
ButtonStyle<dynamic>? focusedStyle,
ButtonStyle<dynamic>? tappedStyle,
ButtonStyle<dynamic>? selectedStyle,
ButtonStyle<dynamic>? invalidStyle,
void Function(ControlState)? onPressed,
Key? key,
});
}

View File

@ -0,0 +1,84 @@
// 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:copy_with_extension/copy_with_extension.dart';
import 'package:flutter/widgets.dart';
import 'package:wyatt_ui_components/src/core/utils/multi_color.dart';
import 'package:wyatt_ui_components/src/domain/entities/buttons/button_style.dart';
part 'file_selection_button_style.g.dart';
@CopyWith()
class FileSelectionButtonStyle extends ButtonStyle<FileSelectionButtonStyle> {
const FileSelectionButtonStyle({
this.title,
this.subTitle,
super.radius,
super.padding,
super.foregroundColors,
super.backgroundColors,
super.borderColors,
super.stroke,
super.shadow,
});
/// Used for interpolation.
static FileSelectionButtonStyle? lerp(
FileSelectionButtonStyle? a,
FileSelectionButtonStyle? b,
double t,
) {
if (a == null || b == null) {
return null;
}
// b.copyWith to return b attributes even if they are not lerped
return b.copyWith(
title: TextStyle.lerp(a.title, b.title, t),
subTitle: TextStyle.lerp(a.title, b.title, t),
foregroundColors: MultiColor.lerp(
a.foregroundColors,
b.foregroundColors,
t,
),
backgroundColors: MultiColor.lerp(
a.backgroundColors,
b.backgroundColors,
t,
),
borderColors: MultiColor.lerp(
a.borderColors,
b.borderColors,
t,
),
radius: BorderRadiusGeometry.lerp(a.radius, b.radius, t),
padding: EdgeInsetsGeometry.lerp(a.padding, b.padding, t),
stroke: lerpDouble(a.stroke, b.stroke, t),
shadow: BoxShadow.lerp(a.shadow, b.shadow, t),
);
}
/// Title text style
///
/// Default to `TextTheme.labelLarge`
final TextStyle? title;
/// Sub title text style
///
/// Default to `TextTheme.labelSmall`
final TextStyle? subTitle;
}

View File

@ -0,0 +1,152 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'file_selection_button_style.dart';
// **************************************************************************
// CopyWithGenerator
// **************************************************************************
abstract class _$FileSelectionButtonStyleCWProxy {
FileSelectionButtonStyle title(TextStyle? title);
FileSelectionButtonStyle subTitle(TextStyle? subTitle);
FileSelectionButtonStyle radius(BorderRadiusGeometry? radius);
FileSelectionButtonStyle padding(EdgeInsetsGeometry? padding);
FileSelectionButtonStyle foregroundColors(MultiColor? foregroundColors);
FileSelectionButtonStyle backgroundColors(MultiColor? backgroundColors);
FileSelectionButtonStyle borderColors(MultiColor? borderColors);
FileSelectionButtonStyle stroke(double? stroke);
FileSelectionButtonStyle shadow(BoxShadow? shadow);
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `FileSelectionButtonStyle(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
///
/// Usage
/// ```dart
/// FileSelectionButtonStyle(...).copyWith(id: 12, name: "My name")
/// ````
FileSelectionButtonStyle call({
TextStyle? title,
TextStyle? subTitle,
BorderRadiusGeometry? radius,
EdgeInsetsGeometry? padding,
MultiColor? foregroundColors,
MultiColor? backgroundColors,
MultiColor? borderColors,
double? stroke,
BoxShadow? shadow,
});
}
/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfFileSelectionButtonStyle.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfFileSelectionButtonStyle.copyWith.fieldName(...)`
class _$FileSelectionButtonStyleCWProxyImpl
implements _$FileSelectionButtonStyleCWProxy {
const _$FileSelectionButtonStyleCWProxyImpl(this._value);
final FileSelectionButtonStyle _value;
@override
FileSelectionButtonStyle title(TextStyle? title) => this(title: title);
@override
FileSelectionButtonStyle subTitle(TextStyle? subTitle) =>
this(subTitle: subTitle);
@override
FileSelectionButtonStyle radius(BorderRadiusGeometry? radius) =>
this(radius: radius);
@override
FileSelectionButtonStyle padding(EdgeInsetsGeometry? padding) =>
this(padding: padding);
@override
FileSelectionButtonStyle foregroundColors(MultiColor? foregroundColors) =>
this(foregroundColors: foregroundColors);
@override
FileSelectionButtonStyle backgroundColors(MultiColor? backgroundColors) =>
this(backgroundColors: backgroundColors);
@override
FileSelectionButtonStyle borderColors(MultiColor? borderColors) =>
this(borderColors: borderColors);
@override
FileSelectionButtonStyle stroke(double? stroke) => this(stroke: stroke);
@override
FileSelectionButtonStyle shadow(BoxShadow? shadow) => this(shadow: shadow);
@override
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `FileSelectionButtonStyle(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
///
/// Usage
/// ```dart
/// FileSelectionButtonStyle(...).copyWith(id: 12, name: "My name")
/// ````
FileSelectionButtonStyle call({
Object? title = const $CopyWithPlaceholder(),
Object? subTitle = const $CopyWithPlaceholder(),
Object? radius = const $CopyWithPlaceholder(),
Object? padding = const $CopyWithPlaceholder(),
Object? foregroundColors = const $CopyWithPlaceholder(),
Object? backgroundColors = const $CopyWithPlaceholder(),
Object? borderColors = const $CopyWithPlaceholder(),
Object? stroke = const $CopyWithPlaceholder(),
Object? shadow = const $CopyWithPlaceholder(),
}) {
return FileSelectionButtonStyle(
title: title == const $CopyWithPlaceholder()
? _value.title
// ignore: cast_nullable_to_non_nullable
: title as TextStyle?,
subTitle: subTitle == const $CopyWithPlaceholder()
? _value.subTitle
// ignore: cast_nullable_to_non_nullable
: subTitle as TextStyle?,
radius: radius == const $CopyWithPlaceholder()
? _value.radius
// ignore: cast_nullable_to_non_nullable
: radius as BorderRadiusGeometry?,
padding: padding == const $CopyWithPlaceholder()
? _value.padding
// ignore: cast_nullable_to_non_nullable
: padding as EdgeInsetsGeometry?,
foregroundColors: foregroundColors == const $CopyWithPlaceholder()
? _value.foregroundColors
// ignore: cast_nullable_to_non_nullable
: foregroundColors as MultiColor?,
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?,
stroke: stroke == const $CopyWithPlaceholder()
? _value.stroke
// ignore: cast_nullable_to_non_nullable
: stroke as double?,
shadow: shadow == const $CopyWithPlaceholder()
? _value.shadow
// ignore: cast_nullable_to_non_nullable
: shadow as BoxShadow?,
);
}
}
extension $FileSelectionButtonStyleCopyWith on FileSelectionButtonStyle {
/// Returns a callable class that can be used as follows: `instanceOfFileSelectionButtonStyle.copyWith(...)` or like so:`instanceOfFileSelectionButtonStyle.copyWith.fieldName(...)`.
// ignore: library_private_types_in_public_api
_$FileSelectionButtonStyleCWProxy get copyWith =>
_$FileSelectionButtonStyleCWProxyImpl(this);
}

View File

@ -0,0 +1,60 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/widgets.dart';
import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
part 'flat_button_component.g.dart';
@ComponentProxyExtension()
abstract class FlatButtonComponent extends ButtonComponent
with CopyWithMixin<$FlatButtonComponentCWProxy> {
const FlatButtonComponent({
this.mainAxisSize,
this.prefix,
this.suffix,
this.label,
super.disabledStyle,
super.normalStyle,
super.hoveredStyle,
super.focusedStyle,
super.tappedStyle,
super.onPressed,
super.themeResolver,
super.key,
});
@override
FlatButtonStyle? get disabledStyle;
@override
FlatButtonStyle? get normalStyle;
@override
FlatButtonStyle? get hoveredStyle;
@override
FlatButtonStyle? get focusedStyle;
@override
FlatButtonStyle? get tappedStyle;
final MainAxisSize? mainAxisSize;
final Widget? prefix;
final Widget? suffix;
final TextWrapper? label;
}

View File

@ -0,0 +1,34 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'flat_button_component.dart';
// **************************************************************************
// ComponentProxyGenerator
// **************************************************************************
abstract class $FlatButtonComponentCWProxy {
FlatButtonComponent mainAxisSize(MainAxisSize? mainAxisSize);
FlatButtonComponent prefix(Widget? prefix);
FlatButtonComponent suffix(Widget? suffix);
FlatButtonComponent label(TextWrapper? label);
FlatButtonComponent disabledStyle(ButtonStyle<dynamic>? disabledStyle);
FlatButtonComponent normalStyle(ButtonStyle<dynamic>? normalStyle);
FlatButtonComponent hoveredStyle(ButtonStyle<dynamic>? hoveredStyle);
FlatButtonComponent focusedStyle(ButtonStyle<dynamic>? focusedStyle);
FlatButtonComponent tappedStyle(ButtonStyle<dynamic>? tappedStyle);
FlatButtonComponent onPressed(void Function(ControlState)? onPressed);
FlatButtonComponent key(Key? key);
FlatButtonComponent call({
MainAxisSize? mainAxisSize,
Widget? prefix,
Widget? suffix,
TextWrapper? label,
ButtonStyle<dynamic>? disabledStyle,
ButtonStyle<dynamic>? normalStyle,
ButtonStyle<dynamic>? hoveredStyle,
ButtonStyle<dynamic>? focusedStyle,
ButtonStyle<dynamic>? tappedStyle,
void Function(ControlState)? onPressed,
Key? key,
});
}

View File

@ -0,0 +1,81 @@
// 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:copy_with_extension/copy_with_extension.dart';
import 'package:flutter/widgets.dart';
import 'package:wyatt_ui_components/src/core/utils/multi_color.dart';
import 'package:wyatt_ui_components/src/domain/entities/buttons/button_style.dart';
part 'flat_button_style.g.dart';
@CopyWith()
class FlatButtonStyle extends ButtonStyle<FlatButtonStyle> {
const FlatButtonStyle({
this.label,
super.radius,
super.padding,
super.foregroundColors,
super.backgroundColors,
super.borderColors,
super.stroke,
super.shadow,
});
/// Used for interpolation.
static FlatButtonStyle? lerp(
FlatButtonStyle? a,
FlatButtonStyle? b,
double t,
) {
if (a == null || b == null) {
return null;
}
// b.copyWith to return b attributes even if they are not lerped
return b.copyWith(
label: TextStyle.lerp(a.label, b.label, t),
foregroundColors: MultiColor.lerp(
a.foregroundColors,
b.foregroundColors,
t,
),
backgroundColors: MultiColor.lerp(
a.backgroundColors,
b.backgroundColors,
t,
),
borderColors: MultiColor.lerp(
a.borderColors,
b.borderColors,
t,
),
radius: BorderRadiusGeometry.lerp(a.radius, b.radius, t),
padding: EdgeInsetsGeometry.lerp(a.padding, b.padding, t),
stroke: lerpDouble(a.stroke, b.stroke, t),
shadow: BoxShadow.lerp(a.shadow, b.shadow, t),
);
}
/// Label text style
///
/// Default to `TextTheme.labelLarge`
final TextStyle? label;
@override
String toString() =>
'FlatButtonStyle(label: $label), inherited: ${super.toString()}';
}

View File

@ -0,0 +1,137 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'flat_button_style.dart';
// **************************************************************************
// CopyWithGenerator
// **************************************************************************
abstract class _$FlatButtonStyleCWProxy {
FlatButtonStyle label(TextStyle? label);
FlatButtonStyle radius(BorderRadiusGeometry? radius);
FlatButtonStyle padding(EdgeInsetsGeometry? padding);
FlatButtonStyle foregroundColors(MultiColor? foregroundColors);
FlatButtonStyle backgroundColors(MultiColor? backgroundColors);
FlatButtonStyle borderColors(MultiColor? borderColors);
FlatButtonStyle stroke(double? stroke);
FlatButtonStyle shadow(BoxShadow? shadow);
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `FlatButtonStyle(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
///
/// Usage
/// ```dart
/// FlatButtonStyle(...).copyWith(id: 12, name: "My name")
/// ````
FlatButtonStyle call({
TextStyle? label,
BorderRadiusGeometry? radius,
EdgeInsetsGeometry? padding,
MultiColor? foregroundColors,
MultiColor? backgroundColors,
MultiColor? borderColors,
double? stroke,
BoxShadow? shadow,
});
}
/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfFlatButtonStyle.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfFlatButtonStyle.copyWith.fieldName(...)`
class _$FlatButtonStyleCWProxyImpl implements _$FlatButtonStyleCWProxy {
const _$FlatButtonStyleCWProxyImpl(this._value);
final FlatButtonStyle _value;
@override
FlatButtonStyle label(TextStyle? label) => this(label: label);
@override
FlatButtonStyle radius(BorderRadiusGeometry? radius) => this(radius: radius);
@override
FlatButtonStyle padding(EdgeInsetsGeometry? padding) =>
this(padding: padding);
@override
FlatButtonStyle foregroundColors(MultiColor? foregroundColors) =>
this(foregroundColors: foregroundColors);
@override
FlatButtonStyle backgroundColors(MultiColor? backgroundColors) =>
this(backgroundColors: backgroundColors);
@override
FlatButtonStyle borderColors(MultiColor? borderColors) =>
this(borderColors: borderColors);
@override
FlatButtonStyle stroke(double? stroke) => this(stroke: stroke);
@override
FlatButtonStyle shadow(BoxShadow? shadow) => this(shadow: shadow);
@override
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `FlatButtonStyle(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
///
/// Usage
/// ```dart
/// FlatButtonStyle(...).copyWith(id: 12, name: "My name")
/// ````
FlatButtonStyle call({
Object? label = const $CopyWithPlaceholder(),
Object? radius = const $CopyWithPlaceholder(),
Object? padding = const $CopyWithPlaceholder(),
Object? foregroundColors = const $CopyWithPlaceholder(),
Object? backgroundColors = const $CopyWithPlaceholder(),
Object? borderColors = const $CopyWithPlaceholder(),
Object? stroke = const $CopyWithPlaceholder(),
Object? shadow = const $CopyWithPlaceholder(),
}) {
return FlatButtonStyle(
label: label == const $CopyWithPlaceholder()
? _value.label
// ignore: cast_nullable_to_non_nullable
: label as TextStyle?,
radius: radius == const $CopyWithPlaceholder()
? _value.radius
// ignore: cast_nullable_to_non_nullable
: radius as BorderRadiusGeometry?,
padding: padding == const $CopyWithPlaceholder()
? _value.padding
// ignore: cast_nullable_to_non_nullable
: padding as EdgeInsetsGeometry?,
foregroundColors: foregroundColors == const $CopyWithPlaceholder()
? _value.foregroundColors
// ignore: cast_nullable_to_non_nullable
: foregroundColors as MultiColor?,
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?,
stroke: stroke == const $CopyWithPlaceholder()
? _value.stroke
// ignore: cast_nullable_to_non_nullable
: stroke as double?,
shadow: shadow == const $CopyWithPlaceholder()
? _value.shadow
// ignore: cast_nullable_to_non_nullable
: shadow as BoxShadow?,
);
}
}
extension $FlatButtonStyleCopyWith on FlatButtonStyle {
/// Returns a callable class that can be used as follows: `instanceOfFlatButtonStyle.copyWith(...)` or like so:`instanceOfFlatButtonStyle.copyWith.fieldName(...)`.
// ignore: library_private_types_in_public_api
_$FlatButtonStyleCWProxy get copyWith => _$FlatButtonStyleCWProxyImpl(this);
}

View File

@ -0,0 +1,54 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/widgets.dart';
import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
part 'simple_icon_button_component.g.dart';
@ComponentProxyExtension()
abstract class SimpleIconButtonComponent extends ButtonComponent
with CopyWithMixin<$SimpleIconButtonComponentCWProxy> {
const SimpleIconButtonComponent({
this.icon,
super.disabledStyle,
super.normalStyle,
super.hoveredStyle,
super.focusedStyle,
super.tappedStyle,
super.onPressed,
super.themeResolver,
super.key,
});
@override
SimpleIconButtonStyle? get disabledStyle;
@override
SimpleIconButtonStyle? get normalStyle;
@override
SimpleIconButtonStyle? get hoveredStyle;
@override
SimpleIconButtonStyle? get focusedStyle;
@override
SimpleIconButtonStyle? get tappedStyle;
final Icon? icon;
}

View File

@ -0,0 +1,28 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'simple_icon_button_component.dart';
// **************************************************************************
// ComponentProxyGenerator
// **************************************************************************
abstract class $SimpleIconButtonComponentCWProxy {
SimpleIconButtonComponent icon(Icon? icon);
SimpleIconButtonComponent disabledStyle(ButtonStyle<dynamic>? disabledStyle);
SimpleIconButtonComponent normalStyle(ButtonStyle<dynamic>? normalStyle);
SimpleIconButtonComponent hoveredStyle(ButtonStyle<dynamic>? hoveredStyle);
SimpleIconButtonComponent focusedStyle(ButtonStyle<dynamic>? focusedStyle);
SimpleIconButtonComponent tappedStyle(ButtonStyle<dynamic>? tappedStyle);
SimpleIconButtonComponent onPressed(void Function(ControlState)? onPressed);
SimpleIconButtonComponent key(Key? key);
SimpleIconButtonComponent call({
Icon? icon,
ButtonStyle<dynamic>? disabledStyle,
ButtonStyle<dynamic>? normalStyle,
ButtonStyle<dynamic>? hoveredStyle,
ButtonStyle<dynamic>? focusedStyle,
ButtonStyle<dynamic>? tappedStyle,
void Function(ControlState)? onPressed,
Key? key,
});
}

View File

@ -0,0 +1,77 @@
// 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:copy_with_extension/copy_with_extension.dart';
import 'package:flutter/widgets.dart';
import 'package:wyatt_ui_components/src/core/utils/multi_color.dart';
import 'package:wyatt_ui_components/src/domain/entities/buttons/button_style.dart';
part 'simple_icon_button_style.g.dart';
@CopyWith()
class SimpleIconButtonStyle extends ButtonStyle<SimpleIconButtonStyle> {
const SimpleIconButtonStyle({
this.dimension,
super.radius,
super.padding,
super.foregroundColors,
super.backgroundColors,
super.borderColors,
super.stroke,
super.shadow,
});
/// Used for interpolation.
static SimpleIconButtonStyle? lerp(
SimpleIconButtonStyle? a,
SimpleIconButtonStyle? b,
double t,
) {
if (a == null || b == null) {
return null;
}
// b.copyWith to return b attributes even if they are not lerped
return b.copyWith(
dimension: lerpDouble(a.dimension, b.dimension, t),
foregroundColors: MultiColor.lerp(
a.foregroundColors,
b.foregroundColors,
t,
),
backgroundColors: MultiColor.lerp(
a.backgroundColors,
b.backgroundColors,
t,
),
borderColors: MultiColor.lerp(
a.borderColors,
b.borderColors,
t,
),
radius: BorderRadiusGeometry.lerp(a.radius, b.radius, t),
padding: EdgeInsetsGeometry.lerp(a.padding, b.padding, t),
stroke: lerpDouble(a.stroke, b.stroke, t),
shadow: BoxShadow.lerp(a.shadow, b.shadow, t),
);
}
/// Dimension of this button (as a square)
///
/// Default to `context.buttonTheme.height`
final double? dimension;
}

View File

@ -0,0 +1,141 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'simple_icon_button_style.dart';
// **************************************************************************
// CopyWithGenerator
// **************************************************************************
abstract class _$SimpleIconButtonStyleCWProxy {
SimpleIconButtonStyle dimension(double? dimension);
SimpleIconButtonStyle radius(BorderRadiusGeometry? radius);
SimpleIconButtonStyle padding(EdgeInsetsGeometry? padding);
SimpleIconButtonStyle foregroundColors(MultiColor? foregroundColors);
SimpleIconButtonStyle backgroundColors(MultiColor? backgroundColors);
SimpleIconButtonStyle borderColors(MultiColor? borderColors);
SimpleIconButtonStyle stroke(double? stroke);
SimpleIconButtonStyle shadow(BoxShadow? shadow);
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `SimpleIconButtonStyle(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
///
/// Usage
/// ```dart
/// SimpleIconButtonStyle(...).copyWith(id: 12, name: "My name")
/// ````
SimpleIconButtonStyle call({
double? dimension,
BorderRadiusGeometry? radius,
EdgeInsetsGeometry? padding,
MultiColor? foregroundColors,
MultiColor? backgroundColors,
MultiColor? borderColors,
double? stroke,
BoxShadow? shadow,
});
}
/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfSimpleIconButtonStyle.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfSimpleIconButtonStyle.copyWith.fieldName(...)`
class _$SimpleIconButtonStyleCWProxyImpl
implements _$SimpleIconButtonStyleCWProxy {
const _$SimpleIconButtonStyleCWProxyImpl(this._value);
final SimpleIconButtonStyle _value;
@override
SimpleIconButtonStyle dimension(double? dimension) =>
this(dimension: dimension);
@override
SimpleIconButtonStyle radius(BorderRadiusGeometry? radius) =>
this(radius: radius);
@override
SimpleIconButtonStyle padding(EdgeInsetsGeometry? padding) =>
this(padding: padding);
@override
SimpleIconButtonStyle foregroundColors(MultiColor? foregroundColors) =>
this(foregroundColors: foregroundColors);
@override
SimpleIconButtonStyle backgroundColors(MultiColor? backgroundColors) =>
this(backgroundColors: backgroundColors);
@override
SimpleIconButtonStyle borderColors(MultiColor? borderColors) =>
this(borderColors: borderColors);
@override
SimpleIconButtonStyle stroke(double? stroke) => this(stroke: stroke);
@override
SimpleIconButtonStyle shadow(BoxShadow? shadow) => this(shadow: shadow);
@override
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `SimpleIconButtonStyle(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
///
/// Usage
/// ```dart
/// SimpleIconButtonStyle(...).copyWith(id: 12, name: "My name")
/// ````
SimpleIconButtonStyle call({
Object? dimension = const $CopyWithPlaceholder(),
Object? radius = const $CopyWithPlaceholder(),
Object? padding = const $CopyWithPlaceholder(),
Object? foregroundColors = const $CopyWithPlaceholder(),
Object? backgroundColors = const $CopyWithPlaceholder(),
Object? borderColors = const $CopyWithPlaceholder(),
Object? stroke = const $CopyWithPlaceholder(),
Object? shadow = const $CopyWithPlaceholder(),
}) {
return SimpleIconButtonStyle(
dimension: dimension == const $CopyWithPlaceholder()
? _value.dimension
// ignore: cast_nullable_to_non_nullable
: dimension as double?,
radius: radius == const $CopyWithPlaceholder()
? _value.radius
// ignore: cast_nullable_to_non_nullable
: radius as BorderRadiusGeometry?,
padding: padding == const $CopyWithPlaceholder()
? _value.padding
// ignore: cast_nullable_to_non_nullable
: padding as EdgeInsetsGeometry?,
foregroundColors: foregroundColors == const $CopyWithPlaceholder()
? _value.foregroundColors
// ignore: cast_nullable_to_non_nullable
: foregroundColors as MultiColor?,
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?,
stroke: stroke == const $CopyWithPlaceholder()
? _value.stroke
// ignore: cast_nullable_to_non_nullable
: stroke as double?,
shadow: shadow == const $CopyWithPlaceholder()
? _value.shadow
// ignore: cast_nullable_to_non_nullable
: shadow as BoxShadow?,
);
}
}
extension $SimpleIconButtonStyleCopyWith on SimpleIconButtonStyle {
/// Returns a callable class that can be used as follows: `instanceOfSimpleIconButtonStyle.copyWith(...)` or like so:`instanceOfSimpleIconButtonStyle.copyWith.fieldName(...)`.
// ignore: library_private_types_in_public_api
_$SimpleIconButtonStyleCWProxy get copyWith =>
_$SimpleIconButtonStyleCWProxyImpl(this);
}

View File

@ -0,0 +1,62 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/widgets.dart';
import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
part 'symbol_button_component.g.dart';
@ComponentProxyExtension()
abstract class SymbolButtonComponent extends ButtonComponent
with CopyWithMixin<$SymbolButtonComponentCWProxy> {
const SymbolButtonComponent({
this.mainAxisSize = MainAxisSize.min,
this.label,
this.icon,
super.disabledStyle,
super.normalStyle,
super.hoveredStyle,
super.focusedStyle,
super.tappedStyle,
super.selectedStyle,
super.onPressed,
super.themeResolver,
super.key,
});
@override
SymbolButtonStyle? get disabledStyle;
@override
SymbolButtonStyle? get normalStyle;
@override
SymbolButtonStyle? get hoveredStyle;
@override
SymbolButtonStyle? get focusedStyle;
@override
SymbolButtonStyle? get tappedStyle;
@override
SymbolButtonStyle? get selectedStyle;
final MainAxisSize? mainAxisSize;
final Widget? icon;
final TextWrapper? label;
}

View File

@ -0,0 +1,34 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'symbol_button_component.dart';
// **************************************************************************
// ComponentProxyGenerator
// **************************************************************************
abstract class $SymbolButtonComponentCWProxy {
SymbolButtonComponent mainAxisSize(MainAxisSize? mainAxisSize);
SymbolButtonComponent label(TextWrapper? label);
SymbolButtonComponent icon(Widget? icon);
SymbolButtonComponent disabledStyle(ButtonStyle<dynamic>? disabledStyle);
SymbolButtonComponent normalStyle(ButtonStyle<dynamic>? normalStyle);
SymbolButtonComponent hoveredStyle(ButtonStyle<dynamic>? hoveredStyle);
SymbolButtonComponent focusedStyle(ButtonStyle<dynamic>? focusedStyle);
SymbolButtonComponent tappedStyle(ButtonStyle<dynamic>? tappedStyle);
SymbolButtonComponent selectedStyle(ButtonStyle<dynamic>? selectedStyle);
SymbolButtonComponent onPressed(void Function(ControlState)? onPressed);
SymbolButtonComponent key(Key? key);
SymbolButtonComponent call({
MainAxisSize? mainAxisSize,
TextWrapper? label,
Widget? icon,
ButtonStyle<dynamic>? disabledStyle,
ButtonStyle<dynamic>? normalStyle,
ButtonStyle<dynamic>? hoveredStyle,
ButtonStyle<dynamic>? focusedStyle,
ButtonStyle<dynamic>? tappedStyle,
ButtonStyle<dynamic>? selectedStyle,
void Function(ControlState)? onPressed,
Key? key,
});
}

View File

@ -0,0 +1,84 @@
// 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:copy_with_extension/copy_with_extension.dart';
import 'package:flutter/widgets.dart';
import 'package:wyatt_ui_components/src/core/utils/multi_color.dart';
import 'package:wyatt_ui_components/src/domain/entities/buttons/button_style.dart';
part 'symbol_button_style.g.dart';
@CopyWith()
class SymbolButtonStyle extends ButtonStyle<SymbolButtonStyle> {
const SymbolButtonStyle({
this.label,
this.dimension,
super.radius,
super.padding,
super.foregroundColors,
super.backgroundColors,
super.borderColors,
super.stroke,
super.shadow,
});
/// Used for interpolation.
static SymbolButtonStyle? lerp(
SymbolButtonStyle? a,
SymbolButtonStyle? b,
double t,
) {
if (a == null || b == null) {
return null;
}
// b.copyWith to return b attributes even if they are not lerped
return b.copyWith(
label: TextStyle.lerp(a.label, b.label, t),
dimension: lerpDouble(a.dimension, b.dimension, t),
foregroundColors: MultiColor.lerp(
a.foregroundColors,
b.foregroundColors,
t,
),
backgroundColors: MultiColor.lerp(
a.backgroundColors,
b.backgroundColors,
t,
),
borderColors: MultiColor.lerp(
a.borderColors,
b.borderColors,
t,
),
radius: BorderRadiusGeometry.lerp(a.radius, b.radius, t),
padding: EdgeInsetsGeometry.lerp(a.padding, b.padding, t),
stroke: lerpDouble(a.stroke, b.stroke, t),
shadow: BoxShadow.lerp(a.shadow, b.shadow, t),
);
}
/// Label text style
///
/// Default to `TextTheme.labelLarge`
final TextStyle? label;
/// Dimension of this button (as a square)
///
/// Default to `context.buttonTheme.height`
final double? dimension;
}

View File

@ -0,0 +1,150 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'symbol_button_style.dart';
// **************************************************************************
// CopyWithGenerator
// **************************************************************************
abstract class _$SymbolButtonStyleCWProxy {
SymbolButtonStyle label(TextStyle? label);
SymbolButtonStyle dimension(double? dimension);
SymbolButtonStyle radius(BorderRadiusGeometry? radius);
SymbolButtonStyle padding(EdgeInsetsGeometry? padding);
SymbolButtonStyle foregroundColors(MultiColor? foregroundColors);
SymbolButtonStyle backgroundColors(MultiColor? backgroundColors);
SymbolButtonStyle borderColors(MultiColor? borderColors);
SymbolButtonStyle stroke(double? stroke);
SymbolButtonStyle shadow(BoxShadow? shadow);
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `SymbolButtonStyle(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
///
/// Usage
/// ```dart
/// SymbolButtonStyle(...).copyWith(id: 12, name: "My name")
/// ````
SymbolButtonStyle call({
TextStyle? label,
double? dimension,
BorderRadiusGeometry? radius,
EdgeInsetsGeometry? padding,
MultiColor? foregroundColors,
MultiColor? backgroundColors,
MultiColor? borderColors,
double? stroke,
BoxShadow? shadow,
});
}
/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfSymbolButtonStyle.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfSymbolButtonStyle.copyWith.fieldName(...)`
class _$SymbolButtonStyleCWProxyImpl implements _$SymbolButtonStyleCWProxy {
const _$SymbolButtonStyleCWProxyImpl(this._value);
final SymbolButtonStyle _value;
@override
SymbolButtonStyle label(TextStyle? label) => this(label: label);
@override
SymbolButtonStyle dimension(double? dimension) => this(dimension: dimension);
@override
SymbolButtonStyle radius(BorderRadiusGeometry? radius) =>
this(radius: radius);
@override
SymbolButtonStyle padding(EdgeInsetsGeometry? padding) =>
this(padding: padding);
@override
SymbolButtonStyle foregroundColors(MultiColor? foregroundColors) =>
this(foregroundColors: foregroundColors);
@override
SymbolButtonStyle backgroundColors(MultiColor? backgroundColors) =>
this(backgroundColors: backgroundColors);
@override
SymbolButtonStyle borderColors(MultiColor? borderColors) =>
this(borderColors: borderColors);
@override
SymbolButtonStyle stroke(double? stroke) => this(stroke: stroke);
@override
SymbolButtonStyle shadow(BoxShadow? shadow) => this(shadow: shadow);
@override
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `SymbolButtonStyle(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
///
/// Usage
/// ```dart
/// SymbolButtonStyle(...).copyWith(id: 12, name: "My name")
/// ````
SymbolButtonStyle call({
Object? label = const $CopyWithPlaceholder(),
Object? dimension = const $CopyWithPlaceholder(),
Object? radius = const $CopyWithPlaceholder(),
Object? padding = const $CopyWithPlaceholder(),
Object? foregroundColors = const $CopyWithPlaceholder(),
Object? backgroundColors = const $CopyWithPlaceholder(),
Object? borderColors = const $CopyWithPlaceholder(),
Object? stroke = const $CopyWithPlaceholder(),
Object? shadow = const $CopyWithPlaceholder(),
}) {
return SymbolButtonStyle(
label: label == const $CopyWithPlaceholder()
? _value.label
// ignore: cast_nullable_to_non_nullable
: label as TextStyle?,
dimension: dimension == const $CopyWithPlaceholder()
? _value.dimension
// ignore: cast_nullable_to_non_nullable
: dimension as double?,
radius: radius == const $CopyWithPlaceholder()
? _value.radius
// ignore: cast_nullable_to_non_nullable
: radius as BorderRadiusGeometry?,
padding: padding == const $CopyWithPlaceholder()
? _value.padding
// ignore: cast_nullable_to_non_nullable
: padding as EdgeInsetsGeometry?,
foregroundColors: foregroundColors == const $CopyWithPlaceholder()
? _value.foregroundColors
// ignore: cast_nullable_to_non_nullable
: foregroundColors as MultiColor?,
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?,
stroke: stroke == const $CopyWithPlaceholder()
? _value.stroke
// ignore: cast_nullable_to_non_nullable
: stroke as double?,
shadow: shadow == const $CopyWithPlaceholder()
? _value.shadow
// ignore: cast_nullable_to_non_nullable
: shadow as BoxShadow?,
);
}
}
extension $SymbolButtonStyleCopyWith on SymbolButtonStyle {
/// Returns a callable class that can be used as follows: `instanceOfSymbolButtonStyle.copyWith(...)` or like so:`instanceOfSymbolButtonStyle.copyWith.fieldName(...)`.
// ignore: library_private_types_in_public_api
_$SymbolButtonStyleCWProxy get copyWith =>
_$SymbolButtonStyleCWProxyImpl(this);
}

View File

@ -13,6 +13,8 @@ abstract class $SkillCardComponentCWProxy {
SkillCardComponent description(TextWrapper? description);
SkillCardComponent skills(List<TextWrapper>? skills);
SkillCardComponent leadingIcon(IconData? leadingIcon);
SkillCardComponent secondaryBackgroundColors(
Color? secondaryBackgroundColors);
SkillCardComponent radius(double? radius);
SkillCardComponent padding(double? padding);
SkillCardComponent borderColors(List<Color>? borderColors);
@ -21,8 +23,6 @@ abstract class $SkillCardComponentCWProxy {
SkillCardComponent maxSize(Size? maxSize);
SkillCardComponent shadow(BoxShadow? shadow);
SkillCardComponent background(Widget? background);
SkillCardComponent secondaryBackgroundColors(
Color? secondaryBackgroundColors);
SkillCardComponent key(Key? key);
SkillCardComponent call({
IconData? icon,
@ -31,6 +31,7 @@ abstract class $SkillCardComponentCWProxy {
TextWrapper? description,
List<TextWrapper>? skills,
IconData? leadingIcon,
Color? secondaryBackgroundColors,
double? radius,
double? padding,
List<Color>? borderColors,
@ -39,7 +40,6 @@ abstract class $SkillCardComponentCWProxy {
Size? maxSize,
BoxShadow? shadow,
Widget? background,
Color? secondaryBackgroundColors,
Key? key,
});
}

View File

@ -16,6 +16,7 @@
export './app_bar_component.dart';
export './bottom_navigation_bar_component.dart';
export './buttons/buttons.dart';
export './cards/cards.dart';
export './component.dart';
export './error_widget_component.dart';

View File

@ -9,25 +9,21 @@ environment:
sdk: ">=2.17.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
copy_with_extension: ^5.0.0
flutter: { sdk: flutter }
wyatt_component_copy_with_extension:
git:
url: ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-packages.git
path: packages/wyatt_component_copy_with_extension
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^2.3.3
copy_with_extension_gen: ^5.0.0
flutter_test: { sdk: flutter }
wyatt_analysis:
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
version: ^2.4.0
wyatt_component_copy_with_gen:
git:
url: ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-packages.git
path: packages/wyatt_component_copy_with_gen
wyatt_analysis:
git:
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
ref: wyatt_analysis-v2.4.0
path: packages/wyatt_analysis

View File

@ -25,6 +25,25 @@
UIKit and Design System used in Wyatt Studio.
## Theme negotiation
When building a component, most of its attributes can be 'null'.
The `build()` method then starts to negotiate the theme in the tree to obtain the most consistent style possible.
Explanation:
When you build a component `Button({double? radius})`.
You have several possibilities:
1) Pass the "radius" into the constructor, `Button(radius: 12)`.
2) Set up a theme extension `ButtonThemeExtension(radius: 15)`.
3) Let `wyatt_ui_kit` "negotiate" and try to find a suitable style in the flutter theme.
If this negotiation phase fails, then:
- If the value is mandatory: a hardcoded value in "wyatt_ui_kit" is chosen.
- If not, the style is simply not applied.
If, for example, you don't use option 1, then the radius will be 15. If you use neither option 1 nor option 2 then the radius will be 4 as this is the [official Material Design value](https://m2.material.io/design/shape/about-shape.html#shape-customization-tool).
## Features
TODO: List what your package can do. Maybe include images, gifs, or videos.

View File

@ -1,16 +1,9 @@
# example
# Wyatt UIKIt Example
A new Flutter project.
You can force the launch page. (For debug purposes).
## Getting Started
```shell
flutter run -d macos --dart-define PAGE=1 --dart-define THEME=1
```
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
> This will forces `Buttons` page with `Studio` theme

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 756 KiB

View File

@ -0,0 +1,54 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:wyatt_ui_kit_example/buttons/file_selection_button/file_selection_buttons.dart';
import 'package:wyatt_ui_kit_example/buttons/flat_button/flat_buttons.dart';
import 'package:wyatt_ui_kit_example/buttons/simple_icon_button/simple_icon_buttons.dart';
import 'package:wyatt_ui_kit_example/buttons/symbol_button/symbol_buttons.dart';
class Buttons extends StatelessWidget {
const Buttons({super.key});
@override
Widget build(BuildContext context) => ListView(
cacheExtent: 1000,
children: [
const Gap(20),
Align(
child: Text(
'Buttons',
style: Theme.of(context).textTheme.titleLarge,
),
),
const Gap(20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
FlatButtons(),
Gap(20),
SymbolButtons(),
Gap(20),
SimpleIconButtons(),
],
),
const Gap(20),
const Align(child: FileSelectionButtons()),
],
);
}

View File

@ -0,0 +1,121 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
import 'package:wyatt_ui_kit_example/theme/constants.dart';
class FileSelectionButtons extends StatelessWidget {
const FileSelectionButtons({super.key});
Widget _leading() => const DecoratedBox(
decoration: BoxDecoration(
color: Constants.grey2,
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
child: Padding(
padding: EdgeInsets.all(8),
child: Icon(
Icons.file_upload_outlined,
color: Colors.white,
),
),
);
@override
Widget build(BuildContext context) => Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'FileSelection Buttons',
style: Theme.of(context).textTheme.titleMedium,
),
const Gap(20),
FileSelectionButton(
leading: _leading(),
title: const TextWrapper(
'Ajouter un fichier',
),
subTitle: const TextWrapper('Taille max: 20 Mo'),
),
const Gap(20),
FileSelectionButton(
leading: _leading(),
title: const TextWrapper(
'Enabled',
),
subTitle: const TextWrapper('Subtitle'),
)
..bloc.enable()
..bloc.freeze(),
const Gap(20),
FileSelectionButton(
leading: _leading(),
title: const TextWrapper(
'Disabled',
),
subTitle: const TextWrapper('Subtitle'),
)
..bloc.disable()
..bloc.freeze(),
const Gap(20),
FileSelectionButton(
leading: _leading(),
title: const TextWrapper(
'Hovered',
),
subTitle: const TextWrapper('Subtitle'),
)
..bloc.onMouseEnter()
..bloc.freeze(),
const Gap(20),
FileSelectionButton(
leading: _leading(),
title: const TextWrapper(
'Focused',
),
subTitle: const TextWrapper('Subtitle'),
)
..bloc.onFocus()
..bloc.freeze(),
const Gap(20),
FileSelectionButton(
leading: _leading(),
title: const TextWrapper(
'Tapped',
),
subTitle: const TextWrapper('Subtitle'),
)
..bloc.onClickDown()
..bloc.freeze(),
const Gap(20),
FileSelectionButton(
leading: _leading(),
title: const TextWrapper(
'Invalid',
),
subTitle: const TextWrapper('Subtitle'),
)
..bloc.invalidate()
..bloc.freeze(),
const Gap(20),
],
);
}

View File

@ -0,0 +1,81 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
class FlatButtons extends StatelessWidget {
const FlatButtons({super.key});
@override
Widget build(BuildContext context) => Column(
children: [
Text(
'Flat Buttons',
style: Theme.of(context).textTheme.titleMedium,
),
const Gap(20),
Center(
child: FlatButton(
label: const TextWrapper('Voir notre savoir faire'),
),
),
const Gap(20),
Center(
child: FlatButton(
label: const TextWrapper('Enabled'),
)
..bloc.enable()
..bloc.freeze(),
),
const Gap(20),
Center(
child: FlatButton(
label: const TextWrapper('Disabled'),
)
..bloc.disable()
..bloc.freeze(),
),
const Gap(20),
Center(
child: FlatButton(
label: const TextWrapper('Hovered'),
)
..bloc.onMouseEnter()
..bloc.freeze(),
),
const Gap(20),
Center(
child: FlatButton(
label: const TextWrapper('Focused'),
)
..bloc.onFocus()
..bloc.freeze(),
),
const Gap(20),
Center(
child: FlatButton(
label: const TextWrapper('Tapped'),
)
..bloc.onClickDown()
..bloc.freeze(),
),
const Gap(20),
],
);
}

View File

@ -0,0 +1,112 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
class SimpleIconButtons extends StatelessWidget {
const SimpleIconButtons({super.key});
@override
Widget build(BuildContext context) => Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'SimpleIcon Buttons',
style: Theme.of(context).textTheme.titleMedium,
),
const Gap(20),
SimpleIconButton(
icon: const Icon(
Icons.storm_outlined,
size: 17,
),
),
const Gap(20),
Text(
'Enabled',
style: Theme.of(context).textTheme.labelMedium,
),
const Gap(10),
SimpleIconButton(
icon: const Icon(
Icons.storm_outlined,
size: 17,
),
)
..bloc.enable()
..bloc.freeze(),
const Gap(20),
Text(
'Disabled',
style: Theme.of(context).textTheme.labelMedium,
),
const Gap(10),
SimpleIconButton(
icon: const Icon(
Icons.storm_outlined,
size: 17,
),
)
..bloc.disable()
..bloc.freeze(),
const Gap(20),
Text(
'Hovered',
style: Theme.of(context).textTheme.labelMedium,
),
const Gap(10),
SimpleIconButton(
icon: const Icon(
Icons.storm_outlined,
size: 17,
),
)
..bloc.onMouseEnter()
..bloc.freeze(),
const Gap(20),
Text(
'Focused',
style: Theme.of(context).textTheme.labelMedium,
),
const Gap(10),
SimpleIconButton(
icon: const Icon(
Icons.storm_outlined,
size: 17,
),
)
..bloc.onFocus()
..bloc.freeze(),
const Gap(20),
Text(
'Tapped',
style: Theme.of(context).textTheme.labelMedium,
),
const Gap(10),
SimpleIconButton(
icon: const Icon(
Icons.storm_outlined,
size: 17,
),
)
..bloc.onClickDown()
..bloc.freeze(),
const Gap(20),
],
);
}

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: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';
import 'package:wyatt_ui_kit_example/theme/constants.dart';
class SymbolButtons extends StatelessWidget {
const SymbolButtons({super.key});
Icon _icon(BuildContext context) => Icon(
Icons.android,
size: 25,
color: (Theme.of(context).colorScheme.brightness == Brightness.light)
? Constants.dark
: Constants.white,
);
@override
Widget build(BuildContext context) => Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Symbol Buttons',
style: Theme.of(context).textTheme.titleMedium,
),
const Gap(20),
SymbolButton(
label: const TextWrapper('Text'),
icon: _icon(context),
),
const Gap(20),
SymbolButton(
label: const TextWrapper('Enabled'),
icon: _icon(context),
)
..bloc.enable()
..bloc.freeze(),
const Gap(20),
SymbolButton(
label: const TextWrapper('Disabled'),
icon: _icon(context),
)
..bloc.disable()
..bloc.freeze(),
const Gap(20),
SymbolButton(
label: const TextWrapper('Hovered'),
icon: _icon(context),
)
..bloc.onMouseEnter()
..bloc.freeze(),
const Gap(20),
SymbolButton(
label: const TextWrapper('Focused'),
icon: _icon(context),
)
..bloc.onFocus()
..bloc.freeze(),
const Gap(20),
SymbolButton(
label: const TextWrapper('Tapped'),
icon: _icon(context),
)
..bloc.onClickDown()
..bloc.freeze(),
const Gap(20),
SymbolButton(
label: const TextWrapper('Selected'),
icon: _icon(context),
)
..bloc.select()
..bloc.freeze(),
const Gap(20),
DecoratedBox(
decoration: BoxDecoration(
border: Border.all(color: Constants.red1),
),
child: SymbolButton(
label: const TextWrapper('Trigger zone'),
icon: _icon(context),
),
),
const Gap(20),
],
);
}

View File

@ -9,11 +9,15 @@ class Cards extends StatelessWidget {
const Cards({super.key});
@override
Widget build(BuildContext context) => Column(
Widget build(BuildContext context) => ListView(
cacheExtent: 1000,
children: [
Text(
'Cards',
style: Theme.of(context).textTheme.titleLarge,
const Gap(20),
Align(
child: Text(
'Cards',
style: Theme.of(context).textTheme.titleLarge,
),
),
const Gap(20),
const InformationCards(),

View File

@ -46,7 +46,7 @@ class InformationCards extends StatelessWidget {
child: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/asset_1.png'),
image: AssetImage('assets/images/asset_1.png'),
fit: BoxFit.fitHeight,
alignment: Alignment.centerRight,
),
@ -112,7 +112,7 @@ class InformationCards extends StatelessWidget {
child: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/asset_1.png'),
image: AssetImage('assets/images/asset_1.png'),
fit: BoxFit.fitHeight,
alignment: Alignment.centerRight,
),

View File

@ -39,7 +39,7 @@ class PortfolioCards extends StatelessWidget {
],
assets: [
Image.asset(
'assets/mockup_1.png',
'assets/images/mockup_1.png',
alignment: Alignment.topCenter,
fit: BoxFit.cover,
)
@ -72,7 +72,7 @@ class PortfolioCards extends StatelessWidget {
],
assets: [
Image.asset(
'assets/mockup_1.png',
'assets/images/mockup_1.png',
alignment: Alignment.topCenter,
fit: BoxFit.cover,
)
@ -105,12 +105,12 @@ class PortfolioCards extends StatelessWidget {
],
assets: [
Image.asset(
'assets/mockup_1.png',
'assets/images/mockup_1.png',
alignment: Alignment.topCenter,
fit: BoxFit.cover,
),
Image.asset(
'assets/mockup_1.png',
'assets/images/mockup_1.png',
alignment: Alignment.topCenter,
fit: BoxFit.cover,
)
@ -148,17 +148,17 @@ class PortfolioCards extends StatelessWidget {
],
assets: [
Image.asset(
'assets/mockup_1.png',
'assets/images/mockup_1.png',
alignment: Alignment.topCenter,
fit: BoxFit.cover,
),
Image.asset(
'assets/mockup_2.png',
'assets/images/mockup_2.png',
alignment: Alignment.topCenter,
fit: BoxFit.cover,
),
Image.asset(
'assets/mockup_1.png',
'assets/images/mockup_1.png',
alignment: Alignment.topCenter,
fit: BoxFit.cover,
)

View File

@ -1,39 +1,101 @@
import 'package:adaptive_theme/adaptive_theme.dart';
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/theme/themes.dart';
const String title = 'Wyatt Ui Kit Example';
const String title = 'Wyatt UIKit Example';
class Home extends StatefulWidget {
const Home({super.key});
const Home({super.key, this.forceIndex = 0});
final int forceIndex;
@override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
final List<Widget> pages = const [Cards(), Buttons()];
int currentIndex = 0;
@override
void initState() {
currentIndex = widget.forceIndex;
super.initState();
}
@override
Widget build(BuildContext context) => Scaffold(
drawer: const Drawer(),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
ListTile(
title: const Text('Cards'),
onTap: () {
if (currentIndex != 0) {
setState(() {
currentIndex = 0;
});
Navigator.pop(context);
}
},
),
ListTile(
title: const Text('Buttons'),
onTap: () {
if (currentIndex != 1) {
setState(() {
currentIndex = 1;
});
Navigator.pop(context);
}
},
),
],
),
),
appBar: AppBar(
title: const Text(title),
actions: [
Switch.adaptive(
value: AdaptiveTheme.of(context).isDefault,
onChanged: (_) {
AdaptiveTheme.of(context).isDefault
? AdaptiveTheme.of(context).setDark()
: AdaptiveTheme.of(context).setLight();
},
Row(
children: [
const Text('Mode'),
Switch.adaptive(
value:
AdaptiveTheme.of(context).brightness == Brightness.dark,
onChanged: (_) {
AdaptiveTheme.of(context).brightness == Brightness.light
? AdaptiveTheme.of(context).setDark()
: AdaptiveTheme.of(context).setLight();
},
),
],
),
const Gap(30),
Row(
children: [
const Text('Studio'),
Switch.adaptive(
value: Themes.currentThemeIndex == 1,
onChanged: (_) {
setState(() {
Themes.currentThemeIndex =
(Themes.currentThemeIndex == 1) ? 0 : 1;
});
Themes.auto(context);
},
),
],
)
],
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: ListView(
shrinkWrap: true,
children: const [Cards()],
),
child: pages[currentIndex],
),
);
}

View File

@ -17,102 +17,32 @@
import 'package:adaptive_theme/adaptive_theme.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:wyatt_ui_kit_example/home.dart';
import 'package:wyatt_ui_kit_example/theme_extension.dart';
import 'package:wyatt_ui_kit_example/theme/themes.dart';
void main(List<String> args) {
runApp(const App());
const forcePage = int.fromEnvironment('PAGE');
const forceTheme = int.fromEnvironment('THEME');
Themes.currentThemeIndex = forceTheme;
runApp(
const App(
defaultPage: forcePage,
defaultTheme: forceTheme,
),
);
}
class App extends StatelessWidget {
const App({super.key});
const App({required this.defaultPage, required this.defaultTheme, super.key});
static const String title = 'Wyatt Ui Kit Example';
final int defaultPage;
final int defaultTheme;
@override
Widget build(BuildContext context) => AdaptiveTheme(
initial: AdaptiveThemeMode.light,
light: ThemeData.light().copyWith(
appBarTheme: AppBarTheme(
foregroundColor: const Color.fromRGBO(36, 38, 42, 1),
backgroundColor: Colors.white,
titleTextStyle: GoogleFonts.montserrat(
fontSize: 18,
fontWeight: FontWeight.w500,
color: const Color.fromRGBO(36, 38, 42, 1),
),
),
scaffoldBackgroundColor: Colors.white,
extensions: <ThemeExtension<dynamic>>[
CustomCardColorExtension(
backgroundColors: const [
Color.fromRGBO(246, 246, 246, 1),
],
secondaryBackgroundColors: Colors.white,
borderColor: const [
Color.fromRGBO(221, 224, 227, 1),
Color.fromRGBO(202, 204, 212, 1),
],
title: GoogleFonts.montserrat(
fontSize: 24,
fontWeight: FontWeight.w500,
color: const Color.fromRGBO(36, 38, 42, 1),
),
subtitle: GoogleFonts.montserrat(
fontSize: 15,
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(36, 38, 42, 1),
),
body: GoogleFonts.montserrat(
fontSize: 12,
fontWeight: FontWeight.w300,
height: 1.7,
color: const Color.fromRGBO(36, 38, 42, 1),
),
),
],
),
dark: ThemeData.dark().copyWith(
appBarTheme: AppBarTheme(
foregroundColor: Colors.white,
backgroundColor: const Color.fromRGBO(56, 60, 64, 1),
titleTextStyle: GoogleFonts.montserrat(
fontSize: 18,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
scaffoldBackgroundColor: const Color.fromRGBO(56, 60, 64, 1),
extensions: <ThemeExtension<dynamic>>[
CustomCardColorExtension(
secondaryBackgroundColors: Colors.white.withOpacity(0.04),
backgroundColors: [
Colors.white.withOpacity(0.04),
],
borderColor: const [
Color.fromRGBO(96, 101, 106, 1),
Color.fromRGBO(56, 60, 64, 1),
],
title: GoogleFonts.montserrat(
fontSize: 24,
fontWeight: FontWeight.w500,
color: Colors.white,
),
subtitle: GoogleFonts.montserrat(
fontSize: 15,
fontWeight: FontWeight.w300,
color: Colors.white,
),
body: GoogleFonts.montserrat(
fontSize: 12,
fontWeight: FontWeight.w300,
height: 1.7,
color: Colors.white,
),
),
],
),
light: Themes.lightFromTheme(defaultTheme),
dark: Themes.darkFromTheme(defaultTheme),
builder: (light, dark) => MaterialApp(
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
@ -125,7 +55,9 @@ class App extends StatelessWidget {
Locale('fr', ''),
],
title: title,
home: const Home(),
home: Home(
forceIndex: defaultPage,
),
),
);
}

View File

@ -0,0 +1,46 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/widgets.dart';
abstract class Constants {
static const white = Color(0xFFFFFFFF);
static const dark = Color(0xFF383C40);
static const blue1 = Color(0xFF3C97FB);
static const blue2 = Color(0xFF446DF4);
static const blue3 = Color(0xFF1A84F7);
static const blue4 = Color(0xFF1344E4);
static const grey1 = Color(0xFF60656A);
static const grey2 = Color(0xFF383C40);
static const grey3 = Color(0xFF16191D);
static const grey4 = Color(0xFF33373E);
static const green1 = Color(0xFF50CE99);
static const green2 = Color(0xFF339572);
static const red1 = Color(0xFFFB5E3C);
static const red2 = Color(0xFFF44464);
static const blueGradient = [blue1, blue2];
static const blueDarkGradient = [blue3, blue4];
static const greyGradient = [grey1, grey2];
static const greyDarkGradient = [grey3, grey4];
static const greenGradient = [green1, green2];
static const redGradient = [red1, red2];
}

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:google_fonts/google_fonts.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
import 'package:wyatt_ui_kit_example/theme/constants.dart';
class FileSelectionButtonTheme extends FileSelectionButtonThemeExtension {
const FileSelectionButtonTheme({
super.disabledStyle,
super.focusedStyle,
super.hoveredStyle,
super.normalStyle,
super.tappedStyle,
super.selectedStyle,
super.invalidStyle,
});
factory FileSelectionButtonTheme.light() {
final style = FileSelectionButtonStyle(
title: GoogleFonts.montserrat(
fontSize: 16,
fontWeight: FontWeight.w400,
),
subTitle: GoogleFonts.montserrat(
fontSize: 11,
fontWeight: FontWeight.w400,
),
radius: BorderRadius.circular(12),
padding: const EdgeInsets.all(13),
foregroundColors: const MultiColor.single(Constants.grey2),
backgroundColors: MultiColor.single(Constants.white.withOpacity(0.04)),
borderColors: const MultiColor(Constants.greyGradient),
stroke: 2,
);
return FileSelectionButtonTheme(
normalStyle: style,
disabledStyle: style.copyWith(
foregroundColors: MultiColor.single(Constants.grey1.withOpacity(0.4)),
backgroundColors: const MultiColor.single(Constants.white),
borderColors: MultiColor.single(Constants.grey1.withOpacity(0.4)),
),
hoveredStyle: style.copyWith(
backgroundColors: MultiColor.single(Constants.grey1.withOpacity(0.4)),
),
focusedStyle: style.copyWith(stroke: 4),
tappedStyle: style.copyWith(
backgroundColors: MultiColor.single(Constants.grey1.withOpacity(0.4)),
),
invalidStyle: style.copyWith(
subTitle: GoogleFonts.montserrat(
fontSize: 11,
fontWeight: FontWeight.w400,
color: Constants.red1,
),
borderColors: const MultiColor(Constants.redGradient),
),
// Unused
selectedStyle: style.copyWith(
foregroundColors: const MultiColor.single(Constants.grey2),
borderColors: const MultiColor(Constants.greenGradient),
),
);
}
factory FileSelectionButtonTheme.dark() {
final style = FileSelectionButtonStyle(
title: GoogleFonts.montserrat(
fontSize: 16,
fontWeight: FontWeight.w400,
),
subTitle: GoogleFonts.montserrat(
fontSize: 11,
fontWeight: FontWeight.w400,
),
radius: BorderRadius.circular(12),
padding: const EdgeInsets.all(13),
foregroundColors: const MultiColor.single(Constants.white),
backgroundColors: MultiColor.single(Constants.white.withOpacity(0.04)),
borderColors: const MultiColor(Constants.greyGradient),
stroke: 1,
);
return FileSelectionButtonTheme(
normalStyle: style,
disabledStyle: style.copyWith(
foregroundColors: const MultiColor.single(Constants.grey1),
backgroundColors: const MultiColor.single(Constants.grey4),
),
hoveredStyle: style.copyWith(
borderColors: const MultiColor.single(Constants.white),
),
focusedStyle: style.copyWith(stroke: 3),
tappedStyle: style.copyWith(
backgroundColors: const MultiColor(Constants.greyDarkGradient),
),
invalidStyle: style.copyWith(
subTitle: GoogleFonts.montserrat(
fontSize: 11,
fontWeight: FontWeight.w400,
color: Constants.red1,
),
borderColors: const MultiColor(Constants.redGradient),
),
// Unused
selectedStyle: style.copyWith(
foregroundColors: const MultiColor.single(Constants.white),
borderColors: const MultiColor(Constants.greenGradient),
),
);
}
@override
ThemeExtension<FileSelectionButtonThemeExtension> copyWith({
FileSelectionButtonStyle? disabledStyle,
FileSelectionButtonStyle? focusedStyle,
FileSelectionButtonStyle? hoveredStyle,
FileSelectionButtonStyle? normalStyle,
FileSelectionButtonStyle? tappedStyle,
FileSelectionButtonStyle? selectedStyle,
FileSelectionButtonStyle? invalidStyle,
}) =>
FileSelectionButtonTheme(
disabledStyle: disabledStyle ?? this.disabledStyle,
focusedStyle: focusedStyle ?? this.focusedStyle,
hoveredStyle: hoveredStyle ?? this.hoveredStyle,
normalStyle: normalStyle ?? this.normalStyle,
tappedStyle: tappedStyle ?? this.tappedStyle,
selectedStyle: selectedStyle ?? this.selectedStyle,
invalidStyle: invalidStyle ?? this.invalidStyle,
);
@override
ThemeExtension<FileSelectionButtonThemeExtension> lerp(
covariant ThemeExtension<FileSelectionButtonThemeExtension>? other,
double t,
) {
if (other is! FileSelectionButtonTheme) {
return this;
}
return FileSelectionButtonTheme(
disabledStyle:
FileSelectionButtonStyle.lerp(disabledStyle, other.disabledStyle, t),
focusedStyle:
FileSelectionButtonStyle.lerp(focusedStyle, other.focusedStyle, t),
hoveredStyle:
FileSelectionButtonStyle.lerp(hoveredStyle, other.hoveredStyle, t),
normalStyle:
FileSelectionButtonStyle.lerp(normalStyle, other.normalStyle, t),
tappedStyle:
FileSelectionButtonStyle.lerp(tappedStyle, other.tappedStyle, t),
selectedStyle:
FileSelectionButtonStyle.lerp(selectedStyle, other.selectedStyle, t),
invalidStyle:
FileSelectionButtonStyle.lerp(invalidStyle, other.invalidStyle, t),
);
}
}

View File

@ -0,0 +1,153 @@
// 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';
import 'package:wyatt_ui_kit_example/theme/constants.dart';
class FlatButtonTheme extends FlatButtonThemeExtension {
const FlatButtonTheme({
super.disabledStyle,
super.focusedStyle,
super.hoveredStyle,
super.normalStyle,
super.tappedStyle,
});
factory FlatButtonTheme.light() {
final style = FlatButtonStyle(
label: GoogleFonts.montserrat(
fontSize: 18,
fontWeight: FontWeight.w600,
),
radius: BorderRadius.circular(15),
padding: const EdgeInsets.all(10),
foregroundColors: const MultiColor(Constants.blueGradient),
backgroundColors: const MultiColor.single(Constants.white),
borderColors: const MultiColor(Constants.blueGradient),
stroke: 3,
);
return FlatButtonTheme(
normalStyle: style,
disabledStyle: style.copyWith(
label: GoogleFonts.montserrat(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Constants.blue1.withOpacity(0.4),
),
foregroundColors: MultiColor.single(Constants.blue1.withOpacity(0.4)),
backgroundColors: const MultiColor.single(Constants.white),
borderColors: MultiColor.single(Constants.blue1.withOpacity(0.4)),
stroke: 1,
),
hoveredStyle: style.copyWith(
label: GoogleFonts.montserrat(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Constants.white,
),
foregroundColors: const MultiColor.single(Constants.white),
backgroundColors: const MultiColor(Constants.blueGradient),
),
focusedStyle: style.copyWith(stroke: 5),
tappedStyle: style.copyWith(
label: GoogleFonts.montserrat(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Constants.white,
),
foregroundColors: const MultiColor.single(Constants.white),
backgroundColors: const MultiColor(Constants.blueDarkGradient),
borderColors: const MultiColor(Constants.blueDarkGradient),
),
);
}
factory FlatButtonTheme.dark() {
final style = FlatButtonStyle(
label: GoogleFonts.montserrat(
fontSize: 18,
fontWeight: FontWeight.w600,
),
radius: BorderRadius.circular(15),
padding: const EdgeInsets.all(10),
foregroundColors: const MultiColor.single(Constants.white),
backgroundColors: const MultiColor.single(Constants.dark),
borderColors: const MultiColor(Constants.blueGradient),
stroke: 3,
);
return FlatButtonTheme(
normalStyle: style,
disabledStyle: style.copyWith(
label: GoogleFonts.montserrat(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Constants.grey1,
),
foregroundColors: const MultiColor.single(Constants.grey1),
backgroundColors: const MultiColor.single(Constants.grey4),
borderColors: const MultiColor(Constants.greyGradient),
stroke: 1,
),
hoveredStyle: style.copyWith(
foregroundColors: const MultiColor.single(Constants.white),
backgroundColors: const MultiColor(Constants.blueGradient),
),
focusedStyle: style.copyWith(stroke: 5),
tappedStyle: style.copyWith(
foregroundColors: const MultiColor.single(Constants.white),
backgroundColors: const MultiColor(Constants.blueDarkGradient),
borderColors: const MultiColor(Constants.blueDarkGradient),
),
);
}
@override
ThemeExtension<FlatButtonThemeExtension> copyWith({
FlatButtonStyle? disabledStyle,
FlatButtonStyle? focusedStyle,
FlatButtonStyle? hoveredStyle,
FlatButtonStyle? normalStyle,
FlatButtonStyle? tappedStyle,
}) =>
FlatButtonTheme(
disabledStyle: disabledStyle ?? this.disabledStyle,
focusedStyle: focusedStyle ?? this.focusedStyle,
hoveredStyle: hoveredStyle ?? this.hoveredStyle,
normalStyle: normalStyle ?? this.normalStyle,
tappedStyle: tappedStyle ?? this.tappedStyle,
);
@override
ThemeExtension<FlatButtonThemeExtension> lerp(
covariant ThemeExtension<FlatButtonThemeExtension>? other,
double t,
) {
if (other is! FlatButtonTheme) {
return this;
}
return FlatButtonTheme(
disabledStyle:
FlatButtonStyle.lerp(disabledStyle, other.disabledStyle, t),
focusedStyle: FlatButtonStyle.lerp(focusedStyle, other.focusedStyle, t),
hoveredStyle: FlatButtonStyle.lerp(hoveredStyle, other.hoveredStyle, t),
normalStyle: FlatButtonStyle.lerp(normalStyle, other.normalStyle, t),
tappedStyle: FlatButtonStyle.lerp(tappedStyle, other.tappedStyle, t),
);
}
}

View File

@ -0,0 +1,114 @@
// 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/wyatt_ui_kit.dart';
import 'package:wyatt_ui_kit_example/theme/constants.dart';
class SimpleIconButtonTheme extends SimpleIconButtonThemeExtension {
const SimpleIconButtonTheme({
super.disabledStyle,
super.focusedStyle,
super.hoveredStyle,
super.normalStyle,
super.tappedStyle,
});
factory SimpleIconButtonTheme.light() {
final style = SimpleIconButtonStyle(
dimension: 30,
radius: BorderRadius.circular(5),
padding: const EdgeInsets.all(5),
foregroundColors: const MultiColor.single(Constants.dark),
backgroundColors: MultiColor.single(Constants.grey1.withOpacity(0.2)),
);
return SimpleIconButtonTheme(
normalStyle: style,
disabledStyle: style.copyWith(
foregroundColors: MultiColor.single(Constants.dark.withOpacity(0.4)),
),
hoveredStyle: style.copyWith(
backgroundColors: MultiColor.single(Constants.grey1.withOpacity(0.4)),
),
focusedStyle: style,
tappedStyle: style.copyWith(
backgroundColors: MultiColor.single(Constants.grey1.withOpacity(0.5)),
),
);
}
factory SimpleIconButtonTheme.dark() {
final style = SimpleIconButtonStyle(
dimension: 30,
radius: BorderRadius.circular(5),
padding: const EdgeInsets.all(5),
foregroundColors: const MultiColor.single(Constants.white),
backgroundColors: MultiColor.single(Constants.grey3.withOpacity(0.2)),
);
return SimpleIconButtonTheme(
normalStyle: style,
disabledStyle: style.copyWith(
foregroundColors: MultiColor.single(Constants.white.withOpacity(0.4)),
),
hoveredStyle: style.copyWith(
backgroundColors: MultiColor.single(Constants.grey3.withOpacity(0.4)),
),
focusedStyle: style,
tappedStyle: style.copyWith(
backgroundColors: MultiColor.single(Constants.grey3.withOpacity(0.5)),
),
);
}
@override
ThemeExtension<SimpleIconButtonThemeExtension> copyWith({
SimpleIconButtonStyle? disabledStyle,
SimpleIconButtonStyle? focusedStyle,
SimpleIconButtonStyle? hoveredStyle,
SimpleIconButtonStyle? normalStyle,
SimpleIconButtonStyle? tappedStyle,
}) =>
SimpleIconButtonTheme(
disabledStyle: disabledStyle ?? this.disabledStyle,
focusedStyle: focusedStyle ?? this.focusedStyle,
hoveredStyle: hoveredStyle ?? this.hoveredStyle,
normalStyle: normalStyle ?? this.normalStyle,
tappedStyle: tappedStyle ?? this.tappedStyle,
);
@override
ThemeExtension<SimpleIconButtonThemeExtension> lerp(
covariant ThemeExtension<SimpleIconButtonThemeExtension>? other,
double t,
) {
if (other is! SimpleIconButtonTheme) {
return this;
}
return SimpleIconButtonTheme(
disabledStyle:
SimpleIconButtonStyle.lerp(disabledStyle, other.disabledStyle, t),
focusedStyle:
SimpleIconButtonStyle.lerp(focusedStyle, other.focusedStyle, t),
hoveredStyle:
SimpleIconButtonStyle.lerp(hoveredStyle, other.hoveredStyle, t),
normalStyle:
SimpleIconButtonStyle.lerp(normalStyle, other.normalStyle, t),
tappedStyle:
SimpleIconButtonStyle.lerp(tappedStyle, other.tappedStyle, t),
);
}
}

View File

@ -0,0 +1,157 @@
// 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';
import 'package:wyatt_ui_kit_example/theme/constants.dart';
class SymbolButtonTheme extends SymbolButtonThemeExtension {
const SymbolButtonTheme({
super.disabledStyle,
super.focusedStyle,
super.hoveredStyle,
super.normalStyle,
super.tappedStyle,
super.selectedStyle,
});
factory SymbolButtonTheme.light() {
final style = SymbolButtonStyle(
label: GoogleFonts.montserrat(
fontSize: 14,
fontWeight: FontWeight.w400,
),
dimension: 60,
radius: BorderRadius.circular(12),
padding: const EdgeInsets.all(10),
foregroundColors: const MultiColor.single(Constants.grey2),
backgroundColors: MultiColor.single(Constants.white.withOpacity(0.04)),
borderColors: const MultiColor(Constants.greyGradient),
stroke: 2,
);
return SymbolButtonTheme(
normalStyle: style,
disabledStyle: style.copyWith(
label: GoogleFonts.montserrat(
fontSize: 14,
fontWeight: FontWeight.w400,
color: Constants.grey1,
),
foregroundColors: MultiColor.single(Constants.grey1.withOpacity(0.4)),
backgroundColors: const MultiColor.single(Constants.white),
borderColors: MultiColor.single(Constants.grey1.withOpacity(0.4)),
),
hoveredStyle: style.copyWith(
backgroundColors: MultiColor.single(Constants.grey1.withOpacity(0.4)),
),
focusedStyle: style.copyWith(stroke: 4),
tappedStyle: style.copyWith(
backgroundColors: MultiColor.single(Constants.grey1.withOpacity(0.4)),
),
selectedStyle: style.copyWith(
label: GoogleFonts.montserrat(
fontSize: 14,
fontWeight: FontWeight.w600,
),
foregroundColors: const MultiColor.single(Constants.grey2),
borderColors: const MultiColor(Constants.greenGradient),
),
);
}
factory SymbolButtonTheme.dark() {
final style = SymbolButtonStyle(
label: GoogleFonts.montserrat(
fontSize: 14,
fontWeight: FontWeight.w400,
),
dimension: 60,
radius: BorderRadius.circular(12),
padding: const EdgeInsets.all(10),
foregroundColors: const MultiColor.single(Constants.white),
backgroundColors: MultiColor.single(Constants.white.withOpacity(0.04)),
borderColors: const MultiColor(Constants.greyGradient),
stroke: 2,
);
return SymbolButtonTheme(
normalStyle: style,
disabledStyle: style.copyWith(
label: GoogleFonts.montserrat(
fontSize: 14,
fontWeight: FontWeight.w400,
color: Constants.grey1,
),
foregroundColors: const MultiColor.single(Constants.grey1),
backgroundColors: const MultiColor.single(Constants.grey4),
),
hoveredStyle: style.copyWith(
backgroundColors: const MultiColor(Constants.greyDarkGradient),
),
focusedStyle: style.copyWith(stroke: 4),
tappedStyle: style.copyWith(
backgroundColors: const MultiColor(Constants.greyDarkGradient),
),
selectedStyle: style.copyWith(
label: GoogleFonts.montserrat(
fontSize: 14,
fontWeight: FontWeight.w600,
),
foregroundColors: const MultiColor.single(Constants.white),
borderColors: const MultiColor(Constants.greenGradient),
),
);
}
@override
ThemeExtension<SymbolButtonThemeExtension> copyWith({
SymbolButtonStyle? disabledStyle,
SymbolButtonStyle? focusedStyle,
SymbolButtonStyle? hoveredStyle,
SymbolButtonStyle? normalStyle,
SymbolButtonStyle? tappedStyle,
SymbolButtonStyle? selectedStyle,
}) =>
SymbolButtonTheme(
disabledStyle: disabledStyle ?? this.disabledStyle,
focusedStyle: focusedStyle ?? this.focusedStyle,
hoveredStyle: hoveredStyle ?? this.hoveredStyle,
normalStyle: normalStyle ?? this.normalStyle,
tappedStyle: tappedStyle ?? this.tappedStyle,
selectedStyle: selectedStyle ?? this.selectedStyle,
);
@override
ThemeExtension<SymbolButtonThemeExtension> lerp(
covariant ThemeExtension<SymbolButtonThemeExtension>? other,
double t,
) {
if (other is! SymbolButtonTheme) {
return this;
}
return SymbolButtonTheme(
disabledStyle:
SymbolButtonStyle.lerp(disabledStyle, other.disabledStyle, t),
focusedStyle: SymbolButtonStyle.lerp(focusedStyle, other.focusedStyle, t),
hoveredStyle: SymbolButtonStyle.lerp(hoveredStyle, other.hoveredStyle, t),
normalStyle: SymbolButtonStyle.lerp(normalStyle, other.normalStyle, t),
tappedStyle: SymbolButtonStyle.lerp(tappedStyle, other.tappedStyle, t),
selectedStyle:
SymbolButtonStyle.lerp(selectedStyle, other.selectedStyle, t),
);
}
}

View File

@ -0,0 +1,159 @@
// 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:adaptive_theme/adaptive_theme.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
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_extension.dart';
/// Easely switch between Material and Studio themes.
abstract class Themes {
static int currentThemeIndex = 0;
static List<Set<ThemeData>> themes = [
{materialLight, materialDark},
{studioLight, studioDark},
];
static ThemeData lightFromTheme(int themeId) {
currentThemeIndex = themeId;
return themes[themeId].first;
}
static ThemeData darkFromTheme(int themeId) {
currentThemeIndex = themeId;
return themes[themeId].last;
}
static void auto(BuildContext context) {
if (currentThemeIndex == 1) {
return studio(context);
}
return material(context);
}
static void material(BuildContext context) {
AdaptiveTheme.of(context).setTheme(
light: materialLight,
dark: materialDark,
);
}
static void studio(BuildContext context) {
AdaptiveTheme.of(context).setTheme(
light: studioLight,
dark: studioDark,
);
}
static ThemeData get materialLight => ThemeData.light();
static ThemeData get studioLight => materialLight.copyWith(
appBarTheme: AppBarTheme(
foregroundColor: const Color.fromRGBO(36, 38, 42, 1),
backgroundColor: Colors.white,
titleTextStyle: GoogleFonts.montserrat(
fontSize: 18,
fontWeight: FontWeight.w500,
color: const Color.fromRGBO(36, 38, 42, 1),
),
),
scaffoldBackgroundColor: Colors.white,
extensions: <ThemeExtension<dynamic>>[
CustomCardColorExtension(
backgroundColors: const [
Color.fromRGBO(246, 246, 246, 1),
],
secondaryBackgroundColors: Colors.white,
borderColor: const [
Color.fromRGBO(221, 224, 227, 1),
Color.fromRGBO(202, 204, 212, 1),
],
title: GoogleFonts.montserrat(
fontSize: 24,
fontWeight: FontWeight.w500,
color: const Color.fromRGBO(36, 38, 42, 1),
),
subtitle: GoogleFonts.montserrat(
fontSize: 15,
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(36, 38, 42, 1),
),
body: GoogleFonts.montserrat(
fontSize: 12,
fontWeight: FontWeight.w300,
height: 1.7,
color: const Color.fromRGBO(36, 38, 42, 1),
),
),
FlatButtonTheme.light(),
SymbolButtonTheme.light(),
SimpleIconButtonTheme.light(),
FileSelectionButtonTheme.light(),
],
);
static ThemeData get materialDark => ThemeData.dark();
static ThemeData get studioDark => materialDark.copyWith(
appBarTheme: AppBarTheme(
foregroundColor: Colors.white,
backgroundColor: const Color.fromRGBO(56, 60, 64, 1),
titleTextStyle: GoogleFonts.montserrat(
fontSize: 18,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
scaffoldBackgroundColor: const Color.fromRGBO(56, 60, 64, 1),
extensions: <ThemeExtension<dynamic>>[
CustomCardColorExtension(
secondaryBackgroundColors: Colors.white.withOpacity(0.04),
backgroundColors: [
Colors.white.withOpacity(0.04),
],
borderColor: const [
Color.fromRGBO(96, 101, 106, 1),
Color.fromRGBO(56, 60, 64, 1),
],
title: GoogleFonts.montserrat(
fontSize: 24,
fontWeight: FontWeight.w500,
color: Colors.white,
),
subtitle: GoogleFonts.montserrat(
fontSize: 15,
fontWeight: FontWeight.w300,
color: Colors.white,
),
body: GoogleFonts.montserrat(
fontSize: 12,
fontWeight: FontWeight.w300,
height: 1.7,
color: Colors.white,
),
),
FlatButtonTheme.dark(),
SymbolButtonTheme.dark(),
SimpleIconButtonTheme.dark(),
FileSelectionButtonTheme.dark(),
],
);
}

View File

@ -3,20 +3,27 @@ PODS:
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
DEPENDENCIES:
- FlutterMacOS (from `Flutter/ephemeral`)
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos`)
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/macos`)
EXTERNAL SOURCES:
FlutterMacOS:
:path: Flutter/ephemeral
path_provider_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos
shared_preferences_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/macos
SPEC CHECKSUMS:
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
path_provider_foundation: 37748e03f12783f9de2cb2c4eadfaa25fe6d4852
shared_preferences_foundation: 297b3ebca31b34ec92be11acd7fb0ba932c822ca
PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7

View File

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
</dict>
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
</dict>
</plist>

View File

@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.app-sandbox</key>
<true/>
</dict>

View File

@ -10,8 +10,7 @@ environment:
dependencies:
flutter: { sdk: flutter }
flutter_localizations:
sdk: flutter
flutter_localizations: { sdk: flutter }
gap: ^2.0.1
google_fonts: ^4.0.3
@ -37,4 +36,5 @@ flutter:
uses-material-design: true
assets:
- ./assets/
- ./assets/images/
- ./assets/fonts/montserrat/

View File

@ -0,0 +1,20 @@
// 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 './file_selection_button/file_selection_button.dart';
export './flat_button/flat_button.dart';
export './simple_icon_button/simple_icon_button.dart';
export './symbol_button/symbol_button.dart';

View File

@ -0,0 +1,99 @@
// 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 'button_state.dart';
class ButtonCubit extends Cubit<ButtonState> {
ButtonCubit() : super(const ButtonState.initial(ControlState.normal));
FutureOr<void> onMouseEnter() async {
if (state.isDisabled || state.isFreezed) {
return;
}
emit(state.copyWith(state: ControlState.hovered));
}
FutureOr<void> onMouseLeave() async {
if (state.isDisabled || state.isFreezed) {
return;
}
emit(state.copyWith(state: ControlState.normal));
}
FutureOr<void> onFocus() async {
if (state.isDisabled || state.isFreezed) {
return;
}
emit(state.copyWith(state: ControlState.focused));
}
FutureOr<void> onUnfocus() async {
if (state.isDisabled || state.isFreezed) {
return;
}
emit(state.copyWith(state: ControlState.normal));
}
FutureOr<void> onClickDown() async {
if (state.isDisabled || state.isFreezed) {
return;
}
emit(state.copyWith(state: ControlState.tapped));
}
FutureOr<void> onClickUpIn() async {
if (state.isDisabled) {
return;
}
emit(state.copyWith(state: ControlState.hovered));
}
FutureOr<void> onClickUpOut() async {
if (state.isDisabled) {
return;
}
emit(state.copyWith(state: ControlState.normal));
}
FutureOr<void> disable() async {
if (state.isFreezed) {
return;
}
emit(state.copyWith(state: ControlState.disabled));
}
FutureOr<void> enable() async {
if (state.isFreezed) {
return;
}
emit(state.copyWith(state: ControlState.normal));
}
FutureOr<void> freeze() async {
emit(state.copyWith(freezed: true));
}
FutureOr<void> unfreeze() async {
emit(state.copyWith(freezed: false));
}
}

View File

@ -0,0 +1,71 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first
// 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 'button_cubit.dart';
class ButtonState extends Equatable {
const ButtonState({
required this.state,
required this.selected,
required this.invalid,
required this.freezed,
});
const ButtonState.initial(this.state)
: selected = false,
invalid = false,
freezed = false;
final ControlState state;
// Not in control state, because a button state can be
// a control state + extra state
// e.g : hover + invalid, or selected + tapped
final bool selected;
final bool invalid;
final bool freezed;
bool get isDisabled => state.isDisabled();
bool get isEnabled => state.isEnabled();
bool get isFocused => state.isFocused();
bool get isHovered => state.isHovered();
bool get isTapped => state.isTapped();
// only for consistence
bool get isSelected => selected;
bool get isInvalid => invalid;
bool get isFreezed => freezed;
@override
List<Object?> get props => [state, selected, invalid, freezed];
@override
bool? get stringify => true;
ButtonState copyWith({
ControlState? state,
bool? selected,
bool? invalid,
bool? freezed,
}) =>
ButtonState(
state: state ?? this.state,
selected: selected ?? this.selected,
invalid: invalid ?? this.invalid,
freezed: freezed ?? this.freezed,
);
}

View File

@ -0,0 +1,68 @@
// 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:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
class InvalidButtonCubit extends ButtonCubit {
@override
FutureOr<void> onClickUpIn() async {
if (state.isDisabled || state.isFreezed) {
return;
}
emit(
state.copyWith(
state: ControlState.hovered,
),
);
}
@override
FutureOr<void> onClickUpOut() async {
if (state.isDisabled || state.isFreezed) {
return;
}
emit(
state.copyWith(
state: ControlState.normal,
),
);
}
FutureOr<void> invalidate() async {
if (state.isDisabled || state.isFreezed) {
return;
}
emit(
state.copyWith(invalid: true),
);
}
FutureOr<void> fix() async {
if (state.isDisabled || state.isFreezed) {
return;
}
emit(
state.copyWith(invalid: false),
);
}
}

View File

@ -0,0 +1,60 @@
// 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:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
class SelectableButtonCubit extends ButtonCubit {
@override
FutureOr<void> onClickUpIn() async {
if (state.isDisabled || state.isFreezed) {
return;
}
emit(
state.copyWith(state: ControlState.hovered, selected: !state.selected),
);
}
@override
FutureOr<void> onClickUpOut() async {
if (state.isDisabled || state.isFreezed) {
return;
}
emit(state.copyWith(state: ControlState.normal, selected: !state.selected));
}
FutureOr<void> select() async {
if (state.isDisabled || state.isFreezed) {
return;
}
emit(
state.copyWith(selected: true),
);
}
FutureOr<void> unselect() async {
if (state.isDisabled || state.isFreezed) {
return;
}
emit(
state.copyWith(selected: false),
);
}
}

View File

@ -0,0 +1,103 @@
// 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' hide ButtonStyle;
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/buttons/cubit/invalid_button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/file_selection_button/file_selection_button_screen.dart';
import 'package:wyatt_ui_kit/src/components/buttons/file_selection_button/file_selection_button_theme_resolver.dart';
import 'package:wyatt_ui_kit/src/core/mixin/export_bloc_mixin.dart';
part 'file_selection_button.g.dart';
@ComponentCopyWithExtension()
class FileSelectionButton extends FileSelectionButtonComponent
with $FileSelectionButtonCWMixin, ExportBloc<InvalidButtonCubit> {
FileSelectionButton({
super.leading,
super.title,
super.subTitle,
super.disabledStyle,
super.normalStyle,
super.hoveredStyle,
super.focusedStyle,
super.tappedStyle,
super.selectedStyle,
super.invalidStyle,
super.onPressed,
super.mainAxisSize,
super.themeResolver,
super.key,
});
final InvalidButtonCubit _cubit = InvalidButtonCubit();
@override
InvalidButtonCubit get bloc => _cubit;
@override
FileSelectionButtonStyle? get disabledStyle =>
super.disabledStyle as FileSelectionButtonStyle?;
@override
FileSelectionButtonStyle? get normalStyle =>
super.normalStyle as FileSelectionButtonStyle?;
@override
FileSelectionButtonStyle? get hoveredStyle =>
super.hoveredStyle as FileSelectionButtonStyle?;
@override
FileSelectionButtonStyle? get focusedStyle =>
super.focusedStyle as FileSelectionButtonStyle?;
@override
FileSelectionButtonStyle? get tappedStyle =>
super.tappedStyle as FileSelectionButtonStyle?;
@override
FileSelectionButtonStyle? get selectedStyle =>
super.selectedStyle as FileSelectionButtonStyle?;
@override
FileSelectionButtonStyle? get invalidStyle =>
super.invalidStyle as FileSelectionButtonStyle?;
@override
FileSelectionButtonThemeResolver? get themeResolver =>
super.themeResolver as FileSelectionButtonThemeResolver?;
@override
Widget build(BuildContext context) => exportBloc(
child: FileSelectionButtonScreen(
leading: leading,
title: title,
subTitle: subTitle,
disabledStyle: disabledStyle,
normalStyle: normalStyle,
hoveredStyle: hoveredStyle,
focusedStyle: focusedStyle,
tappedStyle: tappedStyle,
selectedStyle: selectedStyle,
invalidStyle: invalidStyle,
onPressed: onPressed,
mainAxisSize: mainAxisSize,
themeResolver: themeResolver,
key: key,
),
);
}

View File

@ -0,0 +1,91 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'file_selection_button.dart';
// **************************************************************************
// ComponentCopyWithGenerator
// **************************************************************************
class $FileSelectionButtonCWProxyImpl
implements $FileSelectionButtonComponentCWProxy {
const $FileSelectionButtonCWProxyImpl(this._value);
final FileSelectionButton _value;
@override
FileSelectionButton mainAxisSize(MainAxisSize? mainAxisSize) =>
this(mainAxisSize: mainAxisSize);
@override
FileSelectionButton leading(Widget? leading) => this(leading: leading);
@override
FileSelectionButton title(TextWrapper? title) => this(title: title);
@override
FileSelectionButton subTitle(TextWrapper? subTitle) =>
this(subTitle: subTitle);
@override
FileSelectionButton disabledStyle(ButtonStyle<dynamic>? disabledStyle) =>
this(disabledStyle: disabledStyle);
@override
FileSelectionButton normalStyle(ButtonStyle<dynamic>? normalStyle) =>
this(normalStyle: normalStyle);
@override
FileSelectionButton hoveredStyle(ButtonStyle<dynamic>? hoveredStyle) =>
this(hoveredStyle: hoveredStyle);
@override
FileSelectionButton focusedStyle(ButtonStyle<dynamic>? focusedStyle) =>
this(focusedStyle: focusedStyle);
@override
FileSelectionButton tappedStyle(ButtonStyle<dynamic>? tappedStyle) =>
this(tappedStyle: tappedStyle);
@override
FileSelectionButton selectedStyle(ButtonStyle<dynamic>? selectedStyle) =>
this(selectedStyle: selectedStyle);
@override
FileSelectionButton invalidStyle(ButtonStyle<dynamic>? invalidStyle) =>
this(invalidStyle: invalidStyle);
@override
FileSelectionButton onPressed(void Function(ControlState)? onPressed) =>
this(onPressed: onPressed);
@override
FileSelectionButton themeResolver(
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver) =>
this(themeResolver: themeResolver);
@override
FileSelectionButton key(Key? key) => this(key: key);
@override
FileSelectionButton call({
MainAxisSize? mainAxisSize,
Widget? leading,
TextWrapper? title,
TextWrapper? subTitle,
ButtonStyle<dynamic>? disabledStyle,
ButtonStyle<dynamic>? normalStyle,
ButtonStyle<dynamic>? hoveredStyle,
ButtonStyle<dynamic>? focusedStyle,
ButtonStyle<dynamic>? tappedStyle,
ButtonStyle<dynamic>? selectedStyle,
ButtonStyle<dynamic>? invalidStyle,
void Function(ControlState)? onPressed,
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver,
Key? key,
}) =>
FileSelectionButton(
leading: leading ?? _value.leading,
title: title ?? _value.title,
subTitle: subTitle ?? _value.subTitle,
disabledStyle: disabledStyle ?? _value.disabledStyle,
normalStyle: normalStyle ?? _value.normalStyle,
hoveredStyle: hoveredStyle ?? _value.hoveredStyle,
focusedStyle: focusedStyle ?? _value.focusedStyle,
tappedStyle: tappedStyle ?? _value.tappedStyle,
selectedStyle: selectedStyle ?? _value.selectedStyle,
invalidStyle: invalidStyle ?? _value.invalidStyle,
onPressed: onPressed ?? _value.onPressed,
mainAxisSize: mainAxisSize ?? _value.mainAxisSize,
themeResolver: themeResolver ?? _value.themeResolver,
key: key ?? _value.key,
);
}
mixin $FileSelectionButtonCWMixin on Component {
$FileSelectionButtonComponentCWProxy get copyWith =>
$FileSelectionButtonCWProxyImpl(this as FileSelectionButton);
}

View File

@ -0,0 +1,294 @@
// 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:dotted_border/dotted_border.dart';
import 'package:flutter/material.dart' hide ButtonStyle;
import 'package:flutter/services.dart';
import 'package:gap/gap.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/buttons/cubit/button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/invalid_button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/file_selection_button/file_selection_button_theme_resolver.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart';
import 'package:wyatt_ui_kit/src/core/helpers/linear_gradient_helper.dart';
class FileSelectionButtonScreen
extends CubitScreen<InvalidButtonCubit, ButtonState> {
const FileSelectionButtonScreen({
this.leading,
this.title,
this.subTitle,
this.disabledStyle,
this.normalStyle,
this.hoveredStyle,
this.focusedStyle,
this.tappedStyle,
this.selectedStyle,
this.invalidStyle,
this.onPressed,
this.mainAxisSize,
this.themeResolver,
super.key,
});
final Widget? leading;
final TextWrapper? title;
final TextWrapper? subTitle;
final MainAxisSize? mainAxisSize;
final FileSelectionButtonStyle? disabledStyle;
final FileSelectionButtonStyle? normalStyle;
final FileSelectionButtonStyle? hoveredStyle;
final FileSelectionButtonStyle? focusedStyle;
final FileSelectionButtonStyle? tappedStyle;
final FileSelectionButtonStyle? selectedStyle;
final FileSelectionButtonStyle? invalidStyle;
final void Function(ControlState state)? onPressed;
final FileSelectionButtonThemeResolver? themeResolver;
@override
InvalidButtonCubit create(BuildContext context) => InvalidButtonCubit();
/// Negotiate the theme to get a complete style.
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}) {
FileSelectionButtonStyle? style;
switch (extra?.state) {
case ControlState.disabled:
style = disabledStyle;
break;
case ControlState.focused:
style = focusedStyle;
break;
case ControlState.hovered:
style = hoveredStyle;
break;
case ControlState.tapped:
style = tappedStyle;
break;
case ControlState.normal:
case null:
style = normalStyle;
break;
}
if (extra?.isSelected ?? false) {
style = selectedStyle;
}
if (extra?.isInvalid ?? false) {
style = invalidStyle;
}
return style;
},
);
return resolver.negotiate(context, extra: state);
}
Widget _border(
BuildContext context,
FileSelectionButtonStyle style,
Widget child,
) {
if (style.borderColors != null && style.stroke != null) {
return DottedBorder(
padding: EdgeInsets.zero,
dashPattern: const [5, 5],
strokeWidth: style.stroke!,
color: style.borderColors!.color,
borderType: BorderType.RRect,
radius:
style.radius?.resolve(TextDirection.ltr).bottomLeft ?? Radius.zero,
strokeCap: StrokeCap.square,
child: child,
);
} else {
return child;
}
}
@override
Widget onBuild(BuildContext context, ButtonState state) {
final style = resolve(context, state);
return Focus(
onFocusChange: (hasFocus) =>
hasFocus ? bloc(context).onFocus() : bloc(context).onUnfocus(),
onKeyEvent: (focusNode, event) {
if (event.logicalKey == LogicalKeyboardKey.enter && state.isFocused) {
onPressed?.call(state.state);
bloc(context).onClickUpOut();
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
},
child: MouseRegion(
cursor: SystemMouseCursors.click,
onEnter: (event) {
bloc(context).onMouseEnter();
},
onExit: (event) {
bloc(context).onMouseLeave();
},
child: GestureDetector(
onTapDown: (details) {
bloc(context).onClickDown();
},
onTapUp: (details) {
onPressed?.call(state.state);
bloc(context).onClickUpIn();
},
onTapCancel: () {
onPressed?.call(state.state);
bloc(context).onClickUpOut();
},
child: _border(
context,
style,
DecoratedBox(
decoration: BoxDecoration(
color: style.backgroundColors?.color,
// if no gradient colors => no default value
gradient: (style.backgroundColors?.isGradient ?? false)
? LinearGradient(
colors: style.backgroundColors!.colors,
)
: null,
boxShadow: [
if (style.shadow != null) ...[style.shadow!]
],
borderRadius: style.radius,
),
child: ConstrainedBox(
constraints: const BoxConstraints(
minWidth: 200,
minHeight: 50,
), // min sizes for Material buttons
child: Padding(
padding: style.padding ?? EdgeInsets.zero,
child: Row(
mainAxisSize: mainAxisSize ?? MainAxisSize.min,
children: [
if (leading != null) ...[
leading ?? const SizedBox.shrink(),
Gap((style.padding?.horizontal ?? 10)/2),
],
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
/// Choose color
/// title.style.color ??
/// buttonStyle.title.style.color ??
/// context.textTheme.titleLarge.color
///
/// Choose gradient
/// title.gradient ??
/// buttonStyle.foregroundColor.colors ??
/// null
///
/// More infos in `negociate()` method
if (title != null) ...[
Text(
title!.text,
style: title!.style ?? style.title,
).toGradient(
LinearGradientHelper.fromNullableColors(
title?.gradient ??
((style.foregroundColors?.isGradient ??
false)
? style.foregroundColors?.colors
: null),
),
),
],
/// Choose color
/// subTitle.style.color ??
/// buttonStyle.subTitle.style.color ??
/// context.textTheme.subTitleLarge.color
///
/// Choose gradient
/// subTitle.gradient ??
/// buttonStyle.foregroundColor.colors ??
/// null
///
/// More infos in `negociate()` method
if (subTitle != null) ...[
const Gap(5),
Text(
subTitle!.text,
style: subTitle!.style ?? style.subTitle,
).toGradient(
LinearGradientHelper.fromNullableColors(
subTitle?.gradient ??
((style.foregroundColors?.isGradient ??
false)
? style.foregroundColors?.colors
: null),
),
),
],
],
),
],
),
),
),
),
),
),
),
);
}
}

View File

@ -0,0 +1,89 @@
// 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/buttons/cubit/button_cubit.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
class FileSelectionButtonThemeResolver extends ThemeResolver<
FileSelectionButtonStyle, FileSelectionButtonThemeExtension, ButtonState> {
const FileSelectionButtonThemeResolver({
required this.computeExtensionValueFn,
required this.customStyleFn,
});
@override
FileSelectionButtonStyle computeDefaultValue(
BuildContext context, {
ButtonState? extra,
}) {
MultiColor backgroundColor = MultiColor.single(context.colorScheme.primary);
MultiColor foregroundColor =
MultiColor.single(context.colorScheme.onPrimary);
switch (extra?.state) {
case ControlState.disabled:
backgroundColor =
MultiColor.single(context.colorScheme.onSurface.withOpacity(0.12));
foregroundColor =
MultiColor.single(context.colorScheme.onSurface.withOpacity(0.38));
break;
case ControlState.hovered:
backgroundColor =
MultiColor.single(context.colorScheme.primary.withOpacity(0.92));
break;
case ControlState.tapped:
backgroundColor =
MultiColor.single(context.colorScheme.primary.withOpacity(0.92));
break;
case null:
case ControlState.normal:
case ControlState.focused:
break;
}
if (extra?.isInvalid ?? false) {
backgroundColor =
MultiColor.single(context.colorScheme.error);
}
return FileSelectionButtonStyle(
title: context.textTheme.labelLarge,
subTitle: context.textTheme.labelSmall,
radius: (context.buttonTheme.shape is RoundedRectangleBorder)
? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius
: null,
padding: const EdgeInsets.symmetric(horizontal: 10),
foregroundColors: foregroundColor,
backgroundColors: backgroundColor,
);
}
@override
final FileSelectionButtonStyle? Function(
BuildContext context,
FileSelectionButtonStyle defaultValue,
FileSelectionButtonThemeExtension themeExtension, {
ButtonState? extra,
}) computeExtensionValueFn;
@override
final FileSelectionButtonStyle? Function(
BuildContext context, {
ButtonState? extra,
}) customStyleFn;
}

View File

@ -0,0 +1,86 @@
// 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' hide ButtonStyle;
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/buttons/cubit/button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/flat_button/flat_button_screen.dart';
import 'package:wyatt_ui_kit/src/components/buttons/flat_button/flat_button_theme_resolver.dart';
import 'package:wyatt_ui_kit/src/core/mixin/export_bloc_mixin.dart';
part 'flat_button.g.dart';
@ComponentCopyWithExtension()
class FlatButton extends FlatButtonComponent
with $FlatButtonCWMixin, ExportBloc<ButtonCubit> {
FlatButton({
super.prefix,
super.suffix,
super.label,
super.disabledStyle,
super.normalStyle,
super.hoveredStyle,
super.focusedStyle,
super.tappedStyle,
super.onPressed,
super.mainAxisSize,
super.themeResolver,
super.key,
});
final ButtonCubit _cubit = ButtonCubit();
@override
ButtonCubit get bloc => _cubit;
@override
FlatButtonStyle? get disabledStyle => super.disabledStyle as FlatButtonStyle?;
@override
FlatButtonStyle? get normalStyle => super.normalStyle as FlatButtonStyle?;
@override
FlatButtonStyle? get hoveredStyle => super.hoveredStyle as FlatButtonStyle?;
@override
FlatButtonStyle? get focusedStyle => super.focusedStyle as FlatButtonStyle?;
@override
FlatButtonStyle? get tappedStyle => super.tappedStyle as FlatButtonStyle?;
@override
FlatButtonThemeResolver? get themeResolver =>
super.themeResolver as FlatButtonThemeResolver?;
@override
Widget build(BuildContext context) => exportBloc(
child: FlatButtonScreen(
prefix: prefix,
suffix: suffix,
label: label,
disabledStyle: disabledStyle,
normalStyle: normalStyle,
hoveredStyle: hoveredStyle,
focusedStyle: focusedStyle,
tappedStyle: tappedStyle,
onPressed: onPressed,
mainAxisSize: mainAxisSize,
themeResolver: themeResolver,
key: key,
),
);
}

View File

@ -0,0 +1,79 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'flat_button.dart';
// **************************************************************************
// ComponentCopyWithGenerator
// **************************************************************************
class $FlatButtonCWProxyImpl implements $FlatButtonComponentCWProxy {
const $FlatButtonCWProxyImpl(this._value);
final FlatButton _value;
@override
FlatButton mainAxisSize(MainAxisSize? mainAxisSize) =>
this(mainAxisSize: mainAxisSize);
@override
FlatButton prefix(Widget? prefix) => this(prefix: prefix);
@override
FlatButton suffix(Widget? suffix) => this(suffix: suffix);
@override
FlatButton label(TextWrapper? label) => this(label: label);
@override
FlatButton disabledStyle(ButtonStyle<dynamic>? disabledStyle) =>
this(disabledStyle: disabledStyle);
@override
FlatButton normalStyle(ButtonStyle<dynamic>? normalStyle) =>
this(normalStyle: normalStyle);
@override
FlatButton hoveredStyle(ButtonStyle<dynamic>? hoveredStyle) =>
this(hoveredStyle: hoveredStyle);
@override
FlatButton focusedStyle(ButtonStyle<dynamic>? focusedStyle) =>
this(focusedStyle: focusedStyle);
@override
FlatButton tappedStyle(ButtonStyle<dynamic>? tappedStyle) =>
this(tappedStyle: tappedStyle);
@override
FlatButton onPressed(void Function(ControlState)? onPressed) =>
this(onPressed: onPressed);
@override
FlatButton themeResolver(
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver) =>
this(themeResolver: themeResolver);
@override
FlatButton key(Key? key) => this(key: key);
@override
FlatButton call({
MainAxisSize? mainAxisSize,
Widget? prefix,
Widget? suffix,
TextWrapper? label,
ButtonStyle<dynamic>? disabledStyle,
ButtonStyle<dynamic>? normalStyle,
ButtonStyle<dynamic>? hoveredStyle,
ButtonStyle<dynamic>? focusedStyle,
ButtonStyle<dynamic>? tappedStyle,
void Function(ControlState)? onPressed,
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver,
Key? key,
}) =>
FlatButton(
prefix: prefix ?? _value.prefix,
suffix: suffix ?? _value.suffix,
label: label ?? _value.label,
disabledStyle: disabledStyle ?? _value.disabledStyle,
normalStyle: normalStyle ?? _value.normalStyle,
hoveredStyle: hoveredStyle ?? _value.hoveredStyle,
focusedStyle: focusedStyle ?? _value.focusedStyle,
tappedStyle: tappedStyle ?? _value.tappedStyle,
onPressed: onPressed ?? _value.onPressed,
mainAxisSize: mainAxisSize ?? _value.mainAxisSize,
themeResolver: themeResolver ?? _value.themeResolver,
key: key ?? _value.key,
);
}
mixin $FlatButtonCWMixin on Component {
$FlatButtonComponentCWProxy get copyWith =>
$FlatButtonCWProxyImpl(this as FlatButton);
}

View File

@ -0,0 +1,237 @@
// 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' hide ButtonStyle;
import 'package:flutter/services.dart';
import 'package:gap/gap.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/buttons/cubit/button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/flat_button/flat_button_theme_resolver.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart';
import 'package:wyatt_ui_kit/src/core/helpers/linear_gradient_helper.dart';
class FlatButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
const FlatButtonScreen({
this.prefix,
this.suffix,
this.label,
this.disabledStyle,
this.normalStyle,
this.hoveredStyle,
this.focusedStyle,
this.tappedStyle,
this.onPressed,
this.mainAxisSize,
this.themeResolver,
super.key,
});
final Widget? prefix;
final Widget? suffix;
final TextWrapper? label;
final MainAxisSize? mainAxisSize;
final FlatButtonStyle? disabledStyle;
final FlatButtonStyle? normalStyle;
final FlatButtonStyle? hoveredStyle;
final FlatButtonStyle? focusedStyle;
final FlatButtonStyle? tappedStyle;
final void Function(ControlState state)? onPressed;
final FlatButtonThemeResolver? themeResolver;
@override
ButtonCubit create(BuildContext context) => ButtonCubit();
/// Negotiate the theme to get a complete style.
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}) {
switch (extra) {
case ControlState.disabled:
return disabledStyle;
case ControlState.focused:
return focusedStyle;
case ControlState.hovered:
return hoveredStyle;
case ControlState.tapped:
return tappedStyle;
case ControlState.normal:
case null:
return normalStyle;
}
},
);
return resolver.negotiate(context, extra: state);
}
@override
Widget onBuild(BuildContext context, ButtonState state) {
final style = resolve(context, state.state);
return Focus(
onFocusChange: (hasFocus) =>
hasFocus ? bloc(context).onFocus() : bloc(context).onUnfocus(),
onKeyEvent: (focusNode, event) {
if (event.logicalKey == LogicalKeyboardKey.enter && state.isFocused) {
onPressed?.call(state.state);
bloc(context).onClickUpOut();
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
},
child: MouseRegion(
cursor: SystemMouseCursors.click,
onEnter: (event) {
bloc(context).onMouseEnter();
},
onExit: (event) {
bloc(context).onMouseLeave();
},
child: GestureDetector(
onTapDown: (details) {
bloc(context).onClickDown();
},
onTapUp: (details) {
onPressed?.call(state.state);
bloc(context).onClickUpIn();
},
onTapCancel: () {
onPressed?.call(state.state);
bloc(context).onClickUpOut();
},
child: DecoratedBox(
decoration: BoxDecoration(
color: style.backgroundColors?.color,
// If no border color => no default value
border: (style.borderColors != null && style.stroke != null)
? (style.borderColors?.isGradient ?? false)
? GradientBoxBorder(
gradient: LinearGradient(
colors: style.borderColors!.colors,
),
width: style.stroke!,
)
: Border.all(
color: style.borderColors!.color,
width: style.stroke!,
)
: null,
// if no gradient colors => no default value
gradient: (style.backgroundColors?.isGradient ?? false)
? LinearGradient(
colors: style.backgroundColors!.colors,
)
: null,
boxShadow: [
if (style.shadow != null) ...[style.shadow!]
],
borderRadius: style.radius,
),
child: ConstrainedBox(
constraints: const BoxConstraints(
minWidth: 88,
minHeight: 36,
), // min sizes for Material buttons
child: Padding(
padding: style.padding ?? EdgeInsets.zero,
child: Row(
mainAxisSize: mainAxisSize ?? MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if (style.foregroundColors?.color != null &&
prefix != null) ...[
ColorFiltered(
colorFilter: ColorFilter.mode(
style.foregroundColors!.color,
BlendMode.srcIn,
),
child: prefix,
)
] else ...[
prefix ?? const SizedBox.shrink()
],
Gap(style.padding?.vertical ?? 10),
/// Choose color
/// buttonStyle.label.style.color ??
/// context.textTheme.labelLarge.color
///
/// Choose gradient
/// label.gradient ??
/// buttonStyle.foregroundColor.colors ??
/// null
///
/// More infos in ThemeResolver class
if (label != null) ...[
Text(
label!.text,
style: label!.style ?? style.label,
).toGradient(
LinearGradientHelper.fromNullableColors(
label?.gradient ??
((style.foregroundColors?.isGradient ?? false)
? style.foregroundColors?.colors
: null),
),
)
],
Gap(style.padding?.vertical ?? 10),
if (style.foregroundColors?.color != null &&
suffix != null) ...[
ColorFiltered(
colorFilter: ColorFilter.mode(
style.foregroundColors!.color,
BlendMode.srcIn,
),
child: suffix,
)
] else ...[
suffix ?? const SizedBox.shrink()
],
],
),
),
),
),
),
),
);
}
}

View File

@ -0,0 +1,82 @@
// 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/wyatt_ui_kit.dart';
class FlatButtonThemeResolver extends ThemeResolver<FlatButtonStyle,
FlatButtonThemeExtension, ControlState> {
const FlatButtonThemeResolver({
required this.computeExtensionValueFn,
required this.customStyleFn,
});
/// Values taken from <https://api.flutter.dev/flutter/material/ElevatedButton/defaultStyleOf.html>
@override
FlatButtonStyle computeDefaultValue(
BuildContext context, {
ControlState? extra,
}) {
MultiColor backgroundColor = MultiColor.single(context.colorScheme.primary);
MultiColor foregroundColor =
MultiColor.single(context.colorScheme.onPrimary);
switch (extra) {
case ControlState.disabled:
backgroundColor =
MultiColor.single(context.colorScheme.onSurface.withOpacity(0.12));
foregroundColor =
MultiColor.single(context.colorScheme.onSurface.withOpacity(0.38));
break;
case ControlState.hovered:
backgroundColor =
MultiColor.single(context.colorScheme.primary.withOpacity(0.92));
break;
case ControlState.tapped:
backgroundColor =
MultiColor.single(context.colorScheme.primary.withOpacity(0.92));
break;
case null:
case ControlState.normal:
case ControlState.focused:
break;
}
return FlatButtonStyle(
label:
context.textTheme.labelLarge?.copyWith(color: foregroundColor.color),
radius: (context.buttonTheme.shape is RoundedRectangleBorder)
? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius
: null,
padding: context.buttonTheme.padding,
foregroundColors: foregroundColor,
backgroundColors: backgroundColor,
);
}
@override
final FlatButtonStyle? Function(
BuildContext context,
FlatButtonStyle defaultValue,
FlatButtonThemeExtension themeExtension, {
ControlState? extra,
}) computeExtensionValueFn;
@override
final FlatButtonStyle? Function(BuildContext context, {ControlState? extra})
customStyleFn;
}

View File

@ -0,0 +1,85 @@
// 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' hide ButtonStyle;
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/buttons/cubit/button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/simple_icon_button/simple_icon_button_theme_resolver.dart';
import 'package:wyatt_ui_kit/src/components/buttons/simple_icon_button/simple_icon_screen.dart';
import 'package:wyatt_ui_kit/src/core/mixin/export_bloc_mixin.dart';
part 'simple_icon_button.g.dart';
@ComponentCopyWithExtension()
class SimpleIconButton extends SimpleIconButtonComponent
with $SimpleIconButtonCWMixin, ExportBloc<ButtonCubit> {
SimpleIconButton({
super.icon,
super.disabledStyle,
super.normalStyle,
super.hoveredStyle,
super.focusedStyle,
super.tappedStyle,
super.onPressed,
super.themeResolver,
super.key,
});
final ButtonCubit _cubit = ButtonCubit();
@override
ButtonCubit get bloc => _cubit;
@override
SimpleIconButtonStyle? get disabledStyle =>
super.disabledStyle as SimpleIconButtonStyle?;
@override
SimpleIconButtonStyle? get normalStyle =>
super.normalStyle as SimpleIconButtonStyle?;
@override
SimpleIconButtonStyle? get hoveredStyle =>
super.hoveredStyle as SimpleIconButtonStyle?;
@override
SimpleIconButtonStyle? get focusedStyle =>
super.focusedStyle as SimpleIconButtonStyle?;
@override
SimpleIconButtonStyle? get tappedStyle =>
super.tappedStyle as SimpleIconButtonStyle?;
@override
SimpleIconButtonThemeResolver? get themeResolver =>
super.themeResolver as SimpleIconButtonThemeResolver?;
@override
Widget build(BuildContext context) => exportBloc(
child: SimpleIconButtonScreen(
icon: icon,
disabledStyle: disabledStyle,
normalStyle: normalStyle,
hoveredStyle: hoveredStyle,
focusedStyle: focusedStyle,
tappedStyle: tappedStyle,
onPressed: onPressed,
themeResolver: themeResolver,
key: key,
),
);
}

View File

@ -0,0 +1,67 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'simple_icon_button.dart';
// **************************************************************************
// ComponentCopyWithGenerator
// **************************************************************************
class $SimpleIconButtonCWProxyImpl
implements $SimpleIconButtonComponentCWProxy {
const $SimpleIconButtonCWProxyImpl(this._value);
final SimpleIconButton _value;
@override
SimpleIconButton icon(Icon? icon) => this(icon: icon);
@override
SimpleIconButton disabledStyle(ButtonStyle<dynamic>? disabledStyle) =>
this(disabledStyle: disabledStyle);
@override
SimpleIconButton normalStyle(ButtonStyle<dynamic>? normalStyle) =>
this(normalStyle: normalStyle);
@override
SimpleIconButton hoveredStyle(ButtonStyle<dynamic>? hoveredStyle) =>
this(hoveredStyle: hoveredStyle);
@override
SimpleIconButton focusedStyle(ButtonStyle<dynamic>? focusedStyle) =>
this(focusedStyle: focusedStyle);
@override
SimpleIconButton tappedStyle(ButtonStyle<dynamic>? tappedStyle) =>
this(tappedStyle: tappedStyle);
@override
SimpleIconButton onPressed(void Function(ControlState)? onPressed) =>
this(onPressed: onPressed);
@override
SimpleIconButton themeResolver(
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver) =>
this(themeResolver: themeResolver);
@override
SimpleIconButton key(Key? key) => this(key: key);
@override
SimpleIconButton call({
Icon? icon,
ButtonStyle<dynamic>? disabledStyle,
ButtonStyle<dynamic>? normalStyle,
ButtonStyle<dynamic>? hoveredStyle,
ButtonStyle<dynamic>? focusedStyle,
ButtonStyle<dynamic>? tappedStyle,
void Function(ControlState)? onPressed,
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver,
Key? key,
}) =>
SimpleIconButton(
icon: icon ?? _value.icon,
disabledStyle: disabledStyle ?? _value.disabledStyle,
normalStyle: normalStyle ?? _value.normalStyle,
hoveredStyle: hoveredStyle ?? _value.hoveredStyle,
focusedStyle: focusedStyle ?? _value.focusedStyle,
tappedStyle: tappedStyle ?? _value.tappedStyle,
onPressed: onPressed ?? _value.onPressed,
themeResolver: themeResolver ?? _value.themeResolver,
key: key ?? _value.key,
);
}
mixin $SimpleIconButtonCWMixin on Component {
$SimpleIconButtonComponentCWProxy get copyWith =>
$SimpleIconButtonCWProxyImpl(this as SimpleIconButton);
}

View File

@ -0,0 +1,82 @@
// 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/wyatt_ui_kit.dart';
class SimpleIconButtonThemeResolver extends ThemeResolver<SimpleIconButtonStyle,
SimpleIconButtonThemeExtension, ControlState> {
const SimpleIconButtonThemeResolver({
required this.computeExtensionValueFn,
required this.customStyleFn,
});
@override
SimpleIconButtonStyle computeDefaultValue(
BuildContext context, {
ControlState? extra,
}) {
MultiColor backgroundColor = MultiColor.single(context.colorScheme.primary);
MultiColor foregroundColor =
MultiColor.single(context.colorScheme.onPrimary);
switch (extra) {
case ControlState.disabled:
backgroundColor =
MultiColor.single(context.colorScheme.onSurface.withOpacity(0.12));
foregroundColor =
MultiColor.single(context.colorScheme.onSurface.withOpacity(0.38));
break;
case ControlState.hovered:
backgroundColor =
MultiColor.single(context.colorScheme.primary.withOpacity(0.92));
break;
case ControlState.tapped:
backgroundColor =
MultiColor.single(context.colorScheme.primary.withOpacity(0.92));
break;
case null:
case ControlState.normal:
case ControlState.focused:
break;
}
return SimpleIconButtonStyle(
dimension: context.buttonTheme.height,
radius: (context.buttonTheme.shape is RoundedRectangleBorder)
? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius
: null,
padding: EdgeInsets.zero,
foregroundColors: foregroundColor,
backgroundColors: backgroundColor,
);
}
@override
final SimpleIconButtonStyle? Function(
BuildContext context,
SimpleIconButtonStyle defaultValue,
SimpleIconButtonThemeExtension themeExtension, {
ControlState? extra,
}) computeExtensionValueFn;
@override
final SimpleIconButtonStyle? Function(
BuildContext context, {
ControlState? extra,
}) customStyleFn;
}

View File

@ -0,0 +1,210 @@
// 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' hide ButtonStyle;
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/buttons/cubit/button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/simple_icon_button/simple_icon_button_theme_resolver.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_icon.dart';
import 'package:wyatt_ui_kit/src/core/helpers/linear_gradient_helper.dart';
class SimpleIconButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
const SimpleIconButtonScreen({
this.icon,
this.disabledStyle,
this.normalStyle,
this.hoveredStyle,
this.focusedStyle,
this.tappedStyle,
this.onPressed,
this.themeResolver,
super.key,
});
final Icon? icon;
final SimpleIconButtonStyle? disabledStyle;
final SimpleIconButtonStyle? normalStyle;
final SimpleIconButtonStyle? hoveredStyle;
final SimpleIconButtonStyle? focusedStyle;
final SimpleIconButtonStyle? tappedStyle;
final void Function(ControlState state)? onPressed;
final SimpleIconButtonThemeResolver? themeResolver;
@override
ButtonCubit create(BuildContext context) => ButtonCubit();
/// Negotiate the theme to get a complete style.
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}) {
switch (extra) {
case ControlState.disabled:
return disabledStyle;
case ControlState.focused:
return focusedStyle;
case ControlState.hovered:
return hoveredStyle;
case ControlState.tapped:
return tappedStyle;
case ControlState.normal:
case null:
return normalStyle;
}
},
);
return resolver.negotiate(context, extra: state);
}
@override
Widget onBuild(BuildContext context, ButtonState state) {
final style = resolve(context, state.state);
return Focus(
onFocusChange: (hasFocus) =>
hasFocus ? bloc(context).onFocus() : bloc(context).onUnfocus(),
onKeyEvent: (focusNode, event) {
if (event.logicalKey == LogicalKeyboardKey.enter && state.isFocused) {
onPressed?.call(state.state);
bloc(context).onClickUpOut();
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
},
child: MouseRegion(
cursor: SystemMouseCursors.click,
onEnter: (event) {
bloc(context).onMouseEnter();
},
onExit: (event) {
bloc(context).onMouseLeave();
},
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTapDown: (details) {
bloc(context).onClickDown();
},
onTapUp: (details) {
onPressed?.call(state.state);
bloc(context).onClickUpIn();
},
onTapCancel: () {
onPressed?.call(state.state);
bloc(context).onClickUpOut();
},
child: SizedBox.square(
dimension: style.dimension,
child: AspectRatio(
aspectRatio: 1,
child: DecoratedBox(
decoration: BoxDecoration(
color: style.backgroundColors?.color,
// If no border color => no default value
border: (style.borderColors != null && style.stroke != null)
? (style.borderColors?.isGradient ?? false)
? GradientBoxBorder(
gradient: LinearGradient(
colors: style.borderColors!.colors,
),
width: style.stroke!,
)
: Border.all(
color: style.borderColors!.color,
width: style.stroke!,
)
: null,
// if no gradient colors => no default value
gradient: (style.backgroundColors?.isGradient ?? false)
? LinearGradient(
colors: style.backgroundColors!.colors,
)
: null,
boxShadow: [
if (style.shadow != null) ...[style.shadow!]
],
borderRadius: style.radius,
),
child: ConstrainedBox(
constraints: BoxConstraints(
minWidth: style.dimension ?? 30,
),
child: Padding(
padding: style.padding ?? EdgeInsets.zero,
child: Center(
/// Choose color
/// icon.color ??
/// button.foregroundColors.colors ??
/// buttonStyle.foregroundColors.colors ??
/// context.buttonTheme.onPrimary
child: Builder(
builder: (context) {
if (icon?.color != null) {
return icon!;
}
if (!(style.foregroundColors?.isGradient ?? false)) {
return ColorFiltered(
colorFilter: ColorFilter.mode(
style.foregroundColors!.color,
BlendMode.srcIn,
),
child: icon,
);
}
return icon!.toGradient(
LinearGradientHelper.fromMultiColor(
style.foregroundColors!,
),
);
},
),
),
),
),
),
),
),
),
),
);
}
}

View File

@ -0,0 +1,93 @@
// 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' hide ButtonStyle;
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/buttons/cubit/selectable_button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/symbol_button/symbol_button_screen.dart';
import 'package:wyatt_ui_kit/src/components/buttons/symbol_button/symbol_button_theme_resolver.dart';
import 'package:wyatt_ui_kit/src/core/mixin/export_bloc_mixin.dart';
part 'symbol_button.g.dart';
@ComponentCopyWithExtension()
class SymbolButton extends SymbolButtonComponent
with $SymbolButtonCWMixin, ExportBloc<SelectableButtonCubit> {
SymbolButton({
super.icon,
super.label,
super.disabledStyle,
super.normalStyle,
super.hoveredStyle,
super.focusedStyle,
super.tappedStyle,
super.selectedStyle,
super.mainAxisSize,
super.themeResolver,
super.onPressed,
super.key,
});
final SelectableButtonCubit _cubit = SelectableButtonCubit();
@override
SelectableButtonCubit get bloc => _cubit;
@override
SymbolButtonStyle? get disabledStyle =>
super.disabledStyle as SymbolButtonStyle?;
@override
SymbolButtonStyle? get normalStyle => super.normalStyle as SymbolButtonStyle?;
@override
SymbolButtonStyle? get hoveredStyle =>
super.hoveredStyle as SymbolButtonStyle?;
@override
SymbolButtonStyle? get focusedStyle =>
super.focusedStyle as SymbolButtonStyle?;
@override
SymbolButtonStyle? get tappedStyle => super.tappedStyle as SymbolButtonStyle?;
@override
SymbolButtonStyle? get selectedStyle =>
super.selectedStyle as SymbolButtonStyle?;
@override
SymbolButtonThemeResolver? get themeResolver =>
super.themeResolver as SymbolButtonThemeResolver?;
@override
Widget build(BuildContext context) => exportBloc(
child: SymbolButtonScreen(
icon: icon,
label: label,
disabledStyle: disabledStyle,
normalStyle: normalStyle,
hoveredStyle: hoveredStyle,
focusedStyle: focusedStyle,
tappedStyle: tappedStyle,
selectedStyle: selectedStyle,
onPressed: onPressed,
mainAxisSize: mainAxisSize,
themeResolver: themeResolver,
key: key,
),
);
}

View File

@ -0,0 +1,80 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'symbol_button.dart';
// **************************************************************************
// ComponentCopyWithGenerator
// **************************************************************************
class $SymbolButtonCWProxyImpl implements $SymbolButtonComponentCWProxy {
const $SymbolButtonCWProxyImpl(this._value);
final SymbolButton _value;
@override
SymbolButton mainAxisSize(MainAxisSize? mainAxisSize) =>
this(mainAxisSize: mainAxisSize);
@override
SymbolButton label(TextWrapper? label) => this(label: label);
@override
SymbolButton icon(Widget? icon) => this(icon: icon);
@override
SymbolButton disabledStyle(ButtonStyle<dynamic>? disabledStyle) =>
this(disabledStyle: disabledStyle);
@override
SymbolButton normalStyle(ButtonStyle<dynamic>? normalStyle) =>
this(normalStyle: normalStyle);
@override
SymbolButton hoveredStyle(ButtonStyle<dynamic>? hoveredStyle) =>
this(hoveredStyle: hoveredStyle);
@override
SymbolButton focusedStyle(ButtonStyle<dynamic>? focusedStyle) =>
this(focusedStyle: focusedStyle);
@override
SymbolButton tappedStyle(ButtonStyle<dynamic>? tappedStyle) =>
this(tappedStyle: tappedStyle);
@override
SymbolButton selectedStyle(ButtonStyle<dynamic>? selectedStyle) =>
this(selectedStyle: selectedStyle);
@override
SymbolButton onPressed(void Function(ControlState)? onPressed) =>
this(onPressed: onPressed);
@override
SymbolButton themeResolver(
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver) =>
this(themeResolver: themeResolver);
@override
SymbolButton key(Key? key) => this(key: key);
@override
SymbolButton call({
MainAxisSize? mainAxisSize,
TextWrapper? label,
Widget? icon,
ButtonStyle<dynamic>? disabledStyle,
ButtonStyle<dynamic>? normalStyle,
ButtonStyle<dynamic>? hoveredStyle,
ButtonStyle<dynamic>? focusedStyle,
ButtonStyle<dynamic>? tappedStyle,
ButtonStyle<dynamic>? selectedStyle,
void Function(ControlState)? onPressed,
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver,
Key? key,
}) =>
SymbolButton(
icon: icon ?? _value.icon,
label: label ?? _value.label,
disabledStyle: disabledStyle ?? _value.disabledStyle,
normalStyle: normalStyle ?? _value.normalStyle,
hoveredStyle: hoveredStyle ?? _value.hoveredStyle,
focusedStyle: focusedStyle ?? _value.focusedStyle,
tappedStyle: tappedStyle ?? _value.tappedStyle,
selectedStyle: selectedStyle ?? _value.selectedStyle,
mainAxisSize: mainAxisSize ?? _value.mainAxisSize,
themeResolver: themeResolver ?? _value.themeResolver,
onPressed: onPressed ?? _value.onPressed,
key: key ?? _value.key,
);
}
mixin $SymbolButtonCWMixin on Component {
$SymbolButtonComponentCWProxy get copyWith =>
$SymbolButtonCWProxyImpl(this as SymbolButton);
}

View File

@ -0,0 +1,245 @@
// 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' hide ButtonStyle;
import 'package:flutter/services.dart';
import 'package:gap/gap.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/buttons/cubit/button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/selectable_button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/symbol_button/symbol_button_theme_resolver.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart';
import 'package:wyatt_ui_kit/src/core/helpers/linear_gradient_helper.dart';
class SymbolButtonScreen
extends CubitScreen<SelectableButtonCubit, ButtonState> {
const SymbolButtonScreen({
this.icon,
this.label,
this.disabledStyle,
this.normalStyle,
this.hoveredStyle,
this.focusedStyle,
this.tappedStyle,
this.selectedStyle,
this.onPressed,
this.mainAxisSize,
this.themeResolver,
super.key,
});
final Widget? icon;
final TextWrapper? label;
final MainAxisSize? mainAxisSize;
final SymbolButtonStyle? disabledStyle;
final SymbolButtonStyle? normalStyle;
final SymbolButtonStyle? hoveredStyle;
final SymbolButtonStyle? focusedStyle;
final SymbolButtonStyle? tappedStyle;
final SymbolButtonStyle? selectedStyle;
final void Function(ControlState state)? onPressed;
final SymbolButtonThemeResolver? themeResolver;
@override
SelectableButtonCubit create(BuildContext context) => SelectableButtonCubit();
/// Negotiate the theme to get a complete style.
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}) {
SymbolButtonStyle? style;
switch (extra?.state) {
case ControlState.disabled:
style = disabledStyle;
break;
case ControlState.focused:
style = focusedStyle;
break;
case ControlState.hovered:
style = hoveredStyle;
break;
case ControlState.tapped:
style = tappedStyle;
break;
case ControlState.normal:
case null:
style = normalStyle;
break;
}
if (extra?.isSelected ?? false) {
style = selectedStyle;
}
return style;
},
);
return resolver.negotiate(context, extra: state);
}
@override
Widget onBuild(BuildContext context, ButtonState state) {
final style = resolve(context, state);
return Focus(
onFocusChange: (hasFocus) =>
hasFocus ? bloc(context).onFocus() : bloc(context).onUnfocus(),
onKeyEvent: (focusNode, event) {
if (event.logicalKey == LogicalKeyboardKey.enter && state.isFocused) {
onPressed?.call(state.state);
bloc(context).onClickUpOut();
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
},
child: MouseRegion(
cursor: SystemMouseCursors.click,
onEnter: (event) {
bloc(context).onMouseEnter();
},
onExit: (event) {
bloc(context).onMouseLeave();
},
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTapDown: (details) {
bloc(context).onClickDown();
},
onTapUp: (details) {
onPressed?.call(state.state);
bloc(context).onClickUpIn();
},
onTapCancel: () {
onPressed?.call(state.state);
bloc(context).onClickUpOut();
},
child: Row(
mainAxisSize: mainAxisSize ?? MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox.square(
dimension: style.dimension,
child: AspectRatio(
aspectRatio: 1,
child: DecoratedBox(
decoration: BoxDecoration(
color: style.backgroundColors?.color,
// If no border color => no default value
border:
(style.borderColors != null && style.stroke != null)
? (style.borderColors?.isGradient ?? false)
? GradientBoxBorder(
gradient: LinearGradient(
colors: style.borderColors!.colors,
),
width: style.stroke!,
)
: Border.all(
color: style.borderColors!.color,
width: style.stroke!,
)
: null,
// if no gradient colors => no default value
gradient: (style.backgroundColors?.isGradient ?? false)
? LinearGradient(
colors: style.backgroundColors!.colors,
)
: null,
boxShadow: [
if (style.shadow != null) ...[style.shadow!]
],
borderRadius: style.radius,
),
child: ConstrainedBox(
constraints: BoxConstraints(
minWidth: style.dimension ?? 60,
), // min sizes for Material buttons
child: Padding(
padding: style.padding ?? EdgeInsets.zero,
child: Center(child: icon),
),
),
),
),
),
/// Choose color
/// label.style.color ??
/// buttonStyle.label.style.color ??
/// context.textTheme.labelLarge.color
///
/// Choose gradient
/// label.gradient ??
/// buttonStyle.foregroundColor.colors ??
/// null
///
/// More infos in `negociate()` method
if (label != null) ...[
Gap(style.padding?.horizontal ?? 10),
Text(
label!.text,
style: label!.style ?? style.label,
).toGradient(
LinearGradientHelper.fromNullableColors(
label?.gradient ??
((style.foregroundColors?.isGradient ?? false)
? style.foregroundColors?.colors
: null),
),
),
],
],
),
),
),
);
}
}

View File

@ -0,0 +1,84 @@
// 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/buttons/cubit/button_cubit.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
class SymbolButtonThemeResolver extends ThemeResolver<SymbolButtonStyle,
SymbolButtonThemeExtension, ButtonState> {
const SymbolButtonThemeResolver({
required this.computeExtensionValueFn,
required this.customStyleFn,
});
@override
SymbolButtonStyle computeDefaultValue(
BuildContext context, {
ButtonState? extra,
}) {
MultiColor backgroundColor = MultiColor.single(context.colorScheme.primary);
MultiColor foregroundColor =
MultiColor.single(context.colorScheme.onPrimary);
switch (extra?.state) {
case ControlState.disabled:
backgroundColor =
MultiColor.single(context.colorScheme.onSurface.withOpacity(0.12));
foregroundColor =
MultiColor.single(context.colorScheme.onSurface.withOpacity(0.38));
break;
case ControlState.hovered:
backgroundColor =
MultiColor.single(context.colorScheme.primary.withOpacity(0.92));
break;
case ControlState.tapped:
backgroundColor =
MultiColor.single(context.colorScheme.primary.withOpacity(0.92));
break;
case null:
case ControlState.normal:
case ControlState.focused:
break;
}
return SymbolButtonStyle(
label: context.textTheme.labelLarge,
dimension: context.buttonTheme.height*1.5,
radius: (context.buttonTheme.shape is RoundedRectangleBorder)
? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius
: null,
padding: context.buttonTheme.padding,
foregroundColors: foregroundColor,
backgroundColors: backgroundColor,
);
}
@override
final SymbolButtonStyle? Function(
BuildContext context,
SymbolButtonStyle defaultValue,
SymbolButtonThemeExtension themeExtension, {
ButtonState? extra,
}) computeExtensionValueFn;
@override
final SymbolButtonStyle? Function(
BuildContext context, {
ButtonState? extra,
}) customStyleFn;
}

View File

@ -14,4 +14,5 @@
// 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 './buttons/buttons.dart';
export './cards/cards.dart';

View File

@ -16,7 +16,7 @@
import 'package:flutter/widgets.dart';
extension GradientTextExtension on Icon {
extension GradientIconExtension on Icon {
GradientIcon toGradient(Gradient? gradient) =>
GradientIcon.from(this, gradient);
}

Some files were not shown because too many files have changed in this diff Show More