Compare commits

...

2 Commits

Author SHA1 Message Date
4c08a692d2
refactor(ui_kit): move exportable bloc from mixin to widget
Some checks failed
continuous-integration/drone/push Build is failing
2023-02-16 11:55:11 +01:00
8044d07413
fix(ui_component): add style merge in Theme Resolver 2023-02-16 11:54:42 +01:00
15 changed files with 209 additions and 37 deletions

View File

@ -15,6 +15,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/src/domain/entities/theme_style.dart';
/// {@template theme_resolver} /// {@template theme_resolver}
/// In charge of theme negotiation and merge. /// In charge of theme negotiation and merge.
@ -30,7 +31,7 @@ import 'package:flutter/material.dart';
/// - If the value is mandatory: a hardcoded value in "wyatt_ui_kit" is chosen. /// - If the value is mandatory: a hardcoded value in "wyatt_ui_kit" is chosen.
/// - If not, the style is simply not applied. /// - If not, the style is simply not applied.
/// {@endtemplate} /// {@endtemplate}
abstract class ThemeResolver<S, T, E> { abstract class ThemeResolver<S extends ThemeStyle<S>, T, E> {
/// {@macro theme_resolver} /// {@macro theme_resolver}
const ThemeResolver(); const ThemeResolver();
@ -81,8 +82,13 @@ abstract class ThemeResolver<S, T, E> {
/// Choose most suitable style for a given context. /// Choose most suitable style for a given context.
S negotiate(BuildContext context, {E? extra}) { S negotiate(BuildContext context, {E? extra}) {
S style = computeDefaultValue(context, extra: extra); S style = computeDefaultValue(context, extra: extra);
style = computeExtensionValue(context, style, extra: extra) ?? style; final S? extensionStyle =
style = computeCustomValue(context, style, extra: extra) ?? style; computeExtensionValue(context, style, extra: extra);
return style;
style = style.mergeWith(extensionStyle);
final S? customStyle = computeCustomValue(context, style, extra: extra);
return style.mergeWith(customStyle);
} }
} }

View File

@ -26,7 +26,7 @@ abstract class ButtonComponent extends Component {
this.selectedStyle, this.selectedStyle,
this.invalidStyle, this.invalidStyle,
this.onPressed, this.onPressed,
this.themeResolver, super.themeResolver,
super.key, super.key,
}); });
@ -53,7 +53,4 @@ abstract class ButtonComponent extends Component {
/// Callback on button press /// Callback on button press
final void Function(ControlState state)? onPressed; final void Function(ControlState state)? onPressed;
/// Theme Resolver for this component
final ThemeResolver<dynamic, dynamic, dynamic>? themeResolver;
} }

View File

