diff --git a/mason-lock.json b/mason-lock.json index 9a9c7463..83cb506c 100644 --- a/mason-lock.json +++ b/mason-lock.json @@ -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"}}}} \ No newline at end of file +{"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"}}}} \ No newline at end of file diff --git a/mason.yaml b/mason.yaml index e0e797ee..4c3df4a0 100644 --- a/mason.yaml +++ b/mason.yaml @@ -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 . + 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 \ No newline at end of file + 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 \ No newline at end of file diff --git a/packages/wyatt_ui_components/lib/src/core/core.dart b/packages/wyatt_ui_components/lib/src/core/core.dart index 079c0687..a18f1e81 100644 --- a/packages/wyatt_ui_components/lib/src/core/core.dart +++ b/packages/wyatt_ui_components/lib/src/core/core.dart @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +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'; diff --git a/packages/wyatt_ui_components/lib/src/core/enums/control_state.dart b/packages/wyatt_ui_components/lib/src/core/enums/control_state.dart new file mode 100644 index 00000000..e4629e75 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/core/enums/control_state.dart @@ -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 . + +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; +} diff --git a/packages/wyatt_ui_components/lib/src/core/utils/multi_color.dart b/packages/wyatt_ui_components/lib/src/core/utils/multi_color.dart new file mode 100644 index 00000000..8f36e970 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/core/utils/multi_color.dart @@ -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 . + +import 'package:flutter/widgets.dart'; + +class MultiColor { + const MultiColor(this._colors) : _color = null; + const MultiColor.single(this._color) : _colors = null; + + final List? _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 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)'; +} diff --git a/packages/wyatt_ui_components/lib/src/core/utils/theme_resolver.dart b/packages/wyatt_ui_components/lib/src/core/utils/theme_resolver.dart new file mode 100644 index 00000000..cc14f747 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/core/utils/theme_resolver.dart @@ -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 . + +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 { + /// {@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(); + + /// 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; + } +} diff --git a/packages/wyatt_ui_components/lib/src/core/utils/utils.dart b/packages/wyatt_ui_components/lib/src/core/utils/utils.dart new file mode 100644 index 00000000..17821996 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/core/utils/utils.dart @@ -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 . + +export 'multi_color.dart'; +export 'text_wrapper.dart'; +export 'theme_resolver.dart'; diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/buttons/button_component.dart b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/button_component.dart new file mode 100644 index 00000000..a5c285d5 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/button_component.dart @@ -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 . + +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? disabledStyle; + + /// Style of this button in normal state + final ButtonStyle? normalStyle; + + /// Style of this button in hovered state + final ButtonStyle? hoveredStyle; + + /// Style of this button in focused state + final ButtonStyle? focusedStyle; + + /// Style of this button in tapped state + final ButtonStyle? tappedStyle; + + /// Style of this button in selected state + final ButtonStyle? selectedStyle; + + /// Style of this button in invalid state + final ButtonStyle? invalidStyle; + + /// Callback on button press + final void Function(ControlState state)? onPressed; + + /// Theme Resolver for this component + final ThemeResolver? themeResolver; +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/buttons/button_style.dart b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/button_style.dart new file mode 100644 index 00000000..de126460 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/button_style.dart @@ -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 . + +import 'package:flutter/widgets.dart'; +import 'package:wyatt_ui_components/src/core/utils/multi_color.dart'; + +abstract class ButtonStyle { + 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)'; +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/buttons/buttons.dart b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/buttons.dart new file mode 100644 index 00000000..da89e0e5 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/buttons.dart @@ -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 . + +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'; diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/buttons/file_selection_button_component.dart b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/file_selection_button_component.dart new file mode 100644 index 00000000..b0e5866b --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/file_selection_button_component.dart @@ -0,0 +1,70 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/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; +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/buttons/file_selection_button_component.g.dart b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/file_selection_button_component.g.dart new file mode 100644 index 00000000..1c9f5b2d --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/file_selection_button_component.g.dart @@ -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? disabledStyle); + FileSelectionButtonComponent normalStyle(ButtonStyle? normalStyle); + FileSelectionButtonComponent hoveredStyle(ButtonStyle? hoveredStyle); + FileSelectionButtonComponent focusedStyle(ButtonStyle? focusedStyle); + FileSelectionButtonComponent tappedStyle(ButtonStyle? tappedStyle); + FileSelectionButtonComponent selectedStyle( + ButtonStyle? selectedStyle); + FileSelectionButtonComponent invalidStyle(ButtonStyle? invalidStyle); + FileSelectionButtonComponent onPressed( + void Function(ControlState)? onPressed); + FileSelectionButtonComponent key(Key? key); + FileSelectionButtonComponent call({ + MainAxisSize? mainAxisSize, + Widget? leading, + TextWrapper? title, + TextWrapper? subTitle, + ButtonStyle? disabledStyle, + ButtonStyle? normalStyle, + ButtonStyle? hoveredStyle, + ButtonStyle? focusedStyle, + ButtonStyle? tappedStyle, + ButtonStyle? selectedStyle, + ButtonStyle? invalidStyle, + void Function(ControlState)? onPressed, + Key? key, + }); +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/buttons/file_selection_button_style.dart b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/file_selection_button_style.dart new file mode 100644 index 00000000..e543229b --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/file_selection_button_style.dart @@ -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 . + +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 { + 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; +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/buttons/file_selection_button_style.g.dart b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/file_selection_button_style.g.dart new file mode 100644 index 00000000..6576a261 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/file_selection_button_style.g.dart @@ -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); +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/buttons/flat_button_component.dart b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/flat_button_component.dart new file mode 100644 index 00000000..83420a59 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/flat_button_component.dart @@ -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 . + +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; +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/buttons/flat_button_component.g.dart b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/flat_button_component.g.dart new file mode 100644 index 00000000..e234fa3d --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/flat_button_component.g.dart @@ -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? disabledStyle); + FlatButtonComponent normalStyle(ButtonStyle? normalStyle); + FlatButtonComponent hoveredStyle(ButtonStyle? hoveredStyle); + FlatButtonComponent focusedStyle(ButtonStyle? focusedStyle); + FlatButtonComponent tappedStyle(ButtonStyle? tappedStyle); + FlatButtonComponent onPressed(void Function(ControlState)? onPressed); + FlatButtonComponent key(Key? key); + FlatButtonComponent call({ + MainAxisSize? mainAxisSize, + Widget? prefix, + Widget? suffix, + TextWrapper? label, + ButtonStyle? disabledStyle, + ButtonStyle? normalStyle, + ButtonStyle? hoveredStyle, + ButtonStyle? focusedStyle, + ButtonStyle? tappedStyle, + void Function(ControlState)? onPressed, + Key? key, + }); +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/buttons/flat_button_style.dart b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/flat_button_style.dart new file mode 100644 index 00000000..cc57472b --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/flat_button_style.dart @@ -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 . + +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 { + 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()}'; +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/buttons/flat_button_style.g.dart b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/flat_button_style.g.dart new file mode 100644 index 00000000..939a48e1 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/flat_button_style.g.dart @@ -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); +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/buttons/simple_icon_button_component.dart b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/simple_icon_button_component.dart new file mode 100644 index 00000000..b9a3c746 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/simple_icon_button_component.dart @@ -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 . + +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; +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/buttons/simple_icon_button_component.g.dart b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/simple_icon_button_component.g.dart new file mode 100644 index 00000000..b6c02777 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/simple_icon_button_component.g.dart @@ -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? disabledStyle); + SimpleIconButtonComponent normalStyle(ButtonStyle? normalStyle); + SimpleIconButtonComponent hoveredStyle(ButtonStyle? hoveredStyle); + SimpleIconButtonComponent focusedStyle(ButtonStyle? focusedStyle); + SimpleIconButtonComponent tappedStyle(ButtonStyle? tappedStyle); + SimpleIconButtonComponent onPressed(void Function(ControlState)? onPressed); + SimpleIconButtonComponent key(Key? key); + SimpleIconButtonComponent call({ + Icon? icon, + ButtonStyle? disabledStyle, + ButtonStyle? normalStyle, + ButtonStyle? hoveredStyle, + ButtonStyle? focusedStyle, + ButtonStyle? tappedStyle, + void Function(ControlState)? onPressed, + Key? key, + }); +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/buttons/simple_icon_button_style.dart b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/simple_icon_button_style.dart new file mode 100644 index 00000000..3d468e63 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/simple_icon_button_style.dart @@ -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 . + +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 { + 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; +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/buttons/simple_icon_button_style.g.dart b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/simple_icon_button_style.g.dart new file mode 100644 index 00000000..f0ee5153 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/simple_icon_button_style.g.dart @@ -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); +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/buttons/symbol_button_component.dart b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/symbol_button_component.dart new file mode 100644 index 00000000..a09255d0 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/symbol_button_component.dart @@ -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 . + +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; +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/buttons/symbol_button_component.g.dart b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/symbol_button_component.g.dart new file mode 100644 index 00000000..08422d60 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/symbol_button_component.g.dart @@ -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? disabledStyle); + SymbolButtonComponent normalStyle(ButtonStyle? normalStyle); + SymbolButtonComponent hoveredStyle(ButtonStyle? hoveredStyle); + SymbolButtonComponent focusedStyle(ButtonStyle? focusedStyle); + SymbolButtonComponent tappedStyle(ButtonStyle? tappedStyle); + SymbolButtonComponent selectedStyle(ButtonStyle? selectedStyle); + SymbolButtonComponent onPressed(void Function(ControlState)? onPressed); + SymbolButtonComponent key(Key? key); + SymbolButtonComponent call({ + MainAxisSize? mainAxisSize, + TextWrapper? label, + Widget? icon, + ButtonStyle? disabledStyle, + ButtonStyle? normalStyle, + ButtonStyle? hoveredStyle, + ButtonStyle? focusedStyle, + ButtonStyle? tappedStyle, + ButtonStyle? selectedStyle, + void Function(ControlState)? onPressed, + Key? key, + }); +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/buttons/symbol_button_style.dart b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/symbol_button_style.dart new file mode 100644 index 00000000..ab5c44b8 --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/symbol_button_style.dart @@ -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 . + +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 { + 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; +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/buttons/symbol_button_style.g.dart b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/symbol_button_style.g.dart new file mode 100644 index 00000000..a3233cec --- /dev/null +++ b/packages/wyatt_ui_components/lib/src/domain/entities/buttons/symbol_button_style.g.dart @@ -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); +} diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/cards/skill_card_component.g.dart b/packages/wyatt_ui_components/lib/src/domain/entities/cards/skill_card_component.g.dart index b6ac4c3a..a69c819d 100644 --- a/packages/wyatt_ui_components/lib/src/domain/entities/cards/skill_card_component.g.dart +++ b/packages/wyatt_ui_components/lib/src/domain/entities/cards/skill_card_component.g.dart @@ -13,6 +13,8 @@ abstract class $SkillCardComponentCWProxy { SkillCardComponent description(TextWrapper? description); SkillCardComponent skills(List? skills); SkillCardComponent leadingIcon(IconData? leadingIcon); + SkillCardComponent secondaryBackgroundColors( + Color? secondaryBackgroundColors); SkillCardComponent radius(double? radius); SkillCardComponent padding(double? padding); SkillCardComponent borderColors(List? 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? skills, IconData? leadingIcon, + Color? secondaryBackgroundColors, double? radius, double? padding, List? borderColors, @@ -39,7 +40,6 @@ abstract class $SkillCardComponentCWProxy { Size? maxSize, BoxShadow? shadow, Widget? background, - Color? secondaryBackgroundColors, Key? key, }); } diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/entities.dart b/packages/wyatt_ui_components/lib/src/domain/entities/entities.dart index 0d8a3b29..5a07411a 100644 --- a/packages/wyatt_ui_components/lib/src/domain/entities/entities.dart +++ b/packages/wyatt_ui_components/lib/src/domain/entities/entities.dart @@ -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'; diff --git a/packages/wyatt_ui_components/pubspec.yaml b/packages/wyatt_ui_components/pubspec.yaml index 42033ddd..8be94829 100644 --- a/packages/wyatt_ui_components/pubspec.yaml +++ b/packages/wyatt_ui_components/pubspec.yaml @@ -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 diff --git a/packages/wyatt_ui_kit/README.md b/packages/wyatt_ui_kit/README.md index 86e4538b..8ee9ac74 100644 --- a/packages/wyatt_ui_kit/README.md +++ b/packages/wyatt_ui_kit/README.md @@ -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. diff --git a/packages/wyatt_ui_kit/example/README.md b/packages/wyatt_ui_kit/example/README.md index 2b3fce4c..2a7d7923 100644 --- a/packages/wyatt_ui_kit/example/README.md +++ b/packages/wyatt_ui_kit/example/README.md @@ -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 \ No newline at end of file diff --git a/packages/wyatt_ui_kit/example/assets/asset_1.png b/packages/wyatt_ui_kit/example/assets/asset_1.png deleted file mode 100644 index 230d42fb..00000000 Binary files a/packages/wyatt_ui_kit/example/assets/asset_1.png and /dev/null differ diff --git a/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Black.ttf b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Black.ttf new file mode 100644 index 00000000..7bb6575c Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Black.ttf differ diff --git a/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-BlackItalic.ttf b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-BlackItalic.ttf new file mode 100644 index 00000000..172e2498 Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-BlackItalic.ttf differ diff --git a/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Bold.ttf b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Bold.ttf new file mode 100644 index 00000000..efddc834 Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Bold.ttf differ diff --git a/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-BoldItalic.ttf b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-BoldItalic.ttf new file mode 100644 index 00000000..b7d8031b Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-BoldItalic.ttf differ diff --git a/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-ExtraBold.ttf b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-ExtraBold.ttf new file mode 100644 index 00000000..30595072 Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-ExtraBold.ttf differ diff --git a/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-ExtraBoldItalic.ttf b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-ExtraBoldItalic.ttf new file mode 100644 index 00000000..c21a396b Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-ExtraBoldItalic.ttf differ diff --git a/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-ExtraLight.ttf b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-ExtraLight.ttf new file mode 100644 index 00000000..f1b405ec Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-ExtraLight.ttf differ diff --git a/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-ExtraLightItalic.ttf b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-ExtraLightItalic.ttf new file mode 100644 index 00000000..382293d2 Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-ExtraLightItalic.ttf differ diff --git a/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Italic.ttf b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Italic.ttf new file mode 100644 index 00000000..eee45ba9 Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Italic.ttf differ diff --git a/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Light.ttf b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Light.ttf new file mode 100644 index 00000000..c5dfdb76 Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Light.ttf differ diff --git a/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-LightItalic.ttf b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-LightItalic.ttf new file mode 100644 index 00000000..5bdce7fb Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-LightItalic.ttf differ diff --git a/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Medium.ttf b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Medium.ttf new file mode 100644 index 00000000..dfc7e2fc Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Medium.ttf differ diff --git a/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-MediumItalic.ttf b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-MediumItalic.ttf new file mode 100644 index 00000000..ce56883a Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-MediumItalic.ttf differ diff --git a/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Regular.ttf b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Regular.ttf new file mode 100644 index 00000000..aa9033a8 Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Regular.ttf differ diff --git a/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-SemiBold.ttf b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-SemiBold.ttf new file mode 100644 index 00000000..cbf44db9 Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-SemiBold.ttf differ diff --git a/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-SemiBoldItalic.ttf b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-SemiBoldItalic.ttf new file mode 100644 index 00000000..7f9153d2 Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-SemiBoldItalic.ttf differ diff --git a/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Thin.ttf b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Thin.ttf new file mode 100644 index 00000000..7c90a547 Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-Thin.ttf differ diff --git a/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-ThinItalic.ttf b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-ThinItalic.ttf new file mode 100644 index 00000000..94bcf553 Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/fonts/montserrat/Montserrat-ThinItalic.ttf differ diff --git a/packages/wyatt_ui_kit/example/assets/images/asset_1.png b/packages/wyatt_ui_kit/example/assets/images/asset_1.png new file mode 100644 index 00000000..6e88a0b1 Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/images/asset_1.png differ diff --git a/packages/wyatt_ui_kit/example/assets/logo.png b/packages/wyatt_ui_kit/example/assets/images/logo.png similarity index 100% rename from packages/wyatt_ui_kit/example/assets/logo.png rename to packages/wyatt_ui_kit/example/assets/images/logo.png diff --git a/packages/wyatt_ui_kit/example/assets/images/mockup_1.png b/packages/wyatt_ui_kit/example/assets/images/mockup_1.png new file mode 100644 index 00000000..ae978fa2 Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/images/mockup_1.png differ diff --git a/packages/wyatt_ui_kit/example/assets/images/mockup_2.png b/packages/wyatt_ui_kit/example/assets/images/mockup_2.png new file mode 100644 index 00000000..5eba3ad6 Binary files /dev/null and b/packages/wyatt_ui_kit/example/assets/images/mockup_2.png differ diff --git a/packages/wyatt_ui_kit/example/assets/mockup_1.png b/packages/wyatt_ui_kit/example/assets/mockup_1.png deleted file mode 100644 index 7d862198..00000000 Binary files a/packages/wyatt_ui_kit/example/assets/mockup_1.png and /dev/null differ diff --git a/packages/wyatt_ui_kit/example/assets/mockup_2.png b/packages/wyatt_ui_kit/example/assets/mockup_2.png deleted file mode 100644 index d78e5a88..00000000 Binary files a/packages/wyatt_ui_kit/example/assets/mockup_2.png and /dev/null differ diff --git a/packages/wyatt_ui_kit/example/lib/buttons/buttons.dart b/packages/wyatt_ui_kit/example/lib/buttons/buttons.dart new file mode 100644 index 00000000..959cfbfd --- /dev/null +++ b/packages/wyatt_ui_kit/example/lib/buttons/buttons.dart @@ -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 . + +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()), + ], + ); +} diff --git a/packages/wyatt_ui_kit/example/lib/buttons/file_selection_button/file_selection_buttons.dart b/packages/wyatt_ui_kit/example/lib/buttons/file_selection_button/file_selection_buttons.dart new file mode 100644 index 00000000..0f398c13 --- /dev/null +++ b/packages/wyatt_ui_kit/example/lib/buttons/file_selection_button/file_selection_buttons.dart @@ -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 . + +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), + ], + ); +} diff --git a/packages/wyatt_ui_kit/example/lib/buttons/flat_button/flat_buttons.dart b/packages/wyatt_ui_kit/example/lib/buttons/flat_button/flat_buttons.dart new file mode 100644 index 00000000..2a4d684f --- /dev/null +++ b/packages/wyatt_ui_kit/example/lib/buttons/flat_button/flat_buttons.dart @@ -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 . + +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), + ], + ); +} diff --git a/packages/wyatt_ui_kit/example/lib/buttons/simple_icon_button/simple_icon_buttons.dart b/packages/wyatt_ui_kit/example/lib/buttons/simple_icon_button/simple_icon_buttons.dart new file mode 100644 index 00000000..1de93f70 --- /dev/null +++ b/packages/wyatt_ui_kit/example/lib/buttons/simple_icon_button/simple_icon_buttons.dart @@ -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 . + +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), + ], + ); +} diff --git a/packages/wyatt_ui_kit/example/lib/buttons/symbol_button/symbol_buttons.dart b/packages/wyatt_ui_kit/example/lib/buttons/symbol_button/symbol_buttons.dart new file mode 100644 index 00000000..54aa9cb5 --- /dev/null +++ b/packages/wyatt_ui_kit/example/lib/buttons/symbol_button/symbol_buttons.dart @@ -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 . + +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), + ], + ); +} diff --git a/packages/wyatt_ui_kit/example/lib/cards/cards.dart b/packages/wyatt_ui_kit/example/lib/cards/cards.dart index c0a4fe7d..fbbf058b 100644 --- a/packages/wyatt_ui_kit/example/lib/cards/cards.dart +++ b/packages/wyatt_ui_kit/example/lib/cards/cards.dart @@ -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(), diff --git a/packages/wyatt_ui_kit/example/lib/cards/information_card/information_cards.dart b/packages/wyatt_ui_kit/example/lib/cards/information_card/information_cards.dart index e390b787..17cd4c98 100644 --- a/packages/wyatt_ui_kit/example/lib/cards/information_card/information_cards.dart +++ b/packages/wyatt_ui_kit/example/lib/cards/information_card/information_cards.dart @@ -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, ), diff --git a/packages/wyatt_ui_kit/example/lib/cards/portfolio_card/portfolio_cards.dart b/packages/wyatt_ui_kit/example/lib/cards/portfolio_card/portfolio_cards.dart index 1e36df0b..4d3a440a 100644 --- a/packages/wyatt_ui_kit/example/lib/cards/portfolio_card/portfolio_cards.dart +++ b/packages/wyatt_ui_kit/example/lib/cards/portfolio_card/portfolio_cards.dart @@ -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, ) diff --git a/packages/wyatt_ui_kit/example/lib/home.dart b/packages/wyatt_ui_kit/example/lib/home.dart index 2d2d7c20..9e156207 100644 --- a/packages/wyatt_ui_kit/example/lib/home.dart +++ b/packages/wyatt_ui_kit/example/lib/home.dart @@ -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 createState() => _HomeState(); } class _HomeState extends State { + final List 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], ), ); } diff --git a/packages/wyatt_ui_kit/example/lib/main.dart b/packages/wyatt_ui_kit/example/lib/main.dart index 70f24dac..12d39646 100644 --- a/packages/wyatt_ui_kit/example/lib/main.dart +++ b/packages/wyatt_ui_kit/example/lib/main.dart @@ -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 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: >[ - 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: >[ - 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, + ), ), ); } diff --git a/packages/wyatt_ui_kit/example/lib/theme/constants.dart b/packages/wyatt_ui_kit/example/lib/theme/constants.dart new file mode 100644 index 00000000..33152394 --- /dev/null +++ b/packages/wyatt_ui_kit/example/lib/theme/constants.dart @@ -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 . + +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]; +} diff --git a/packages/wyatt_ui_kit/example/lib/theme/file_selection_button_theme.dart b/packages/wyatt_ui_kit/example/lib/theme/file_selection_button_theme.dart new file mode 100644 index 00000000..276960d1 --- /dev/null +++ b/packages/wyatt_ui_kit/example/lib/theme/file_selection_button_theme.dart @@ -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 . + +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 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 lerp( + covariant ThemeExtension? 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), + ); + } +} diff --git a/packages/wyatt_ui_kit/example/lib/theme/flat_button_theme.dart b/packages/wyatt_ui_kit/example/lib/theme/flat_button_theme.dart new file mode 100644 index 00000000..8b8768e0 --- /dev/null +++ b/packages/wyatt_ui_kit/example/lib/theme/flat_button_theme.dart @@ -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 . + +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 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 lerp( + covariant ThemeExtension? 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), + ); + } +} diff --git a/packages/wyatt_ui_kit/example/lib/theme/simple_icon_button_theme.dart b/packages/wyatt_ui_kit/example/lib/theme/simple_icon_button_theme.dart new file mode 100644 index 00000000..3e5c7e0e --- /dev/null +++ b/packages/wyatt_ui_kit/example/lib/theme/simple_icon_button_theme.dart @@ -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 . + +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 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 lerp( + covariant ThemeExtension? 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), + ); + } +} diff --git a/packages/wyatt_ui_kit/example/lib/theme/symbol_button_theme.dart b/packages/wyatt_ui_kit/example/lib/theme/symbol_button_theme.dart new file mode 100644 index 00000000..74a9a19d --- /dev/null +++ b/packages/wyatt_ui_kit/example/lib/theme/symbol_button_theme.dart @@ -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 . + +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 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 lerp( + covariant ThemeExtension? 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), + ); + } +} diff --git a/packages/wyatt_ui_kit/example/lib/theme/themes.dart b/packages/wyatt_ui_kit/example/lib/theme/themes.dart new file mode 100644 index 00000000..ab8720fb --- /dev/null +++ b/packages/wyatt_ui_kit/example/lib/theme/themes.dart @@ -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 . + +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> 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: >[ + 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: >[ + 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(), + ], + ); +} diff --git a/packages/wyatt_ui_kit/example/macos/Podfile.lock b/packages/wyatt_ui_kit/example/macos/Podfile.lock index d1fc289f..9127443a 100644 --- a/packages/wyatt_ui_kit/example/macos/Podfile.lock +++ b/packages/wyatt_ui_kit/example/macos/Podfile.lock @@ -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 diff --git a/packages/wyatt_ui_kit/example/macos/Runner/DebugProfile.entitlements b/packages/wyatt_ui_kit/example/macos/Runner/DebugProfile.entitlements index dddb8a30..dccb3959 100644 --- a/packages/wyatt_ui_kit/example/macos/Runner/DebugProfile.entitlements +++ b/packages/wyatt_ui_kit/example/macos/Runner/DebugProfile.entitlements @@ -1,12 +1,12 @@ - - com.apple.security.app-sandbox - - com.apple.security.cs.allow-jit - - com.apple.security.network.server - - + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + diff --git a/packages/wyatt_ui_kit/example/macos/Runner/Release.entitlements b/packages/wyatt_ui_kit/example/macos/Runner/Release.entitlements index 852fa1a4..3618034f 100644 --- a/packages/wyatt_ui_kit/example/macos/Runner/Release.entitlements +++ b/packages/wyatt_ui_kit/example/macos/Runner/Release.entitlements @@ -2,6 +2,8 @@ + com.apple.security.network.client + com.apple.security.app-sandbox diff --git a/packages/wyatt_ui_kit/example/pubspec.yaml b/packages/wyatt_ui_kit/example/pubspec.yaml index 9d96d8ef..d9953115 100644 --- a/packages/wyatt_ui_kit/example/pubspec.yaml +++ b/packages/wyatt_ui_kit/example/pubspec.yaml @@ -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/ diff --git a/packages/wyatt_ui_kit/example/test/widget_test.dart b/packages/wyatt_ui_kit/example/test/widget_test.dart new file mode 100644 index 00000000..e69de29b diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/buttons.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/buttons.dart new file mode 100644 index 00000000..bf04a627 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/buttons.dart @@ -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 . + +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'; diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/cubit/button_cubit.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/cubit/button_cubit.dart new file mode 100644 index 00000000..d317a181 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/cubit/button_cubit.dart @@ -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 . + +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 { + ButtonCubit() : super(const ButtonState.initial(ControlState.normal)); + + FutureOr onMouseEnter() async { + if (state.isDisabled || state.isFreezed) { + return; + } + emit(state.copyWith(state: ControlState.hovered)); + } + + FutureOr onMouseLeave() async { + if (state.isDisabled || state.isFreezed) { + return; + } + + emit(state.copyWith(state: ControlState.normal)); + } + + FutureOr onFocus() async { + if (state.isDisabled || state.isFreezed) { + return; + } + emit(state.copyWith(state: ControlState.focused)); + } + + FutureOr onUnfocus() async { + if (state.isDisabled || state.isFreezed) { + return; + } + emit(state.copyWith(state: ControlState.normal)); + } + + FutureOr onClickDown() async { + if (state.isDisabled || state.isFreezed) { + return; + } + emit(state.copyWith(state: ControlState.tapped)); + } + + FutureOr onClickUpIn() async { + if (state.isDisabled) { + return; + } + emit(state.copyWith(state: ControlState.hovered)); + } + + FutureOr onClickUpOut() async { + if (state.isDisabled) { + return; + } + emit(state.copyWith(state: ControlState.normal)); + } + + FutureOr disable() async { + if (state.isFreezed) { + return; + } + emit(state.copyWith(state: ControlState.disabled)); + } + + FutureOr enable() async { + if (state.isFreezed) { + return; + } + emit(state.copyWith(state: ControlState.normal)); + } + + FutureOr freeze() async { + emit(state.copyWith(freezed: true)); + } + + FutureOr unfreeze() async { + emit(state.copyWith(freezed: false)); + } +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/cubit/button_state.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/cubit/button_state.dart new file mode 100644 index 00000000..1d2e5350 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/cubit/button_state.dart @@ -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 . + +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 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, + ); +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/cubit/invalid_button_cubit.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/cubit/invalid_button_cubit.dart new file mode 100644 index 00000000..30626192 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/cubit/invalid_button_cubit.dart @@ -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 . + +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 onClickUpIn() async { + if (state.isDisabled || state.isFreezed) { + return; + } + + emit( + state.copyWith( + state: ControlState.hovered, + ), + ); + } + + @override + FutureOr onClickUpOut() async { + if (state.isDisabled || state.isFreezed) { + return; + } + + emit( + state.copyWith( + state: ControlState.normal, + ), + ); + } + + FutureOr invalidate() async { + if (state.isDisabled || state.isFreezed) { + return; + } + + emit( + state.copyWith(invalid: true), + ); + } + + FutureOr fix() async { + if (state.isDisabled || state.isFreezed) { + return; + } + + emit( + state.copyWith(invalid: false), + ); + } +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/cubit/selectable_button_cubit.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/cubit/selectable_button_cubit.dart new file mode 100644 index 00000000..9b747ad4 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/cubit/selectable_button_cubit.dart @@ -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 . + +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 onClickUpIn() async { + if (state.isDisabled || state.isFreezed) { + return; + } + emit( + state.copyWith(state: ControlState.hovered, selected: !state.selected), + ); + } + + @override + FutureOr onClickUpOut() async { + if (state.isDisabled || state.isFreezed) { + return; + } + emit(state.copyWith(state: ControlState.normal, selected: !state.selected)); + } + + FutureOr select() async { + if (state.isDisabled || state.isFreezed) { + return; + } + + emit( + state.copyWith(selected: true), + ); + } + + FutureOr unselect() async { + if (state.isDisabled || state.isFreezed) { + return; + } + + emit( + state.copyWith(selected: false), + ); + } +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button.dart new file mode 100644 index 00000000..aeebaa43 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button.dart @@ -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 . + +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 { + 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, + ), + ); +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button.g.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button.g.dart new file mode 100644 index 00000000..45b7eca4 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button.g.dart @@ -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? disabledStyle) => + this(disabledStyle: disabledStyle); + @override + FileSelectionButton normalStyle(ButtonStyle? normalStyle) => + this(normalStyle: normalStyle); + @override + FileSelectionButton hoveredStyle(ButtonStyle? hoveredStyle) => + this(hoveredStyle: hoveredStyle); + @override + FileSelectionButton focusedStyle(ButtonStyle? focusedStyle) => + this(focusedStyle: focusedStyle); + @override + FileSelectionButton tappedStyle(ButtonStyle? tappedStyle) => + this(tappedStyle: tappedStyle); + @override + FileSelectionButton selectedStyle(ButtonStyle? selectedStyle) => + this(selectedStyle: selectedStyle); + @override + FileSelectionButton invalidStyle(ButtonStyle? invalidStyle) => + this(invalidStyle: invalidStyle); + @override + FileSelectionButton onPressed(void Function(ControlState)? onPressed) => + this(onPressed: onPressed); + @override + FileSelectionButton themeResolver( + ThemeResolver? themeResolver) => + this(themeResolver: themeResolver); + @override + FileSelectionButton key(Key? key) => this(key: key); + @override + FileSelectionButton call({ + MainAxisSize? mainAxisSize, + Widget? leading, + TextWrapper? title, + TextWrapper? subTitle, + ButtonStyle? disabledStyle, + ButtonStyle? normalStyle, + ButtonStyle? hoveredStyle, + ButtonStyle? focusedStyle, + ButtonStyle? tappedStyle, + ButtonStyle? selectedStyle, + ButtonStyle? invalidStyle, + void Function(ControlState)? onPressed, + ThemeResolver? 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); +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button_screen.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button_screen.dart new file mode 100644 index 00000000..b763751c --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button_screen.dart @@ -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 . + +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 { + 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), + ), + ), + ], + ], + ), + ], + ), + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button_theme_resolver.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button_theme_resolver.dart new file mode 100644 index 00000000..7c1f9634 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button_theme_resolver.dart @@ -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 . + +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; +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button.dart new file mode 100644 index 00000000..123b91c2 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button.dart @@ -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 . + +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 { + 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, + ), + ); +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button.g.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button.g.dart new file mode 100644 index 00000000..2fb990d5 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button.g.dart @@ -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? disabledStyle) => + this(disabledStyle: disabledStyle); + @override + FlatButton normalStyle(ButtonStyle? normalStyle) => + this(normalStyle: normalStyle); + @override + FlatButton hoveredStyle(ButtonStyle? hoveredStyle) => + this(hoveredStyle: hoveredStyle); + @override + FlatButton focusedStyle(ButtonStyle? focusedStyle) => + this(focusedStyle: focusedStyle); + @override + FlatButton tappedStyle(ButtonStyle? tappedStyle) => + this(tappedStyle: tappedStyle); + @override + FlatButton onPressed(void Function(ControlState)? onPressed) => + this(onPressed: onPressed); + @override + FlatButton themeResolver( + ThemeResolver? themeResolver) => + this(themeResolver: themeResolver); + @override + FlatButton key(Key? key) => this(key: key); + @override + FlatButton call({ + MainAxisSize? mainAxisSize, + Widget? prefix, + Widget? suffix, + TextWrapper? label, + ButtonStyle? disabledStyle, + ButtonStyle? normalStyle, + ButtonStyle? hoveredStyle, + ButtonStyle? focusedStyle, + ButtonStyle? tappedStyle, + void Function(ControlState)? onPressed, + ThemeResolver? 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); +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button_screen.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button_screen.dart new file mode 100644 index 00000000..b0803388 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button_screen.dart @@ -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 . + +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 { + 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() + ], + ], + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button_theme_resolver.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button_theme_resolver.dart new file mode 100644 index 00000000..c48c6b8e --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button_theme_resolver.dart @@ -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 . + +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 { + const FlatButtonThemeResolver({ + required this.computeExtensionValueFn, + required this.customStyleFn, + }); + + /// Values taken from + @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; +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/simple_icon_button/simple_icon_button.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/simple_icon_button/simple_icon_button.dart new file mode 100644 index 00000000..0322265a --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/simple_icon_button/simple_icon_button.dart @@ -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 . + +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 { + 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, + ), + ); +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/simple_icon_button/simple_icon_button.g.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/simple_icon_button/simple_icon_button.g.dart new file mode 100644 index 00000000..79bfba6a --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/simple_icon_button/simple_icon_button.g.dart @@ -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? disabledStyle) => + this(disabledStyle: disabledStyle); + @override + SimpleIconButton normalStyle(ButtonStyle? normalStyle) => + this(normalStyle: normalStyle); + @override + SimpleIconButton hoveredStyle(ButtonStyle? hoveredStyle) => + this(hoveredStyle: hoveredStyle); + @override + SimpleIconButton focusedStyle(ButtonStyle? focusedStyle) => + this(focusedStyle: focusedStyle); + @override + SimpleIconButton tappedStyle(ButtonStyle? tappedStyle) => + this(tappedStyle: tappedStyle); + @override + SimpleIconButton onPressed(void Function(ControlState)? onPressed) => + this(onPressed: onPressed); + @override + SimpleIconButton themeResolver( + ThemeResolver? themeResolver) => + this(themeResolver: themeResolver); + @override + SimpleIconButton key(Key? key) => this(key: key); + @override + SimpleIconButton call({ + Icon? icon, + ButtonStyle? disabledStyle, + ButtonStyle? normalStyle, + ButtonStyle? hoveredStyle, + ButtonStyle? focusedStyle, + ButtonStyle? tappedStyle, + void Function(ControlState)? onPressed, + ThemeResolver? 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); +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/simple_icon_button/simple_icon_button_theme_resolver.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/simple_icon_button/simple_icon_button_theme_resolver.dart new file mode 100644 index 00000000..7de436bd --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/simple_icon_button/simple_icon_button_theme_resolver.dart @@ -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 . + +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 { + 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; +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/simple_icon_button/simple_icon_screen.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/simple_icon_button/simple_icon_screen.dart new file mode 100644 index 00000000..13ea6b8b --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/simple_icon_button/simple_icon_screen.dart @@ -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 . + +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 { + 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!, + ), + ); + }, + ), + ), + ), + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/symbol_button/symbol_button.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/symbol_button/symbol_button.dart new file mode 100644 index 00000000..1a328042 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/symbol_button/symbol_button.dart @@ -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 . + +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 { + 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, + ), + ); +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/symbol_button/symbol_button.g.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/symbol_button/symbol_button.g.dart new file mode 100644 index 00000000..c7e06ab2 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/symbol_button/symbol_button.g.dart @@ -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? disabledStyle) => + this(disabledStyle: disabledStyle); + @override + SymbolButton normalStyle(ButtonStyle? normalStyle) => + this(normalStyle: normalStyle); + @override + SymbolButton hoveredStyle(ButtonStyle? hoveredStyle) => + this(hoveredStyle: hoveredStyle); + @override + SymbolButton focusedStyle(ButtonStyle? focusedStyle) => + this(focusedStyle: focusedStyle); + @override + SymbolButton tappedStyle(ButtonStyle? tappedStyle) => + this(tappedStyle: tappedStyle); + @override + SymbolButton selectedStyle(ButtonStyle? selectedStyle) => + this(selectedStyle: selectedStyle); + @override + SymbolButton onPressed(void Function(ControlState)? onPressed) => + this(onPressed: onPressed); + @override + SymbolButton themeResolver( + ThemeResolver? themeResolver) => + this(themeResolver: themeResolver); + @override + SymbolButton key(Key? key) => this(key: key); + @override + SymbolButton call({ + MainAxisSize? mainAxisSize, + TextWrapper? label, + Widget? icon, + ButtonStyle? disabledStyle, + ButtonStyle? normalStyle, + ButtonStyle? hoveredStyle, + ButtonStyle? focusedStyle, + ButtonStyle? tappedStyle, + ButtonStyle? selectedStyle, + void Function(ControlState)? onPressed, + ThemeResolver? 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); +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/symbol_button/symbol_button_screen.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/symbol_button/symbol_button_screen.dart new file mode 100644 index 00000000..2491b496 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/symbol_button/symbol_button_screen.dart @@ -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 . + +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 { + 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), + ), + ), + ], + ], + ), + ), + ), + ); + } +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/symbol_button/symbol_button_theme_resolver.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/symbol_button/symbol_button_theme_resolver.dart new file mode 100644 index 00000000..8d679e22 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/symbol_button/symbol_button_theme_resolver.dart @@ -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 . + +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 { + 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; +} diff --git a/packages/wyatt_ui_kit/lib/src/components/components.dart b/packages/wyatt_ui_kit/lib/src/components/components.dart index 75c4ba26..b696808e 100644 --- a/packages/wyatt_ui_kit/lib/src/components/components.dart +++ b/packages/wyatt_ui_kit/lib/src/components/components.dart @@ -14,4 +14,5 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +export './buttons/buttons.dart'; export './cards/cards.dart'; diff --git a/packages/wyatt_ui_kit/lib/src/components/gradients/gradient_icon.dart b/packages/wyatt_ui_kit/lib/src/components/gradients/gradient_icon.dart index 6f7864e3..a6e2a38f 100644 --- a/packages/wyatt_ui_kit/lib/src/components/gradients/gradient_icon.dart +++ b/packages/wyatt_ui_kit/lib/src/components/gradients/gradient_icon.dart @@ -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); } diff --git a/packages/wyatt_ui_kit/lib/src/core/extensions/theme_extensions.dart b/packages/wyatt_ui_kit/lib/src/core/extensions/theme_extensions.dart index 2cf2e32c..5e39a69c 100644 --- a/packages/wyatt_ui_kit/lib/src/core/extensions/theme_extensions.dart +++ b/packages/wyatt_ui_kit/lib/src/core/extensions/theme_extensions.dart @@ -16,6 +16,9 @@ import 'package:flutter/material.dart'; -extension ThemeExtension on BuildContext { +extension BuildContextThemeExtension on BuildContext { + T? themeExtension() => Theme.of(this).extension(); TextTheme get textTheme => Theme.of(this).textTheme; + ColorScheme get colorScheme => Theme.of(this).colorScheme; + ButtonThemeData get buttonTheme => Theme.of(this).buttonTheme; } diff --git a/packages/wyatt_ui_kit/lib/src/core/helpers/linear_gradient_helper.dart b/packages/wyatt_ui_kit/lib/src/core/helpers/linear_gradient_helper.dart index 7e3af2cd..e102ba2e 100644 --- a/packages/wyatt_ui_kit/lib/src/core/helpers/linear_gradient_helper.dart +++ b/packages/wyatt_ui_kit/lib/src/core/helpers/linear_gradient_helper.dart @@ -15,8 +15,12 @@ // along with this program. If not, see . import 'package:flutter/material.dart'; +import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; class LinearGradientHelper { static LinearGradient? fromNullableColors(List? colors) => colors != null ? LinearGradient(colors: colors) : null; + + static LinearGradient? fromMultiColor(MultiColor multiColor) => + multiColor.isGradient ? LinearGradient(colors: multiColor.colors) : null; } diff --git a/packages/wyatt_ui_kit/lib/src/core/mixin/export_bloc_mixin.dart b/packages/wyatt_ui_kit/lib/src/core/mixin/export_bloc_mixin.dart new file mode 100644 index 00000000..f2ae41bf --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/core/mixin/export_bloc_mixin.dart @@ -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 . + +import 'package:flutter/widgets.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +mixin ExportBloc> { + T get bloc; + Widget exportBloc({required Widget child}) => BlocProvider.value( + value: bloc, + child: child, + ); +} diff --git a/packages/wyatt_ui_kit/lib/src/domain/button_theme_extension/button_theme_extension.dart b/packages/wyatt_ui_kit/lib/src/domain/button_theme_extension/button_theme_extension.dart new file mode 100644 index 00000000..d2467ee2 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/domain/button_theme_extension/button_theme_extension.dart @@ -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 . + +export 'file_selection_button_theme_extension.dart'; +export 'flat_button_theme_extension.dart'; +export 'simple_icon_button_theme_extension.dart'; +export 'symbol_button_theme_extension.dart'; diff --git a/packages/wyatt_ui_kit/lib/src/domain/button_theme_extension/file_selection_button_theme_extension.dart b/packages/wyatt_ui_kit/lib/src/domain/button_theme_extension/file_selection_button_theme_extension.dart new file mode 100644 index 00000000..b5e882fa --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/domain/button_theme_extension/file_selection_button_theme_extension.dart @@ -0,0 +1,52 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/material.dart'; +import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; + +abstract class FileSelectionButtonThemeExtension + extends ThemeExtension { + const FileSelectionButtonThemeExtension({ + this.disabledStyle, + this.focusedStyle, + this.hoveredStyle, + this.normalStyle, + this.tappedStyle, + this.selectedStyle, + this.invalidStyle, + }); + + /// Style of this button in disabled state + final FileSelectionButtonStyle? disabledStyle; + + /// Style of this button in focused state + final FileSelectionButtonStyle? focusedStyle; + + /// Style of this button in hovered state + final FileSelectionButtonStyle? hoveredStyle; + + /// Style of this button in normal state + final FileSelectionButtonStyle? normalStyle; + + /// Style of this button in tapped state + final FileSelectionButtonStyle? tappedStyle; + + /// Style of this button in selected state + final FileSelectionButtonStyle? selectedStyle; + + /// Style of this button in invalid state + final FileSelectionButtonStyle? invalidStyle; +} diff --git a/packages/wyatt_ui_kit/lib/src/domain/button_theme_extension/flat_button_theme_extension.dart b/packages/wyatt_ui_kit/lib/src/domain/button_theme_extension/flat_button_theme_extension.dart new file mode 100644 index 00000000..c851e8a7 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/domain/button_theme_extension/flat_button_theme_extension.dart @@ -0,0 +1,44 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/material.dart'; +import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; + +abstract class FlatButtonThemeExtension + extends ThemeExtension { + const FlatButtonThemeExtension({ + this.disabledStyle, + this.focusedStyle, + this.hoveredStyle, + this.normalStyle, + this.tappedStyle, + }); + + /// Style of this button in disabled state + final FlatButtonStyle? disabledStyle; + + /// Style of this button in focused state + final FlatButtonStyle? focusedStyle; + + /// Style of this button in hovered state + final FlatButtonStyle? hoveredStyle; + + /// Style of this button in normal state + final FlatButtonStyle? normalStyle; + + /// Style of this button in tapped state + final FlatButtonStyle? tappedStyle; +} diff --git a/packages/wyatt_ui_kit/lib/src/domain/button_theme_extension/simple_icon_button_theme_extension.dart b/packages/wyatt_ui_kit/lib/src/domain/button_theme_extension/simple_icon_button_theme_extension.dart new file mode 100644 index 00000000..8912fc38 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/domain/button_theme_extension/simple_icon_button_theme_extension.dart @@ -0,0 +1,44 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/material.dart'; +import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; + +abstract class SimpleIconButtonThemeExtension + extends ThemeExtension { + const SimpleIconButtonThemeExtension({ + this.disabledStyle, + this.focusedStyle, + this.hoveredStyle, + this.normalStyle, + this.tappedStyle, + }); + + /// Style of this button in disabled state + final SimpleIconButtonStyle? disabledStyle; + + /// Style of this button in focused state + final SimpleIconButtonStyle? focusedStyle; + + /// Style of this button in hovered state + final SimpleIconButtonStyle? hoveredStyle; + + /// Style of this button in normal state + final SimpleIconButtonStyle? normalStyle; + + /// Style of this button in tapped state + final SimpleIconButtonStyle? tappedStyle; +} diff --git a/packages/wyatt_ui_kit/lib/src/domain/button_theme_extension/symbol_button_theme_extension.dart b/packages/wyatt_ui_kit/lib/src/domain/button_theme_extension/symbol_button_theme_extension.dart new file mode 100644 index 00000000..e6be4650 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/domain/button_theme_extension/symbol_button_theme_extension.dart @@ -0,0 +1,48 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/material.dart'; +import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; + +abstract class SymbolButtonThemeExtension + extends ThemeExtension { + const SymbolButtonThemeExtension({ + this.disabledStyle, + this.focusedStyle, + this.hoveredStyle, + this.normalStyle, + this.tappedStyle, + this.selectedStyle, + }); + + /// Style of this button in disabled state + final SymbolButtonStyle? disabledStyle; + + /// Style of this button in focused state + final SymbolButtonStyle? focusedStyle; + + /// Style of this button in hovered state + final SymbolButtonStyle? hoveredStyle; + + /// Style of this button in normal state + final SymbolButtonStyle? normalStyle; + + /// Style of this button in tapped state + final SymbolButtonStyle? tappedStyle; + + /// Style of this button in selected state + final SymbolButtonStyle? selectedStyle; +} diff --git a/packages/wyatt_ui_kit/lib/src/domain/domain.dart b/packages/wyatt_ui_kit/lib/src/domain/domain.dart new file mode 100644 index 00000000..901c7de9 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/domain/domain.dart @@ -0,0 +1,18 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +export 'button_theme_extension/button_theme_extension.dart'; +export 'card_theme_extension.dart'; diff --git a/packages/wyatt_ui_kit/lib/src/src.dart b/packages/wyatt_ui_kit/lib/src/src.dart index 554793d9..406639aa 100644 --- a/packages/wyatt_ui_kit/lib/src/src.dart +++ b/packages/wyatt_ui_kit/lib/src/src.dart @@ -14,22 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -// 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 . - export './components/components.dart'; export './core/core.dart'; -export './domain/card_theme_extension.dart'; +export './domain/domain.dart'; diff --git a/packages/wyatt_ui_kit/lib/wyatt_ui_kit.dart b/packages/wyatt_ui_kit/lib/wyatt_ui_kit.dart index 815ae892..61041f92 100644 --- a/packages/wyatt_ui_kit/lib/wyatt_ui_kit.dart +++ b/packages/wyatt_ui_kit/lib/wyatt_ui_kit.dart @@ -17,4 +17,6 @@ /// UIKit and Design System used in Wyatt Studio. library wyatt_ui_kit; +export 'package:wyatt_ui_components/src/core/extensions/build_context_extensions.dart'; + export './src/src.dart'; diff --git a/packages/wyatt_ui_kit/models/button_state_diagram.puml b/packages/wyatt_ui_kit/models/button_state_diagram.puml new file mode 100644 index 00000000..1f3ed7ef --- /dev/null +++ b/packages/wyatt_ui_kit/models/button_state_diagram.puml @@ -0,0 +1,12 @@ +@startuml button_state_diagram +[*] --> normal +[*] --> disabled +normal --> hovered : on mouse enter +hovered --> normal : on mouse leave +hovered --> tapped : on mouse click down +tapped --> hovered : on mouse click up in (the cursor is in button) +tapped --> normal : on mouse click up out (the cursor is out of button) +normal --> focused : on focus +focused --> normal : on unfocus +focused --> tapped : on enter press down +@enduml \ No newline at end of file diff --git a/packages/wyatt_ui_kit/models/selectable_button_state_diagram.puml b/packages/wyatt_ui_kit/models/selectable_button_state_diagram.puml new file mode 100644 index 00000000..ca56770e --- /dev/null +++ b/packages/wyatt_ui_kit/models/selectable_button_state_diagram.puml @@ -0,0 +1,14 @@ +@startuml selectable_button_state_diagram +[*] --> normal +[*] --> disabled +normal --> hovered : on mouse enter +hovered --> normal : on mouse leave +hovered --> tapped : on mouse click down +tapped --> selected : on mouse click up and the previous state was not selected +selected --> tapped : on mouse click down +tapped --> hovered : on mouse click up in (the cursor is in button) +tapped --> normal : on mouse click up out (the cursor is out of button) +normal --> focused : on focus +focused --> normal : on unfocus +focused --> tapped : on enter press down +@enduml \ No newline at end of file diff --git a/packages/wyatt_ui_kit/pubspec.yaml b/packages/wyatt_ui_kit/pubspec.yaml index 083d7fa6..319289e2 100644 --- a/packages/wyatt_ui_kit/pubspec.yaml +++ b/packages/wyatt_ui_kit/pubspec.yaml @@ -9,9 +9,17 @@ environment: sdk: ">=2.19.0 <3.0.0" dependencies: + dotted_border: ^2.0.0+3 + equatable: ^2.0.5 flutter: { sdk: flutter } - gap: ^2.0.1 flutter_animate: ^3.0.0 + flutter_bloc: ^8.1.2 + gap: ^2.0.1 + meta: ^1.8.0 + wyatt_bloc_helper: + git: + url: ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-packages.git + path: packages/wyatt_bloc_helper wyatt_component_copy_with_extension: git: url: ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-packages.git