@ -16,8 +16,9 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:wyatt_ui_components/src/core/utils/multi_color.dart'; import 'package:wyatt_ui_components/src/core/utils/multi_color.dart';
import 'package:wyatt_ui_components/src/domain/entities/theme_style.dart';
abstract class ButtonStyle<T> { abstract class ButtonStyle<T> extends ThemeStyle<T> {
const ButtonStyle({ const ButtonStyle({
this.radius, this.radius,
this.padding, this.padding,

View File

@ -37,6 +37,31 @@ class FileSelectionButtonStyle extends ButtonStyle<FileSelectionButtonStyle> {
super.shadow, super.shadow,
}); });
/// Merges non-null `b` attributes in `a`
static FileSelectionButtonStyle? merge(
FileSelectionButtonStyle? a,
FileSelectionButtonStyle? b,
) {
if (b == null) {
return a?.copyWith();
}
if (a == null) {
return b.copyWith();
}
return a.copyWith(
title: b.title,
subTitle: b.subTitle,
radius: b.radius,
padding: b.padding,
foregroundColors: b.foregroundColors,
backgroundColors: b.backgroundColors,
borderColors: b.borderColors,
stroke: b.stroke,
shadow: b.shadow,
);
}
/// Used for interpolation. /// Used for interpolation.
static FileSelectionButtonStyle? lerp( static FileSelectionButtonStyle? lerp(
FileSelectionButtonStyle? a, FileSelectionButtonStyle? a,
@ -81,4 +106,15 @@ class FileSelectionButtonStyle extends ButtonStyle<FileSelectionButtonStyle> {
/// ///
/// Default to `TextTheme.labelSmall` /// Default to `TextTheme.labelSmall`
final TextStyle? subTitle; final TextStyle? subTitle;
@override
FileSelectionButtonStyle mergeWith(FileSelectionButtonStyle? other) =>
FileSelectionButtonStyle.merge(this, other)!;
@override
FileSelectionButtonStyle? lerpWith(
FileSelectionButtonStyle? other,
double t,
) =>
FileSelectionButtonStyle.lerp(this, other, t);
} }

View File

@ -36,6 +36,30 @@ class FlatButtonStyle extends ButtonStyle<FlatButtonStyle> {
super.shadow, super.shadow,
}); });
/// Merges non-null `b` attributes in `a`
static FlatButtonStyle? merge(
FlatButtonStyle? a,
FlatButtonStyle? b,
) {
if (b == null) {
return a?.copyWith();
}
if (a == null) {
return b.copyWith();
}
return a.copyWith(
label: b.label,
radius: b.radius,
padding: b.padding,
foregroundColors: b.foregroundColors,
backgroundColors: b.backgroundColors,
borderColors: b.borderColors,
stroke: b.stroke,
shadow: b.shadow,
);
}
/// Used for interpolation. /// Used for interpolation.
static FlatButtonStyle? lerp( static FlatButtonStyle? lerp(
FlatButtonStyle? a, FlatButtonStyle? a,
@ -76,6 +100,10 @@ class FlatButtonStyle extends ButtonStyle<FlatButtonStyle> {
final TextStyle? label; final TextStyle? label;
@override @override
String toString() => FlatButtonStyle mergeWith(FlatButtonStyle? other) =>
'FlatButtonStyle(label: $label), inherited: ${super.toString()}'; FlatButtonStyle.merge(this, other)!;
@override
FlatButtonStyle? lerpWith(FlatButtonStyle? other, double t) =>
FlatButtonStyle.lerp(this, other, t);
} }

View File

@ -36,6 +36,30 @@ class SimpleIconButtonStyle extends ButtonStyle<SimpleIconButtonStyle> {
super.shadow, super.shadow,
}); });
/// Merges non-null `b` attributes in `a`
static SimpleIconButtonStyle? merge(
SimpleIconButtonStyle? a,
SimpleIconButtonStyle? b,
) {
if (b == null) {
return a?.copyWith();
}
if (a == null) {
return b.copyWith();
}
return a.copyWith(
dimension: b.dimension,
radius: b.radius,
padding: b.padding,
foregroundColors: b.foregroundColors,
backgroundColors: b.backgroundColors,
borderColors: b.borderColors,
stroke: b.stroke,
shadow: b.shadow,
);
}
/// Used for interpolation. /// Used for interpolation.
static SimpleIconButtonStyle? lerp( static SimpleIconButtonStyle? lerp(
SimpleIconButtonStyle? a, SimpleIconButtonStyle? a,
@ -74,4 +98,12 @@ class SimpleIconButtonStyle extends ButtonStyle<SimpleIconButtonStyle> {
/// ///
/// Default to `context.buttonTheme.height` /// Default to `context.buttonTheme.height`
final double? dimension; final double? dimension;
@override
SimpleIconButtonStyle mergeWith(SimpleIconButtonStyle? other) =>
SimpleIconButtonStyle.merge(this, other)!;
@override
SimpleIconButtonStyle? lerpWith(SimpleIconButtonStyle? other, double t) =>
SimpleIconButtonStyle.lerp(this, other, t);
} }

View File

@ -37,6 +37,31 @@ class SymbolButtonStyle extends ButtonStyle<SymbolButtonStyle> {
super.shadow, super.shadow,
}); });
/// Merges non-null `b` attributes in `a`
static SymbolButtonStyle? merge(
SymbolButtonStyle? a,
SymbolButtonStyle? b,
) {
if (b == null) {
return a?.copyWith();
}
if (a == null) {
return b.copyWith();
}
return a.copyWith(
label: b.label,
dimension: b.dimension,
radius: b.radius,
padding: b.padding,
foregroundColors: b.foregroundColors,
backgroundColors: b.backgroundColors,
borderColors: b.borderColors,
stroke: b.stroke,
shadow: b.shadow,
);
}
/// Used for interpolation. /// Used for interpolation.
static SymbolButtonStyle? lerp( static SymbolButtonStyle? lerp(
SymbolButtonStyle? a, SymbolButtonStyle? a,
@ -81,4 +106,12 @@ class SymbolButtonStyle extends ButtonStyle<SymbolButtonStyle> {
/// ///
/// Default to `context.buttonTheme.height` /// Default to `context.buttonTheme.height`
final double? dimension; final double? dimension;
@override
SymbolButtonStyle mergeWith(SymbolButtonStyle? other) =>
SymbolButtonStyle.merge(this, other)!;
@override
SymbolButtonStyle? lerpWith(SymbolButtonStyle? other, double t) =>
SymbolButtonStyle.lerp(this, other, t);
} }

View File

@ -15,7 +15,11 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/src/core/utils/theme_resolver.dart';
abstract class Component extends StatelessWidget { abstract class Component extends StatelessWidget {
const Component({super.key}); const Component({this.themeResolver, super.key});
/// Theme Resolver for this component
final ThemeResolver<dynamic, dynamic, dynamic>? themeResolver;
} }

View File

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

View File

@ -14,13 +14,12 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/widgets.dart'; abstract class ThemeStyle<T> {
import 'package:flutter_bloc/flutter_bloc.dart'; const ThemeStyle();
mixin ExportBloc<T extends StateStreamableSource<Object?>> { /// Merges non-null `other` attributes in `this` and returns a copy.
T get bloc; T mergeWith(T? other);
Widget exportBloc({required Widget child}) => BlocProvider<T>.value(
value: bloc, /// Used for interpolation.
child: child, T? lerpWith(T? other, double t);
);
} }

View File

@ -0,0 +1,36 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class ExportableBloc<T extends StateStreamableSource<Object?>>
extends StatelessWidget {
const ExportableBloc({
required this.bloc,
required this.child,
super.key,
});
final T bloc;
final Widget child;
@override
Widget build(BuildContext context) => BlocProvider<T>.value(
value: bloc,
child: child,
);
}

View File

@ -18,15 +18,15 @@ import 'package:flutter/material.dart' hide ButtonStyle;
import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart'; import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; import 'package:wyatt_ui_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/cubit/invalid_button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/exportable_bloc.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_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/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'; part 'file_selection_button.g.dart';
@ComponentCopyWithExtension() @ComponentCopyWithExtension()
class FileSelectionButton extends FileSelectionButtonComponent class FileSelectionButton extends FileSelectionButtonComponent
with $FileSelectionButtonCWMixin, ExportBloc<InvalidButtonCubit> { with $FileSelectionButtonCWMixin {
FileSelectionButton({ FileSelectionButton({
super.leading, super.leading,
super.title, super.title,
@ -46,7 +46,6 @@ class FileSelectionButton extends FileSelectionButtonComponent
final InvalidButtonCubit _cubit = InvalidButtonCubit(); final InvalidButtonCubit _cubit = InvalidButtonCubit();
@override
InvalidButtonCubit get bloc => _cubit; InvalidButtonCubit get bloc => _cubit;
@override @override
@ -82,7 +81,8 @@ class FileSelectionButton extends FileSelectionButtonComponent
super.themeResolver as FileSelectionButtonThemeResolver?; super.themeResolver as FileSelectionButtonThemeResolver?;
@override @override
Widget build(BuildContext context) => exportBloc( Widget build(BuildContext context) => ExportableBloc(
bloc: _cubit,
child: FileSelectionButtonScreen( child: FileSelectionButtonScreen(
leading: leading, leading: leading,
title: title, title: title,

View File

@ -18,15 +18,14 @@ import 'package:flutter/material.dart' hide ButtonStyle;
import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart'; import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; import 'package:wyatt_ui_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/button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/exportable_bloc.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_screen.dart';
import 'package:wyatt_ui_kit/src/components/buttons/flat_button/flat_button_theme_resolver.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'; part 'flat_button.g.dart';
@ComponentCopyWithExtension() @ComponentCopyWithExtension()
class FlatButton extends FlatButtonComponent class FlatButton extends FlatButtonComponent with $FlatButtonCWMixin {
with $FlatButtonCWMixin, ExportBloc<ButtonCubit> {
FlatButton({ FlatButton({
super.prefix, super.prefix,
super.suffix, super.suffix,
@ -44,7 +43,6 @@ class FlatButton extends FlatButtonComponent
final ButtonCubit _cubit = ButtonCubit(); final ButtonCubit _cubit = ButtonCubit();
@override
ButtonCubit get bloc => _cubit; ButtonCubit get bloc => _cubit;
@override @override
@ -67,7 +65,8 @@ class FlatButton extends FlatButtonComponent
super.themeResolver as FlatButtonThemeResolver?; super.themeResolver as FlatButtonThemeResolver?;
@override @override
Widget build(BuildContext context) => exportBloc( Widget build(BuildContext context) => ExportableBloc(
bloc: _cubit,
child: FlatButtonScreen( child: FlatButtonScreen(
prefix: prefix, prefix: prefix,
suffix: suffix, suffix: suffix,

View File

@ -18,15 +18,15 @@ import 'package:flutter/material.dart' hide ButtonStyle;
import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart'; import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; import 'package:wyatt_ui_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/button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/exportable_bloc.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_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/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'; part 'simple_icon_button.g.dart';
@ComponentCopyWithExtension() @ComponentCopyWithExtension()
class SimpleIconButton extends SimpleIconButtonComponent class SimpleIconButton extends SimpleIconButtonComponent
with $SimpleIconButtonCWMixin, ExportBloc<ButtonCubit> { with $SimpleIconButtonCWMixin {
SimpleIconButton({ SimpleIconButton({
super.icon, super.icon,
super.disabledStyle, super.disabledStyle,
@ -41,7 +41,6 @@ class SimpleIconButton extends SimpleIconButtonComponent
final ButtonCubit _cubit = ButtonCubit(); final ButtonCubit _cubit = ButtonCubit();
@override
ButtonCubit get bloc => _cubit; ButtonCubit get bloc => _cubit;
@override @override
@ -69,7 +68,8 @@ class SimpleIconButton extends SimpleIconButtonComponent
super.themeResolver as SimpleIconButtonThemeResolver?; super.themeResolver as SimpleIconButtonThemeResolver?;
@override @override
Widget build(BuildContext context) => exportBloc( Widget build(BuildContext context) => ExportableBloc(
bloc: _cubit,
child: SimpleIconButtonScreen( child: SimpleIconButtonScreen(
icon: icon, icon: icon,
disabledStyle: disabledStyle, disabledStyle: disabledStyle,

View File

@ -18,15 +18,15 @@ import 'package:flutter/material.dart' hide ButtonStyle;
import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart'; import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; import 'package:wyatt_ui_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/cubit/selectable_button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/exportable_bloc.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_screen.dart';
import 'package:wyatt_ui_kit/src/components/buttons/symbol_button/symbol_button_theme_resolver.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'; part 'symbol_button.g.dart';
@ComponentCopyWithExtension() @ComponentCopyWithExtension()
class SymbolButton extends SymbolButtonComponent class SymbolButton extends SymbolButtonComponent
with $SymbolButtonCWMixin, ExportBloc<SelectableButtonCubit> { with $SymbolButtonCWMixin{
SymbolButton({ SymbolButton({
super.icon, super.icon,
super.label, super.label,
@ -44,7 +44,6 @@ class SymbolButton extends SymbolButtonComponent
final SelectableButtonCubit _cubit = SelectableButtonCubit(); final SelectableButtonCubit _cubit = SelectableButtonCubit();
@override
SelectableButtonCubit get bloc => _cubit; SelectableButtonCubit get bloc => _cubit;
@override @override
@ -74,7 +73,8 @@ class SymbolButton extends SymbolButtonComponent
super.themeResolver as SymbolButtonThemeResolver?; super.themeResolver as SymbolButtonThemeResolver?;
@override @override
Widget build(BuildContext context) => exportBloc( Widget build(BuildContext context) => ExportableBloc(
bloc: _cubit,
child: SymbolButtonScreen( child: SymbolButtonScreen(
icon: icon, icon: icon,
label: label, label: label,