Compare commits

..

No commits in common. "8f5e3923d6b8d7b097b27e8782295e4b696b212c" and "0d5109fc77c91e95335dca00e34813584219a58f" have entirely different histories.

122 changed files with 2287 additions and 3994 deletions

View File

@ -99,12 +99,6 @@ If you need specific settings, or pass parameters to your component, call `copyW
) )
``` ```
## Default implementation
To use this package, you have to create your own implementation of the components. You can check out [Wyatt UI Kit](https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_ui_kit) package for an example.
But default theme extensions (used in all implementations as fallback for styles) are available in `lib/src/domain/theme_extensions` folder.
## Development ## Development
> Common to this, and Wyatt UI Kit packages. > Common to this, and Wyatt UI Kit packages.

View File

@ -37,67 +37,38 @@ abstract class ThemeResolver<Style extends ThemeStyle<Style>, Extension,
/// {@macro theme_resolver} /// {@macro theme_resolver}
const ThemeResolver(); const ThemeResolver();
/// Compute extension value from a given extension. /// Compute default value from Flutter Theme or with hardcoded values.
Style computeDefaultValue(
BuildContext context, {
Extra? extra,
});
/// Compute custom style from context.
Style? Function(BuildContext context, {Extra? extra}) get customStyleFn;
/// Compute extension value from custom component extension.
Style? computeExtensionValueFn( Style? computeExtensionValueFn(
BuildContext context, BuildContext context,
Extension? themeExtension, { Extension? themeExtension, {
Extra? extra, Extra? extra,
}); });
/// Return the default extension containing Flutter's default values and
/// hardcoded values.
Extension? getDefaultExtension(BuildContext context);
/// Compute default value from Flutter Theme or with hardcoded values.
///
/// If no default value is found, it will throw a [FlutterError].
Style computeDefaultValue(
BuildContext context, {
Extra? extra,
}) {
final extension = getDefaultExtension(context);
if (extension == null) {
throw FlutterError('No default extension found for $Extension\n'
'Please provide a default extension in your theme using '
'`wyatt_ui_components` default extensions kit.');
}
final style = computeExtensionValueFn(context, extension, extra: extra);
if (style == null) {
throw FlutterError(
'No default style found for $Style in $Extension${extra != null ? ' with $extra' : ''}',
);
}
return style;
}
/// Compute custom style from context.
Style? Function(BuildContext context, {Extra? extra}) get customStyleFn;
/// Choose most suitable style for a given context. /// Choose most suitable style for a given context.
Style negotiate(BuildContext context, {Extra? extra}) { Style negotiate(BuildContext context, {Extra? extra}) {
// 1) Custom style passed in constructor (cannot be null) // 1) Custom style passed in constructor (cannot be null)
final style = computeDefaultValue(context, extra: extra); final style = computeDefaultValue(context, extra: extra);
return ThemeHelper.getElement<Style, Style>( return ThemeHelper.getElement<Style, Style>(
[ [
// 3) Default // 1) Custom style passed in constructor
style, customStyleFn(context, extra: extra),
// -> then, try to find better style, and merge it with the default
// 2) Theme extension // 2) Theme extension
computeExtensionValueFn( computeExtensionValueFn(
context, context,
Theme.of(context).extension<Extension>(), Theme.of(context).extension<Extension>(),
extra: extra, extra: extra,
), ),
// 3) Default
// -> then, try to find better style, and merge it with the one above style,
// 1) Custom style passed in constructor
customStyleFn(context, extra: extra),
], ],
transform: (value) => value, transform: (value) => value,
combine: (value, element) => value?.mergeWith(element), combine: (value, element) => value?.mergeWith(element),

View File

@ -1,17 +0,0 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'theme_extensions/theme_extensions.dart';

View File

@ -1,20 +0,0 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'file_selection_button_theme_extension_default.dart';
export 'flat_button_theme_extension_default.dart';
export 'simple_icon_button_theme_extension_default.dart';
export 'symbol_button_theme_extension_default.dart';

View File

@ -1,81 +0,0 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
/// {@template file_selection_button_theme_extension}
/// Default file selection button theme extension using Flutter's
/// default theme and opinionated defaults.
/// {@endtemplate}
class FileSelectionButtonThemeExtensionDefault
extends FileSelectionButtonThemeExtension {
/// {@macro file_selection_button_theme_extension}
const FileSelectionButtonThemeExtensionDefault({
required super.disabledStyle,
required super.focusedStyle,
required super.hoveredStyle,
required super.normalStyle,
required super.tappedStyle,
required super.selectedStyle,
required super.invalidStyle,
});
/// Creates a [FileSelectionButtonThemeExtensionDefault] given a [ThemeData]
///
/// {@macro file_selection_button_theme_extension}
factory FileSelectionButtonThemeExtensionDefault.from(ThemeData theme) {
final style = FileSelectionButtonStyle(
titleStyle: theme.textTheme.labelLarge,
subtitleStyle: theme.textTheme.labelSmall,
radius: (theme.buttonTheme.shape is RoundedRectangleBorder)
? (theme.buttonTheme.shape as RoundedRectangleBorder).borderRadius
: null,
padding: const EdgeInsets.symmetric(horizontal: 10),
foregroundColors: MultiColor.single(theme.colorScheme.onPrimary),
backgroundColors: MultiColor.single(theme.colorScheme.primary),
);
return FileSelectionButtonThemeExtensionDefault(
normalStyle: style,
focusedStyle: style,
hoveredStyle: style.copyWith(
backgroundColors:
MultiColor.single(theme.colorScheme.primary.withOpacity(0.92)),
),
tappedStyle: style.copyWith(
backgroundColors:
MultiColor.single(theme.colorScheme.primary.withOpacity(0.92)),
),
selectedStyle: style,
disabledStyle: style.copyWith(
foregroundColors:
MultiColor.single(theme.colorScheme.onSurface.withOpacity(0.12)),
backgroundColors:
MultiColor.single(theme.colorScheme.onSurface.withOpacity(0.38)),
),
invalidStyle: style,
);
}
/// Creates a [FileSelectionButtonThemeExtensionDefault] from a dark theme
factory FileSelectionButtonThemeExtensionDefault.dark() =>
FileSelectionButtonThemeExtensionDefault.from(ThemeData.dark());
/// Creates a [FileSelectionButtonThemeExtensionDefault] from a light theme
factory FileSelectionButtonThemeExtensionDefault.light() =>
FileSelectionButtonThemeExtensionDefault.from(ThemeData.light());
}

View File

@ -1,78 +0,0 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
/// {@template flat_button_theme_extension_default}
/// Default flat button theme extension using Flutter's default values.
/// {@endtemplate}
class FlatButtonThemeExtensionDefault extends FlatButtonThemeExtension {
/// {@macro flat_button_theme_extension_default}
const FlatButtonThemeExtensionDefault({
required super.disabledStyle,
required super.focusedStyle,
required super.hoveredStyle,
required super.normalStyle,
required super.tappedStyle,
});
/// Creates a [FlatButtonThemeExtensionDefault] given a [ThemeData]
///
/// {@macro flat_button_theme_extension_default}
factory FlatButtonThemeExtensionDefault.from(ThemeData theme) {
final backgroundColor = MultiColor.single(theme.colorScheme.primary);
final foregroundColor = MultiColor.single(theme.colorScheme.onPrimary);
final style = FlatButtonStyle(
labelStyle:
theme.textTheme.labelLarge?.copyWith(color: foregroundColor.color),
radius: (theme.buttonTheme.shape is RoundedRectangleBorder)
? (theme.buttonTheme.shape as RoundedRectangleBorder).borderRadius
: null,
padding: theme.buttonTheme.padding,
foregroundColors: foregroundColor,
backgroundColors: backgroundColor,
);
return FlatButtonThemeExtensionDefault(
normalStyle: style,
focusedStyle: style,
hoveredStyle: style.copyWith(
backgroundColors:
MultiColor.single(theme.colorScheme.primary.withOpacity(0.92)),
),
tappedStyle: style.copyWith(
backgroundColors:
MultiColor.single(theme.colorScheme.primary.withOpacity(0.92)),
),
disabledStyle: style.copyWith(
foregroundColors:
MultiColor.single(theme.colorScheme.onSurface.withOpacity(0.12)),
backgroundColors:
MultiColor.single(theme.colorScheme.onSurface.withOpacity(0.38)),
),
);
}
/// Creates a [FlatButtonThemeExtensionDefault] from a dark theme
factory FlatButtonThemeExtensionDefault.dark() =>
FlatButtonThemeExtensionDefault.from(ThemeData.dark());
/// Creates a [FlatButtonThemeExtensionDefault] from a light theme
factory FlatButtonThemeExtensionDefault.light() =>
FlatButtonThemeExtensionDefault.from(ThemeData.light());
}

View File

@ -1,78 +0,0 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
/// {@template simple_icon_button_theme_extension}
/// Default simple icon button theme extension using Flutter's default values.
/// {@endtemplate}
class SimpleIconButtonThemeExtensionDefault
extends SimpleIconButtonThemeExtension {
/// {@macro simple_icon_button_theme_extension}
const SimpleIconButtonThemeExtensionDefault({
required super.disabledStyle,
required super.focusedStyle,
required super.hoveredStyle,
required super.normalStyle,
required super.tappedStyle,
});
/// Creates a [SimpleIconButtonThemeExtensionDefault] given a [ThemeData]
///
/// {@macro file_selection_button_theme_extension}
factory SimpleIconButtonThemeExtensionDefault.from(ThemeData theme) {
final backgroundColor = MultiColor.single(theme.colorScheme.primary);
final foregroundColor = MultiColor.single(theme.colorScheme.onPrimary);
final style = SimpleIconButtonStyle(
dimension: theme.buttonTheme.height,
radius: (theme.buttonTheme.shape is RoundedRectangleBorder)
? (theme.buttonTheme.shape as RoundedRectangleBorder).borderRadius
: null,
padding: theme.buttonTheme.padding,
foregroundColors: foregroundColor,
backgroundColors: backgroundColor,
);
return SimpleIconButtonThemeExtensionDefault(
normalStyle: style,
focusedStyle: style,
hoveredStyle: style.copyWith(
backgroundColors:
MultiColor.single(theme.colorScheme.primary.withOpacity(0.92)),
),
tappedStyle: style.copyWith(
backgroundColors:
MultiColor.single(theme.colorScheme.primary.withOpacity(0.92)),
),
disabledStyle: style.copyWith(
foregroundColors:
MultiColor.single(theme.colorScheme.onSurface.withOpacity(0.12)),
backgroundColors:
MultiColor.single(theme.colorScheme.onSurface.withOpacity(0.38)),
),
);
}
/// Creates a [SimpleIconButtonThemeExtensionDefault] from a dark theme
factory SimpleIconButtonThemeExtensionDefault.dark() =>
SimpleIconButtonThemeExtensionDefault.from(ThemeData.dark());
/// Creates a [SimpleIconButtonThemeExtensionDefault] from a light theme
factory SimpleIconButtonThemeExtensionDefault.light() =>
SimpleIconButtonThemeExtensionDefault.from(ThemeData.light());
}

View File

@ -1,84 +0,0 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
/// {@template symbol_button_theme_extension}
/// Default symbol button theme extension using Flutter's default values.
/// {@endtemplate}
class SymbolButtonThemeExtensionDefault extends SymbolButtonThemeExtension {
/// {@macro flat_button_theme_extension}
const SymbolButtonThemeExtensionDefault({
required super.disabledStyle,
required super.focusedStyle,
required super.hoveredStyle,
required super.normalStyle,
required super.tappedStyle,
required super.selectedStyle,
});
/// Creates a [SymbolButtonThemeExtensionDefault] given a [ThemeData]
///
/// {@macro file_selection_button_theme_extension}
factory SymbolButtonThemeExtensionDefault.from(ThemeData theme) {
final backgroundColor = MultiColor.single(theme.colorScheme.primary);
final foregroundColor = MultiColor.single(theme.colorScheme.onPrimary);
final style = SymbolButtonStyle(
labelStyle:
theme.textTheme.labelLarge?.copyWith(color: foregroundColor.color),
dimension: theme.buttonTheme.height * 1.5,
radius: (theme.buttonTheme.shape is RoundedRectangleBorder)
? (theme.buttonTheme.shape as RoundedRectangleBorder).borderRadius
: null,
padding: theme.buttonTheme.padding,
foregroundColors: foregroundColor,
backgroundColors: backgroundColor,
);
return SymbolButtonThemeExtensionDefault(
normalStyle: style,
focusedStyle: style,
hoveredStyle: style.copyWith(
backgroundColors:
MultiColor.single(theme.colorScheme.primary.withOpacity(0.92)),
),
tappedStyle: style.copyWith(
backgroundColors:
MultiColor.single(theme.colorScheme.primary.withOpacity(0.92)),
),
disabledStyle: style.copyWith(
foregroundColors:
MultiColor.single(theme.colorScheme.onSurface.withOpacity(0.12)),
backgroundColors:
MultiColor.single(theme.colorScheme.onSurface.withOpacity(0.38)),
),
selectedStyle: style.copyWith(
backgroundColors:
MultiColor.single(theme.colorScheme.primary.withOpacity(0.92)),
),
);
}
/// Creates a [SymbolButtonThemeExtensionDefault] from a dark theme
factory SymbolButtonThemeExtensionDefault.dark() =>
SymbolButtonThemeExtensionDefault.from(ThemeData.dark());
/// Creates a [SymbolButtonThemeExtensionDefault] from a light theme
factory SymbolButtonThemeExtensionDefault.light() =>
SymbolButtonThemeExtensionDefault.from(ThemeData.light());
}

View File

@ -1,67 +0,0 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/src/core/utils/multi_color.dart';
import 'package:wyatt_ui_components/src/domain/theme_extensions/theme_extensions.dart';
/// {@template card_theme_extension_default}
/// Default card theme extension using Flutter's default card theme and
/// opinionated defaults.
/// {@endtemplate}
class CardThemeExtensionDefault extends CardThemeExtension {
/// {@macro card_theme_extension_default}
const CardThemeExtensionDefault({
required super.radius,
required super.padding,
required super.backgroundColors,
required super.borderColors,
required super.stroke,
required super.shadow,
required super.minSize,
required super.maxSize,
required super.titleStyle,
required super.subtitleStyle,
required super.bodyStyle,
});
/// Creates a [CardThemeExtensionDefault] from a [ThemeData]
/// and opinionated defaults.
///
/// {@macro card_theme_extension_default}
factory CardThemeExtensionDefault.from(ThemeData theme) =>
CardThemeExtensionDefault(
radius: const BorderRadius.all(Radius.circular(12)),
padding: theme.cardTheme.margin,
backgroundColors: MultiColor.single(theme.cardTheme.color),
borderColors: MultiColor.single(theme.cardTheme.color),
minSize: const Size(330, 0),
maxSize: const Size(390, double.infinity),
titleStyle: theme.textTheme.titleLarge,
subtitleStyle: theme.textTheme.titleMedium,
bodyStyle: theme.textTheme.bodyMedium,
stroke: 1,
shadow: null,
);
/// Creates a [CardThemeExtensionDefault] from a dark [ThemeData]
factory CardThemeExtensionDefault.dark() =>
CardThemeExtensionDefault.from(ThemeData.dark());
/// Creates a [CardThemeExtensionDefault] from a light [ThemeData]
factory CardThemeExtensionDefault.light() =>
CardThemeExtensionDefault.from(ThemeData.light());
}

View File

@ -1,97 +0,0 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/src/domain/entities/text_inputs/text_input_style.dart';
import 'package:wyatt_ui_components/src/domain/theme_extensions/text_input_theme_extension.dart';
/// {@template text_input_theme_extension_default}
/// The default implementation of [TextInputThemeExtension].
/// {@endtemplate}
class TextInputThemeExtensionDefault extends TextInputThemeExtension {
/// {@macro text_input_theme_extension_default}
const TextInputThemeExtensionDefault({
required super.normalStyle,
required super.focusedStyle,
required super.disabledStyle,
required super.invalidStyle,
});
/// Creates a [TextInputThemeExtensionDefault] from a [ThemeData].
///
/// {@macro text_input_theme_extension_default}
factory TextInputThemeExtensionDefault.from(ThemeData theme) {
final labelStyle = theme.textTheme.labelLarge
?.copyWith(color: theme.unselectedWidgetColor);
final hintStyle = theme.textTheme.labelLarge;
final prefixStyle = theme.textTheme.bodyMedium;
final suffixStyle = theme.textTheme.bodyMedium;
final inputStyle = theme.textTheme.bodyMedium;
final iconColor = theme.colorScheme.inversePrimary;
final prefixIconColor = theme.unselectedWidgetColor;
final suffixIconColor = theme.unselectedWidgetColor;
final borderColors = theme.unselectedWidgetColor;
final style = TextInputStyle(
labelStyle: labelStyle,
hintStyle: hintStyle,
iconColor: iconColor,
prefixIconColor: prefixIconColor,
prefixStyle: prefixStyle,
suffixStyle: suffixStyle,
suffixIconColor: suffixIconColor,
borderColors: borderColors,
inputStyle: inputStyle,
);
return TextInputThemeExtensionDefault(
normalStyle: style,
focusedStyle: style.copyWith(
prefixIconColor: theme.colorScheme.primary,
suffixIconColor: theme.colorScheme.primary,
iconColor: theme.colorScheme.primary,
borderColors: theme.colorScheme.primary,
labelStyle: labelStyle?.copyWith(color: theme.colorScheme.primary),
),
disabledStyle: style.copyWith(
labelStyle: labelStyle?.copyWith(color: theme.disabledColor),
hintStyle: hintStyle?.copyWith(color: theme.disabledColor),
prefixStyle: prefixStyle?.copyWith(color: theme.disabledColor),
suffixStyle: suffixStyle?.copyWith(color: theme.disabledColor),
inputStyle: inputStyle?.copyWith(color: theme.disabledColor),
borderColors: theme.disabledColor,
prefixIconColor: theme.disabledColor,
suffixIconColor: theme.disabledColor,
),
invalidStyle: style.copyWith(
labelStyle: theme.textTheme.labelLarge
?.copyWith(color: theme.colorScheme.error),
borderColors: theme.colorScheme.error,
),
);
}
/// Creates a [TextInputThemeExtensionDefault] from a [ThemeData.light].
factory TextInputThemeExtensionDefault.light() =>
TextInputThemeExtensionDefault.from(ThemeData.light());
/// Creates a [TextInputThemeExtensionDefault] from a [ThemeData.dark].
factory TextInputThemeExtensionDefault.dark() =>
TextInputThemeExtensionDefault.from(ThemeData.dark());
}

View File

@ -1,19 +0,0 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'button_theme_extension/button_theme_extension.dart';
export 'card_theme_extension_default.dart';
export 'text_input_theme_extension_default.dart';

View File

@ -15,4 +15,3 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
export './entities/entities.dart'; export './entities/entities.dart';
export './theme_extensions/theme_extensions.dart';

View File

@ -17,11 +17,7 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_ui_components.dart';
/// {@template button_component}
/// A button component is a component that can be pressed.
/// {@endtemplate}
abstract class ButtonComponent extends Component { abstract class ButtonComponent extends Component {
/// {@macro button_component}
const ButtonComponent({ const ButtonComponent({
this.disabledStyle, this.disabledStyle,
this.normalStyle, this.normalStyle,

View File

@ -18,11 +18,7 @@ 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'; import 'package:wyatt_ui_components/src/domain/entities/theme_style.dart';
/// {@template button_style}
/// Base class for button styles.
/// {@endtemplate}
abstract class ButtonStyle<T> extends ThemeStyle<T> { abstract class ButtonStyle<T> extends ThemeStyle<T> {
/// {@macro button_style}
const ButtonStyle({ const ButtonStyle({
this.radius, this.radius,
this.padding, this.padding,

View File

@ -24,10 +24,10 @@ part 'file_selection_button_component.g.dart';
abstract class FileSelectionButtonComponent extends ButtonComponent abstract class FileSelectionButtonComponent extends ButtonComponent
with CopyWithMixin<$FileSelectionButtonComponentCWProxy> { with CopyWithMixin<$FileSelectionButtonComponentCWProxy> {
const FileSelectionButtonComponent({ const FileSelectionButtonComponent({
this.mainAxisSize, this.mainAxisSize = MainAxisSize.min,
this.leading, this.leading,
this.title, this.title,
this.subtitle, this.subTitle,
super.disabledStyle, super.disabledStyle,
super.normalStyle, super.normalStyle,
super.hoveredStyle, super.hoveredStyle,
@ -64,15 +64,8 @@ abstract class FileSelectionButtonComponent extends ButtonComponent
@override @override
FileSelectionButtonStyle? get invalidStyle; FileSelectionButtonStyle? get invalidStyle;
/// The main axis size of the button
final MainAxisSize? mainAxisSize; final MainAxisSize? mainAxisSize;
/// The leading widget of the button
final Widget? leading; final Widget? leading;
/// The title of the button
final TextWrapper? title; final TextWrapper? title;
final TextWrapper? subTitle;
/// The subtitle of the button
final TextWrapper? subtitle;
} }

View File

@ -10,7 +10,7 @@ abstract class $FileSelectionButtonComponentCWProxy {
FileSelectionButtonComponent mainAxisSize(MainAxisSize? mainAxisSize); FileSelectionButtonComponent mainAxisSize(MainAxisSize? mainAxisSize);
FileSelectionButtonComponent leading(Widget? leading); FileSelectionButtonComponent leading(Widget? leading);
FileSelectionButtonComponent title(TextWrapper? title); FileSelectionButtonComponent title(TextWrapper? title);
FileSelectionButtonComponent subtitle(TextWrapper? subtitle); FileSelectionButtonComponent subTitle(TextWrapper? subTitle);
FileSelectionButtonComponent disabledStyle( FileSelectionButtonComponent disabledStyle(
ButtonStyle<dynamic>? disabledStyle); ButtonStyle<dynamic>? disabledStyle);
FileSelectionButtonComponent normalStyle(ButtonStyle<dynamic>? normalStyle); FileSelectionButtonComponent normalStyle(ButtonStyle<dynamic>? normalStyle);
@ -30,7 +30,7 @@ abstract class $FileSelectionButtonComponentCWProxy {
MainAxisSize? mainAxisSize, MainAxisSize? mainAxisSize,
Widget? leading, Widget? leading,
TextWrapper? title, TextWrapper? title,
TextWrapper? subtitle, TextWrapper? subTitle,
ButtonStyle<dynamic>? disabledStyle, ButtonStyle<dynamic>? disabledStyle,
ButtonStyle<dynamic>? normalStyle, ButtonStyle<dynamic>? normalStyle,
ButtonStyle<dynamic>? hoveredStyle, ButtonStyle<dynamic>? hoveredStyle,

View File

@ -20,16 +20,10 @@ 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/buttons/button_style.dart'; import 'package:wyatt_ui_components/src/domain/entities/buttons/button_style.dart';
/// {@template file_selection_button_style}
/// File selection button style.
///
/// This style is used for the FileSelectionButton widget.
/// {@endtemplate}
class FileSelectionButtonStyle extends ButtonStyle<FileSelectionButtonStyle> { class FileSelectionButtonStyle extends ButtonStyle<FileSelectionButtonStyle> {
/// {@macro file_selection_button_style}
const FileSelectionButtonStyle({ const FileSelectionButtonStyle({
this.titleStyle, this.title,
this.subtitleStyle, this.subTitle,
super.radius, super.radius,
super.padding, super.padding,
super.foregroundColors, super.foregroundColors,
@ -52,8 +46,8 @@ class FileSelectionButtonStyle extends ButtonStyle<FileSelectionButtonStyle> {
} }
return a.copyWith( return a.copyWith(
titleStyle: b.titleStyle, title: b.title,
subtitleStyle: b.subtitleStyle, subTitle: b.subTitle,
radius: b.radius, radius: b.radius,
padding: b.padding, padding: b.padding,
foregroundColors: b.foregroundColors, foregroundColors: b.foregroundColors,
@ -75,8 +69,8 @@ class FileSelectionButtonStyle extends ButtonStyle<FileSelectionButtonStyle> {
} }
// b.copyWith to return b attributes even if they are not lerped // b.copyWith to return b attributes even if they are not lerped
return b.copyWith( return b.copyWith(
titleStyle: TextStyle.lerp(a.titleStyle, b.titleStyle, t), title: TextStyle.lerp(a.title, b.title, t),
subtitleStyle: TextStyle.lerp(a.subtitleStyle, b.subtitleStyle, t), subTitle: TextStyle.lerp(a.title, b.title, t),
foregroundColors: MultiColor.lerp( foregroundColors: MultiColor.lerp(
a.foregroundColors, a.foregroundColors,
b.foregroundColors, b.foregroundColors,
@ -102,12 +96,12 @@ class FileSelectionButtonStyle extends ButtonStyle<FileSelectionButtonStyle> {
/// Title text style /// Title text style
/// ///
/// Default to `TextTheme.labelLarge` /// Default to `TextTheme.labelLarge`
final TextStyle? titleStyle; final TextStyle? title;
/// Sub title text style /// Sub title text style
/// ///
/// Default to `TextTheme.labelSmall` /// Default to `TextTheme.labelSmall`
final TextStyle? subtitleStyle; final TextStyle? subTitle;
@override @override
FileSelectionButtonStyle? mergeWith(FileSelectionButtonStyle? other) => FileSelectionButtonStyle? mergeWith(FileSelectionButtonStyle? other) =>
@ -115,8 +109,8 @@ class FileSelectionButtonStyle extends ButtonStyle<FileSelectionButtonStyle> {
@override @override
FileSelectionButtonStyle? copyWith({ FileSelectionButtonStyle? copyWith({
TextStyle? titleStyle, TextStyle? title,
TextStyle? subtitleStyle, TextStyle? subTitle,
BorderRadiusGeometry? radius, BorderRadiusGeometry? radius,
EdgeInsetsGeometry? padding, EdgeInsetsGeometry? padding,
MultiColor? foregroundColors, MultiColor? foregroundColors,
@ -126,8 +120,8 @@ class FileSelectionButtonStyle extends ButtonStyle<FileSelectionButtonStyle> {
BoxShadow? shadow, BoxShadow? shadow,
}) => }) =>
FileSelectionButtonStyle( FileSelectionButtonStyle(
titleStyle: titleStyle ?? this.titleStyle, title: title ?? this.title,
subtitleStyle: subtitleStyle ?? this.subtitleStyle, subTitle: subTitle ?? this.subTitle,
radius: radius ?? this.radius, radius: radius ?? this.radius,
padding: padding ?? this.padding, padding: padding ?? this.padding,
foregroundColors: foregroundColors ?? this.foregroundColors, foregroundColors: foregroundColors ?? this.foregroundColors,

View File

@ -54,15 +54,8 @@ abstract class FlatButtonComponent extends ButtonComponent
@override @override
FlatButtonStyle? get tappedStyle; FlatButtonStyle? get tappedStyle;
/// The main axis size of the button.
final MainAxisSize? mainAxisSize; final MainAxisSize? mainAxisSize;
/// The prefix widget of the button.
final Widget? prefix; final Widget? prefix;
/// The suffix widget of the button.
final Widget? suffix; final Widget? suffix;
/// The label widget of the button.
final TextWrapper? label; final TextWrapper? label;
} }

View File

@ -20,15 +20,9 @@ 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/buttons/button_style.dart'; import 'package:wyatt_ui_components/src/domain/entities/buttons/button_style.dart';
/// {@template flat_button_style}
/// Flat button style.
///
/// This style is used for the FlatButton widget.
/// {@endtemplate}
class FlatButtonStyle extends ButtonStyle<FlatButtonStyle> { class FlatButtonStyle extends ButtonStyle<FlatButtonStyle> {
/// {@macro flat_button_style}
const FlatButtonStyle({ const FlatButtonStyle({
this.labelStyle, this.label,
super.radius, super.radius,
super.padding, super.padding,
super.foregroundColors, super.foregroundColors,
@ -51,7 +45,7 @@ class FlatButtonStyle extends ButtonStyle<FlatButtonStyle> {
} }
return a.copyWith( return a.copyWith(
labelStyle: b.labelStyle, label: b.label,
radius: b.radius, radius: b.radius,
padding: b.padding, padding: b.padding,
foregroundColors: b.foregroundColors, foregroundColors: b.foregroundColors,
@ -73,7 +67,7 @@ class FlatButtonStyle extends ButtonStyle<FlatButtonStyle> {
} }
// b.copyWith to return b attributes even if they are not lerped // b.copyWith to return b attributes even if they are not lerped
return b.copyWith( return b.copyWith(
labelStyle: TextStyle.lerp(a.labelStyle, b.labelStyle, t), label: TextStyle.lerp(a.label, b.label, t),
foregroundColors: MultiColor.lerp( foregroundColors: MultiColor.lerp(
a.foregroundColors, a.foregroundColors,
b.foregroundColors, b.foregroundColors,
@ -96,10 +90,10 @@ class FlatButtonStyle extends ButtonStyle<FlatButtonStyle> {
); );
} }
/// labelStyle text style /// Label text style
/// ///
/// Default to `TextTheme.labelLarge` /// Default to `TextTheme.labelLarge`
final TextStyle? labelStyle; final TextStyle? label;
@override @override
FlatButtonStyle? mergeWith(FlatButtonStyle? other) => FlatButtonStyle? mergeWith(FlatButtonStyle? other) =>
@ -107,7 +101,7 @@ class FlatButtonStyle extends ButtonStyle<FlatButtonStyle> {
@override @override
FlatButtonStyle? copyWith({ FlatButtonStyle? copyWith({
TextStyle? labelStyle, TextStyle? label,
BorderRadiusGeometry? radius, BorderRadiusGeometry? radius,
EdgeInsetsGeometry? padding, EdgeInsetsGeometry? padding,
MultiColor? foregroundColors, MultiColor? foregroundColors,
@ -117,7 +111,7 @@ class FlatButtonStyle extends ButtonStyle<FlatButtonStyle> {
BoxShadow? shadow, BoxShadow? shadow,
}) => }) =>
FlatButtonStyle( FlatButtonStyle(
labelStyle: labelStyle ?? this.labelStyle, label: label ?? this.label,
radius: radius ?? this.radius, radius: radius ?? this.radius,
padding: padding ?? this.padding, padding: padding ?? this.padding,
foregroundColors: foregroundColors ?? this.foregroundColors, foregroundColors: foregroundColors ?? this.foregroundColors,

View File

@ -51,6 +51,5 @@ abstract class SimpleIconButtonComponent extends ButtonComponent
@override @override
SimpleIconButtonStyle? get tappedStyle; SimpleIconButtonStyle? get tappedStyle;
/// The icon to display inside the button. final Icon? icon;
final Widget? icon;
} }

View File

@ -7,7 +7,7 @@ part of 'simple_icon_button_component.dart';
// ************************************************************************** // **************************************************************************
abstract class $SimpleIconButtonComponentCWProxy { abstract class $SimpleIconButtonComponentCWProxy {
SimpleIconButtonComponent icon(Widget? icon); SimpleIconButtonComponent icon(Icon? icon);
SimpleIconButtonComponent disabledStyle(ButtonStyle<dynamic>? disabledStyle); SimpleIconButtonComponent disabledStyle(ButtonStyle<dynamic>? disabledStyle);
SimpleIconButtonComponent normalStyle(ButtonStyle<dynamic>? normalStyle); SimpleIconButtonComponent normalStyle(ButtonStyle<dynamic>? normalStyle);
SimpleIconButtonComponent hoveredStyle(ButtonStyle<dynamic>? hoveredStyle); SimpleIconButtonComponent hoveredStyle(ButtonStyle<dynamic>? hoveredStyle);
@ -19,7 +19,7 @@ abstract class $SimpleIconButtonComponentCWProxy {
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver); ThemeResolver<dynamic, dynamic, dynamic>? themeResolver);
SimpleIconButtonComponent key(Key? key); SimpleIconButtonComponent key(Key? key);
SimpleIconButtonComponent call({ SimpleIconButtonComponent call({
Widget? icon, Icon? icon,
ButtonStyle<dynamic>? disabledStyle, ButtonStyle<dynamic>? disabledStyle,
ButtonStyle<dynamic>? normalStyle, ButtonStyle<dynamic>? normalStyle,
ButtonStyle<dynamic>? hoveredStyle, ButtonStyle<dynamic>? hoveredStyle,

View File

@ -20,13 +20,7 @@ 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/buttons/button_style.dart'; import 'package:wyatt_ui_components/src/domain/entities/buttons/button_style.dart';
/// {@template simple_icon_button_style}
/// Simple icon button style.
///
/// This style is used for the SimpleIconButton widget.
/// {@endtemplate}
class SimpleIconButtonStyle extends ButtonStyle<SimpleIconButtonStyle> { class SimpleIconButtonStyle extends ButtonStyle<SimpleIconButtonStyle> {
/// {@macro simple_icon_button_style}
const SimpleIconButtonStyle({ const SimpleIconButtonStyle({
this.dimension, this.dimension,
super.radius, super.radius,

View File

@ -24,7 +24,7 @@ part 'symbol_button_component.g.dart';
abstract class SymbolButtonComponent extends ButtonComponent abstract class SymbolButtonComponent extends ButtonComponent
with CopyWithMixin<$SymbolButtonComponentCWProxy> { with CopyWithMixin<$SymbolButtonComponentCWProxy> {
const SymbolButtonComponent({ const SymbolButtonComponent({
this.mainAxisSize, this.mainAxisSize = MainAxisSize.min,
this.label, this.label,
this.icon, this.icon,
super.disabledStyle, super.disabledStyle,
@ -57,12 +57,7 @@ abstract class SymbolButtonComponent extends ButtonComponent
@override @override
SymbolButtonStyle? get selectedStyle; SymbolButtonStyle? get selectedStyle;
/// The main axis size of the button.
final MainAxisSize? mainAxisSize; final MainAxisSize? mainAxisSize;
/// The icon widget of the button.
final Widget? icon; final Widget? icon;
/// The label widget of the button.
final TextWrapper? label; final TextWrapper? label;
} }

View File

@ -20,15 +20,9 @@ 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/buttons/button_style.dart'; import 'package:wyatt_ui_components/src/domain/entities/buttons/button_style.dart';
/// {@template symbol_button_style}
/// Symbol button style.
///
/// This style is used for the SymbolButton widget.
/// {@endtemplate}
class SymbolButtonStyle extends ButtonStyle<SymbolButtonStyle> { class SymbolButtonStyle extends ButtonStyle<SymbolButtonStyle> {
/// {@macro symbol_button_style}
const SymbolButtonStyle({ const SymbolButtonStyle({
this.labelStyle, this.label,
this.dimension, this.dimension,
super.radius, super.radius,
super.padding, super.padding,
@ -52,7 +46,7 @@ class SymbolButtonStyle extends ButtonStyle<SymbolButtonStyle> {
} }
return a.copyWith( return a.copyWith(
labelStyle: b.labelStyle, label: b.label,
dimension: b.dimension, dimension: b.dimension,
radius: b.radius, radius: b.radius,
padding: b.padding, padding: b.padding,
@ -75,7 +69,7 @@ class SymbolButtonStyle extends ButtonStyle<SymbolButtonStyle> {
} }
// b.copyWith to return b attributes even if they are not lerped // b.copyWith to return b attributes even if they are not lerped
return b.copyWith( return b.copyWith(
labelStyle: TextStyle.lerp(a.labelStyle, b.labelStyle, t), label: TextStyle.lerp(a.label, b.label, t),
dimension: lerpDouble(a.dimension, b.dimension, t), dimension: lerpDouble(a.dimension, b.dimension, t),
foregroundColors: MultiColor.lerp( foregroundColors: MultiColor.lerp(
a.foregroundColors, a.foregroundColors,
@ -99,10 +93,10 @@ class SymbolButtonStyle extends ButtonStyle<SymbolButtonStyle> {
); );
} }
/// labelStyle text style /// Label text style
/// ///
/// Default to `TextTheme.labelLarge` /// Default to `TextTheme.labelLarge`
final TextStyle? labelStyle; final TextStyle? label;
/// Dimension of this button (as a square) /// Dimension of this button (as a square)
/// ///
@ -115,7 +109,7 @@ class SymbolButtonStyle extends ButtonStyle<SymbolButtonStyle> {
@override @override
SymbolButtonStyle? copyWith({ SymbolButtonStyle? copyWith({
TextStyle? labelStyle, TextStyle? label,
double? dimension, double? dimension,
BorderRadiusGeometry? radius, BorderRadiusGeometry? radius,
EdgeInsetsGeometry? padding, EdgeInsetsGeometry? padding,
@ -126,7 +120,7 @@ class SymbolButtonStyle extends ButtonStyle<SymbolButtonStyle> {
BoxShadow? shadow, BoxShadow? shadow,
}) => }) =>
SymbolButtonStyle( SymbolButtonStyle(
labelStyle: labelStyle ?? this.labelStyle, label: label ?? this.label,
dimension: dimension ?? this.dimension, dimension: dimension ?? this.dimension,
radius: radius ?? this.radius, radius: radius ?? this.radius,
padding: padding ?? this.padding, padding: padding ?? this.padding,

View File

@ -18,81 +18,43 @@ 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/component.dart'; import 'package:wyatt_ui_components/src/domain/entities/component.dart';
/// {@template card_component}
/// Card component.
/// Used to display a card with a background and a shadow.
/// {@endtemplate}
abstract class CardComponent extends Component { abstract class CardComponent extends Component {
const CardComponent({ const CardComponent({
this.radius, this.radius = 12,
this.padding, this.padding = 25,
this.backgroundColors,
this.borderColors, this.borderColors,
this.stroke, this.backgroundColors,
this.minSize, this.minSize = const Size(330, 230),
this.maxSize, this.maxSize = const Size(330, 530),
this.shadow, this.shadow = const BoxShadow(
this.titleStyle, blurRadius: 30,
this.subtitleStyle, offset: Offset(0, 5),
this.bodyStyle, color: Color.fromRGBO(0, 0, 0, 0.05),
),
this.background, this.background,
super.key, super.key,
}); });
/// Card radius /// Card radius
/// final double? radius;
/// Default to `BorderRadius.all(Radius.circular(12.0))`
final BorderRadiusGeometry? radius;
/// Padding and gaps of this card /// Padding and gaps of this card
/// final double? padding;
/// Default to `Theme.cardTheme.margin`
final EdgeInsetsGeometry? padding;
/// Card background gradient colors (from left to right) /// Border gradient color (from left to right)
///
/// Default to `Theme.cardTheme.color`
final MultiColor? backgroundColors;
/// Border colors (from left to right).
///
/// Default to `null`
final MultiColor? borderColors; final MultiColor? borderColors;
/// Stroke of the border /// Card background color
/// final MultiColor? backgroundColors;
/// Default to `null`
final double? stroke;
/// Drop shadow /// Minimum size for this card
///
/// Default to `null`
final BoxShadow? shadow;
/// Minimum size of the card
///
/// Default to `const Size(330, double.infinity)`
final Size? minSize; final Size? minSize;
/// Maximum size of the card /// Maximum size for this card
///
/// Default to `const Size(double.infinity, double.infinity)`
final Size? maxSize; final Size? maxSize;
/// Title text style /// Drop shadow
/// final BoxShadow? shadow;
/// Default to `Theme.textTheme.titleLarge`
final TextStyle? titleStyle;
/// Subtitle text style
///
/// Default to `Theme.textTheme.titleMedium`
final TextStyle? subtitleStyle;
/// Body text style
///
/// Default to `Theme.textTheme.bodyMedium`
final TextStyle? bodyStyle;
/// Background of the card /// Background of the card
final Widget? background; final Widget? background;

View File

@ -14,7 +14,6 @@
// 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/>.
export './card_component.dart';
export './information_card_component.dart'; export './information_card_component.dart';
export './portfolio_card_component.dart'; export './portfolio_card_component.dart';
export './quote_card_component.dart'; export './quote_card_component.dart';

View File

@ -16,6 +16,7 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:wyatt_component_copy_with_extension/wyatt_component_copy_with_extension.dart'; import 'package:wyatt_component_copy_with_extension/wyatt_component_copy_with_extension.dart';
import 'package:wyatt_ui_components/src/domain/entities/cards/card_component.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_ui_components.dart';
part 'information_card_component.g.dart'; part 'information_card_component.g.dart';
@ -28,40 +29,21 @@ abstract class InformationCardComponent extends CardComponent
this.title, this.title,
this.subtitle, this.subtitle,
this.body, this.body,
this.axis, this.axis = Axis.vertical,
super.radius, super.radius,
super.padding, super.padding,
super.borderColors, super.borderColors,
super.backgroundColors, super.backgroundColors,
super.stroke,
super.minSize, super.minSize,
super.maxSize, super.maxSize,
super.shadow, super.shadow,
super.titleStyle,
super.subtitleStyle,
super.bodyStyle,
super.background, super.background,
super.key, super.key,
}); });
/// Axis of the card
///
/// If [axis] is [Axis.horizontal] then only the first icon will be displayed.
/// Used in header of the card.
final Axis? axis; final Axis? axis;
/// Icons of the card
///
/// If [axis] is [Axis.horizontal] then only the first icon will be displayed
/// on the left side of the card and the rest will be ignored.
final List<Widget>? icons; final List<Widget>? icons;
/// Title of the card
final TextWrapper? title; final TextWrapper? title;
/// Subtitle of the card
final TextWrapper? subtitle; final TextWrapper? subtitle;
/// Body of the card
final TextWrapper? body; final TextWrapper? body;
} }

View File

@ -12,17 +12,13 @@ abstract class $InformationCardComponentCWProxy {
InformationCardComponent subtitle(TextWrapper? subtitle); InformationCardComponent subtitle(TextWrapper? subtitle);
InformationCardComponent body(TextWrapper? body); InformationCardComponent body(TextWrapper? body);
InformationCardComponent axis(Axis? axis); InformationCardComponent axis(Axis? axis);
InformationCardComponent radius(BorderRadiusGeometry? radius); InformationCardComponent radius(double? radius);
InformationCardComponent padding(EdgeInsetsGeometry? padding); InformationCardComponent padding(double? padding);
InformationCardComponent borderColors(MultiColor? borderColors); InformationCardComponent borderColors(MultiColor? borderColors);
InformationCardComponent backgroundColors(MultiColor? backgroundColors); InformationCardComponent backgroundColors(MultiColor? backgroundColors);
InformationCardComponent stroke(double? stroke);
InformationCardComponent minSize(Size? minSize); InformationCardComponent minSize(Size? minSize);
InformationCardComponent maxSize(Size? maxSize); InformationCardComponent maxSize(Size? maxSize);
InformationCardComponent shadow(BoxShadow? shadow); InformationCardComponent shadow(BoxShadow? shadow);
InformationCardComponent titleStyle(TextStyle? titleStyle);
InformationCardComponent subtitleStyle(TextStyle? subtitleStyle);
InformationCardComponent bodyStyle(TextStyle? bodyStyle);
InformationCardComponent background(Widget? background); InformationCardComponent background(Widget? background);
InformationCardComponent key(Key? key); InformationCardComponent key(Key? key);
InformationCardComponent call({ InformationCardComponent call({
@ -31,17 +27,13 @@ abstract class $InformationCardComponentCWProxy {
TextWrapper? subtitle, TextWrapper? subtitle,
TextWrapper? body, TextWrapper? body,
Axis? axis, Axis? axis,
BorderRadiusGeometry? radius, double? radius,
EdgeInsetsGeometry? padding, double? padding,
MultiColor? borderColors, MultiColor? borderColors,
MultiColor? backgroundColors, MultiColor? backgroundColors,
double? stroke,
Size? minSize, Size? minSize,
Size? maxSize, Size? maxSize,
BoxShadow? shadow, BoxShadow? shadow,
TextStyle? titleStyle,
TextStyle? subtitleStyle,
TextStyle? bodyStyle,
Widget? background, Widget? background,
Key? key, Key? key,
}); });

View File

@ -16,6 +16,7 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:wyatt_component_copy_with_extension/wyatt_component_copy_with_extension.dart'; import 'package:wyatt_component_copy_with_extension/wyatt_component_copy_with_extension.dart';
import 'package:wyatt_ui_components/src/domain/entities/cards/card_component.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_ui_components.dart';
part 'portfolio_card_component.g.dart'; part 'portfolio_card_component.g.dart';
@ -24,9 +25,9 @@ part 'portfolio_card_component.g.dart';
abstract class PortfolioCardComponent extends CardComponent abstract class PortfolioCardComponent extends CardComponent
with CopyWithMixin<$PortfolioCardComponentCWProxy> { with CopyWithMixin<$PortfolioCardComponentCWProxy> {
const PortfolioCardComponent({ const PortfolioCardComponent({
this.showAssetsOnTop, this.secondaryBackgroundColors,
this.keywords, this.showImagesOnTop,
this.keywordsBackgroundColors, this.keyword,
this.description, this.description,
this.logo, this.logo,
this.projectName, this.projectName,
@ -37,42 +38,20 @@ abstract class PortfolioCardComponent extends CardComponent
super.padding, super.padding,
super.borderColors, super.borderColors,
super.backgroundColors, super.backgroundColors,
super.stroke,
super.minSize, super.minSize,
super.maxSize, super.maxSize,
super.shadow, super.shadow,
super.titleStyle,
super.subtitleStyle,
super.bodyStyle,
super.background, super.background,
super.key, super.key,
}); });
/// Keywords of the portfolio final bool? showImagesOnTop;
final List<TextWrapper>? keywords; final List<TextWrapper>? keyword;
/// Background colors for the keywords badges
final MultiColor? keywordsBackgroundColors;
/// Assets to display
final List<Widget>? assets; final List<Widget>? assets;
/// Whether to show the assets on top or on bottom
/// of the card
final bool? showAssetsOnTop;
/// Logo of the portfolio
final Widget? logo;
/// Description of the portfolio
final TextWrapper? description; final TextWrapper? description;
final Widget? logo;
/// Name of the portfolio
final TextWrapper? projectName; final TextWrapper? projectName;
/// Subtitle of the portfolio
final TextWrapper? subtitle; final TextWrapper? subtitle;
/// Call to actions of the portfolio
final List<Widget>? ctas; final List<Widget>? ctas;
final Color? secondaryBackgroundColors;
} }

View File

@ -7,50 +7,42 @@ part of 'portfolio_card_component.dart';
// ************************************************************************** // **************************************************************************
abstract class $PortfolioCardComponentCWProxy { abstract class $PortfolioCardComponentCWProxy {
PortfolioCardComponent showAssetsOnTop(bool? showAssetsOnTop); PortfolioCardComponent secondaryBackgroundColors(
PortfolioCardComponent keywords(List<TextWrapper>? keywords); Color? secondaryBackgroundColors);
PortfolioCardComponent keywordsBackgroundColors( PortfolioCardComponent showImagesOnTop(bool? showImagesOnTop);
MultiColor? keywordsBackgroundColors); PortfolioCardComponent keyword(List<TextWrapper>? keyword);
PortfolioCardComponent description(TextWrapper? description); PortfolioCardComponent description(TextWrapper? description);
PortfolioCardComponent logo(Widget? logo); PortfolioCardComponent logo(Widget? logo);
PortfolioCardComponent projectName(TextWrapper? projectName); PortfolioCardComponent projectName(TextWrapper? projectName);
PortfolioCardComponent subtitle(TextWrapper? subtitle); PortfolioCardComponent subtitle(TextWrapper? subtitle);
PortfolioCardComponent ctas(List<Widget>? ctas); PortfolioCardComponent ctas(List<Widget>? ctas);
PortfolioCardComponent assets(List<Widget>? assets); PortfolioCardComponent assets(List<Widget>? assets);
PortfolioCardComponent radius(BorderRadiusGeometry? radius); PortfolioCardComponent radius(double? radius);
PortfolioCardComponent padding(EdgeInsetsGeometry? padding); PortfolioCardComponent padding(double? padding);
PortfolioCardComponent borderColors(MultiColor? borderColors); PortfolioCardComponent borderColors(MultiColor? borderColors);
PortfolioCardComponent backgroundColors(MultiColor? backgroundColors); PortfolioCardComponent backgroundColors(MultiColor? backgroundColors);
PortfolioCardComponent stroke(double? stroke);
PortfolioCardComponent minSize(Size? minSize); PortfolioCardComponent minSize(Size? minSize);
PortfolioCardComponent maxSize(Size? maxSize); PortfolioCardComponent maxSize(Size? maxSize);
PortfolioCardComponent shadow(BoxShadow? shadow); PortfolioCardComponent shadow(BoxShadow? shadow);
PortfolioCardComponent titleStyle(TextStyle? titleStyle);
PortfolioCardComponent subtitleStyle(TextStyle? subtitleStyle);
PortfolioCardComponent bodyStyle(TextStyle? bodyStyle);
PortfolioCardComponent background(Widget? background); PortfolioCardComponent background(Widget? background);
PortfolioCardComponent key(Key? key); PortfolioCardComponent key(Key? key);
PortfolioCardComponent call({ PortfolioCardComponent call({
bool? showAssetsOnTop, Color? secondaryBackgroundColors,
List<TextWrapper>? keywords, bool? showImagesOnTop,
MultiColor? keywordsBackgroundColors, List<TextWrapper>? keyword,
TextWrapper? description, TextWrapper? description,
Widget? logo, Widget? logo,
TextWrapper? projectName, TextWrapper? projectName,
TextWrapper? subtitle, TextWrapper? subtitle,
List<Widget>? ctas, List<Widget>? ctas,
List<Widget>? assets, List<Widget>? assets,
BorderRadiusGeometry? radius, double? radius,
EdgeInsetsGeometry? padding, double? padding,
MultiColor? borderColors, MultiColor? borderColors,
MultiColor? backgroundColors, MultiColor? backgroundColors,
double? stroke,
Size? minSize, Size? minSize,
Size? maxSize, Size? maxSize,
BoxShadow? shadow, BoxShadow? shadow,
TextStyle? titleStyle,
TextStyle? subtitleStyle,
TextStyle? bodyStyle,
Widget? background, Widget? background,
Key? key, Key? key,
}); });

View File

@ -16,6 +16,7 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:wyatt_component_copy_with_extension/wyatt_component_copy_with_extension.dart'; import 'package:wyatt_component_copy_with_extension/wyatt_component_copy_with_extension.dart';
import 'package:wyatt_ui_components/src/domain/entities/cards/card_component.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_ui_components.dart';
part 'quote_card_component.g.dart'; part 'quote_card_component.g.dart';
@ -27,6 +28,7 @@ abstract class QuoteCardComponent extends CardComponent
this.avatar, this.avatar,
this.name, this.name,
this.subtitle, this.subtitle,
this.gradient,
this.quote, this.quote,
this.leftQuote, this.leftQuote,
this.rightQuote, this.rightQuote,
@ -34,32 +36,19 @@ abstract class QuoteCardComponent extends CardComponent
super.padding, super.padding,
super.borderColors, super.borderColors,
super.backgroundColors, super.backgroundColors,
super.stroke,
super.minSize, super.minSize,
super.maxSize, super.maxSize,
super.shadow, super.shadow,
super.titleStyle,
super.subtitleStyle,
super.bodyStyle,
super.background, super.background,
super.key, super.key,
}); });
/// Avatar of the contact who wrote the quote
final Widget? avatar; final Widget? avatar;
/// Name of the contact who wrote the quote
final TextWrapper? name; final TextWrapper? name;
/// Subtitle, usually the date of the quote or the company of the contact
final TextWrapper? subtitle; final TextWrapper? subtitle;
/// Quote
final TextWrapper? quote; final TextWrapper? quote;
/// Left quote, usually a double quote final Gradient? gradient;
final Widget? leftQuote; final Widget? leftQuote;
/// Right quote, usually a double quote
final Widget? rightQuote; final Widget? rightQuote;
} }

View File

@ -10,40 +10,34 @@ abstract class $QuoteCardComponentCWProxy {
QuoteCardComponent avatar(Widget? avatar); QuoteCardComponent avatar(Widget? avatar);
QuoteCardComponent name(TextWrapper? name); QuoteCardComponent name(TextWrapper? name);
QuoteCardComponent subtitle(TextWrapper? subtitle); QuoteCardComponent subtitle(TextWrapper? subtitle);
QuoteCardComponent gradient(Gradient? gradient);
QuoteCardComponent quote(TextWrapper? quote); QuoteCardComponent quote(TextWrapper? quote);
QuoteCardComponent leftQuote(Widget? leftQuote); QuoteCardComponent leftQuote(Widget? leftQuote);
QuoteCardComponent rightQuote(Widget? rightQuote); QuoteCardComponent rightQuote(Widget? rightQuote);
QuoteCardComponent radius(BorderRadiusGeometry? radius); QuoteCardComponent radius(double? radius);
QuoteCardComponent padding(EdgeInsetsGeometry? padding); QuoteCardComponent padding(double? padding);
QuoteCardComponent borderColors(MultiColor? borderColors); QuoteCardComponent borderColors(MultiColor? borderColors);
QuoteCardComponent backgroundColors(MultiColor? backgroundColors); QuoteCardComponent backgroundColors(MultiColor? backgroundColors);
QuoteCardComponent stroke(double? stroke);
QuoteCardComponent minSize(Size? minSize); QuoteCardComponent minSize(Size? minSize);
QuoteCardComponent maxSize(Size? maxSize); QuoteCardComponent maxSize(Size? maxSize);
QuoteCardComponent shadow(BoxShadow? shadow); QuoteCardComponent shadow(BoxShadow? shadow);
QuoteCardComponent titleStyle(TextStyle? titleStyle);
QuoteCardComponent subtitleStyle(TextStyle? subtitleStyle);
QuoteCardComponent bodyStyle(TextStyle? bodyStyle);
QuoteCardComponent background(Widget? background); QuoteCardComponent background(Widget? background);
QuoteCardComponent key(Key? key); QuoteCardComponent key(Key? key);
QuoteCardComponent call({ QuoteCardComponent call({
Widget? avatar, Widget? avatar,
TextWrapper? name, TextWrapper? name,
TextWrapper? subtitle, TextWrapper? subtitle,
Gradient? gradient,
TextWrapper? quote, TextWrapper? quote,
Widget? leftQuote, Widget? leftQuote,
Widget? rightQuote, Widget? rightQuote,
BorderRadiusGeometry? radius, double? radius,
EdgeInsetsGeometry? padding, double? padding,
MultiColor? borderColors, MultiColor? borderColors,
MultiColor? backgroundColors, MultiColor? backgroundColors,
double? stroke,
Size? minSize, Size? minSize,
Size? maxSize, Size? maxSize,
BoxShadow? shadow, BoxShadow? shadow,
TextStyle? titleStyle,
TextStyle? subtitleStyle,
TextStyle? bodyStyle,
Widget? background, Widget? background,
Key? key, Key? key,
}); });

View File

@ -16,6 +16,7 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:wyatt_component_copy_with_extension/wyatt_component_copy_with_extension.dart'; import 'package:wyatt_component_copy_with_extension/wyatt_component_copy_with_extension.dart';
import 'package:wyatt_ui_components/src/domain/entities/cards/card_component.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_ui_components.dart';
part 'skill_card_component.g.dart'; part 'skill_card_component.g.dart';
@ -24,56 +25,29 @@ part 'skill_card_component.g.dart';
abstract class SkillCardComponent extends CardComponent abstract class SkillCardComponent extends CardComponent
with CopyWithMixin<$SkillCardComponentCWProxy> { with CopyWithMixin<$SkillCardComponentCWProxy> {
const SkillCardComponent({ const SkillCardComponent({
this.axis, this.icon,
this.icons, this.gradient,
this.title, this.title,
this.subtitle,
this.description, this.description,
this.skills, this.skills,
this.bulletColors, this.leadingIcon,
this.bulletIcon, this.secondaryBackgroundColors,
super.radius, super.radius,
super.padding, super.padding,
super.borderColors, super.borderColors,
super.backgroundColors, super.backgroundColors,
super.stroke,
super.minSize, super.minSize,
super.maxSize, super.maxSize,
super.shadow, super.shadow,
super.titleStyle,
super.subtitleStyle,
super.bodyStyle,
super.background, super.background,
super.key, super.key,
}); });
/// Axis of the card final Widget? icon;
/// final List<Color>? gradient;
/// If [axis] is [Axis.horizontal] then only the first icon will be displayed.
/// Used in header of the card.
final Axis? axis;
/// Icons of the card
///
/// If [axis] is [Axis.horizontal] then only the first icon will be displayed
/// on the left side of the card and the rest will be ignored.
final List<Widget>? icons;
/// Title of the card
final TextWrapper? title; final TextWrapper? title;
/// Subtitle of the card
final TextWrapper? subtitle;
/// Description of the card
final TextWrapper? description; final TextWrapper? description;
/// Skills to be displayed
final List<TextWrapper>? skills; final List<TextWrapper>? skills;
final IconData? leadingIcon;
/// Gradient of skill icons. final Color? secondaryBackgroundColors;
final MultiColor? bulletColors;
/// Icon to be displayed before each skill.
final Widget? bulletIcon;
} }

View File

@ -7,47 +7,38 @@ part of 'skill_card_component.dart';
// ************************************************************************** // **************************************************************************
abstract class $SkillCardComponentCWProxy { abstract class $SkillCardComponentCWProxy {
SkillCardComponent axis(Axis? axis); SkillCardComponent icon(Widget? icon);
SkillCardComponent icons(List<Widget>? icons); SkillCardComponent gradient(List<Color>? gradient);
SkillCardComponent title(TextWrapper? title); SkillCardComponent title(TextWrapper? title);
SkillCardComponent subtitle(TextWrapper? subtitle);
SkillCardComponent description(TextWrapper? description); SkillCardComponent description(TextWrapper? description);
SkillCardComponent skills(List<TextWrapper>? skills); SkillCardComponent skills(List<TextWrapper>? skills);
SkillCardComponent bulletColors(MultiColor? bulletColors); SkillCardComponent leadingIcon(IconData? leadingIcon);
SkillCardComponent bulletIcon(Widget? bulletIcon); SkillCardComponent secondaryBackgroundColors(
SkillCardComponent radius(BorderRadiusGeometry? radius); Color? secondaryBackgroundColors);
SkillCardComponent padding(EdgeInsetsGeometry? padding); SkillCardComponent radius(double? radius);
SkillCardComponent padding(double? padding);
SkillCardComponent borderColors(MultiColor? borderColors); SkillCardComponent borderColors(MultiColor? borderColors);
SkillCardComponent backgroundColors(MultiColor? backgroundColors); SkillCardComponent backgroundColors(MultiColor? backgroundColors);
SkillCardComponent stroke(double? stroke);
SkillCardComponent minSize(Size? minSize); SkillCardComponent minSize(Size? minSize);
SkillCardComponent maxSize(Size? maxSize); SkillCardComponent maxSize(Size? maxSize);
SkillCardComponent shadow(BoxShadow? shadow); SkillCardComponent shadow(BoxShadow? shadow);
SkillCardComponent titleStyle(TextStyle? titleStyle);
SkillCardComponent subtitleStyle(TextStyle? subtitleStyle);
SkillCardComponent bodyStyle(TextStyle? bodyStyle);
SkillCardComponent background(Widget? background); SkillCardComponent background(Widget? background);
SkillCardComponent key(Key? key); SkillCardComponent key(Key? key);
SkillCardComponent call({ SkillCardComponent call({
Axis? axis, Widget? icon,
List<Widget>? icons, List<Color>? gradient,
TextWrapper? title, TextWrapper? title,
TextWrapper? subtitle,
TextWrapper? description, TextWrapper? description,
List<TextWrapper>? skills, List<TextWrapper>? skills,
MultiColor? bulletColors, IconData? leadingIcon,
Widget? bulletIcon, Color? secondaryBackgroundColors,
BorderRadiusGeometry? radius, double? radius,
EdgeInsetsGeometry? padding, double? padding,
MultiColor? borderColors, MultiColor? borderColors,
MultiColor? backgroundColors, MultiColor? backgroundColors,
double? stroke,
Size? minSize, Size? minSize,
Size? maxSize, Size? maxSize,
BoxShadow? shadow, BoxShadow? shadow,
TextStyle? titleStyle,
TextStyle? subtitleStyle,
TextStyle? bodyStyle,
Widget? background, Widget? background,
Key? key, Key? key,
}); });

View File

@ -16,43 +16,17 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
/// {@template rich_text_style_parameter}
/// Rich text style parameter used to parse the text.
/// {@endtemplate}
class RichTextStyleParameter { class RichTextStyleParameter {
/// {@macro rich_text_style_parameter}
const RichTextStyleParameter( const RichTextStyleParameter(
this.defaultStyle, this.defaultStyle,
this.definedStyle, this.definedStyle,
this.styleName, this.styleName,
); );
/// Default style to use if no style is defined.
final TextStyle? defaultStyle; final TextStyle? defaultStyle;
/// Map of defined styles. The key is the style name.
///
/// Example:
/// ```dart
/// definedStyle: {
/// 'bold': TextStyle(fontWeight: FontWeight.bold),
/// 'italic': TextStyle(fontStyle: FontStyle.italic),
/// }
/// ```
/// then, the text `This is <bold>bold</bold> and <italic>italic</italic>`
/// will be parsed and the word `bold` will be bold and the word `italic`
/// will be italic in the RichText widget.
final Map<String, TextStyle> definedStyle; final Map<String, TextStyle> definedStyle;
/// Style name to use for the text.
/// If no style is defined and no default style is defined, the text will be
/// displayed with the default style of the RichText widget.
final String? styleName; final String? styleName;
/// Returns the style to use for the given style name.
/// If no style is defined for the given style name, the default style is
/// returned. If no default style is defined, the default style of the
/// RichText widget is returned.
TextStyle get style { TextStyle get style {
if (definedStyle.containsKey(styleName)) { if (definedStyle.containsKey(styleName)) {
return definedStyle[styleName]!; return definedStyle[styleName]!;
@ -72,47 +46,11 @@ class RichTextStyleParameter {
); );
} }
/// {@template rich_text_node}
/// Rich text node.
///
/// Used as a node in the tree of the RichText widget.
/// {@endtemplate}
class RichTextNode { class RichTextNode {
/// {@macro rich_text_node} RichTextNode(this.nodes);
const RichTextNode(this.nodes);
/// List of nodes.
final List<RichTextNode> nodes; final List<RichTextNode> nodes;
/// Returns a RichTextNode from the given content.
/// If the content contains a match with the given regex, the content is
/// split into multiple nodes. If the content does not contain a match with
/// the given regex, a leaf node is returned.
///
/// Example:
/// ```dart
/// RichTextNode.from(
/// 'This is <bold>bold</bold> and <italic>italic</italic>',
/// RegExp(r'<(\w+)>(.*?)</\1>'),
/// RichTextStyleParameter(
/// TextStyle(fontWeight: FontWeight.w400),
/// {'bold': TextStyle(fontWeight: FontWeight.bold)},
/// {'italic': TextStyle(fontStyle: FontStyle.italic)},
/// ),
/// );
/// ```
/// will return a RichTextNode with 5 nodes:
/// - `This is `
/// - `<bold>bold</bold>`
/// - ` and `
/// - `<italic>italic</italic>`
/// - `` (empty string)
///
/// The first node is a leaf node with the default style of the RichText
/// widget. The second node is a node with bold paramters. The third node is
/// a leaf node with the default style of the RichText widget.
/// The fourth node is a node italic parameters. The fifth node is a
/// leaf node with the default style of the RichText widget.
static RichTextNode from( static RichTextNode from(
String content, String content,
RegExp regex, RegExp regex,
@ -150,11 +88,6 @@ class RichTextNode {
} }
} }
/// Returns an InlineSpan from the given RichTextNode.
/// The given RichTextParser is used to convert the RichTextNode to an
/// InlineSpan.
///
/// InlineSpan is used to display text in the RichText widget.
InlineSpan toInlineSpan(RichTextParser parser) { InlineSpan toInlineSpan(RichTextParser parser) {
final children = <InlineSpan>[]; final children = <InlineSpan>[];
for (final node in nodes) { for (final node in nodes) {
@ -164,17 +97,10 @@ class RichTextNode {
} }
} }
/// {@template rich_text_leaf}
/// Rich text leaf.
/// {@endtemplate}
class RichTextLeaf extends RichTextNode { class RichTextLeaf extends RichTextNode {
/// {@macro rich_text_leaf} RichTextLeaf(this.style, this.content) : super([]);
const RichTextLeaf(this.style, this.content) : super(const []);
/// Style to use for the text.
final TextStyle style; final TextStyle style;
/// Text content.
final String content; final String content;
@override @override
@ -182,26 +108,13 @@ class RichTextLeaf extends RichTextNode {
parser.nodeBuilder.call(content, style); parser.nodeBuilder.call(content, style);
} }
/// {@template rich_text_parser}
/// Rich text parser.
/// {@endtemplate}
class RichTextParser { class RichTextParser {
/// {@macro rich_text_parser}
const RichTextParser({required this.nodeBuilder}); const RichTextParser({required this.nodeBuilder});
/// Returns a default RichTextParser.
/// The default RichTextParser uses the given nodeBuilder to convert a
/// RichTextNode to an InlineSpan.
///
/// By default, the nodeBuilder returns a TextSpan with the given content
/// and style.
factory RichTextParser.defaultBuilder() => RichTextParser( factory RichTextParser.defaultBuilder() => RichTextParser(
nodeBuilder: (content, style) => TextSpan( nodeBuilder: (content, style) => TextSpan(
text: content, text: content,
style: style, style: style,
), ),
); );
/// Converts the given RichTextNode to an InlineSpan.
final InlineSpan Function(String content, TextStyle style) nodeBuilder; final InlineSpan Function(String content, TextStyle style) nodeBuilder;
} }

View File

@ -39,8 +39,8 @@ abstract class TextInputComponent extends Component
this.hint, this.hint,
this.normalStyle, this.normalStyle,
this.focusedStyle, this.focusedStyle,
this.invalidStyle, this.errorStyle,
this.disabledStyle, this.disableStyle,
this.controller, this.controller,
this.focusNode, this.focusNode,
this.keyboardType, this.keyboardType,
@ -156,11 +156,10 @@ abstract class TextInputComponent extends Component
final bool Function(String)? validator; final bool Function(String)? validator;
final String? Function(String)? onError; final String? Function(String)? onError;
// Styles
final TextInputStyle? normalStyle; final TextInputStyle? normalStyle;
final TextInputStyle? focusedStyle; final TextInputStyle? focusedStyle;
final TextInputStyle? invalidStyle; final TextInputStyle? errorStyle;
final TextInputStyle? disabledStyle; final TextInputStyle? disableStyle;
final bool? expand; final bool? expand;

View File

@ -18,8 +18,8 @@ abstract class $TextInputComponentCWProxy {
TextInputComponent hint(TextWrapper? hint); TextInputComponent hint(TextWrapper? hint);
TextInputComponent normalStyle(TextInputStyle? normalStyle); TextInputComponent normalStyle(TextInputStyle? normalStyle);
TextInputComponent focusedStyle(TextInputStyle? focusedStyle); TextInputComponent focusedStyle(TextInputStyle? focusedStyle);
TextInputComponent invalidStyle(TextInputStyle? invalidStyle); TextInputComponent errorStyle(TextInputStyle? errorStyle);
TextInputComponent disabledStyle(TextInputStyle? disabledStyle); TextInputComponent disableStyle(TextInputStyle? disableStyle);
TextInputComponent controller(TextEditingController? controller); TextInputComponent controller(TextEditingController? controller);
TextInputComponent focusNode(FocusNode? focusNode); TextInputComponent focusNode(FocusNode? focusNode);
TextInputComponent keyboardType(TextInputType? keyboardType); TextInputComponent keyboardType(TextInputType? keyboardType);
@ -96,8 +96,8 @@ abstract class $TextInputComponentCWProxy {
TextWrapper? hint, TextWrapper? hint,
TextInputStyle? normalStyle, TextInputStyle? normalStyle,
TextInputStyle? focusedStyle, TextInputStyle? focusedStyle,
TextInputStyle? invalidStyle, TextInputStyle? errorStyle,
TextInputStyle? disabledStyle, TextInputStyle? disableStyle,
TextEditingController? controller, TextEditingController? controller,
FocusNode? focusNode, FocusNode? focusNode,
TextInputType? keyboardType, TextInputType? keyboardType,

View File

@ -23,7 +23,7 @@ class TextInputStyle extends ThemeStyle<TextInputStyle> {
this.hintStyle, this.hintStyle,
this.backgroundColors, this.backgroundColors,
this.borderColors, this.borderColors,
this.shadow, this.boxShadow,
this.radius, this.radius,
this.inputStyle, this.inputStyle,
this.iconColor, this.iconColor,
@ -44,7 +44,7 @@ class TextInputStyle extends ThemeStyle<TextInputStyle> {
final MultiColor? backgroundColors; final MultiColor? backgroundColors;
final Color? borderColors; final Color? borderColors;
final BoxShadow? shadow; final BoxShadow? boxShadow;
final BorderRadiusGeometry? radius; final BorderRadiusGeometry? radius;
final TextStyle? inputStyle; final TextStyle? inputStyle;
@ -60,7 +60,7 @@ class TextInputStyle extends ThemeStyle<TextInputStyle> {
hintStyle: b.hintStyle, hintStyle: b.hintStyle,
backgroundColors: b.backgroundColors, backgroundColors: b.backgroundColors,
borderColors: b.borderColors, borderColors: b.borderColors,
shadow: b.shadow, boxShadow: b.boxShadow,
radius: b.radius, radius: b.radius,
inputStyle: b.inputStyle, inputStyle: b.inputStyle,
iconColor: b.iconColor, iconColor: b.iconColor,
@ -87,7 +87,7 @@ class TextInputStyle extends ThemeStyle<TextInputStyle> {
MultiColor.lerp(a.backgroundColors, b.backgroundColors, t), MultiColor.lerp(a.backgroundColors, b.backgroundColors, t),
radius: BorderRadiusGeometry.lerp(a.radius, b.radius, t), radius: BorderRadiusGeometry.lerp(a.radius, b.radius, t),
borderColors: Color.lerp(a.borderColors, b.borderColors, t), borderColors: Color.lerp(a.borderColors, b.borderColors, t),
shadow: BoxShadow.lerp(a.shadow, b.shadow, t), boxShadow: BoxShadow.lerp(a.boxShadow, b.boxShadow, t),
inputStyle: TextStyle.lerp(a.inputStyle, b.inputStyle, t), inputStyle: TextStyle.lerp(a.inputStyle, b.inputStyle, t),
prefixStyle: TextStyle.lerp(a.prefixStyle, b.prefixStyle, t), prefixStyle: TextStyle.lerp(a.prefixStyle, b.prefixStyle, t),
suffixStyle: TextStyle.lerp(a.suffixStyle, b.suffixStyle, t), suffixStyle: TextStyle.lerp(a.suffixStyle, b.suffixStyle, t),
@ -107,7 +107,7 @@ class TextInputStyle extends ThemeStyle<TextInputStyle> {
TextStyle? hintStyle, TextStyle? hintStyle,
MultiColor? backgroundColors, MultiColor? backgroundColors,
Color? borderColors, Color? borderColors,
BoxShadow? shadow, BoxShadow? boxShadow,
BorderRadiusGeometry? radius, BorderRadiusGeometry? radius,
TextStyle? inputStyle, TextStyle? inputStyle,
Color? iconColor, Color? iconColor,
@ -122,7 +122,7 @@ class TextInputStyle extends ThemeStyle<TextInputStyle> {
backgroundColors: backgroundColors ?? this.backgroundColors, backgroundColors: backgroundColors ?? this.backgroundColors,
radius: radius ?? this.radius, radius: radius ?? this.radius,
borderColors: borderColors ?? this.borderColors, borderColors: borderColors ?? this.borderColors,
shadow: shadow ?? this.shadow, boxShadow: boxShadow ?? this.boxShadow,
inputStyle: inputStyle ?? this.inputStyle, inputStyle: inputStyle ?? this.inputStyle,
prefixStyle: prefixStyle ?? this.prefixStyle, prefixStyle: prefixStyle ?? this.prefixStyle,
suffixStyle: suffixStyle ?? this.suffixStyle, suffixStyle: suffixStyle ?? this.suffixStyle,

View File

@ -1,103 +0,0 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
/// {@template file_selection_button_theme_extension}
/// File selection button theme extension that extends [ThemeExtension] and
/// implements copyWith, and lerp methods so you don't have to.
/// {@endtemplate}
class FileSelectionButtonThemeExtension
extends ThemeExtension<FileSelectionButtonThemeExtension> {
/// {@macro file_selection_button_theme_extension}
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;
@override
ThemeExtension<FileSelectionButtonThemeExtension> copyWith({
FileSelectionButtonStyle? disabledStyle,
FileSelectionButtonStyle? focusedStyle,
FileSelectionButtonStyle? hoveredStyle,
FileSelectionButtonStyle? normalStyle,
FileSelectionButtonStyle? tappedStyle,
FileSelectionButtonStyle? selectedStyle,
FileSelectionButtonStyle? invalidStyle,
}) =>
FileSelectionButtonThemeExtension(
disabledStyle: disabledStyle ?? this.disabledStyle,
focusedStyle: focusedStyle ?? this.focusedStyle,
hoveredStyle: hoveredStyle ?? this.hoveredStyle,
normalStyle: normalStyle ?? this.normalStyle,
tappedStyle: tappedStyle ?? this.tappedStyle,
selectedStyle: selectedStyle ?? this.selectedStyle,
invalidStyle: invalidStyle ?? this.invalidStyle,
);
@override
ThemeExtension<FileSelectionButtonThemeExtension> lerp(
covariant ThemeExtension<FileSelectionButtonThemeExtension>? other,
double t,
) {
if (other is! FileSelectionButtonThemeExtension) {
return this;
}
return FileSelectionButtonThemeExtension(
disabledStyle:
FileSelectionButtonStyle.lerp(disabledStyle, other.disabledStyle, t),
focusedStyle:
FileSelectionButtonStyle.lerp(focusedStyle, other.focusedStyle, t),
hoveredStyle:
FileSelectionButtonStyle.lerp(hoveredStyle, other.hoveredStyle, t),
normalStyle:
FileSelectionButtonStyle.lerp(normalStyle, other.normalStyle, t),
tappedStyle:
FileSelectionButtonStyle.lerp(tappedStyle, other.tappedStyle, t),
selectedStyle:
FileSelectionButtonStyle.lerp(selectedStyle, other.selectedStyle, t),
invalidStyle:
FileSelectionButtonStyle.lerp(invalidStyle, other.invalidStyle, t),
);
}
}

View File

@ -1,83 +0,0 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
/// {@template flat_button_theme_extension}
/// Flat button theme extension that extends [ThemeExtension] and
/// implements copyWith, and lerp methods so you don't have to.
/// {@endtemplate}
class FlatButtonThemeExtension
extends ThemeExtension<FlatButtonThemeExtension> {
/// {@macro flat_button_theme_extension}
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;
@override
ThemeExtension<FlatButtonThemeExtension> copyWith({
FlatButtonStyle? disabledStyle,
FlatButtonStyle? focusedStyle,
FlatButtonStyle? hoveredStyle,
FlatButtonStyle? normalStyle,
FlatButtonStyle? tappedStyle,
}) =>
FlatButtonThemeExtension(
disabledStyle: disabledStyle ?? this.disabledStyle,
focusedStyle: focusedStyle ?? this.focusedStyle,
hoveredStyle: hoveredStyle ?? this.hoveredStyle,
normalStyle: normalStyle ?? this.normalStyle,
tappedStyle: tappedStyle ?? this.tappedStyle,
);
@override
ThemeExtension<FlatButtonThemeExtension> lerp(
covariant ThemeExtension<FlatButtonThemeExtension>? other,
double t,
) {
if (other is! FlatButtonThemeExtension) {
return this;
}
return FlatButtonThemeExtension(
disabledStyle:
FlatButtonStyle.lerp(disabledStyle, other.disabledStyle, t),
focusedStyle: FlatButtonStyle.lerp(focusedStyle, other.focusedStyle, t),
hoveredStyle: FlatButtonStyle.lerp(hoveredStyle, other.hoveredStyle, t),
normalStyle: FlatButtonStyle.lerp(normalStyle, other.normalStyle, t),
tappedStyle: FlatButtonStyle.lerp(tappedStyle, other.tappedStyle, t),
);
}
}

View File

@ -1,91 +0,0 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
/// {@template symbol_button_theme_extension}
/// Symbol button theme extension that extends [ThemeExtension] and
/// implements copyWith, and lerp methods so you don't have to.
/// {@endtemplate}
class SymbolButtonThemeExtension
extends ThemeExtension<SymbolButtonThemeExtension> {
/// {@macro symbol_button_theme_extension}
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;
@override
ThemeExtension<SymbolButtonThemeExtension> copyWith({
SymbolButtonStyle? disabledStyle,
SymbolButtonStyle? focusedStyle,
SymbolButtonStyle? hoveredStyle,
SymbolButtonStyle? normalStyle,
SymbolButtonStyle? tappedStyle,
SymbolButtonStyle? selectedStyle,
}) =>
SymbolButtonThemeExtension(
disabledStyle: disabledStyle ?? this.disabledStyle,
focusedStyle: focusedStyle ?? this.focusedStyle,
hoveredStyle: hoveredStyle ?? this.hoveredStyle,
normalStyle: normalStyle ?? this.normalStyle,
tappedStyle: tappedStyle ?? this.tappedStyle,
selectedStyle: selectedStyle ?? this.selectedStyle,
);
@override
ThemeExtension<SymbolButtonThemeExtension> lerp(
covariant ThemeExtension<SymbolButtonThemeExtension>? other,
double t,
) {
if (other is! SymbolButtonThemeExtension) {
return this;
}
return SymbolButtonThemeExtension(
disabledStyle:
SymbolButtonStyle.lerp(disabledStyle, other.disabledStyle, t),
focusedStyle: SymbolButtonStyle.lerp(focusedStyle, other.focusedStyle, t),
hoveredStyle: SymbolButtonStyle.lerp(hoveredStyle, other.hoveredStyle, t),
normalStyle: SymbolButtonStyle.lerp(normalStyle, other.normalStyle, t),
tappedStyle: SymbolButtonStyle.lerp(tappedStyle, other.tappedStyle, t),
selectedStyle:
SymbolButtonStyle.lerp(selectedStyle, other.selectedStyle, t),
);
}
}

View File

@ -1,143 +0,0 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/src/core/utils/multi_color.dart';
/// {@template card_theme_extension}
/// Card theme extension that extends [ThemeExtension] and
/// implements copyWith, and lerp methods so you don't have to.
/// {@endtemplate}
class CardThemeExtension extends ThemeExtension<CardThemeExtension> {
/// {@macro card_theme_extension}
const CardThemeExtension({
this.radius,
this.padding,
this.backgroundColors,
this.borderColors,
this.stroke,
this.shadow,
this.minSize,
this.maxSize,
this.titleStyle,
this.subtitleStyle,
this.bodyStyle,
});
/// Card radius
///
/// Default to `BorderRadius.all(Radius.circular(12.0))`
final BorderRadiusGeometry? radius;
/// Padding and gaps of this card
///
/// Default to `Theme.cardTheme.margin`
final EdgeInsetsGeometry? padding;
/// Card background gradient colors (from left to right)
///
/// Default to `Theme.cardTheme.color`
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;
/// Minimum size of the card
///
/// Default to `const Size(330, 0)`
final Size? minSize;
/// Maximum size of the card
///
/// Default to `const Size(double.infinity, double.infinity)`
final Size? maxSize;
/// Title text style
///
/// Default to `Theme.textTheme.titleLarge`
final TextStyle? titleStyle;
/// Subtitle text style
///
/// Default to `Theme.textTheme.titleMedium`
final TextStyle? subtitleStyle;
/// Body text style
///
/// Default to `Theme.textTheme.bodyMedium`
final TextStyle? bodyStyle;
@override
ThemeExtension<CardThemeExtension> copyWith({
BorderRadiusGeometry? radius,
EdgeInsetsGeometry? padding,
MultiColor? backgroundColors,
MultiColor? borderColors,
double? stroke,
BoxShadow? shadow,
Size? minSize,
Size? maxSize,
TextStyle? titleStyle,
TextStyle? subtitleStyle,
TextStyle? bodyStyle,
}) =>
CardThemeExtension(
radius: radius ?? this.radius,
padding: padding ?? this.padding,
backgroundColors: backgroundColors ?? this.backgroundColors,
borderColors: borderColors ?? this.borderColors,
stroke: stroke ?? this.stroke,
shadow: shadow ?? this.shadow,
minSize: minSize ?? this.minSize,
maxSize: maxSize ?? this.maxSize,
titleStyle: titleStyle ?? this.titleStyle,
subtitleStyle: subtitleStyle ?? this.subtitleStyle,
bodyStyle: bodyStyle ?? this.bodyStyle,
);
@override
ThemeExtension<CardThemeExtension> lerp(
covariant ThemeExtension<CardThemeExtension>? other,
double t,
) {
if (other is! CardThemeExtension) {
return this;
}
return CardThemeExtension(
radius: BorderRadiusGeometry.lerp(radius, other.radius, t),
padding: EdgeInsetsGeometry.lerp(padding, other.padding, t),
backgroundColors:
MultiColor.lerp(backgroundColors, other.backgroundColors, t),
borderColors: MultiColor.lerp(borderColors, other.borderColors, t),
shadow: BoxShadow.lerp(shadow, other.shadow, t),
bodyStyle: TextStyle.lerp(bodyStyle, other.bodyStyle, t),
titleStyle: TextStyle.lerp(titleStyle, other.titleStyle, t),
subtitleStyle: TextStyle.lerp(subtitleStyle, other.subtitleStyle, t),
);
}
}

View File

@ -1,69 +0,0 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/src/domain/entities/text_inputs/text_input_style.dart';
class TextInputThemeExtension extends ThemeExtension<TextInputThemeExtension> {
const TextInputThemeExtension({
this.normalStyle,
this.focusedStyle,
this.invalidStyle,
this.disabledStyle,
});
/// The default style for TextInputs.
final TextInputStyle? normalStyle;
/// The style for TextInputs when they are focused.
final TextInputStyle? focusedStyle;
/// The style for TextInputs when they are invalid.
final TextInputStyle? invalidStyle;
/// The style for TextInputs when they are disabled.
final TextInputStyle? disabledStyle;
@override
ThemeExtension<TextInputThemeExtension> lerp(
covariant ThemeExtension<TextInputThemeExtension>? other,
double t,
) {
if (other is! TextInputThemeExtension) {
return this;
}
return TextInputThemeExtension(
normalStyle: TextInputStyle.lerp(normalStyle, other.normalStyle, t),
focusedStyle: TextInputStyle.lerp(focusedStyle, other.focusedStyle, t),
disabledStyle: TextInputStyle.lerp(disabledStyle, other.disabledStyle, t),
invalidStyle: TextInputStyle.lerp(invalidStyle, other.invalidStyle, t),
);
}
@override
ThemeExtension<TextInputThemeExtension> copyWith({
TextInputStyle? normalStyle,
TextInputStyle? focusedStyle,
TextInputStyle? disabledStyle,
TextInputStyle? invalidStyle,
}) =>
TextInputThemeExtension(
normalStyle: normalStyle ?? this.normalStyle,
focusedStyle: focusedStyle ?? this.focusedStyle,
disabledStyle: disabledStyle ?? this.disabledStyle,
invalidStyle: invalidStyle ?? this.invalidStyle,
);
}

View File

@ -1,19 +0,0 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'button_theme_extension/button_theme_extension.dart';
export 'card_theme_extension.dart';
export 'text_input_theme_extension.dart';

View File

@ -15,6 +15,5 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'core/core.dart'; export 'core/core.dart';
export 'data/data.dart';
export 'domain/domain.dart'; export 'domain/domain.dart';
export 'features/features.dart'; export 'features/features.dart';

View File

@ -17,9 +17,8 @@ class Bars extends DemoPage {
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
child: Image.asset('assets/images/studio_logo.png'), child: Image.asset('assets/images/studio_logo.png'),
), ),
title: const TextWrapper( title: 'Wyatt Studio'.wrap(
'Wyatt Studio', gradientColors: const MultiColor(
gradientColors: MultiColor(
[ [
Color.fromRGBO(57, 167, 254, 1), Color.fromRGBO(57, 167, 254, 1),
Color.fromRGBO(71, 94, 241, 1), Color.fromRGBO(71, 94, 241, 1),
@ -36,9 +35,8 @@ class Bars extends DemoPage {
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
child: Image.asset('assets/images/studio_logo.png'), child: Image.asset('assets/images/studio_logo.png'),
), ),
title: const TextWrapper( title: 'Wyatt Studio'.wrap(
'Wyatt Studio', gradientColors: const MultiColor(
gradientColors: MultiColor(
[ [
Color.fromRGBO(57, 167, 254, 1), Color.fromRGBO(57, 167, 254, 1),
Color.fromRGBO(71, 94, 241, 1), Color.fromRGBO(71, 94, 241, 1),
@ -69,20 +67,21 @@ class Bars extends DemoPage {
padding: const EdgeInsets.symmetric(horizontal: 20), padding: const EdgeInsets.symmetric(horizontal: 20),
child: Image.asset('assets/images/studio_long_logo.png'), child: Image.asset('assets/images/studio_long_logo.png'),
), ),
actions: const [ actions: [
Padding( Padding(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 25), padding:
const EdgeInsets.symmetric(horizontal: 20, vertical: 25),
child: FlatButton( child: FlatButton(
label: TextWrapper('Estimer mon projet'), label: 'Estimer mon projet'.wrap(),
), ),
), ),
], ],
navigationItems: const [ navigationItems: [
TextWrapper('ACCUEIL'), 'ACCEUIL'.wrap(),
TextWrapper('VOTRE PROGRAMME'), 'VOTRE PROGRAMME'.wrap(),
TextWrapper('LE STUDIO'), 'LE STUDIO'.wrap(),
TextWrapper('SAVOIR FAIRE') 'SAVOIR FAIRE'.wrap()
], ].whereType<TextWrapper>().toList(),
), ),
], ],
); );

View File

@ -63,7 +63,7 @@ class _FileSelectionButtonsState extends State<FileSelectionButtons> {
title: const TextWrapper( title: const TextWrapper(
'Ajouter un fichier', 'Ajouter un fichier',
), ),
subtitle: const TextWrapper('Taille max: 20 Mo'), subTitle: const TextWrapper('Taille max: 20 Mo'),
), ),
const Gap(20), const Gap(20),
BlocProvider( BlocProvider(
@ -73,7 +73,7 @@ class _FileSelectionButtonsState extends State<FileSelectionButtons> {
title: const TextWrapper( title: const TextWrapper(
'Enabled', 'Enabled',
), ),
subtitle: const TextWrapper('subtitle'), subTitle: const TextWrapper('Subtitle'),
), ),
), ),
const Gap(20), const Gap(20),
@ -83,7 +83,7 @@ class _FileSelectionButtonsState extends State<FileSelectionButtons> {
title: const TextWrapper( title: const TextWrapper(
'Disabled', 'Disabled',
), ),
subtitle: const TextWrapper('subtitle'), subTitle: const TextWrapper('Subtitle'),
disabled: _disabled, disabled: _disabled,
), ),
const Gap(20), const Gap(20),
@ -94,7 +94,7 @@ class _FileSelectionButtonsState extends State<FileSelectionButtons> {
title: const TextWrapper( title: const TextWrapper(
'Hovered', 'Hovered',
), ),
subtitle: const TextWrapper('subtitle'), subTitle: const TextWrapper('Subtitle'),
), ),
), ),
const Gap(20), const Gap(20),
@ -105,7 +105,7 @@ class _FileSelectionButtonsState extends State<FileSelectionButtons> {
title: const TextWrapper( title: const TextWrapper(
'Focused', 'Focused',
), ),
subtitle: const TextWrapper('subtitle'), subTitle: const TextWrapper('Subtitle'),
), ),
), ),
const Gap(20), const Gap(20),
@ -116,7 +116,7 @@ class _FileSelectionButtonsState extends State<FileSelectionButtons> {
title: const TextWrapper( title: const TextWrapper(
'Tapped', 'Tapped',
), ),
subtitle: const TextWrapper('subtitle'), subTitle: const TextWrapper('Subtitle'),
), ),
), ),
const Gap(20), const Gap(20),
@ -127,7 +127,7 @@ class _FileSelectionButtonsState extends State<FileSelectionButtons> {
title: const TextWrapper( title: const TextWrapper(
'Invalid', 'Invalid',
), ),
subtitle: const TextWrapper('subtitle'), subTitle: const TextWrapper('Subtitle'),
), ),
), ),
const Gap(20), const Gap(20),
@ -154,7 +154,7 @@ class _FileSelectionButtonsState extends State<FileSelectionButtons> {
title: const TextWrapper( title: const TextWrapper(
'Dynamic', 'Dynamic',
), ),
subtitle: const TextWrapper('subtitle'), subTitle: const TextWrapper('Subtitle'),
disabled: _dynamic, disabled: _dynamic,
), ),
], ],

View File

@ -25,8 +25,8 @@ class InformationCards extends StatelessWidget {
FlutterLogo(size: 60), FlutterLogo(size: 60),
], ],
title: TextWrapper('Flutter'), title: TextWrapper('Flutter'),
subtitle: TextWrapper('One single code base.'), subtitle: TextWrapper.text('One single code base.'),
body: TextWrapper( body: TextWrapper.text(
'Cupidatat reprehenderit aliqua eiusmod Lorem. ' 'Cupidatat reprehenderit aliqua eiusmod Lorem. '
'Qui ipsum id ea ea nulla labore aute ullamco aute ' 'Qui ipsum id ea ea nulla labore aute ullamco aute '
'quis elit ut amet velit. Incididunt fugiat proident ' 'quis elit ut amet velit. Incididunt fugiat proident '
@ -57,13 +57,11 @@ class InformationCards extends StatelessWidget {
FlutterLogo(size: 60), FlutterLogo(size: 60),
FlutterLogo(size: 60), FlutterLogo(size: 60),
], ],
title: const TextWrapper( title: 'Flutter'.wrap(
'Flutter', gradientColors: const MultiColor([Colors.blue, Colors.green]),
gradientColors: MultiColor([Colors.blue, Colors.green]),
), ),
subtitle: const TextWrapper('One single code base.'), subtitle: const TextWrapper.text('One single code base.'),
body: const TextWrapper( body: 'Cupidatat reprehenderit aliqua eiusmod Lorem. '
'Cupidatat reprehenderit aliqua eiusmod Lorem. '
'Qui ipsum id ea ea nulla labore aute ullamco aute ' 'Qui ipsum id ea ea nulla labore aute ullamco aute '
'quis elit ut amet velit. Incididunt fugiat proident ' 'quis elit ut amet velit. Incididunt fugiat proident '
'proident deserunt tempor Lorem cillum qui do ' 'proident deserunt tempor Lorem cillum qui do '
@ -73,7 +71,8 @@ class InformationCards extends StatelessWidget {
'excepteur eu commodo consectetur qui exercitation ' 'excepteur eu commodo consectetur qui exercitation '
'officia consequat ullamco sit adipisicing. Ullamco ' 'officia consequat ullamco sit adipisicing. Ullamco '
'magna cupidatat Lorem nulla cupidatat voluptate ' 'magna cupidatat Lorem nulla cupidatat voluptate '
'irure ex reprehenderit.'), 'irure ex reprehenderit.'
.wrap(),
), ),
], ],
), ),
@ -82,15 +81,14 @@ class InformationCards extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
const InformationCard( InformationCard(
icons: [ icons: const [
FlutterLogo(size: 60), FlutterLogo(size: 60),
], ],
axis: Axis.horizontal, axis: Axis.horizontal,
title: TextWrapper('Flutter'), title: const TextWrapper.text('Flutter'),
subtitle: TextWrapper('One single code base.'), subtitle: const TextWrapper.text('One single code base.'),
body: TextWrapper( body: 'Cupidatat reprehenderit aliqua eiusmod Lorem. '
'Cupidatat reprehenderit aliqua eiusmod Lorem. '
'Qui ipsum id ea ea nulla labore aute ullamco aute ' 'Qui ipsum id ea ea nulla labore aute ullamco aute '
'quis elit ut amet velit. Incididunt fugiat proident ' 'quis elit ut amet velit. Incididunt fugiat proident '
'proident deserunt tempor Lorem cillum qui do ' 'proident deserunt tempor Lorem cillum qui do '
@ -100,8 +98,9 @@ class InformationCards extends StatelessWidget {
'excepteur eu commodo consectetur qui exercitation ' 'excepteur eu commodo consectetur qui exercitation '
'officia consequat ullamco sit adipisicing. Ullamco ' 'officia consequat ullamco sit adipisicing. Ullamco '
'magna cupidatat Lorem nulla cupidatat voluptate ' 'magna cupidatat Lorem nulla cupidatat voluptate '
'irure ex reprehenderit.', 'irure ex reprehenderit.'
gradientColors: MultiColor([ .wrap(
gradientColors: const MultiColor([
Colors.red, Colors.red,
Colors.orange, Colors.orange,
]), ]),
@ -124,15 +123,14 @@ class InformationCards extends StatelessWidget {
FlutterLogo(size: 60), FlutterLogo(size: 60),
], ],
axis: Axis.horizontal, axis: Axis.horizontal,
title: const TextWrapper('Flutter'), title: const TextWrapper.text('Flutter'),
subtitle: TextWrapper( subtitle: 'One single code base.'.wrap(
'One single code base.', // gradient: [Colors.blue, Colors.green],
style: Theme.of(context).textTheme.titleMedium?.copyWith( style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
body: const TextWrapper( body: const TextWrapper.text(
'Cupidatat reprehenderit aliqua eiusmod Lorem. ' 'Cupidatat reprehenderit aliqua eiusmod Lorem. '
'Qui ipsum id ea ea nulla labore aute ullamco aute ' 'Qui ipsum id ea ea nulla labore aute ullamco aute '
'quis elit ut amet velit. Incididunt fugiat proident ' 'quis elit ut amet velit. Incididunt fugiat proident '

View File

@ -44,7 +44,7 @@ class PortfolioCards extends StatelessWidget {
fit: BoxFit.cover, fit: BoxFit.cover,
) )
], ],
keywords: const [ keyword: const [
TextWrapper('UI Design'), TextWrapper('UI Design'),
TextWrapper('Developpement'), TextWrapper('Developpement'),
TextWrapper('Deploiement') TextWrapper('Deploiement')
@ -52,7 +52,7 @@ class PortfolioCards extends StatelessWidget {
), ),
const Gap(20), const Gap(20),
PortfolioCard( PortfolioCard(
showAssetsOnTop: true, showImagesOnTop: true,
logo: const FlutterLogo( logo: const FlutterLogo(
size: 50, size: 50,
), ),
@ -115,7 +115,7 @@ class PortfolioCards extends StatelessWidget {
fit: BoxFit.cover, fit: BoxFit.cover,
) )
], ],
keywords: const [ keyword: const [
TextWrapper('UI Design'), TextWrapper('UI Design'),
TextWrapper('Developpement'), TextWrapper('Developpement'),
TextWrapper('Deploiement') TextWrapper('Deploiement')
@ -163,7 +163,7 @@ class PortfolioCards extends StatelessWidget {
fit: BoxFit.cover, fit: BoxFit.cover,
) )
], ],
keywords: const [ keyword: const [
TextWrapper('UI Design'), TextWrapper('UI Design'),
TextWrapper('Developpement'), TextWrapper('Developpement'),
TextWrapper('Deploiement') TextWrapper('Deploiement')

View File

@ -33,33 +33,33 @@ class QuoteCards extends StatelessWidget {
Row( Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: const [ children: [
QuoteCard( QuoteCard(
quote: quote: 'Cupidatat reprehenderit aliqua eiusmod Lorem. '
TextWrapper('Cupidatat reprehenderit aliqua eiusmod Lorem. '
'Qui ipsum id ea ea nulla labore aute ullamco aute ' 'Qui ipsum id ea ea nulla labore aute ullamco aute '
'quis elit ut amet velit. Incididunt fugiat proident ' 'quis elit ut amet velit. Incididunt fugiat proident '
'proident deserunt tempor Lorem cillum qui do ' 'proident deserunt tempor Lorem cillum qui do '
'ullamco Lorem magna ipsum. Ullamco cupidatat velit '), 'ullamco Lorem magna ipsum. Ullamco cupidatat velit '
.wrap(),
), ),
Gap(20), const Gap(20),
QuoteCard( QuoteCard(
quote: TextWrapper( quote: 'Cupidatat reprehenderit aliqua eiusmod Lorem. '
'Cupidatat reprehenderit aliqua eiusmod Lorem. '
'Qui ipsum id ea ea nulla labore aute ullamco aute ' 'Qui ipsum id ea ea nulla labore aute ullamco aute '
'quis elit ut amet velit. Incididunt fugiat proident ' 'quis elit ut amet velit. Incididunt fugiat proident '
'proident deserunt tempor Lorem cillum qui do ' 'proident deserunt tempor Lorem cillum qui do '
'ullamco Lorem magna ipsum. Ullamco cupidatat velit ', 'ullamco Lorem magna ipsum. Ullamco cupidatat velit '
gradientColors: MultiColor([ .wrap(
gradientColors: const MultiColor([
Colors.red, Colors.red,
Colors.orange, Colors.orange,
]), ]),
), ),
avatar: FlutterLogo( avatar: const FlutterLogo(
size: 40, size: 40,
), ),
name: TextWrapper('John Doe'), name: 'John Doe'.wrap(),
subtitle: TextWrapper('Agence anonyme'), subtitle: 'Agence anonyme'.wrap(),
), ),
], ],
), ),

View File

@ -35,61 +35,58 @@ class SkillCards extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
SkillCard( SkillCard(
icons: [ gradient: const [Colors.red, Colors.orange],
Container( icon: Container(
padding: const EdgeInsets.all(15), padding: const EdgeInsets.all(15),
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
color: Colors.white.withOpacity(0.04), color: Colors.white.withOpacity(0.04),
), ),
child: GradientIcon( child: const GradientIcon(
icon: Icons.ac_unit_sharp, Icons.ac_unit_sharp,
gradientColors: gradient:
const MultiColor([Colors.red, Colors.orange]), LinearGradient(colors: [Colors.red, Colors.orange]),
), ),
) ),
], title: 'Lorem Ipsum'.wrap(),
bulletColors: const MultiColor([Colors.red, Colors.orange]), description: 'Cupidatat reprehenderit aliqua eiusmod Lorem. '
title: const TextWrapper('Lorem Ipsum'),
description: const TextWrapper(
'Cupidatat reprehenderit aliqua eiusmod Lorem. '
'Qui ipsum id ea ea nulla labore aute ullamco aute ' 'Qui ipsum id ea ea nulla labore aute ullamco aute '
'quis elit ut amet velit. Incididunt fugiat proident ' 'quis elit ut amet velit. Incididunt fugiat proident '
'proident deserunt tempor Lorem cillum qui do ' 'proident deserunt tempor Lorem cillum qui do '
'ullamco Lorem magna ipsum. Ullamco cupidatat velit '), 'ullamco Lorem magna ipsum. Ullamco cupidatat velit '
.wrap(),
skills: const [ skills: const [
TextWrapper('Firebase'), TextWrapper.text('Firebase'),
TextWrapper( TextWrapper.text(
'Qui ipsum id ea ea nulla labore aute ullamco aute ', 'Qui ipsum id ea ea nulla labore aute ullamco aute ',
), ),
], ],
), ),
const Gap(20), const Gap(20),
SkillCard( SkillCard(
icons: [ gradient: const [Colors.blue, Colors.green],
Container( icon: Container(
padding: const EdgeInsets.all(15), padding: const EdgeInsets.all(15),
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
color: Colors.white.withOpacity(0.04), color: Colors.white.withOpacity(0.04),
), ),
child: GradientIcon( child: const GradientIcon(
icon: Icons.ac_unit_sharp, Icons.ac_unit_sharp,
gradientColors: gradient: LinearGradient(
const MultiColor([Colors.blue, Colors.green]), colors: [Colors.blue, Colors.green],
), ),
) ),
], ),
bulletColors: const MultiColor([Colors.blue, Colors.green]), title: 'Lorem Ipsum'.wrap(),
title: const TextWrapper('Lorem Ipsum'), description: 'Cupidatat reprehenderit aliqua eiusmod Lorem. '
description: const TextWrapper(
'Cupidatat reprehenderit aliqua eiusmod Lorem. '
'Qui ipsum id ea ea nulla labore aute ullamco aute ' 'Qui ipsum id ea ea nulla labore aute ullamco aute '
'quis elit ut amet velit. Incididunt fugiat proident ' 'quis elit ut amet velit. Incididunt fugiat proident '
'proident deserunt tempor Lorem cillum qui do ' 'proident deserunt tempor Lorem cillum qui do '
'ullamco Lorem magna ipsum. Ullamco cupidatat velit '), 'ullamco Lorem magna ipsum. Ullamco cupidatat velit '
.wrap(),
skills: const [ skills: const [
TextWrapper('Firebase'), TextWrapper.text('Firebase'),
TextWrapper( TextWrapper(
'Qui ipsum id ea ea nulla labore aute ullamco aute ', 'Qui ipsum id ea ea nulla labore aute ullamco aute ',
gradientColors: MultiColor([ gradientColors: MultiColor([
@ -97,11 +94,11 @@ class SkillCards extends StatelessWidget {
Colors.orange, Colors.orange,
]), ]),
), ),
TextWrapper('Firebase'), TextWrapper.text('Firebase'),
TextWrapper('Firebase'), TextWrapper.text('Firebase'),
TextWrapper('Firebase'), TextWrapper.text('Firebase'),
TextWrapper('Firebase'), TextWrapper.text('Firebase'),
TextWrapper('Firebase'), TextWrapper.text('Firebase'),
], ],
), ),
], ],

View File

@ -75,7 +75,7 @@ class _TextInputsCoreState extends State<TextInputsCore> {
key: _formKey6, key: _formKey6,
controller: _controller6, controller: _controller6,
focusNode: _focusNode6, focusNode: _focusNode6,
label: const TextWrapper('Nom / Prénom'), label: 'Nom / Prénom'.wrap(),
onError: (value) => 'Erreur : ${value.length} > 5.', onError: (value) => 'Erreur : ${value.length} > 5.',
validator: (value) => value.length > 5, validator: (value) => value.length > 5,
), ),
@ -85,7 +85,7 @@ class _TextInputsCoreState extends State<TextInputsCore> {
enabled: _enable, enabled: _enable,
controller: _controller, controller: _controller,
focusNode: _focusNode, focusNode: _focusNode,
label: const TextWrapper('Nom / Prénom'), label: 'Nom / Prénom'.wrap(),
onError: (value) => 'Erreur : ${value.length} > 5.', onError: (value) => 'Erreur : ${value.length} > 5.',
validator: (value) => value.length > 5, validator: (value) => value.length > 5,
), ),
@ -105,7 +105,7 @@ class _TextInputsCoreState extends State<TextInputsCore> {
controller: _controller3, controller: _controller3,
focusNode: _focusNode3, focusNode: _focusNode3,
expand: false, expand: false,
label: const TextWrapper('Nom / Prénom'), label: 'Nom / Prénom'.wrap(),
onError: (value) => 'Erreur : ${value.length} > 5.', onError: (value) => 'Erreur : ${value.length} > 5.',
validator: (value) => value.length > 5, validator: (value) => value.length > 5,
onChanged: (value) {}, onChanged: (value) {},
@ -116,7 +116,7 @@ class _TextInputsCoreState extends State<TextInputsCore> {
expand: false, expand: false,
controller: _controller4, controller: _controller4,
focusNode: _focusNode4, focusNode: _focusNode4,
label: const TextWrapper('Nom / Prénom'), label: 'Nom / Prénom'.wrap(),
maxLines: 3, maxLines: 3,
onError: (value) => 'Erreur : ${value.length} > 5.', onError: (value) => 'Erreur : ${value.length} > 5.',
validator: (value) => value.length > 5, validator: (value) => value.length > 5,
@ -129,7 +129,7 @@ class _TextInputsCoreState extends State<TextInputsCore> {
suffixIcon: const Icon(Icons.architecture), suffixIcon: const Icon(Icons.architecture),
controller: _controller5, controller: _controller5,
focusNode: _focusNode5, focusNode: _focusNode5,
label: const TextWrapper('Nom / Prénom'), label: 'Nom / Prénom'.wrap(),
onError: (value) => 'Erreur : ${value.length} > 5.', onError: (value) => 'Erreur : ${value.length} > 5.',
validator: (value) => value.length > 5, validator: (value) => value.length > 5,
), ),

View File

@ -0,0 +1,127 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
class CardTheme extends CardThemeExtension {
const CardTheme({
super.backgroundColors,
super.body,
super.borderColors,
super.secondaryBackgroundColor,
super.shadowColor,
super.subtitle,
super.title,
});
factory CardTheme.light() => CardTheme(
backgroundColors: const MultiColor.single(Color(0xFFF6F6F6)),
secondaryBackgroundColor: Colors.white,
borderColors: const MultiColor([
Color(0xFFDDE0E3),
Color(0xFFCACCD4),
]),
title: GoogleFonts.montserrat(
fontSize: 24,
fontWeight: FontWeight.w500,
color: const Color(0xFF24262A),
),
subtitle: GoogleFonts.montserrat(
fontSize: 15,
fontWeight: FontWeight.w300,
color: const Color(0xFF24262A),
),
body: GoogleFonts.montserrat(
fontSize: 12,
fontWeight: FontWeight.w300,
height: 1.7,
color: const Color(0xFF24262A),
),
);
factory CardTheme.dark() => CardTheme(
backgroundColors:
MultiColor.single(const Color(0xFFFFFFFF).withOpacity(0.04)),
secondaryBackgroundColor: const Color(0xFFFFFFFF).withOpacity(0.04),
borderColors: const MultiColor([
Color(0xFF60656A),
Color(0xFF383C40),
]),
title: GoogleFonts.montserrat(
fontSize: 24,
fontWeight: FontWeight.w500,
color: const Color(0xFFFFFFFF),
),
subtitle: GoogleFonts.montserrat(
fontSize: 15,
fontWeight: FontWeight.w300,
color: const Color(0xFFFFFFFF),
),
body: GoogleFonts.montserrat(
fontSize: 12,
fontWeight: FontWeight.w300,
height: 1.7,
color: const Color(0xFFFFFFFF),
),
);
@override
ThemeExtension<CardThemeExtension> copyWith({
MultiColor? backgroundColors,
Color? secondaryBackgroundColor,
MultiColor? borderColors,
BoxShadow? shadowColor,
TextStyle? body,
TextStyle? title,
TextStyle? subtitle,
}) =>
CardTheme(
backgroundColors: backgroundColors ?? this.backgroundColors,
secondaryBackgroundColor:
secondaryBackgroundColor ?? this.secondaryBackgroundColor,
borderColors: borderColors ?? this.borderColors,
shadowColor: shadowColor ?? this.shadowColor,
body: body ?? this.body,
title: title ?? this.title,
subtitle: subtitle ?? this.subtitle,
);
@override
ThemeExtension<CardThemeExtension> lerp(
covariant ThemeExtension<CardThemeExtension>? other,
double t,
) {
if (other is! CardTheme) {
return this;
}
return CardTheme(
backgroundColors: other.backgroundColors,
secondaryBackgroundColor: Color.lerp(
secondaryBackgroundColor,
other.secondaryBackgroundColor,
t,
),
borderColors: other.borderColors,
shadowColor: BoxShadow.lerp(shadowColor, other.shadowColor, t),
body: TextStyle.lerp(body, other.body, t),
title: TextStyle.lerp(title, other.title, t),
subtitle: TextStyle.lerp(subtitle, other.subtitle, t),
);
}
}

View File

@ -0,0 +1,172 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
import 'package:wyatt_ui_kit_example/theme/constants.dart';
class FileSelectionButtonTheme extends FileSelectionButtonThemeExtension {
const FileSelectionButtonTheme({
super.disabledStyle,
super.focusedStyle,
super.hoveredStyle,
super.normalStyle,
super.tappedStyle,
super.selectedStyle,
super.invalidStyle,
});
factory FileSelectionButtonTheme.light() {
final style = FileSelectionButtonStyle(
title: GoogleFonts.montserrat(
fontSize: 16,
fontWeight: FontWeight.w400,
),
subTitle: GoogleFonts.montserrat(
fontSize: 11,
fontWeight: FontWeight.w400,
),
radius: BorderRadius.circular(12),
padding: const EdgeInsets.all(13),
foregroundColors: const MultiColor.single(Constants.grey2),
backgroundColors: MultiColor.single(Constants.white.withOpacity(0.04)),
borderColors: const MultiColor(Constants.greyGradient),
stroke: 2,
);
return FileSelectionButtonTheme(
normalStyle: style,
disabledStyle: style.copyWith(
foregroundColors: MultiColor.single(Constants.grey1.withOpacity(0.4)),
backgroundColors: const MultiColor.single(Constants.white),
borderColors: MultiColor.single(Constants.grey1.withOpacity(0.4)),
),
hoveredStyle: style.copyWith(
backgroundColors: MultiColor.single(Constants.grey1.withOpacity(0.4)),
),
focusedStyle: style.copyWith(stroke: 4),
tappedStyle: style.copyWith(
backgroundColors: MultiColor.single(Constants.grey1.withOpacity(0.4)),
),
invalidStyle: style.copyWith(
subTitle: GoogleFonts.montserrat(
fontSize: 11,
fontWeight: FontWeight.w400,
color: Constants.red1,
),
borderColors: const MultiColor(Constants.redGradient),
),
// Unused
selectedStyle: style.copyWith(
foregroundColors: const MultiColor.single(Constants.grey2),
borderColors: const MultiColor(Constants.greenGradient),
),
);
}
factory FileSelectionButtonTheme.dark() {
final style = FileSelectionButtonStyle(
title: GoogleFonts.montserrat(
fontSize: 16,
fontWeight: FontWeight.w400,
),
subTitle: GoogleFonts.montserrat(
fontSize: 11,
fontWeight: FontWeight.w400,
),
radius: BorderRadius.circular(12),
padding: const EdgeInsets.all(13),
foregroundColors: const MultiColor.single(Constants.white),
backgroundColors: MultiColor.single(Constants.white.withOpacity(0.04)),
borderColors: const MultiColor(Constants.greyGradient),
stroke: 1,
);
return FileSelectionButtonTheme(
normalStyle: style,
disabledStyle: style.copyWith(
foregroundColors: const MultiColor.single(Constants.grey1),
backgroundColors: const MultiColor.single(Constants.grey4),
),
hoveredStyle: style.copyWith(
borderColors: const MultiColor.single(Constants.white),
),
focusedStyle: style.copyWith(stroke: 3),
tappedStyle: style.copyWith(
backgroundColors: const MultiColor(Constants.greyDarkGradient),
),
invalidStyle: style.copyWith(
subTitle: GoogleFonts.montserrat(
fontSize: 11,
fontWeight: FontWeight.w400,
color: Constants.red1,
),
borderColors: const MultiColor(Constants.redGradient),
),
// Unused
selectedStyle: style.copyWith(
foregroundColors: const MultiColor.single(Constants.white),
borderColors: const MultiColor(Constants.greenGradient),
),
);
}
@override
ThemeExtension<FileSelectionButtonThemeExtension> copyWith({
FileSelectionButtonStyle? disabledStyle,
FileSelectionButtonStyle? focusedStyle,
FileSelectionButtonStyle? hoveredStyle,
FileSelectionButtonStyle? normalStyle,
FileSelectionButtonStyle? tappedStyle,
FileSelectionButtonStyle? selectedStyle,
FileSelectionButtonStyle? invalidStyle,
}) =>
FileSelectionButtonTheme(
disabledStyle: disabledStyle ?? this.disabledStyle,
focusedStyle: focusedStyle ?? this.focusedStyle,
hoveredStyle: hoveredStyle ?? this.hoveredStyle,
normalStyle: normalStyle ?? this.normalStyle,
tappedStyle: tappedStyle ?? this.tappedStyle,
selectedStyle: selectedStyle ?? this.selectedStyle,
invalidStyle: invalidStyle ?? this.invalidStyle,
);
@override
ThemeExtension<FileSelectionButtonThemeExtension> lerp(
covariant ThemeExtension<FileSelectionButtonThemeExtension>? other,
double t,
) {
if (other is! FileSelectionButtonTheme) {
return this;
}
return FileSelectionButtonTheme(
disabledStyle:
FileSelectionButtonStyle.lerp(disabledStyle, other.disabledStyle, t),
focusedStyle:
FileSelectionButtonStyle.lerp(focusedStyle, other.focusedStyle, t),
hoveredStyle:
FileSelectionButtonStyle.lerp(hoveredStyle, other.hoveredStyle, t),
normalStyle:
FileSelectionButtonStyle.lerp(normalStyle, other.normalStyle, t),
tappedStyle:
FileSelectionButtonStyle.lerp(tappedStyle, other.tappedStyle, t),
selectedStyle:
FileSelectionButtonStyle.lerp(selectedStyle, other.selectedStyle, t),
invalidStyle:
FileSelectionButtonStyle.lerp(invalidStyle, other.invalidStyle, t),
);
}
}

View File

@ -0,0 +1,153 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
import 'package:wyatt_ui_kit_example/theme/constants.dart';
class FlatButtonTheme extends FlatButtonThemeExtension {
const FlatButtonTheme({
super.disabledStyle,
super.focusedStyle,
super.hoveredStyle,
super.normalStyle,
super.tappedStyle,
});
factory FlatButtonTheme.light() {
final style = FlatButtonStyle(
label: GoogleFonts.montserrat(
fontSize: 18,
fontWeight: FontWeight.w600,
),
radius: BorderRadius.circular(15),
padding: const EdgeInsets.all(10),
foregroundColors: const MultiColor(Constants.blueGradient),
backgroundColors: const MultiColor.single(Constants.white),
borderColors: const MultiColor(Constants.blueGradient),
stroke: 3,
);
return FlatButtonTheme(
normalStyle: style,
disabledStyle: style.copyWith(
label: GoogleFonts.montserrat(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Constants.blue1.withOpacity(0.4),
),
foregroundColors: MultiColor.single(Constants.blue1.withOpacity(0.4)),
backgroundColors: const MultiColor.single(Constants.white),
borderColors: MultiColor.single(Constants.blue1.withOpacity(0.4)),
stroke: 1,
),
hoveredStyle: style.copyWith(
label: GoogleFonts.montserrat(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Constants.white,
),
foregroundColors: const MultiColor.single(Constants.white),
backgroundColors: const MultiColor(Constants.blueGradient),
),
focusedStyle: style.copyWith(stroke: 5),
tappedStyle: style.copyWith(
label: GoogleFonts.montserrat(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Constants.white,
),
foregroundColors: const MultiColor.single(Constants.white),
backgroundColors: const MultiColor(Constants.blueDarkGradient),
borderColors: const MultiColor(Constants.blueDarkGradient),
),
);
}
factory FlatButtonTheme.dark() {
final style = FlatButtonStyle(
label: GoogleFonts.montserrat(
fontSize: 18,
fontWeight: FontWeight.w600,
),
radius: BorderRadius.circular(15),
padding: const EdgeInsets.all(10),
foregroundColors: const MultiColor.single(Constants.white),
backgroundColors: const MultiColor.single(Constants.dark),
borderColors: const MultiColor(Constants.blueGradient),
stroke: 3,
);
return FlatButtonTheme(
normalStyle: style,
disabledStyle: style.copyWith(
label: GoogleFonts.montserrat(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Constants.grey1,
),
foregroundColors: const MultiColor.single(Constants.grey1),
backgroundColors: const MultiColor.single(Constants.grey4),
borderColors: const MultiColor(Constants.greyGradient),
stroke: 1,
),
hoveredStyle: style.copyWith(
foregroundColors: const MultiColor.single(Constants.white),
backgroundColors: const MultiColor(Constants.blueGradient),
),
focusedStyle: style.copyWith(stroke: 5),
tappedStyle: style.copyWith(
foregroundColors: const MultiColor.single(Constants.white),
backgroundColors: const MultiColor(Constants.blueDarkGradient),
borderColors: const MultiColor(Constants.blueDarkGradient),
),
);
}
@override
ThemeExtension<FlatButtonThemeExtension> copyWith({
FlatButtonStyle? disabledStyle,
FlatButtonStyle? focusedStyle,
FlatButtonStyle? hoveredStyle,
FlatButtonStyle? normalStyle,
FlatButtonStyle? tappedStyle,
}) =>
FlatButtonTheme(
disabledStyle: disabledStyle ?? this.disabledStyle,
focusedStyle: focusedStyle ?? this.focusedStyle,
hoveredStyle: hoveredStyle ?? this.hoveredStyle,
normalStyle: normalStyle ?? this.normalStyle,
tappedStyle: tappedStyle ?? this.tappedStyle,
);
@override
ThemeExtension<FlatButtonThemeExtension> lerp(
covariant ThemeExtension<FlatButtonThemeExtension>? other,
double t,
) {
if (other is! FlatButtonTheme) {
return this;
}
return FlatButtonTheme(
disabledStyle:
FlatButtonStyle.lerp(disabledStyle, other.disabledStyle, t),
focusedStyle: FlatButtonStyle.lerp(focusedStyle, other.focusedStyle, t),
hoveredStyle: FlatButtonStyle.lerp(hoveredStyle, other.hoveredStyle, t),
normalStyle: FlatButtonStyle.lerp(normalStyle, other.normalStyle, t),
tappedStyle: FlatButtonStyle.lerp(tappedStyle, other.tappedStyle, t),
);
}
}

View File

@ -16,36 +16,63 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
import 'package:wyatt_ui_kit_example/theme/constants.dart';
/// {@template simple_icon_button_theme_extension} class SimpleIconButtonTheme extends SimpleIconButtonThemeExtension {
/// Simple icon button theme extension that extends [ThemeExtension] and const SimpleIconButtonTheme({
/// implements copyWith, and lerp methods so you don't have to. super.disabledStyle,
/// {@endtemplate} super.focusedStyle,
class SimpleIconButtonThemeExtension super.hoveredStyle,
extends ThemeExtension<SimpleIconButtonThemeExtension> { super.normalStyle,
/// {@macro simple_icon_button_theme_extension} super.tappedStyle,
const SimpleIconButtonThemeExtension({
this.disabledStyle,
this.focusedStyle,
this.hoveredStyle,
this.normalStyle,
this.tappedStyle,
}); });
/// Style of this button in disabled state factory SimpleIconButtonTheme.light() {
final SimpleIconButtonStyle? disabledStyle; 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)),
),
);
}
/// Style of this button in focused state factory SimpleIconButtonTheme.dark() {
final SimpleIconButtonStyle? focusedStyle; final style = SimpleIconButtonStyle(
dimension: 30,
/// Style of this button in hovered state radius: BorderRadius.circular(5),
final SimpleIconButtonStyle? hoveredStyle; padding: const EdgeInsets.all(5),
foregroundColors: const MultiColor.single(Constants.white),
/// Style of this button in normal state backgroundColors: MultiColor.single(Constants.grey3.withOpacity(0.2)),
final SimpleIconButtonStyle? normalStyle; );
return SimpleIconButtonTheme(
/// Style of this button in tapped state normalStyle: style,
final SimpleIconButtonStyle? tappedStyle; 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 @override
ThemeExtension<SimpleIconButtonThemeExtension> copyWith({ ThemeExtension<SimpleIconButtonThemeExtension> copyWith({
@ -55,7 +82,7 @@ class SimpleIconButtonThemeExtension
SimpleIconButtonStyle? normalStyle, SimpleIconButtonStyle? normalStyle,
SimpleIconButtonStyle? tappedStyle, SimpleIconButtonStyle? tappedStyle,
}) => }) =>
SimpleIconButtonThemeExtension( SimpleIconButtonTheme(
disabledStyle: disabledStyle ?? this.disabledStyle, disabledStyle: disabledStyle ?? this.disabledStyle,
focusedStyle: focusedStyle ?? this.focusedStyle, focusedStyle: focusedStyle ?? this.focusedStyle,
hoveredStyle: hoveredStyle ?? this.hoveredStyle, hoveredStyle: hoveredStyle ?? this.hoveredStyle,
@ -68,10 +95,10 @@ class SimpleIconButtonThemeExtension
covariant ThemeExtension<SimpleIconButtonThemeExtension>? other, covariant ThemeExtension<SimpleIconButtonThemeExtension>? other,
double t, double t,
) { ) {
if (other is! SimpleIconButtonThemeExtension) { if (other is! SimpleIconButtonTheme) {
return this; return this;
} }
return SimpleIconButtonThemeExtension( return SimpleIconButtonTheme(
disabledStyle: disabledStyle:
SimpleIconButtonStyle.lerp(disabledStyle, other.disabledStyle, t), SimpleIconButtonStyle.lerp(disabledStyle, other.disabledStyle, t),
focusedStyle: focusedStyle:

View File

@ -0,0 +1,157 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
import 'package:wyatt_ui_kit_example/theme/constants.dart';
class SymbolButtonTheme extends SymbolButtonThemeExtension {
const SymbolButtonTheme({
super.disabledStyle,
super.focusedStyle,
super.hoveredStyle,
super.normalStyle,
super.tappedStyle,
super.selectedStyle,
});
factory SymbolButtonTheme.light() {
final style = SymbolButtonStyle(
label: GoogleFonts.montserrat(
fontSize: 14,
fontWeight: FontWeight.w400,
),
dimension: 60,
radius: BorderRadius.circular(12),
padding: const EdgeInsets.all(10),
foregroundColors: const MultiColor.single(Constants.grey2),
backgroundColors: MultiColor.single(Constants.white.withOpacity(0.04)),
borderColors: const MultiColor(Constants.greyGradient),
stroke: 2,
);
return SymbolButtonTheme(
normalStyle: style,
disabledStyle: style.copyWith(
label: GoogleFonts.montserrat(
fontSize: 14,
fontWeight: FontWeight.w400,
color: Constants.grey1,
),
foregroundColors: MultiColor.single(Constants.grey1.withOpacity(0.4)),
backgroundColors: const MultiColor.single(Constants.white),
borderColors: MultiColor.single(Constants.grey1.withOpacity(0.4)),
),
hoveredStyle: style.copyWith(
backgroundColors: MultiColor.single(Constants.grey1.withOpacity(0.4)),
),
focusedStyle: style.copyWith(stroke: 4),
tappedStyle: style.copyWith(
backgroundColors: MultiColor.single(Constants.grey1.withOpacity(0.4)),
),
selectedStyle: style.copyWith(
label: GoogleFonts.montserrat(
fontSize: 14,
fontWeight: FontWeight.w600,
),
foregroundColors: const MultiColor.single(Constants.grey2),
borderColors: const MultiColor(Constants.greenGradient),
),
);
}
factory SymbolButtonTheme.dark() {
final style = SymbolButtonStyle(
label: GoogleFonts.montserrat(
fontSize: 14,
fontWeight: FontWeight.w400,
),
dimension: 60,
radius: BorderRadius.circular(12),
padding: const EdgeInsets.all(10),
foregroundColors: const MultiColor.single(Constants.white),
backgroundColors: MultiColor.single(Constants.white.withOpacity(0.04)),
borderColors: const MultiColor(Constants.greyGradient),
stroke: 2,
);
return SymbolButtonTheme(
normalStyle: style,
disabledStyle: style.copyWith(
label: GoogleFonts.montserrat(
fontSize: 14,
fontWeight: FontWeight.w400,
color: Constants.grey1,
),
foregroundColors: const MultiColor.single(Constants.grey1),
backgroundColors: const MultiColor.single(Constants.grey4),
),
hoveredStyle: style.copyWith(
backgroundColors: const MultiColor(Constants.greyDarkGradient),
),
focusedStyle: style.copyWith(stroke: 4),
tappedStyle: style.copyWith(
backgroundColors: const MultiColor(Constants.greyDarkGradient),
),
selectedStyle: style.copyWith(
label: GoogleFonts.montserrat(
fontSize: 14,
fontWeight: FontWeight.w600,
),
foregroundColors: const MultiColor.single(Constants.white),
borderColors: const MultiColor(Constants.greenGradient),
),
);
}
@override
ThemeExtension<SymbolButtonThemeExtension> copyWith({
SymbolButtonStyle? disabledStyle,
SymbolButtonStyle? focusedStyle,
SymbolButtonStyle? hoveredStyle,
SymbolButtonStyle? normalStyle,
SymbolButtonStyle? tappedStyle,
SymbolButtonStyle? selectedStyle,
}) =>
SymbolButtonTheme(
disabledStyle: disabledStyle ?? this.disabledStyle,
focusedStyle: focusedStyle ?? this.focusedStyle,
hoveredStyle: hoveredStyle ?? this.hoveredStyle,
normalStyle: normalStyle ?? this.normalStyle,
tappedStyle: tappedStyle ?? this.tappedStyle,
selectedStyle: selectedStyle ?? this.selectedStyle,
);
@override
ThemeExtension<SymbolButtonThemeExtension> lerp(
covariant ThemeExtension<SymbolButtonThemeExtension>? other,
double t,
) {
if (other is! SymbolButtonTheme) {
return this;
}
return SymbolButtonTheme(
disabledStyle:
SymbolButtonStyle.lerp(disabledStyle, other.disabledStyle, t),
focusedStyle: SymbolButtonStyle.lerp(focusedStyle, other.focusedStyle, t),
hoveredStyle: SymbolButtonStyle.lerp(hoveredStyle, other.hoveredStyle, t),
normalStyle: SymbolButtonStyle.lerp(normalStyle, other.normalStyle, t),
tappedStyle: SymbolButtonStyle.lerp(tappedStyle, other.tappedStyle, t),
selectedStyle:
SymbolButtonStyle.lerp(selectedStyle, other.selectedStyle, t),
);
}
}

View File

@ -0,0 +1,161 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
class TextInputTheme extends TextInputThemeExtension {
const TextInputTheme({
super.normalStyle,
super.focusedStyle,
super.disableStyle,
super.errorStyle,
});
factory TextInputTheme.light() => TextInputTheme(
normalStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const Color.fromRGBO(221, 224, 227, 1),
labelStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(55, 65, 81, 1),
),
inputStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(55, 65, 81, 1),
),
),
focusedStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const Color.fromRGBO(60, 125, 251, 1),
labelStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(55, 65, 81, 1),
),
inputStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(55, 65, 81, 1),
),
),
errorStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const Color.fromRGBO(244, 68, 100, 1),
labelStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(244, 68, 100, 1),
),
inputStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(55, 65, 81, 1),
),
),
disableStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const Color.fromRGBO(229, 231, 235, 1),
labelStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(156, 163, 175, 1),
),
inputStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(156, 163, 175, 1),
),
),
);
factory TextInputTheme.dark() => TextInputTheme(
normalStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const Color.fromRGBO(96, 101, 106, 1),
labelStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(204, 204, 204, 1),
),
inputStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(255, 255, 255, 1),
),
),
focusedStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const Color.fromRGBO(60, 125, 251, 1),
labelStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(204, 204, 204, 1),
),
inputStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(255, 255, 255, 1),
),
),
errorStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const Color.fromRGBO(244, 68, 100, 1),
labelStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(244, 68, 100, 1),
),
inputStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(255, 255, 255, 1),
),
),
disableStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const Color.fromRGBO(96, 101, 106, 1),
labelStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(96, 101, 106, 1),
),
inputStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w300,
color: const Color.fromRGBO(255, 255, 255, 1),
),
),
);
@override
ThemeExtension<TextInputThemeExtension> lerp(
covariant ThemeExtension<TextInputThemeExtension>? other,
double t,
) {
if (other is! TextInputTheme) {
return this;
}
return TextInputTheme(
normalStyle: TextInputStyle.lerp(normalStyle, other.normalStyle, t),
focusedStyle: TextInputStyle.lerp(focusedStyle, other.focusedStyle, t),
disableStyle: TextInputStyle.lerp(disableStyle, other.disableStyle, t),
errorStyle: TextInputStyle.lerp(errorStyle, other.errorStyle, t),
);
}
@override
ThemeExtension<TextInputThemeExtension> copyWith({
TextInputStyle? normalStyle,
TextInputStyle? focusedStyle,
TextInputStyle? disableStyle,
TextInputStyle? errorStyle,
}) =>
TextInputTheme(
normalStyle: normalStyle ?? this.normalStyle,
focusedStyle: focusedStyle ?? this.focusedStyle,
disableStyle: disableStyle ?? this.disableStyle,
errorStyle: errorStyle ?? this.errorStyle,
);
}

View File

@ -17,17 +17,21 @@
import 'package:adaptive_theme/adaptive_theme.dart'; import 'package:adaptive_theme/adaptive_theme.dart';
import 'package:flutter/material.dart' hide CardTheme; import 'package:flutter/material.dart' hide CardTheme;
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart'; import 'package:wyatt_ui_kit_example/theme/card_theme.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.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/loader_theme.dart'; import 'package:wyatt_ui_kit_example/theme/loader_theme.dart';
import 'package:wyatt_ui_kit_example/theme/rich_text_builder_theme.dart'; import 'package:wyatt_ui_kit_example/theme/rich_text_builder_theme.dart';
import 'package:wyatt_ui_kit_example/theme/simple_icon_button_theme.dart';
import 'package:wyatt_ui_kit_example/theme/symbol_button_theme.dart';
import 'package:wyatt_ui_kit_example/theme/text_input_theme.dart';
import 'package:wyatt_ui_kit_example/theme/top_bar_theme.dart'; import 'package:wyatt_ui_kit_example/theme/top_bar_theme.dart';
/// Easely switch between Material and Studio themes. /// Easely switch between Material and Studio themes.
abstract class Themes { abstract class Themes {
static int currentThemeIndex = 0; static int currentThemeIndex = 0;
static List<Set<ThemeData>> get themes => [ static List<Set<ThemeData>> themes = [
{materialLight, materialDark}, {materialLight, materialDark},
{studioLight, studioDark}, {studioLight, studioDark},
]; ];
@ -63,25 +67,9 @@ abstract class Themes {
); );
} }
static ThemeData get materialLight => ThemeData.light().copyWith( static ThemeData get materialLight => ThemeData.light();
textTheme: GoogleFonts.robotoTextTheme(
ThemeData.light().textTheme,
),
extensions: <ThemeExtension<dynamic>>[
// Cards
CardThemeExtensionDefault.light(),
// Buttons
FileSelectionButtonThemeExtensionDefault.light(),
FlatButtonThemeExtensionDefault.light(),
SimpleIconButtonThemeExtensionDefault.light(),
SymbolButtonThemeExtensionDefault.light(),
// TextInput
TextInputThemeExtensionDefault.light(),
],
);
static ThemeData get studioLight { static ThemeData get studioLight => materialLight.copyWith(
final theme = ThemeData.light().copyWith(
appBarTheme: AppBarTheme( appBarTheme: AppBarTheme(
foregroundColor: const Color(0xFF24262A), foregroundColor: const Color(0xFF24262A),
backgroundColor: const Color(0xFFFFFFFF), backgroundColor: const Color(0xFFFFFFFF),
@ -92,53 +80,29 @@ abstract class Themes {
), ),
), ),
scaffoldBackgroundColor: Colors.white, scaffoldBackgroundColor: Colors.white,
textTheme: GoogleFonts.montserratTextTheme(
ThemeData.light().textTheme,
),
);
return theme.copyWith(
extensions: <ThemeExtension<dynamic>>[ extensions: <ThemeExtension<dynamic>>[
// Cards // Cards
CardThemeExtensionImpl.light(theme: theme), CardTheme.light(),
// Buttons // Buttons
FileSelectionButtonThemeExtensionImpl.light(theme: theme), FlatButtonTheme.light(),
FlatButtonThemeExtensionImpl.light(theme: theme), SymbolButtonTheme.light(),
SimpleIconButtonThemeExtensionImpl.light(theme: theme), SimpleIconButtonTheme.light(),
SymbolButtonThemeExtensionImpl.light(theme: theme), FileSelectionButtonTheme.light(),
// Loader // Loader
LoaderTheme.light(), LoaderTheme.light(),
// Rich Text // Rich Text
RichTextBuilderTheme.light(), RichTextBuilderTheme.light(),
// TextInput TextInputTheme.light(),
TextInputThemeExtensionImpl.light(theme: theme),
TopAppBarTheme.light(), TopAppBarTheme.light(),
], ],
); );
}
static ThemeData get materialDark => ThemeData.dark().copyWith( static ThemeData get materialDark => ThemeData.dark();
textTheme: GoogleFonts.robotoTextTheme(
ThemeData.dark().textTheme,
),
extensions: <ThemeExtension<dynamic>>[
// Cards
CardThemeExtensionDefault.dark(),
// Buttons
FileSelectionButtonThemeExtensionDefault.dark(),
FlatButtonThemeExtensionDefault.dark(),
SimpleIconButtonThemeExtensionDefault.dark(),
SymbolButtonThemeExtensionDefault.dark(),
// TextInput
TextInputThemeExtensionDefault.dark(),
],
);
static ThemeData get studioDark { static ThemeData get studioDark => materialDark.copyWith(
final theme = ThemeData.dark().copyWith(
appBarTheme: AppBarTheme( appBarTheme: AppBarTheme(
foregroundColor: const Color(0xFFFFFFFF), foregroundColor: const Color(0xFFFFFFFF),
backgroundColor: const Color(0xFF2B3139), backgroundColor: const Color(0xFF383C40),
titleTextStyle: GoogleFonts.montserrat( titleTextStyle: GoogleFonts.montserrat(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -148,29 +112,21 @@ abstract class Themes {
drawerTheme: const DrawerThemeData( drawerTheme: const DrawerThemeData(
backgroundColor: Color(0xFF383C40), backgroundColor: Color(0xFF383C40),
), ),
scaffoldBackgroundColor: const Color(0xFF171A1E), scaffoldBackgroundColor: const Color(0xFF383C40),
textTheme: GoogleFonts.montserratTextTheme(
ThemeData.dark().textTheme,
),
);
return theme.copyWith(
extensions: <ThemeExtension<dynamic>>[ extensions: <ThemeExtension<dynamic>>[
// Cards // Cards
CardThemeExtensionImpl.dark(theme: theme), CardTheme.dark(),
// Buttons // Buttons
FileSelectionButtonThemeExtensionImpl.dark(theme: theme), FlatButtonTheme.dark(),
FlatButtonThemeExtensionImpl.dark(theme: theme), SymbolButtonTheme.dark(),
SimpleIconButtonThemeExtensionImpl.dark(theme: theme), SimpleIconButtonTheme.dark(),
SymbolButtonThemeExtensionImpl.dark(theme: theme), FileSelectionButtonTheme.dark(),
// Loader // Loader
LoaderTheme.dark(), LoaderTheme.dark(),
// Rich Text // Rich Text
RichTextBuilderTheme.dark(), RichTextBuilderTheme.dark(),
// TextInput TextInputTheme.dark(),
TextInputThemeExtensionImpl.dark(theme: theme),
TopAppBarTheme.dark(), TopAppBarTheme.dark(),
], ],
); );
} }
}

View File

@ -8,7 +8,5 @@
<true/> <true/>
<key>com.apple.security.network.server</key> <key>com.apple.security.network.server</key>
<true/> <true/>
<key>com.apple.security.network.client</key>
<true/>
</dict> </dict>
</plist> </plist>

View File

@ -6,7 +6,5 @@
<true/> <true/>
<key>com.apple.security.app-sandbox</key> <key>com.apple.security.app-sandbox</key>
<true/> <true/>
<key>com.apple.security.network.client</key>
<true/>
</dict> </dict>
</plist> </plist>

View File

@ -50,16 +50,16 @@ class TopAppBar extends TopAppBarComponent with $TopAppBarCWMixin {
@override @override
Widget build(BuildContext context) => DecoratedBox( Widget build(BuildContext context) => DecoratedBox(
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: ThemeHelper.maybeGetElement<MultiColor, Gradient>( gradient: ThemeHelper.getThemeElement<MultiColor, Gradient>(
[ [
backgroundColor, backgroundColor,
context.themeExtension<TopBarThemeExtension>()?.backgroundColors, context.themeExtension<TopBarThemeExtension>()?.backgroundColors,
], ],
valueValidator: (value) => value?.isGradient, valueValidator: (value) => value?.isGradient,
transform: (value) => transform: (value) =>
GradientHelper.linearFromNullableColors(value?.colors), LinearGradientHelper.fromNullableColors(value?.colors),
), ),
color: ThemeHelper.maybeGetElement<MultiColor, Color>( color: ThemeHelper.getThemeElement<MultiColor, Color>(
[ [
backgroundColor, backgroundColor,
context.themeExtension<TopBarThemeExtension>()?.backgroundColors, context.themeExtension<TopBarThemeExtension>()?.backgroundColors,
@ -82,7 +82,8 @@ class TopAppBar extends TopAppBarComponent with $TopAppBarCWMixin {
scrolledUnderElevation: scrolledUnderElevation, scrolledUnderElevation: scrolledUnderElevation,
shadowColor: shadowColor, shadowColor: shadowColor,
surfaceTintColor: surfaceTintColor, surfaceTintColor: surfaceTintColor,
iconTheme: ThemeHelper.getElement<IconThemeData, IconThemeData>( iconTheme:
ThemeHelper.getThemeElement<IconThemeData, IconThemeData>(
[ [
iconTheme, iconTheme,
context.themeExtension<TopBarThemeExtension>()?.iconTheme, context.themeExtension<TopBarThemeExtension>()?.iconTheme,
@ -94,9 +95,9 @@ class TopAppBar extends TopAppBarComponent with $TopAppBarCWMixin {
primary: primary ?? true, primary: primary ?? true,
excludeHeaderSemantics: excludeHeaderSemantics ?? false, excludeHeaderSemantics: excludeHeaderSemantics ?? false,
leadingWidth: leadingWidth, leadingWidth: leadingWidth,
title: GradientText( title: Text(
data: title?.data ?? '', title?.data ?? '',
style: ThemeHelper.getElement<TextStyle, TextStyle>( style: ThemeHelper.getThemeElement<TextStyle, TextStyle>(
[ [
context.textTheme.titleLarge, context.textTheme.titleLarge,
context.themeExtension<TopBarThemeExtension>()?.titleStyle, context.themeExtension<TopBarThemeExtension>()?.titleStyle,
@ -106,15 +107,14 @@ class TopAppBar extends TopAppBarComponent with $TopAppBarCWMixin {
combine: (p0, p1) => p0?.merge(p1), combine: (p0, p1) => p0?.merge(p1),
transform: (value) => value, transform: (value) => value,
), ),
gradientColors: const MultiColor([]), ).toGradient(gradientColors: title?.gradientColors),
),
leading: leading, leading: leading,
actions: actions, actions: actions,
centerTitle: centerTitle ?? false, centerTitle: centerTitle ?? false,
), ),
if (expandedWidget != null) if (expandedWidget != null)
...ListTile.divideTiles( ...ListTile.divideTiles(
color: ThemeHelper.getElement<Color, Color>( color: ThemeHelper.getThemeElement<Color, Color>(
[ [
context context
.themeExtension<TopBarThemeExtension>() .themeExtension<TopBarThemeExtension>()

View File

@ -54,16 +54,16 @@ class TopNavigationBar extends TopNavigationBarComponent
@override @override
Widget build(BuildContext context) => DecoratedBox( Widget build(BuildContext context) => DecoratedBox(
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: ThemeHelper.maybeGetElement<MultiColor, Gradient>( gradient: ThemeHelper.getThemeElement<MultiColor, Gradient>(
[ [
backgroundColor, backgroundColor,
context.themeExtension<TopBarThemeExtension>()?.backgroundColors, context.themeExtension<TopBarThemeExtension>()?.backgroundColors,
], ],
valueValidator: (value) => value?.isGradient, valueValidator: (value) => value?.isGradient,
transform: (value) => transform: (value) =>
GradientHelper.linearFromNullableColors(value?.colors), LinearGradientHelper.fromNullableColors(value?.colors),
), ),
color: ThemeHelper.maybeGetElement<MultiColor, Color>( color: ThemeHelper.getThemeElement<MultiColor, Color>(
[ [
backgroundColor, backgroundColor,
context.themeExtension<TopBarThemeExtension>()?.backgroundColors, context.themeExtension<TopBarThemeExtension>()?.backgroundColors,
@ -85,7 +85,7 @@ class TopNavigationBar extends TopNavigationBarComponent
scrolledUnderElevation: scrolledUnderElevation, scrolledUnderElevation: scrolledUnderElevation,
shadowColor: shadowColor, shadowColor: shadowColor,
surfaceTintColor: surfaceTintColor, surfaceTintColor: surfaceTintColor,
iconTheme: ThemeHelper.getElement<IconThemeData, IconThemeData>( iconTheme: ThemeHelper.getThemeElement<IconThemeData, IconThemeData>(
[ [
iconTheme, iconTheme,
context.themeExtension<TopBarThemeExtension>()?.iconTheme, context.themeExtension<TopBarThemeExtension>()?.iconTheme,

View File

@ -33,7 +33,7 @@ class NavigationItem extends StatelessWidget {
children: [ children: [
if (selected) if (selected)
Container( Container(
height: ThemeHelper.getElement<double, double>( height: ThemeHelper.getThemeElement<double, double>(
[ [
context context
.themeExtension<TopBarThemeExtension>() .themeExtension<TopBarThemeExtension>()
@ -44,7 +44,7 @@ class NavigationItem extends StatelessWidget {
valueValidator: (value) => value != null, valueValidator: (value) => value != null,
transform: (value) => value, transform: (value) => value,
), ),
width: ThemeHelper.getElement<double, double>( width: ThemeHelper.getThemeElement<double, double>(
[ [
context context
.themeExtension<TopBarThemeExtension>() .themeExtension<TopBarThemeExtension>()
@ -57,7 +57,7 @@ class NavigationItem extends StatelessWidget {
), ),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100), borderRadius: BorderRadius.circular(100),
color: ThemeHelper.getElement<Color, Color>( color: ThemeHelper.getThemeElement<Color, Color>(
[ [
context context
.themeExtension<TopBarThemeExtension>() .themeExtension<TopBarThemeExtension>()
@ -71,7 +71,7 @@ class NavigationItem extends StatelessWidget {
), ),
ConstrainedBox( ConstrainedBox(
constraints: BoxConstraints( constraints: BoxConstraints(
minWidth: ThemeHelper.getElement<double, double>( minWidth: ThemeHelper.getThemeElement<double, double>(
[ [
context context
.themeExtension<TopBarThemeExtension>() .themeExtension<TopBarThemeExtension>()
@ -81,14 +81,15 @@ class NavigationItem extends StatelessWidget {
], ],
valueValidator: (value) => value != null, valueValidator: (value) => value != null,
transform: (value) => value, transform: (value) => value,
), ) ??
double.infinity,
), ),
child: SizedBox( child: SizedBox(
height: 50, height: 50,
child: Center( child: Center(
child: Text( child: Text(
item.data, item.data,
style: ThemeHelper.getElement<TextStyle, TextStyle>( style: ThemeHelper.getThemeElement<TextStyle, TextStyle>(
[ [
context.textTheme.titleMedium, context.textTheme.titleMedium,
context context

View File

@ -28,7 +28,7 @@ class FileSelectionButton extends FileSelectionButtonComponent
const FileSelectionButton({ const FileSelectionButton({
super.leading, super.leading,
super.title, super.title,
super.subtitle, super.subTitle,
super.disabledStyle, super.disabledStyle,
super.normalStyle, super.normalStyle,
super.hoveredStyle, super.hoveredStyle,
@ -79,7 +79,7 @@ class FileSelectionButton extends FileSelectionButtonComponent
Widget build(BuildContext context) => FileSelectionButtonScreen( Widget build(BuildContext context) => FileSelectionButtonScreen(
leading: leading, leading: leading,
title: title, title: title,
subtitle: subtitle, subTitle: subTitle,
disabledStyle: disabledStyle, disabledStyle: disabledStyle,
normalStyle: normalStyle, normalStyle: normalStyle,
hoveredStyle: hoveredStyle, hoveredStyle: hoveredStyle,

View File

@ -18,8 +18,8 @@ class $FileSelectionButtonCWProxyImpl
@override @override
FileSelectionButton title(TextWrapper? title) => this(title: title); FileSelectionButton title(TextWrapper? title) => this(title: title);
@override @override
FileSelectionButton subtitle(TextWrapper? subtitle) => FileSelectionButton subTitle(TextWrapper? subTitle) =>
this(subtitle: subtitle); this(subTitle: subTitle);
@override @override
FileSelectionButton disabledStyle(ButtonStyle<dynamic>? disabledStyle) => FileSelectionButton disabledStyle(ButtonStyle<dynamic>? disabledStyle) =>
this(disabledStyle: disabledStyle); this(disabledStyle: disabledStyle);
@ -58,7 +58,7 @@ class $FileSelectionButtonCWProxyImpl
MainAxisSize? mainAxisSize, MainAxisSize? mainAxisSize,
Widget? leading, Widget? leading,
TextWrapper? title, TextWrapper? title,
TextWrapper? subtitle, TextWrapper? subTitle,
ButtonStyle<dynamic>? disabledStyle, ButtonStyle<dynamic>? disabledStyle,
ButtonStyle<dynamic>? normalStyle, ButtonStyle<dynamic>? normalStyle,
ButtonStyle<dynamic>? hoveredStyle, ButtonStyle<dynamic>? hoveredStyle,
@ -74,7 +74,7 @@ class $FileSelectionButtonCWProxyImpl
FileSelectionButton( FileSelectionButton(
leading: leading ?? _value.leading, leading: leading ?? _value.leading,
title: title ?? _value.title, title: title ?? _value.title,
subtitle: subtitle ?? _value.subtitle, subTitle: subTitle ?? _value.subTitle,
disabledStyle: disabledStyle ?? _value.disabledStyle, disabledStyle: disabledStyle ?? _value.disabledStyle,
normalStyle: normalStyle ?? _value.normalStyle, normalStyle: normalStyle ?? _value.normalStyle,
hoveredStyle: hoveredStyle ?? _value.hoveredStyle, hoveredStyle: hoveredStyle ?? _value.hoveredStyle,

View File

@ -31,7 +31,7 @@ class FileSelectionButtonScreen
const FileSelectionButtonScreen({ const FileSelectionButtonScreen({
this.leading, this.leading,
this.title, this.title,
this.subtitle, this.subTitle,
this.disabledStyle, this.disabledStyle,
this.normalStyle, this.normalStyle,
this.hoveredStyle, this.hoveredStyle,
@ -46,19 +46,11 @@ class FileSelectionButtonScreen
super.key, super.key,
}); });
/// The leading widget of the button.
final Widget? leading; final Widget? leading;
/// The title widget of the button.
final TextWrapper? title; final TextWrapper? title;
final TextWrapper? subTitle;
/// The subtitle widget of the button.
final TextWrapper? subtitle;
/// The main axis size of the button.
final MainAxisSize? mainAxisSize; final MainAxisSize? mainAxisSize;
// Styles
final FileSelectionButtonStyle? disabledStyle; final FileSelectionButtonStyle? disabledStyle;
final FileSelectionButtonStyle? normalStyle; final FileSelectionButtonStyle? normalStyle;
final FileSelectionButtonStyle? hoveredStyle; final FileSelectionButtonStyle? hoveredStyle;
@ -67,13 +59,8 @@ class FileSelectionButtonScreen
final FileSelectionButtonStyle? selectedStyle; final FileSelectionButtonStyle? selectedStyle;
final FileSelectionButtonStyle? invalidStyle; final FileSelectionButtonStyle? invalidStyle;
/// The callback to be called when the button is pressed.
final void Function(ControlState state)? onPressed; final void Function(ControlState state)? onPressed;
/// The notifier to be used to disable the button.
final ValueNotifier<bool>? disabled; final ValueNotifier<bool>? disabled;
/// The theme resolver to be used to resolve the theme.
final FileSelectionButtonThemeResolver? themeResolver; final FileSelectionButtonThemeResolver? themeResolver;
@override @override
@ -211,28 +198,43 @@ class FileSelectionButtonScreen
/// ///
/// More infos in `ThemeResolver` class /// More infos in `ThemeResolver` class
if (title != null) ...[ if (title != null) ...[
GradientText.fromWrapper( Text(
title!, title!.data,
style: title!.style ?? style.title,
textAlign: title!.textAlign,
textDirection: title!.textDirection,
softWrap: title!.softWrap,
overflow: title!.overflow,
maxLines: title!.maxLines,
selectionColor: title!.selectionColor,
).toGradient(
gradientColors: style.foregroundColors, gradientColors: style.foregroundColors,
) ),
], ],
/// Choose color /// Choose color
/// subtitle.style.color ?? /// subTitle.style.color ??
/// buttonStyle.subtitle.style.color ?? /// buttonStyle.subTitle.style.color ??
/// context.textTheme.subtitleLarge.color /// context.textTheme.subTitleLarge.color
/// ///
/// Choose gradient /// Choose gradient
/// subtitle.gradient ?? /// subTitle.gradient ??
/// buttonStyle.foregroundColor.colors ?? /// buttonStyle.foregroundColor.colors ??
/// null /// null
/// ///
/// More infos in `ThemeResolver` class /// More infos in `ThemeResolver` class
if (subtitle != null) ...[ if (subTitle != null) ...[
const Gap(5), const Gap(5),
GradientText.fromWrapper( Text(
subtitle!, subTitle!.data,
style: style.subtitleStyle, style: subTitle!.style ?? style.subTitle,
textAlign: title!.textAlign,
textDirection: title!.textDirection,
softWrap: title!.softWrap,
overflow: title!.overflow,
maxLines: title!.maxLines,
selectionColor: title!.selectionColor,
).toGradient(
gradientColors: style.foregroundColors, gradientColors: style.foregroundColors,
), ),
], ],

View File

@ -24,6 +24,58 @@ class FileSelectionButtonThemeResolver extends ThemeResolver<
required this.customStyleFn, 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, {
ButtonState? extra,
}) customStyleFn;
@override @override
FileSelectionButtonStyle? computeExtensionValueFn( FileSelectionButtonStyle? computeExtensionValueFn(
BuildContext context, BuildContext context,
@ -44,31 +96,17 @@ class FileSelectionButtonThemeResolver extends ThemeResolver<
case ControlState.tapped: case ControlState.tapped:
style = themeExtension?.tappedStyle; style = themeExtension?.tappedStyle;
break; break;
case null:
case ControlState.normal: case ControlState.normal:
case null:
style = themeExtension?.normalStyle; style = themeExtension?.normalStyle;
break; break;
} }
if (extra?.isInvalid ?? false) {
style = themeExtension?.invalidStyle;
}
if (extra?.isSelected ?? false) { if (extra?.isSelected ?? false) {
style = themeExtension?.selectedStyle; style = themeExtension?.selectedStyle;
} }
if (extra?.isInvalid ?? false) {
style = themeExtension?.invalidStyle;
}
return style; return style;
} }
@override
FileSelectionButtonThemeExtension? getDefaultExtension(
BuildContext context,
) =>
FileSelectionButtonThemeExtensionDefault.from(Theme.of(context));
@override
final FileSelectionButtonStyle? Function(
BuildContext context, {
ButtonState? extra,
}) customStyleFn;
} }

View File

@ -208,9 +208,16 @@ class FlatButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
/// ///
/// More infos in ThemeResolver class /// More infos in ThemeResolver class
if (label != null) ...[ if (label != null) ...[
GradientText.fromWrapper( Text(
label!, label!.data,
style: style.labelStyle, style: label!.style ?? style.label,
textAlign: label!.textAlign,
textDirection: label!.textDirection,
softWrap: label!.softWrap,
overflow: label!.overflow,
maxLines: label!.maxLines,
selectionColor: label!.selectionColor,
).toGradient(
gradientColors: style.foregroundColors, gradientColors: style.foregroundColors,
) )
], ],

View File

@ -16,6 +16,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
class FlatButtonThemeResolver extends ThemeResolver<FlatButtonStyle, class FlatButtonThemeResolver extends ThemeResolver<FlatButtonStyle,
FlatButtonThemeExtension, ControlState> { FlatButtonThemeExtension, ControlState> {
@ -23,42 +24,73 @@ class FlatButtonThemeResolver extends ThemeResolver<FlatButtonStyle,
required this.customStyleFn, required this.customStyleFn,
}); });
/// Values taken from <https://api.flutter.dev/flutter/material/ElevatedButton/defaultStyleOf.html>
@override @override
FlatButtonStyle? computeExtensionValueFn( FlatButtonStyle computeDefaultValue(
BuildContext context, BuildContext context, {
FlatButtonThemeExtension? themeExtension, {
ControlState? extra, ControlState? extra,
}) { }) {
FlatButtonStyle? style; MultiColor backgroundColor = MultiColor.single(context.colorScheme.primary);
MultiColor foregroundColor =
MultiColor.single(context.colorScheme.onPrimary);
switch (extra) { switch (extra) {
case ControlState.disabled: case ControlState.disabled:
style = themeExtension?.disabledStyle; backgroundColor =
break; MultiColor.single(context.colorScheme.onSurface.withOpacity(0.12));
case ControlState.focused: foregroundColor =
style = themeExtension?.focusedStyle; MultiColor.single(context.colorScheme.onSurface.withOpacity(0.38));
break; break;
case ControlState.hovered: case ControlState.hovered:
style = themeExtension?.hoveredStyle; backgroundColor =
MultiColor.single(context.colorScheme.primary.withOpacity(0.92));
break; break;
case ControlState.tapped: case ControlState.tapped:
style = themeExtension?.tappedStyle; backgroundColor =
MultiColor.single(context.colorScheme.primary.withOpacity(0.92));
break; break;
case null: case null:
case ControlState.normal: case ControlState.normal:
style = themeExtension?.normalStyle; case ControlState.focused:
break; break;
} }
return style; 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
FlatButtonThemeExtension? getDefaultExtension(BuildContext context) =>
FlatButtonThemeExtensionDefault.from(Theme.of(context));
@override @override
final FlatButtonStyle? Function( final FlatButtonStyle? Function(
BuildContext context, { BuildContext context, {
ControlState? extra, ControlState? extra,
}) customStyleFn; }) customStyleFn;
@override
FlatButtonStyle? computeExtensionValueFn(
BuildContext context,
FlatButtonThemeExtension? themeExtension, {
ControlState? 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;
}
}
} }

View File

@ -11,7 +11,7 @@ class $SimpleIconButtonCWProxyImpl
const $SimpleIconButtonCWProxyImpl(this._value); const $SimpleIconButtonCWProxyImpl(this._value);
final SimpleIconButton _value; final SimpleIconButton _value;
@override @override
SimpleIconButton icon(Widget? icon) => this(icon: icon); SimpleIconButton icon(Icon? icon) => this(icon: icon);
@override @override
SimpleIconButton disabledStyle(ButtonStyle<dynamic>? disabledStyle) => SimpleIconButton disabledStyle(ButtonStyle<dynamic>? disabledStyle) =>
this(disabledStyle: disabledStyle); this(disabledStyle: disabledStyle);
@ -41,7 +41,7 @@ class $SimpleIconButtonCWProxyImpl
SimpleIconButton key(Key? key) => this(key: key); SimpleIconButton key(Key? key) => this(key: key);
@override @override
SimpleIconButton call({ SimpleIconButton call({
Widget? icon, Icon? icon,
ButtonStyle<dynamic>? disabledStyle, ButtonStyle<dynamic>? disabledStyle,
ButtonStyle<dynamic>? normalStyle, ButtonStyle<dynamic>? normalStyle,
ButtonStyle<dynamic>? hoveredStyle, ButtonStyle<dynamic>? hoveredStyle,

View File

@ -16,6 +16,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
class SimpleIconButtonThemeResolver extends ThemeResolver<SimpleIconButtonStyle, class SimpleIconButtonThemeResolver extends ThemeResolver<SimpleIconButtonStyle,
SimpleIconButtonThemeExtension, ControlState> { SimpleIconButtonThemeExtension, ControlState> {
@ -24,41 +25,70 @@ class SimpleIconButtonThemeResolver extends ThemeResolver<SimpleIconButtonStyle,
}); });
@override @override
SimpleIconButtonStyle? computeExtensionValueFn( SimpleIconButtonStyle computeDefaultValue(
BuildContext context, BuildContext context, {
SimpleIconButtonThemeExtension? themeExtension, {
ControlState? extra, ControlState? extra,
}) { }) {
SimpleIconButtonStyle? style; MultiColor backgroundColor = MultiColor.single(context.colorScheme.primary);
MultiColor foregroundColor =
MultiColor.single(context.colorScheme.onPrimary);
switch (extra) { switch (extra) {
case ControlState.disabled: case ControlState.disabled:
style = themeExtension?.disabledStyle; backgroundColor =
break; MultiColor.single(context.colorScheme.onSurface.withOpacity(0.12));
case ControlState.focused: foregroundColor =
style = themeExtension?.focusedStyle; MultiColor.single(context.colorScheme.onSurface.withOpacity(0.38));
break; break;
case ControlState.hovered: case ControlState.hovered:
style = themeExtension?.hoveredStyle; backgroundColor =
MultiColor.single(context.colorScheme.primary.withOpacity(0.92));
break; break;
case ControlState.tapped: case ControlState.tapped:
style = themeExtension?.tappedStyle; backgroundColor =
MultiColor.single(context.colorScheme.primary.withOpacity(0.92));
break; break;
case null: case null:
case ControlState.normal: case ControlState.normal:
style = themeExtension?.normalStyle; case ControlState.focused:
break; break;
} }
return style; 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
SimpleIconButtonThemeExtension? getDefaultExtension(BuildContext context) =>
SimpleIconButtonThemeExtensionDefault.from(Theme.of(context));
@override @override
final SimpleIconButtonStyle? Function( final SimpleIconButtonStyle? Function(
BuildContext context, { BuildContext context, {
ControlState? extra, ControlState? extra,
}) customStyleFn; }) customStyleFn;
@override
SimpleIconButtonStyle? computeExtensionValueFn(
BuildContext context,
SimpleIconButtonThemeExtension? themeExtension, {
ControlState? 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;
}
}
} }

View File

@ -18,9 +18,12 @@ import 'package:flutter/material.dart' hide ButtonStyle;
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart'; import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart'; import 'package:wyatt_ui_components/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/state_listener.dart'; import 'package:wyatt_ui_kit/src/components/buttons/cubit/state_listener.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/wyatt_ui_kit.dart'; import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_icon.dart';
import 'package:wyatt_ui_kit/src/core/helpers/linear_gradient_helper.dart';
class SimpleIconButtonScreen extends CubitScreen<ButtonCubit, ButtonState> { class SimpleIconButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
const SimpleIconButtonScreen({ const SimpleIconButtonScreen({
@ -36,7 +39,7 @@ class SimpleIconButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
super.key, super.key,
}); });
final Widget? icon; final Icon? icon;
final SimpleIconButtonStyle? disabledStyle; final SimpleIconButtonStyle? disabledStyle;
final SimpleIconButtonStyle? normalStyle; final SimpleIconButtonStyle? normalStyle;
@ -168,23 +171,25 @@ class SimpleIconButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
/// context.buttonTheme.onPrimary /// context.buttonTheme.onPrimary
child: Builder( child: Builder(
builder: (context) { builder: (context) {
if (icon != null) { if (icon?.color != null) {
if (icon is GradientIcon) {
return icon!; return icon!;
} }
if (icon is Icon) {
return GradientIcon.fromIcon( if (!(style.foregroundColors?.isGradient ?? false)) {
(icon as Icon?)!, return ColorFiltered(
gradientColors: style.foregroundColors, colorFilter: ColorFilter.mode(
); style.foregroundColors!.color,
} BlendMode.srcIn,
return GradientIcon.fromWidget( ),
icon!, child: icon,
gradientColors: style.foregroundColors,
); );
} }
return const SizedBox.shrink(); return icon!.toGradient(
LinearGradientHelper.fromMultiColor(
style.foregroundColors!,
),
);
}, },
), ),
), ),

View File

@ -209,9 +209,16 @@ class SymbolButtonScreen
/// More infos in `negociate()` method /// More infos in `negociate()` method
if (label != null) ...[ if (label != null) ...[
Gap(style.padding?.horizontal ?? 10), Gap(style.padding?.horizontal ?? 10),
GradientText.fromWrapper( Text(
label!, label!.data,
style: style.labelStyle, style: label!.style ?? style.label,
textAlign: label!.textAlign,
textDirection: label!.textDirection,
softWrap: label!.softWrap,
overflow: label!.overflow,
maxLines: label!.maxLines,
selectionColor: label!.selectionColor,
).toGradient(
gradientColors: style.foregroundColors, gradientColors: style.foregroundColors,
), ),
], ],

View File

@ -24,6 +24,54 @@ class SymbolButtonThemeResolver extends ThemeResolver<SymbolButtonStyle,
required this.customStyleFn, 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, {
ButtonState? extra,
}) customStyleFn;
@override @override
SymbolButtonStyle? computeExtensionValueFn( SymbolButtonStyle? computeExtensionValueFn(
BuildContext context, BuildContext context,
@ -44,28 +92,15 @@ class SymbolButtonThemeResolver extends ThemeResolver<SymbolButtonStyle,
case ControlState.tapped: case ControlState.tapped:
style = themeExtension?.tappedStyle; style = themeExtension?.tappedStyle;
break; break;
case null:
case ControlState.normal: case ControlState.normal:
case null:
style = themeExtension?.normalStyle; style = themeExtension?.normalStyle;
break; break;
} }
if (extra?.isSelected ?? false) { if (extra?.isSelected ?? false) {
style = themeExtension?.selectedStyle; style = themeExtension?.selectedStyle;
} }
return style; return style;
} }
@override
SymbolButtonThemeExtension? getDefaultExtension(
BuildContext context,
) =>
SymbolButtonThemeExtensionDefault.from(Theme.of(context));
@override
final SymbolButtonStyle? Function(
BuildContext context, {
ButtonState? extra,
}) customStyleFn;
} }

View File

@ -40,52 +40,20 @@ class InformationCard extends InformationCardComponent
super.padding, super.padding,
super.borderColors, super.borderColors,
super.backgroundColors, super.backgroundColors,
super.stroke,
super.minSize, super.minSize,
super.maxSize, super.maxSize = const Size(330, double.infinity),
super.shadow, super.shadow,
super.titleStyle,
super.subtitleStyle,
super.bodyStyle,
super.background, super.background,
super.key, super.key,
}); });
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) => CardWrapper(
final themeTitleStyle = ThemeHelper.maybeGetElement<TextStyle, TextStyle>(
[
titleStyle,
Theme.of(context).extension<CardThemeExtension>()?.titleStyle,
CardThemeExtensionDefault.from(Theme.of(context)).titleStyle,
],
);
final themeSubtitleStyle =
ThemeHelper.maybeGetElement<TextStyle, TextStyle>(
[
subtitleStyle,
Theme.of(context).extension<CardThemeExtension>()?.subtitleStyle,
CardThemeExtensionDefault.from(Theme.of(context)).subtitleStyle,
],
);
final themeBodyStyle = ThemeHelper.maybeGetElement<TextStyle, TextStyle>(
[
bodyStyle,
Theme.of(context).extension<CardThemeExtension>()?.bodyStyle,
CardThemeExtensionDefault.from(Theme.of(context)).bodyStyle,
],
);
return CardWrapper(
background: background, background: background,
padding: padding, padding: padding,
radius: radius,
backgroundColors: backgroundColors, backgroundColors: backgroundColors,
borderColors: borderColors, borderColors: borderColors,
shadow: shadow, shadow: shadow,
stroke: stroke,
maxSize: maxSize, maxSize: maxSize,
minSize: minSize, minSize: minSize,
child: Column( child: Column(
@ -97,28 +65,25 @@ class InformationCard extends InformationCardComponent
axis: axis, axis: axis,
title: title, title: title,
subtitle: subtitle, subtitle: subtitle,
titleStyle: themeTitleStyle,
subtitleStyle: themeSubtitleStyle,
), ),
] else ...[ ] else if (axis == Axis.vertical) ...[
InformationCardVerticalHeader( InformationCardVerticalHeader(
icons: icons, icons: icons,
axis: axis, axis: axis,
title: title, title: title,
subtitle: subtitle, subtitle: subtitle,
titleStyle: themeTitleStyle,
subtitleStyle: themeSubtitleStyle,
), ),
], ],
if (body != null) ...[ if (body != null) ...[
const Gap(_bodyTopSpacing), const Gap(_bodyTopSpacing),
CardText.fromWrapper( CardText(
body!, body!,
style: themeBodyStyle, textType: TextType.body,
style: body!.style,
gradientColors: body!.gradientColors,
), ),
], ],
], ],
), ),
); );
} }
}

View File

@ -20,10 +20,9 @@ class $InformationCardCWProxyImpl implements $InformationCardComponentCWProxy {
@override @override
InformationCard axis(Axis? axis) => this(axis: axis); InformationCard axis(Axis? axis) => this(axis: axis);
@override @override
InformationCard radius(BorderRadiusGeometry? radius) => this(radius: radius); InformationCard radius(double? radius) => this(radius: radius);
@override @override
InformationCard padding(EdgeInsetsGeometry? padding) => InformationCard padding(double? padding) => this(padding: padding);
this(padding: padding);
@override @override
InformationCard borderColors(MultiColor? borderColors) => InformationCard borderColors(MultiColor? borderColors) =>
this(borderColors: borderColors); this(borderColors: borderColors);
@ -31,22 +30,12 @@ class $InformationCardCWProxyImpl implements $InformationCardComponentCWProxy {
InformationCard backgroundColors(MultiColor? backgroundColors) => InformationCard backgroundColors(MultiColor? backgroundColors) =>
this(backgroundColors: backgroundColors); this(backgroundColors: backgroundColors);
@override @override
InformationCard stroke(double? stroke) => this(stroke: stroke);
@override
InformationCard minSize(Size? minSize) => this(minSize: minSize); InformationCard minSize(Size? minSize) => this(minSize: minSize);
@override @override
InformationCard maxSize(Size? maxSize) => this(maxSize: maxSize); InformationCard maxSize(Size? maxSize) => this(maxSize: maxSize);
@override @override
InformationCard shadow(BoxShadow? shadow) => this(shadow: shadow); InformationCard shadow(BoxShadow? shadow) => this(shadow: shadow);
@override @override
InformationCard titleStyle(TextStyle? titleStyle) =>
this(titleStyle: titleStyle);
@override
InformationCard subtitleStyle(TextStyle? subtitleStyle) =>
this(subtitleStyle: subtitleStyle);
@override
InformationCard bodyStyle(TextStyle? bodyStyle) => this(bodyStyle: bodyStyle);
@override
InformationCard background(Widget? background) => InformationCard background(Widget? background) =>
this(background: background); this(background: background);
@override @override
@ -58,17 +47,13 @@ class $InformationCardCWProxyImpl implements $InformationCardComponentCWProxy {
TextWrapper? subtitle, TextWrapper? subtitle,
TextWrapper? body, TextWrapper? body,
Axis? axis, Axis? axis,
BorderRadiusGeometry? radius, double? radius,
EdgeInsetsGeometry? padding, double? padding,
MultiColor? borderColors, MultiColor? borderColors,
MultiColor? backgroundColors, MultiColor? backgroundColors,
double? stroke,
Size? minSize, Size? minSize,
Size? maxSize, Size? maxSize,
BoxShadow? shadow, BoxShadow? shadow,
TextStyle? titleStyle,
TextStyle? subtitleStyle,
TextStyle? bodyStyle,
Widget? background, Widget? background,
Key? key, Key? key,
}) => }) =>
@ -82,13 +67,9 @@ class $InformationCardCWProxyImpl implements $InformationCardComponentCWProxy {
padding: padding ?? _value.padding, padding: padding ?? _value.padding,
borderColors: borderColors ?? _value.borderColors, borderColors: borderColors ?? _value.borderColors,
backgroundColors: backgroundColors ?? _value.backgroundColors, backgroundColors: backgroundColors ?? _value.backgroundColors,
stroke: stroke ?? _value.stroke,
minSize: minSize ?? _value.minSize, minSize: minSize ?? _value.minSize,
maxSize: maxSize ?? _value.maxSize, maxSize: maxSize ?? _value.maxSize,
shadow: shadow ?? _value.shadow, shadow: shadow ?? _value.shadow,
titleStyle: titleStyle ?? _value.titleStyle,
subtitleStyle: subtitleStyle ?? _value.subtitleStyle,
bodyStyle: bodyStyle ?? _value.bodyStyle,
background: background ?? _value.background, background: background ?? _value.background,
key: key ?? _value.key, key: key ?? _value.key,
); );

View File

@ -23,32 +23,17 @@ const _avatarAndTitlesSpacing = 25.0;
class InformationCardHorizontalHeader extends StatelessWidget { class InformationCardHorizontalHeader extends StatelessWidget {
const InformationCardHorizontalHeader({ const InformationCardHorizontalHeader({
this.icons,
this.axis,
this.title, this.title,
this.subtitle, this.subtitle,
this.titleStyle, this.axis,
this.subtitleStyle, this.icons,
super.key, super.key,
}); });
/// The icons of the card header.
final List<Widget>? icons;
/// The axis of the card header.
final Axis? axis;
/// The title of the card.
final TextWrapper? title; final TextWrapper? title;
/// The subtitle of the card.
final TextWrapper? subtitle; final TextWrapper? subtitle;
final Axis? axis;
/// Styles the title of the card. final List<Widget>? icons;
final TextStyle? titleStyle;
/// Styles the subtitle of the card.
final TextStyle? subtitleStyle;
@override @override
Widget build(BuildContext context) => Row( Widget build(BuildContext context) => Row(
@ -59,11 +44,9 @@ class InformationCardHorizontalHeader extends StatelessWidget {
], ],
Expanded( Expanded(
child: InformationCardTitles( child: InformationCardTitles(
axis: axis,
title: title, title: title,
subtitle: subtitle, subtitle: subtitle,
titleStyle: titleStyle, axis: axis,
subtitleStyle: subtitleStyle,
), ),
), ),
], ],

View File

@ -25,7 +25,6 @@ class InformationCardIcons extends StatelessWidget {
this.icons, this.icons,
}); });
/// The icons of the card header.
final List<Widget>? icons; final List<Widget>? icons;
@override @override

View File

@ -23,28 +23,15 @@ const _titlesLineSpacing = 5.0;
class InformationCardTitles extends StatelessWidget { class InformationCardTitles extends StatelessWidget {
const InformationCardTitles({ const InformationCardTitles({
this.axis,
this.title, this.title,
this.subtitle, this.subtitle,
this.titleStyle, this.axis,
this.subtitleStyle,
super.key, super.key,
}); });
/// The axis of the card header.
final Axis? axis;
/// The title of the card.
final TextWrapper? title; final TextWrapper? title;
/// The subtitle of the card.
final TextWrapper? subtitle; final TextWrapper? subtitle;
final Axis? axis;
/// Styles the title of the card.
final TextStyle? titleStyle;
/// Styles the subtitle of the card.
final TextStyle? subtitleStyle;
@override @override
Widget build(BuildContext context) => Column( Widget build(BuildContext context) => Column(
@ -53,18 +40,20 @@ class InformationCardTitles extends StatelessWidget {
: CrossAxisAlignment.center, : CrossAxisAlignment.center,
children: [ children: [
if (title != null) ...[ if (title != null) ...[
CardText.fromWrapper( CardText(
title!, title!,
style: titleStyle,
textType: TextType.title, textType: TextType.title,
style: title!.style,
gradientColors: title!.gradientColors,
), ),
], ],
if (subtitle != null) ...[ if (subtitle != null) ...[
const Gap(_titlesLineSpacing), const Gap(_titlesLineSpacing),
CardText.fromWrapper( CardText(
subtitle!, subtitle!,
style: subtitleStyle,
textType: TextType.subtitle, textType: TextType.subtitle,
style: subtitle!.style,
gradientColors: subtitle!.gradientColors,
), ),
], ],
], ],

View File

@ -24,32 +24,17 @@ const _avatarAndTitlesSpacing = 25.0;
class InformationCardVerticalHeader extends StatelessWidget { class InformationCardVerticalHeader extends StatelessWidget {
const InformationCardVerticalHeader({ const InformationCardVerticalHeader({
this.icons,
this.axis,
this.title, this.title,
this.subtitle, this.subtitle,
this.titleStyle, this.axis,
this.subtitleStyle, this.icons,
super.key, super.key,
}); });
/// The icons of the card header.
final List<Widget>? icons;
/// The axis of the card header.
final Axis? axis;
/// The title of the card.
final TextWrapper? title; final TextWrapper? title;
/// The subtitle of the card.
final TextWrapper? subtitle; final TextWrapper? subtitle;
final Axis? axis;
/// Styles the title of the card. final List<Widget>? icons;
final TextStyle? titleStyle;
/// Styles the subtitle of the card.
final TextStyle? subtitleStyle;
@override @override
Widget build(BuildContext context) => Column( Widget build(BuildContext context) => Column(
@ -61,11 +46,9 @@ class InformationCardVerticalHeader extends StatelessWidget {
const Gap(_avatarAndTitlesSpacing), const Gap(_avatarAndTitlesSpacing),
], ],
InformationCardTitles( InformationCardTitles(
axis: axis,
title: title, title: title,
subtitle: subtitle, subtitle: subtitle,
titleStyle: titleStyle, axis: axis,
subtitleStyle: subtitleStyle,
), ),
], ],
); );

View File

@ -25,14 +25,11 @@ import 'package:wyatt_ui_kit/src/components/cards/widgets/card_wrapper.dart';
part 'portfolio_card.g.dart'; part 'portfolio_card.g.dart';
const _spacing = 20.0;
@ComponentCopyWithExtension() @ComponentCopyWithExtension()
class PortfolioCard extends PortfolioCardComponent with $PortfolioCardCWMixin { class PortfolioCard extends PortfolioCardComponent with $PortfolioCardCWMixin {
const PortfolioCard({ const PortfolioCard({
super.showAssetsOnTop, super.showImagesOnTop,
super.keywords, super.keyword,
super.keywordsBackgroundColors,
super.description, super.description,
super.logo, super.logo,
super.projectName, super.projectName,
@ -43,129 +40,79 @@ class PortfolioCard extends PortfolioCardComponent with $PortfolioCardCWMixin {
super.padding, super.padding,
super.borderColors, super.borderColors,
super.backgroundColors, super.backgroundColors,
super.stroke, super.secondaryBackgroundColors,
super.minSize, super.minSize,
super.maxSize, super.maxSize = const Size(330, double.infinity),
super.shadow, super.shadow,
super.titleStyle,
super.subtitleStyle,
super.bodyStyle,
super.background, super.background,
super.key, super.key,
}); });
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) => CardWrapper(
final themeTitleStyle = ThemeHelper.maybeGetElement<TextStyle, TextStyle>(
[
titleStyle,
Theme.of(context).extension<CardThemeExtension>()?.titleStyle,
CardThemeExtensionDefault.from(Theme.of(context)).titleStyle,
],
);
final themeSubtitleStyle =
ThemeHelper.maybeGetElement<TextStyle, TextStyle>(
[
subtitleStyle,
Theme.of(context).extension<CardThemeExtension>()?.subtitleStyle,
CardThemeExtensionDefault.from(Theme.of(context)).subtitleStyle,
],
);
final themeBodyStyle = ThemeHelper.maybeGetElement<TextStyle, TextStyle>(
[
bodyStyle,
Theme.of(context).extension<CardThemeExtension>()?.bodyStyle,
CardThemeExtensionDefault.from(Theme.of(context)).bodyStyle,
],
);
final themeBorderRadius =
ThemeHelper.maybeGetElement<BorderRadiusGeometry, BorderRadiusGeometry>(
[
radius,
Theme.of(context).extension<CardThemeExtension>()?.radius,
CardThemeExtensionDefault.from(Theme.of(context)).radius,
],
);
final themeMaxSize = ThemeHelper.maybeGetElement<Size, Size>(
[
maxSize,
Theme.of(context).extension<CardThemeExtension>()?.maxSize,
CardThemeExtensionDefault.from(Theme.of(context)).maxSize,
],
);
return CardWrapper(
background: background, background: background,
padding: padding, padding: padding,
radius: radius,
backgroundColors: backgroundColors, backgroundColors: backgroundColors,
borderColors: borderColors, borderColors: borderColors,
shadow: shadow, shadow: shadow,
stroke: stroke,
maxSize: maxSize, maxSize: maxSize,
minSize: minSize, minSize: minSize,
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
if (showAssetsOnTop ?? false) ...[ if (showImagesOnTop ?? false) ...[
if (assets != null) ...[ if (assets != null) ...[
PortfolioCardImages( PortfolioCardImages(
assets: assets, radius: radius,
radius: themeBorderRadius, maxSize: maxSize,
maxSize: themeMaxSize, images: assets,
), ),
const Gap(_spacing), const Gap(20),
], ],
CardText.fromWrapper( CardText(
description!, description!,
style: themeBodyStyle, textType: TextType.body,
style: description!.style,
gradientColors: description!.gradientColors,
), ),
const Gap(_spacing), const Gap(20),
PortfolioCardHeader( PortfolioCardHeader(
secondaryBackgroundColors: secondaryBackgroundColors,
logo: logo, logo: logo,
padding: padding,
radius: radius,
projectName: projectName, projectName: projectName,
subtitle: subtitle, subtitle: subtitle,
keywords: keywords, keyword: keyword,
keywordsBackgroundColors: keywordsBackgroundColors,
titleStyle: themeTitleStyle,
subtitleStyle: themeSubtitleStyle,
keywordsStyle: themeBodyStyle,
), ),
] else ...[ ] else ...[
PortfolioCardHeader( PortfolioCardHeader(
secondaryBackgroundColors: secondaryBackgroundColors,
logo: logo, logo: logo,
padding: padding,
radius: radius,
projectName: projectName, projectName: projectName,
subtitle: subtitle, subtitle: subtitle,
keywords: keywords, keyword: keyword,
keywordsBackgroundColors: keywordsBackgroundColors,
titleStyle: themeTitleStyle,
subtitleStyle: themeSubtitleStyle,
keywordsStyle: themeBodyStyle,
), ),
const Gap(10), const Gap(10),
if (assets != null) ...[ if (assets != null) ...[
PortfolioCardImages( PortfolioCardImages(
assets: assets, radius: radius,
radius: themeBorderRadius, maxSize: maxSize,
maxSize: themeMaxSize, images: assets,
), ),
const Gap(_spacing), const Gap(20),
], ],
CardText.fromWrapper( CardText(
description!, description!,
style: themeBodyStyle, textType: TextType.body,
style: description!.style,
gradientColors: description!.gradientColors,
), ),
], ],
if (ctas != null) if (ctas != null) ...[const Gap(20), ...ctas!],
...[const Gap(_spacing), ...ctas!].map(
(e) => SelectionContainer.disabled(child: e),
),
], ],
), ),
); );
} }
}

View File

@ -10,15 +10,13 @@ class $PortfolioCardCWProxyImpl implements $PortfolioCardComponentCWProxy {
const $PortfolioCardCWProxyImpl(this._value); const $PortfolioCardCWProxyImpl(this._value);
final PortfolioCard _value; final PortfolioCard _value;
@override @override
PortfolioCard showAssetsOnTop(bool? showAssetsOnTop) => PortfolioCard secondaryBackgroundColors(Color? secondaryBackgroundColors) =>
this(showAssetsOnTop: showAssetsOnTop); this(secondaryBackgroundColors: secondaryBackgroundColors);
@override @override
PortfolioCard keywords(List<TextWrapper>? keywords) => PortfolioCard showImagesOnTop(bool? showImagesOnTop) =>
this(keywords: keywords); this(showImagesOnTop: showImagesOnTop);
@override @override
PortfolioCard keywordsBackgroundColors( PortfolioCard keyword(List<TextWrapper>? keyword) => this(keyword: keyword);
MultiColor? keywordsBackgroundColors) =>
this(keywordsBackgroundColors: keywordsBackgroundColors);
@override @override
PortfolioCard description(TextWrapper? description) => PortfolioCard description(TextWrapper? description) =>
this(description: description); this(description: description);
@ -34,9 +32,9 @@ class $PortfolioCardCWProxyImpl implements $PortfolioCardComponentCWProxy {
@override @override
PortfolioCard assets(List<Widget>? assets) => this(assets: assets); PortfolioCard assets(List<Widget>? assets) => this(assets: assets);
@override @override
PortfolioCard radius(BorderRadiusGeometry? radius) => this(radius: radius); PortfolioCard radius(double? radius) => this(radius: radius);
@override @override
PortfolioCard padding(EdgeInsetsGeometry? padding) => this(padding: padding); PortfolioCard padding(double? padding) => this(padding: padding);
@override @override
PortfolioCard borderColors(MultiColor? borderColors) => PortfolioCard borderColors(MultiColor? borderColors) =>
this(borderColors: borderColors); this(borderColors: borderColors);
@ -44,55 +42,39 @@ class $PortfolioCardCWProxyImpl implements $PortfolioCardComponentCWProxy {
PortfolioCard backgroundColors(MultiColor? backgroundColors) => PortfolioCard backgroundColors(MultiColor? backgroundColors) =>
this(backgroundColors: backgroundColors); this(backgroundColors: backgroundColors);
@override @override
PortfolioCard stroke(double? stroke) => this(stroke: stroke);
@override
PortfolioCard minSize(Size? minSize) => this(minSize: minSize); PortfolioCard minSize(Size? minSize) => this(minSize: minSize);
@override @override
PortfolioCard maxSize(Size? maxSize) => this(maxSize: maxSize); PortfolioCard maxSize(Size? maxSize) => this(maxSize: maxSize);
@override @override
PortfolioCard shadow(BoxShadow? shadow) => this(shadow: shadow); PortfolioCard shadow(BoxShadow? shadow) => this(shadow: shadow);
@override @override
PortfolioCard titleStyle(TextStyle? titleStyle) =>
this(titleStyle: titleStyle);
@override
PortfolioCard subtitleStyle(TextStyle? subtitleStyle) =>
this(subtitleStyle: subtitleStyle);
@override
PortfolioCard bodyStyle(TextStyle? bodyStyle) => this(bodyStyle: bodyStyle);
@override
PortfolioCard background(Widget? background) => this(background: background); PortfolioCard background(Widget? background) => this(background: background);
@override @override
PortfolioCard key(Key? key) => this(key: key); PortfolioCard key(Key? key) => this(key: key);
@override @override
PortfolioCard call({ PortfolioCard call({
bool? showAssetsOnTop, Color? secondaryBackgroundColors,
List<TextWrapper>? keywords, bool? showImagesOnTop,
MultiColor? keywordsBackgroundColors, List<TextWrapper>? keyword,
TextWrapper? description, TextWrapper? description,
Widget? logo, Widget? logo,
TextWrapper? projectName, TextWrapper? projectName,
TextWrapper? subtitle, TextWrapper? subtitle,
List<Widget>? ctas, List<Widget>? ctas,
List<Widget>? assets, List<Widget>? assets,
BorderRadiusGeometry? radius, double? radius,
EdgeInsetsGeometry? padding, double? padding,
MultiColor? borderColors, MultiColor? borderColors,
MultiColor? backgroundColors, MultiColor? backgroundColors,
double? stroke,
Size? minSize, Size? minSize,
Size? maxSize, Size? maxSize,
BoxShadow? shadow, BoxShadow? shadow,
TextStyle? titleStyle,
TextStyle? subtitleStyle,
TextStyle? bodyStyle,
Widget? background, Widget? background,
Key? key, Key? key,
}) => }) =>
PortfolioCard( PortfolioCard(
showAssetsOnTop: showAssetsOnTop ?? _value.showAssetsOnTop, showImagesOnTop: showImagesOnTop ?? _value.showImagesOnTop,
keywords: keywords ?? _value.keywords, keyword: keyword ?? _value.keyword,
keywordsBackgroundColors:
keywordsBackgroundColors ?? _value.keywordsBackgroundColors,
description: description ?? _value.description, description: description ?? _value.description,
logo: logo ?? _value.logo, logo: logo ?? _value.logo,
projectName: projectName ?? _value.projectName, projectName: projectName ?? _value.projectName,
@ -103,13 +85,11 @@ class $PortfolioCardCWProxyImpl implements $PortfolioCardComponentCWProxy {
padding: padding ?? _value.padding, padding: padding ?? _value.padding,
borderColors: borderColors ?? _value.borderColors, borderColors: borderColors ?? _value.borderColors,
backgroundColors: backgroundColors ?? _value.backgroundColors, backgroundColors: backgroundColors ?? _value.backgroundColors,
stroke: stroke ?? _value.stroke, secondaryBackgroundColors:
secondaryBackgroundColors ?? _value.secondaryBackgroundColors,
minSize: minSize ?? _value.minSize, minSize: minSize ?? _value.minSize,
maxSize: maxSize ?? _value.maxSize, maxSize: maxSize ?? _value.maxSize,
shadow: shadow ?? _value.shadow, shadow: shadow ?? _value.shadow,
titleStyle: titleStyle ?? _value.titleStyle,
subtitleStyle: subtitleStyle ?? _value.subtitleStyle,
bodyStyle: bodyStyle ?? _value.bodyStyle,
background: background ?? _value.background, background: background ?? _value.background,
key: key ?? _value.key, key: key ?? _value.key,
); );

View File

@ -17,7 +17,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gap/gap.dart'; import 'package:gap/gap.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/cards/portfolio_card/widgets/portfolio_card_titles.dart'; import 'package:wyatt_ui_kit/src/components/cards/information_card/widgets/information_card_titles.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
const _avatarAndTitlesSpacing = 25.0; const _avatarAndTitlesSpacing = 25.0;
@ -25,39 +25,22 @@ const _avatarAndTitlesSpacing = 25.0;
class PortfolioCardHeader extends StatelessWidget { class PortfolioCardHeader extends StatelessWidget {
const PortfolioCardHeader({ const PortfolioCardHeader({
this.logo, this.logo,
this.padding,
this.radius,
this.projectName, this.projectName,
this.subtitle, this.subtitle,
this.keywords, this.keyword,
this.keywordsBackgroundColors, this.secondaryBackgroundColors,
this.titleStyle,
this.subtitleStyle,
this.keywordsStyle,
super.key, super.key,
}); });
/// The logo of the portfolio card.
final Widget? logo; final Widget? logo;
final double? padding;
/// Project name of the portfolio card. final double? radius;
final TextWrapper? projectName; final TextWrapper? projectName;
/// Subtitle of the portfolio card.
final TextWrapper? subtitle; final TextWrapper? subtitle;
final List<TextWrapper>? keyword;
/// The keywords of the portfolio card. final Color? secondaryBackgroundColors;
final List<TextWrapper>? keywords;
/// Background colors for the keywords badges
final MultiColor? keywordsBackgroundColors;
/// Styles the title of the card.
final TextStyle? titleStyle;
/// Styles the subtitle of the card.
final TextStyle? subtitleStyle;
/// Styles the keywords of the card.
final TextStyle? keywordsStyle;
@override @override
Widget build(BuildContext context) => Column( Widget build(BuildContext context) => Column(
@ -68,12 +51,10 @@ class PortfolioCardHeader extends StatelessWidget {
if (logo != null) logo!, if (logo != null) logo!,
const Gap(_avatarAndTitlesSpacing), const Gap(_avatarAndTitlesSpacing),
Expanded( Expanded(
child: PortfolioCardTitles( child: InformationCardTitles(
axis: Axis.horizontal, axis: Axis.horizontal,
title: projectName, title: projectName,
subtitle: subtitle, subtitle: subtitle,
titleStyle: titleStyle,
subtitleStyle: subtitleStyle,
), ),
), ),
], ],
@ -81,47 +62,27 @@ class PortfolioCardHeader extends StatelessWidget {
const Gap(10), const Gap(10),
Wrap( Wrap(
children: [ children: [
if (keywords != null) if (keyword != null)
...keywords!.map( ...keyword!.map(
(word) => Container( (word) => Container(
margin: const EdgeInsets.all(3), margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(6), padding: const EdgeInsets.all(6),
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: color: secondaryBackgroundColors ??
ThemeHelper.maybeGetElement<MultiColor, Gradient>(
[
keywordsBackgroundColors,
Theme.of(context) Theme.of(context)
.extension<CardThemeExtension>() .extension<CardThemeExtension>()
?.borderColors, ?.secondaryBackgroundColor,
CardThemeExtensionDefault.from(Theme.of(context))
.borderColors,
],
valueValidator: (multiColor) => multiColor?.isGradient,
transform: (multiColor) =>
GradientHelper.linearFromMultiColor(multiColor!),
),
color: ThemeHelper.maybeGetElement<MultiColor, Color>(
[
keywordsBackgroundColors,
Theme.of(context)
.extension<CardThemeExtension>()
?.borderColors,
MultiColor.single(
Theme.of(context).cardTheme.surfaceTintColor,
),
CardThemeExtensionDefault.from(Theme.of(context))
.borderColors,
],
valueValidator: (multiColor) =>
multiColor != null && multiColor.isColor,
transform: (multiColor) => multiColor?.color,
),
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
child: GradientText.fromWrapper( child: Text(
word, word.data,
style: context.textTheme.bodySmall, style: word.style ?? context.textTheme.bodySmall,
textAlign: word.textAlign,
textDirection: word.textDirection,
softWrap: word.softWrap,
overflow: word.overflow,
maxLines: word.maxLines,
selectionColor: word.selectionColor,
), ),
), ),
), ),

View File

@ -19,34 +19,29 @@ import 'package:gap/gap.dart';
class PortfolioCardImages extends StatelessWidget { class PortfolioCardImages extends StatelessWidget {
const PortfolioCardImages({ const PortfolioCardImages({
this.assets, this.images,
this.radius, this.radius,
this.maxSize, this.maxSize,
super.key, super.key,
}); });
/// The assets to display. final List<Widget>? images;
final List<Widget>? assets; final double? radius;
/// The radius of the assets.
final BorderRadiusGeometry? radius;
/// The max size of the assets.
final Size? maxSize; final Size? maxSize;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final result = <Widget>[]; final result = <Widget>[];
for (final asset in assets ?? List<Widget>.empty()) { for (final image in images ?? List<Widget>.empty()) {
result.addAll([ result.addAll([
Expanded( Expanded(
child: ClipRRect( child: ClipRRect(
borderRadius: radius ?? BorderRadius.zero, borderRadius: BorderRadius.circular(radius ?? 0),
child: Container( child: Container(
constraints: BoxConstraints( constraints: BoxConstraints(
maxHeight: maxSize != null ? maxSize!.width : double.infinity, maxHeight: maxSize != null ? maxSize!.width : 100,
), ),
child: asset, child: image,
), ),
), ),
), ),

View File

@ -1,72 +0,0 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/cards/widgets/card_text.dart';
const _titlesLineSpacing = 5.0;
class PortfolioCardTitles extends StatelessWidget {
const PortfolioCardTitles({
this.axis,
this.title,
this.subtitle,
this.titleStyle,
this.subtitleStyle,
super.key,
});
/// The axis of the card header.
final Axis? axis;
/// The title of the card.
final TextWrapper? title;
/// The subtitle of the card.
final TextWrapper? subtitle;
/// Styles the title of the card.
final TextStyle? titleStyle;
/// Styles the subtitle of the card.
final TextStyle? subtitleStyle;
@override
Widget build(BuildContext context) => Column(
crossAxisAlignment: axis == Axis.horizontal
? CrossAxisAlignment.start
: CrossAxisAlignment.center,
children: [
if (title != null) ...[
CardText.fromWrapper(
title!,
style: titleStyle,
textType: TextType.title,
),
],
if (subtitle != null) ...[
const Gap(_titlesLineSpacing),
CardText.fromWrapper(
subtitle!,
style: subtitleStyle,
textType: TextType.subtitle,
),
],
],
);
}

View File

@ -20,6 +20,7 @@ import 'package:wyatt_component_copy_with_extension/wyatt_component_copy_with_ex
import 'package:wyatt_ui_components/wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/cards/widgets/card_text.dart'; import 'package:wyatt_ui_kit/src/components/cards/widgets/card_text.dart';
import 'package:wyatt_ui_kit/src/components/cards/widgets/card_wrapper.dart'; import 'package:wyatt_ui_kit/src/components/cards/widgets/card_wrapper.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
part 'quote_card.g.dart'; part 'quote_card.g.dart';
@ -29,6 +30,7 @@ class QuoteCard extends QuoteCardComponent with $QuoteCardCWMixin {
super.avatar, super.avatar,
super.name, super.name,
super.subtitle, super.subtitle,
super.gradient,
super.quote, super.quote,
super.leftQuote, super.leftQuote,
super.rightQuote, super.rightQuote,
@ -36,76 +38,56 @@ class QuoteCard extends QuoteCardComponent with $QuoteCardCWMixin {
super.padding, super.padding,
super.borderColors, super.borderColors,
super.backgroundColors, super.backgroundColors,
super.stroke,
super.minSize, super.minSize,
super.maxSize, super.maxSize,
super.shadow, super.shadow,
super.titleStyle,
super.subtitleStyle,
super.bodyStyle,
super.background, super.background,
super.key, super.key,
}); });
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) => CardWrapper(
final themeTitleStyle = ThemeHelper.maybeGetElement<TextStyle, TextStyle>(
[
titleStyle,
Theme.of(context).extension<CardThemeExtension>()?.titleStyle,
CardThemeExtensionDefault.from(Theme.of(context)).titleStyle,
],
);
final themeSubtitleStyle =
ThemeHelper.maybeGetElement<TextStyle, TextStyle>(
[
subtitleStyle,
Theme.of(context).extension<CardThemeExtension>()?.subtitleStyle,
CardThemeExtensionDefault.from(Theme.of(context)).subtitleStyle,
],
);
final themeBodyStyle = ThemeHelper.maybeGetElement<TextStyle, TextStyle>(
[
bodyStyle,
Theme.of(context).extension<CardThemeExtension>()?.bodyStyle,
CardThemeExtensionDefault.from(Theme.of(context)).bodyStyle,
],
);
return CardWrapper(
background: background, background: background,
padding: padding, padding: padding,
radius: radius,
backgroundColors: backgroundColors, backgroundColors: backgroundColors,
borderColors: borderColors, borderColors: borderColors,
shadow: shadow, shadow: shadow,
stroke: stroke,
maxSize: maxSize, maxSize: maxSize,
minSize: minSize, minSize: minSize,
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
leftQuote ?? leftQuote ??
const Align( Align(
alignment: Alignment.topLeft, alignment: Alignment.topLeft,
child: Text( child: GradientText(
'', '',
style: GradientTextStyle.from(
context.textTheme.titleLarge
?.copyWith(fontWeight: FontWeight.bold),
MultiColor(gradient?.colors),
),
), ),
), ),
if (quote != null) ...[ if (quote != null) ...[
CardText.fromWrapper( CardText(
quote!, quote!,
style: themeBodyStyle, textType: TextType.body,
style: quote!.style,
gradientColors: quote!.gradientColors,
), ),
], ],
const Gap(15), const Gap(15),
rightQuote ?? rightQuote ??
const Align( Align(
alignment: Alignment.bottomRight, alignment: Alignment.bottomRight,
child: Text( child: GradientText(
'', '',
style: GradientTextStyle.from(
context.textTheme.titleLarge
?.copyWith(fontWeight: FontWeight.bold),
MultiColor(gradient?.colors),
),
), ),
), ),
Row( Row(
@ -119,17 +101,19 @@ class QuoteCard extends QuoteCardComponent with $QuoteCardCWMixin {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
if (name != null) ...[ if (name != null) ...[
CardText.fromWrapper( CardText(
name!, name!,
style: themeTitleStyle, textType: TextType.body,
textType: TextType.title, style: name!.style,
gradientColors: name!.gradientColors,
), ),
], ],
if (subtitle != null) ...[ if (subtitle != null) ...[
CardText.fromWrapper( CardText(
subtitle!, subtitle!,
style: themeSubtitleStyle,
textType: TextType.subtitle, textType: TextType.subtitle,
style: subtitle!.style,
gradientColors: subtitle!.gradientColors,
), ),
], ],
], ],
@ -141,4 +125,3 @@ class QuoteCard extends QuoteCardComponent with $QuoteCardCWMixin {
), ),
); );
} }
}

View File

@ -16,15 +16,17 @@ class $QuoteCardCWProxyImpl implements $QuoteCardComponentCWProxy {
@override @override
QuoteCard subtitle(TextWrapper? subtitle) => this(subtitle: subtitle); QuoteCard subtitle(TextWrapper? subtitle) => this(subtitle: subtitle);
@override @override
QuoteCard gradient(Gradient? gradient) => this(gradient: gradient);
@override
QuoteCard quote(TextWrapper? quote) => this(quote: quote); QuoteCard quote(TextWrapper? quote) => this(quote: quote);
@override @override
QuoteCard leftQuote(Widget? leftQuote) => this(leftQuote: leftQuote); QuoteCard leftQuote(Widget? leftQuote) => this(leftQuote: leftQuote);
@override @override
QuoteCard rightQuote(Widget? rightQuote) => this(rightQuote: rightQuote); QuoteCard rightQuote(Widget? rightQuote) => this(rightQuote: rightQuote);
@override @override
QuoteCard radius(BorderRadiusGeometry? radius) => this(radius: radius); QuoteCard radius(double? radius) => this(radius: radius);
@override @override
QuoteCard padding(EdgeInsetsGeometry? padding) => this(padding: padding); QuoteCard padding(double? padding) => this(padding: padding);
@override @override
QuoteCard borderColors(MultiColor? borderColors) => QuoteCard borderColors(MultiColor? borderColors) =>
this(borderColors: borderColors); this(borderColors: borderColors);
@ -32,21 +34,12 @@ class $QuoteCardCWProxyImpl implements $QuoteCardComponentCWProxy {
QuoteCard backgroundColors(MultiColor? backgroundColors) => QuoteCard backgroundColors(MultiColor? backgroundColors) =>
this(backgroundColors: backgroundColors); this(backgroundColors: backgroundColors);
@override @override
QuoteCard stroke(double? stroke) => this(stroke: stroke);
@override
QuoteCard minSize(Size? minSize) => this(minSize: minSize); QuoteCard minSize(Size? minSize) => this(minSize: minSize);
@override @override
QuoteCard maxSize(Size? maxSize) => this(maxSize: maxSize); QuoteCard maxSize(Size? maxSize) => this(maxSize: maxSize);
@override @override
QuoteCard shadow(BoxShadow? shadow) => this(shadow: shadow); QuoteCard shadow(BoxShadow? shadow) => this(shadow: shadow);
@override @override
QuoteCard titleStyle(TextStyle? titleStyle) => this(titleStyle: titleStyle);
@override
QuoteCard subtitleStyle(TextStyle? subtitleStyle) =>
this(subtitleStyle: subtitleStyle);
@override
QuoteCard bodyStyle(TextStyle? bodyStyle) => this(bodyStyle: bodyStyle);
@override
QuoteCard background(Widget? background) => this(background: background); QuoteCard background(Widget? background) => this(background: background);
@override @override
QuoteCard key(Key? key) => this(key: key); QuoteCard key(Key? key) => this(key: key);
@ -55,20 +48,17 @@ class $QuoteCardCWProxyImpl implements $QuoteCardComponentCWProxy {
Widget? avatar, Widget? avatar,
TextWrapper? name, TextWrapper? name,
TextWrapper? subtitle, TextWrapper? subtitle,
Gradient? gradient,
TextWrapper? quote, TextWrapper? quote,
Widget? leftQuote, Widget? leftQuote,
Widget? rightQuote, Widget? rightQuote,
BorderRadiusGeometry? radius, double? radius,
EdgeInsetsGeometry? padding, double? padding,
MultiColor? borderColors, MultiColor? borderColors,
MultiColor? backgroundColors, MultiColor? backgroundColors,
double? stroke,
Size? minSize, Size? minSize,
Size? maxSize, Size? maxSize,
BoxShadow? shadow, BoxShadow? shadow,
TextStyle? titleStyle,
TextStyle? subtitleStyle,
TextStyle? bodyStyle,
Widget? background, Widget? background,
Key? key, Key? key,
}) => }) =>
@ -76,6 +66,7 @@ class $QuoteCardCWProxyImpl implements $QuoteCardComponentCWProxy {
avatar: avatar ?? _value.avatar, avatar: avatar ?? _value.avatar,
name: name ?? _value.name, name: name ?? _value.name,
subtitle: subtitle ?? _value.subtitle, subtitle: subtitle ?? _value.subtitle,
gradient: gradient ?? _value.gradient,
quote: quote ?? _value.quote, quote: quote ?? _value.quote,
leftQuote: leftQuote ?? _value.leftQuote, leftQuote: leftQuote ?? _value.leftQuote,
rightQuote: rightQuote ?? _value.rightQuote, rightQuote: rightQuote ?? _value.rightQuote,
@ -83,13 +74,9 @@ class $QuoteCardCWProxyImpl implements $QuoteCardComponentCWProxy {
padding: padding ?? _value.padding, padding: padding ?? _value.padding,
borderColors: borderColors ?? _value.borderColors, borderColors: borderColors ?? _value.borderColors,
backgroundColors: backgroundColors ?? _value.backgroundColors, backgroundColors: backgroundColors ?? _value.backgroundColors,
stroke: stroke ?? _value.stroke,
minSize: minSize ?? _value.minSize, minSize: minSize ?? _value.minSize,
maxSize: maxSize ?? _value.maxSize, maxSize: maxSize ?? _value.maxSize,
shadow: shadow ?? _value.shadow, shadow: shadow ?? _value.shadow,
titleStyle: titleStyle ?? _value.titleStyle,
subtitleStyle: subtitleStyle ?? _value.subtitleStyle,
bodyStyle: bodyStyle ?? _value.bodyStyle,
background: background ?? _value.background, background: background ?? _value.background,
key: key ?? _value.key, key: key ?? _value.key,
); );

View File

@ -18,118 +18,68 @@ import 'package:flutter/material.dart';
import 'package:gap/gap.dart'; import 'package:gap/gap.dart';
import 'package:wyatt_component_copy_with_extension/wyatt_component_copy_with_extension.dart'; import 'package:wyatt_component_copy_with_extension/wyatt_component_copy_with_extension.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/cards/skill_card/widgets/skill_card_horizontal_header.dart'; import 'package:wyatt_ui_kit/src/components/cards/skill_card/widgets/skill_card_header.dart';
import 'package:wyatt_ui_kit/src/components/cards/skill_card/widgets/skill_card_skills.dart'; import 'package:wyatt_ui_kit/src/components/cards/skill_card/widgets/skill_card_skills.dart';
import 'package:wyatt_ui_kit/src/components/cards/skill_card/widgets/skill_card_vertical_header.dart';
import 'package:wyatt_ui_kit/src/components/cards/widgets/card_text.dart'; import 'package:wyatt_ui_kit/src/components/cards/widgets/card_text.dart';
import 'package:wyatt_ui_kit/src/components/cards/widgets/card_wrapper.dart'; import 'package:wyatt_ui_kit/src/components/cards/widgets/card_wrapper.dart';
part 'skill_card.g.dart'; part 'skill_card.g.dart';
const _bodyTopSpacing = 25.0;
@ComponentCopyWithExtension() @ComponentCopyWithExtension()
class SkillCard extends SkillCardComponent with $SkillCardCWMixin { class SkillCard extends SkillCardComponent with $SkillCardCWMixin {
const SkillCard({ const SkillCard({
super.axis, super.icon,
super.icons, super.gradient,
super.secondaryBackgroundColors,
super.title, super.title,
super.subtitle,
super.description, super.description,
super.skills, super.skills,
super.bulletColors, super.leadingIcon,
super.bulletIcon,
super.radius, super.radius,
super.padding, super.padding,
super.borderColors, super.borderColors,
super.backgroundColors, super.backgroundColors,
super.stroke,
super.minSize, super.minSize,
super.maxSize, super.maxSize = const Size(330, double.infinity),
super.shadow, super.shadow,
super.titleStyle,
super.subtitleStyle,
super.bodyStyle,
super.background, super.background,
super.key, super.key,
}); });
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) => CardWrapper(
final themeTitleStyle = ThemeHelper.maybeGetElement<TextStyle, TextStyle>(
[
titleStyle,
Theme.of(context).extension<CardThemeExtension>()?.titleStyle,
CardThemeExtensionDefault.from(Theme.of(context)).titleStyle,
],
);
final themeSubtitleStyle =
ThemeHelper.maybeGetElement<TextStyle, TextStyle>(
[
subtitleStyle,
Theme.of(context).extension<CardThemeExtension>()?.subtitleStyle,
CardThemeExtensionDefault.from(Theme.of(context)).subtitleStyle,
],
);
final themeBodyStyle = ThemeHelper.maybeGetElement<TextStyle, TextStyle>(
[
bodyStyle,
Theme.of(context).extension<CardThemeExtension>()?.bodyStyle,
CardThemeExtensionDefault.from(Theme.of(context)).bodyStyle,
],
);
return CardWrapper(
background: background, background: background,
padding: padding, padding: padding,
radius: radius,
backgroundColors: backgroundColors, backgroundColors: backgroundColors,
borderColors: borderColors, borderColors: borderColors,
shadow: shadow, shadow: shadow,
stroke: stroke,
maxSize: maxSize, maxSize: maxSize,
minSize: minSize, minSize: minSize,
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
if (axis == Axis.horizontal) ...[ SkillCardHeader(
SkillCardHorizontalHeader( secondaryBackgroundColors: secondaryBackgroundColors,
icons: icons, icon: icon,
axis: axis,
title: title, title: title,
subtitle: subtitle,
titleStyle: themeTitleStyle,
subtitleStyle: themeSubtitleStyle,
), ),
] else ...[ const Gap(25),
SkillCardVerticalHeader(
icons: icons,
axis: axis,
title: title,
subtitle: subtitle,
titleStyle: themeTitleStyle,
subtitleStyle: themeSubtitleStyle,
),
],
const Gap(_bodyTopSpacing),
if (description != null) ...[ if (description != null) ...[
CardText.fromWrapper( CardText(
description!, description!,
style: themeBodyStyle, textType: TextType.body,
style: description!.style,
gradientColors: description!.gradientColors,
), ),
const Gap(_bodyTopSpacing), const Gap(25),
], ],
if (skills != null) if (skills != null)
SkillCardSkills( SkillCardSkills(
gradient: gradient,
skills: skills, skills: skills,
bulletColors: bulletColors, leadingIcon: leadingIcon,
bulletIcon: bulletIcon,
bodyStyle: themeBodyStyle,
), ),
], ],
), ),
); );
} }
}

View File

@ -10,27 +10,26 @@ class $SkillCardCWProxyImpl implements $SkillCardComponentCWProxy {
const $SkillCardCWProxyImpl(this._value); const $SkillCardCWProxyImpl(this._value);
final SkillCard _value; final SkillCard _value;
@override @override
SkillCard axis(Axis? axis) => this(axis: axis); SkillCard icon(Widget? icon) => this(icon: icon);
@override @override
SkillCard icons(List<Widget>? icons) => this(icons: icons); SkillCard gradient(List<Color>? gradient) => this(gradient: gradient);
@override @override
SkillCard title(TextWrapper? title) => this(title: title); SkillCard title(TextWrapper? title) => this(title: title);
@override @override
SkillCard subtitle(TextWrapper? subtitle) => this(subtitle: subtitle);
@override
SkillCard description(TextWrapper? description) => SkillCard description(TextWrapper? description) =>
this(description: description); this(description: description);
@override @override
SkillCard skills(List<TextWrapper>? skills) => this(skills: skills); SkillCard skills(List<TextWrapper>? skills) => this(skills: skills);
@override @override
SkillCard bulletColors(MultiColor? bulletColors) => SkillCard leadingIcon(IconData? leadingIcon) =>
this(bulletColors: bulletColors); this(leadingIcon: leadingIcon);
@override @override
SkillCard bulletIcon(Widget? bulletIcon) => this(bulletIcon: bulletIcon); SkillCard secondaryBackgroundColors(Color? secondaryBackgroundColors) =>
this(secondaryBackgroundColors: secondaryBackgroundColors);
@override @override
SkillCard radius(BorderRadiusGeometry? radius) => this(radius: radius); SkillCard radius(double? radius) => this(radius: radius);
@override @override
SkillCard padding(EdgeInsetsGeometry? padding) => this(padding: padding); SkillCard padding(double? padding) => this(padding: padding);
@override @override
SkillCard borderColors(MultiColor? borderColors) => SkillCard borderColors(MultiColor? borderColors) =>
this(borderColors: borderColors); this(borderColors: borderColors);
@ -38,68 +37,50 @@ class $SkillCardCWProxyImpl implements $SkillCardComponentCWProxy {
SkillCard backgroundColors(MultiColor? backgroundColors) => SkillCard backgroundColors(MultiColor? backgroundColors) =>
this(backgroundColors: backgroundColors); this(backgroundColors: backgroundColors);
@override @override
SkillCard stroke(double? stroke) => this(stroke: stroke);
@override
SkillCard minSize(Size? minSize) => this(minSize: minSize); SkillCard minSize(Size? minSize) => this(minSize: minSize);
@override @override
SkillCard maxSize(Size? maxSize) => this(maxSize: maxSize); SkillCard maxSize(Size? maxSize) => this(maxSize: maxSize);
@override @override
SkillCard shadow(BoxShadow? shadow) => this(shadow: shadow); SkillCard shadow(BoxShadow? shadow) => this(shadow: shadow);
@override @override
SkillCard titleStyle(TextStyle? titleStyle) => this(titleStyle: titleStyle);
@override
SkillCard subtitleStyle(TextStyle? subtitleStyle) =>
this(subtitleStyle: subtitleStyle);
@override
SkillCard bodyStyle(TextStyle? bodyStyle) => this(bodyStyle: bodyStyle);
@override
SkillCard background(Widget? background) => this(background: background); SkillCard background(Widget? background) => this(background: background);
@override @override
SkillCard key(Key? key) => this(key: key); SkillCard key(Key? key) => this(key: key);
@override @override
SkillCard call({ SkillCard call({
Axis? axis, Widget? icon,
List<Widget>? icons, List<Color>? gradient,
TextWrapper? title, TextWrapper? title,
TextWrapper? subtitle,
TextWrapper? description, TextWrapper? description,
List<TextWrapper>? skills, List<TextWrapper>? skills,
MultiColor? bulletColors, IconData? leadingIcon,
Widget? bulletIcon, Color? secondaryBackgroundColors,
BorderRadiusGeometry? radius, double? radius,
EdgeInsetsGeometry? padding, double? padding,
MultiColor? borderColors, MultiColor? borderColors,
MultiColor? backgroundColors, MultiColor? backgroundColors,
double? stroke,
Size? minSize, Size? minSize,
Size? maxSize, Size? maxSize,
BoxShadow? shadow, BoxShadow? shadow,
TextStyle? titleStyle,
TextStyle? subtitleStyle,
TextStyle? bodyStyle,
Widget? background, Widget? background,
Key? key, Key? key,
}) => }) =>
SkillCard( SkillCard(
axis: axis ?? _value.axis, icon: icon ?? _value.icon,
icons: icons ?? _value.icons, gradient: gradient ?? _value.gradient,
secondaryBackgroundColors:
secondaryBackgroundColors ?? _value.secondaryBackgroundColors,
title: title ?? _value.title, title: title ?? _value.title,
subtitle: subtitle ?? _value.subtitle,
description: description ?? _value.description, description: description ?? _value.description,
skills: skills ?? _value.skills, skills: skills ?? _value.skills,
bulletColors: bulletColors ?? _value.bulletColors, leadingIcon: leadingIcon ?? _value.leadingIcon,
bulletIcon: bulletIcon ?? _value.bulletIcon,
radius: radius ?? _value.radius, radius: radius ?? _value.radius,
padding: padding ?? _value.padding, padding: padding ?? _value.padding,
borderColors: borderColors ?? _value.borderColors, borderColors: borderColors ?? _value.borderColors,
backgroundColors: backgroundColors ?? _value.backgroundColors, backgroundColors: backgroundColors ?? _value.backgroundColors,
stroke: stroke ?? _value.stroke,
minSize: minSize ?? _value.minSize, minSize: minSize ?? _value.minSize,
maxSize: maxSize ?? _value.maxSize, maxSize: maxSize ?? _value.maxSize,
shadow: shadow ?? _value.shadow, shadow: shadow ?? _value.shadow,
titleStyle: titleStyle ?? _value.titleStyle,
subtitleStyle: subtitleStyle ?? _value.subtitleStyle,
bodyStyle: bodyStyle ?? _value.bodyStyle,
background: background ?? _value.background, background: background ?? _value.background,
key: key ?? _value.key, key: key ?? _value.key,
); );

View File

@ -19,54 +19,37 @@ import 'package:gap/gap.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/cards/widgets/card_text.dart'; import 'package:wyatt_ui_kit/src/components/cards/widgets/card_text.dart';
const _titlesLineSpacing = 5.0; class SkillCardHeader extends StatelessWidget {
const SkillCardHeader({
class SkillCardTitles extends StatelessWidget {
const SkillCardTitles({
this.axis,
this.title,
this.subtitle,
this.titleStyle,
this.subtitleStyle,
super.key, super.key,
this.icon,
this.title,
this.secondaryBackgroundColors,
}); });
/// The axis of the card header. final Widget? icon;
final Axis? axis;
/// The title of the card.
final TextWrapper? title; final TextWrapper? title;
final Color? secondaryBackgroundColors;
/// The subtitle of the card.
final TextWrapper? subtitle;
/// Styles the title of the card.
final TextStyle? titleStyle;
/// Styles the subtitle of the card.
final TextStyle? subtitleStyle;
@override @override
Widget build(BuildContext context) => Column( Widget build(BuildContext context) => Column(
crossAxisAlignment: axis == Axis.horizontal children: [
? CrossAxisAlignment.start if (icon != null) ...[
: CrossAxisAlignment.center, icon!,
const Gap(25),
],
Column(
children: [ children: [
if (title != null) ...[ if (title != null) ...[
CardText.fromWrapper( CardText(
title!, title!,
style: titleStyle,
textType: TextType.title, textType: TextType.title,
style: title!.style,
gradientColors: title!.gradientColors,
), ),
], ],
if (subtitle != null) ...[
const Gap(_titlesLineSpacing),
CardText.fromWrapper(
subtitle!,
style: subtitleStyle,
textType: TextType.subtitle,
),
], ],
)
], ],
); );
} }

View File

@ -1,71 +0,0 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/cards/skill_card/widgets/skill_card_titles.dart';
const _avatarAndTitlesSpacing = 25.0;
class SkillCardHorizontalHeader extends StatelessWidget {
const SkillCardHorizontalHeader({
this.icons,
this.axis,
this.title,
this.subtitle,
this.titleStyle,
this.subtitleStyle,
super.key,
});
/// The icons of the card header.
final List<Widget>? icons;
/// The axis of the card header.
final Axis? axis;
/// The title of the card.
final TextWrapper? title;
/// The subtitle of the card.
final TextWrapper? subtitle;
/// Styles the title of the card.
final TextStyle? titleStyle;
/// Styles the subtitle of the card.
final TextStyle? subtitleStyle;
@override
Widget build(BuildContext context) => Row(
children: [
if (icons?.first != null) ...[
icons!.first,
const Gap(_avatarAndTitlesSpacing),
],
Expanded(
child: SkillCardTitles(
axis: axis,
title: title,
subtitle: subtitle,
titleStyle: titleStyle,
subtitleStyle: subtitleStyle,
),
),
],
);
}

View File

@ -19,27 +19,19 @@ import 'package:gap/gap.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/cards/widgets/card_text.dart'; import 'package:wyatt_ui_kit/src/components/cards/widgets/card_text.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_icon.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 SkillCardSkills extends StatelessWidget { class SkillCardSkills extends StatelessWidget {
const SkillCardSkills({ const SkillCardSkills({
super.key, super.key,
this.skills, this.skills,
this.bulletColors, this.leadingIcon,
this.bulletIcon, this.gradient,
this.bodyStyle,
}); });
/// Skills to be displayed
final List<TextWrapper>? skills; final List<TextWrapper>? skills;
final IconData? leadingIcon;
/// Gradient of skill icons. final List<Color>? gradient;
final MultiColor? bulletColors;
/// Icon to be displayed before each skill.
final Widget? bulletIcon;
/// Body style of the card.
final TextStyle? bodyStyle;
@override @override
Widget build(BuildContext context) => Column( Widget build(BuildContext context) => Column(
@ -47,22 +39,18 @@ class SkillCardSkills extends StatelessWidget {
.map( .map(
(skill) => Row( (skill) => Row(
children: [ children: [
if (bulletIcon != null) ...[ Icon(
GradientIcon.fromWidget( leadingIcon ?? Icons.check,
bulletIcon!, ).toGradient(
gradientColors: bulletColors, LinearGradientHelper.fromNullableColors(gradient),
), ),
] else ...[
GradientIcon(
icon: Icons.check,
gradientColors: bulletColors ?? const MultiColor([]),
),
],
const Gap(10), const Gap(10),
Expanded( Expanded(
child: CardText.fromWrapper( child: CardText(
skill, skill,
style: bodyStyle, textType: TextType.body,
style: skill.style,
gradientColors: skill.gradientColors,
), ),
), ),
], ],

View File

@ -1,72 +0,0 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/cards/skill_card/widgets/skill_card_icons.dart';
import 'package:wyatt_ui_kit/src/components/cards/skill_card/widgets/skill_card_titles.dart';
const _avatarAndTitlesSpacing = 25.0;
class SkillCardVerticalHeader extends StatelessWidget {
const SkillCardVerticalHeader({
this.icons,
this.axis,
this.title,
this.subtitle,
this.titleStyle,
this.subtitleStyle,
super.key,
});
/// The icons of the card header.
final List<Widget>? icons;
/// The axis of the card header.
final Axis? axis;
/// The title of the card.
final TextWrapper? title;
/// The subtitle of the card.
final TextWrapper? subtitle;
/// Styles the title of the card.
final TextStyle? titleStyle;
/// Styles the subtitle of the card.
final TextStyle? subtitleStyle;
@override
Widget build(BuildContext context) => Column(
children: [
if (icons != null && icons!.isNotEmpty) ...[
SkillCardIcons(
icons: icons,
),
const Gap(_avatarAndTitlesSpacing),
],
SkillCardTitles(
axis: axis,
title: title,
subtitle: subtitle,
titleStyle: titleStyle,
subtitleStyle: subtitleStyle,
),
],
);
}

View File

@ -1,16 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
/// {@template card_background}
/// A widget that displays a background for a card.
/// {@endtemplate}
class CardBackground extends StatefulWidget { class CardBackground extends StatefulWidget {
/// {@macro card_background}
const CardBackground({super.key, this.background, this.cardKey}); const CardBackground({super.key, this.background, this.cardKey});
/// Background to display
final Widget? background; final Widget? background;
/// Key of the card to display the background for
final GlobalKey? cardKey; final GlobalKey? cardKey;
@override @override

View File

@ -24,67 +24,46 @@ enum TextType {
body; body;
} }
/// {@template card_text}
/// Wrapper for [GradientText] that uses the [CardThemeExtension] to
/// determine the text style to use depending on the [textType].
/// {@endtemplate}
class CardText extends StatelessWidget { class CardText extends StatelessWidget {
/// {@macro card_text}
const CardText( const CardText(
this.text, { this.text, {
this.textType = TextType.body, required this.textType,
this.style,
this.gradientColors,
super.key, super.key,
}); });
/// Creates a [CardText] from a [TextWrapper]. final TextWrapper text;
///
/// The [textType] is used to determine the [CardThemeExtension] style to use.
///
/// You can also pass a [gradientColors] and [style] as fallbacks if the
/// [TextWrapper] doesn't have them.
factory CardText.fromWrapper(
TextWrapper wrapper, {
TextType textType = TextType.body,
MultiColor? gradientColors,
TextStyle? style,
}) =>
CardText(
GradientText.fromWrapper(
wrapper,
gradientColors: gradientColors,
style: style,
),
textType: textType,
);
final GradientText text;
final TextType textType; final TextType textType;
final TextStyle? style;
final MultiColor? gradientColors;
TextStyle? _getStyle(BuildContext context) { TextStyle? _getStyle(BuildContext context) {
if (text.style != null) { if (style != null) {
return text.style; return style;
} else { } else {
final cardThemeExtension = final cardThemeExtension =
Theme.of(context).extension<CardThemeExtension>() ?? Theme.of(context).extension<CardThemeExtension>();
CardThemeExtensionDefault.from(Theme.of(context));
switch (textType) { switch (textType) {
case TextType.title: case TextType.title:
return cardThemeExtension.titleStyle ?? return cardThemeExtension?.title ?? context.textTheme.titleLarge;
CardThemeExtensionDefault.from(Theme.of(context)).titleStyle;
case TextType.subtitle: case TextType.subtitle:
return cardThemeExtension.subtitleStyle ?? return cardThemeExtension?.subtitle ?? context.textTheme.titleMedium;
CardThemeExtensionDefault.from(Theme.of(context)).subtitleStyle;
case TextType.body: case TextType.body:
return cardThemeExtension.bodyStyle ?? return cardThemeExtension?.body ?? context.textTheme.bodyMedium;
CardThemeExtensionDefault.from(Theme.of(context)).bodyStyle;
} }
} }
} }
@override @override
Widget build(BuildContext context) => text.copyWith Widget build(BuildContext context) => Text(
.call( text.data,
style: _getStyle(context), style: _getStyle(context),
) textAlign: text.textAlign,
.build(context); textDirection: text.textDirection,
softWrap: text.softWrap,
overflow: text.overflow,
maxLines: text.maxLines,
selectionColor: text.selectionColor,
).toGradient(gradientColors: gradientColors);
} }

View File

@ -19,89 +19,31 @@ import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/cards/widgets/card_background.dart'; import 'package:wyatt_ui_kit/src/components/cards/widgets/card_background.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
/// {@template card_wrapper}
/// Common wrapper for all cards
/// {@endtemplate}
class CardWrapper extends StatelessWidget { class CardWrapper extends StatelessWidget {
/// {@macro card_wrapper}
CardWrapper({ CardWrapper({
required this.child, required this.child,
this.radius, required this.backgroundColors,
this.padding, required this.borderColors,
this.foregroundColors, required this.shadow,
this.backgroundColors, required this.minSize,
this.borderColors, required this.maxSize,
this.stroke, required this.padding,
this.shadow, required this.background,
this.minSize,
this.maxSize,
this.background,
super.key, super.key,
}); });
/// Card radius
///
/// Default to `BorderRadius.all(Radius.circular(12.0))`
final BorderRadiusGeometry? radius;
/// Padding and gaps of this card
///
/// Default to `Theme.cardTheme.margin`
final EdgeInsetsGeometry? padding;
/// Card foreground gradient colors (from left to right)
///
/// Default to `Theme.colorScheme.onPrimary`
final MultiColor? foregroundColors;
/// Card background gradient colors (from left to right)
///
/// Default to `Theme.cardTheme.color`
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;
/// Minimum size of the card
///
/// Default to `const Size(330, double.infinity)`
final Size? minSize;
/// Maximum size of the card
///
/// Default to `const Size(double.infinity, double.infinity)`
final Size? maxSize;
/// Background of the card
final Widget? background; final Widget? background;
final Widget child; final Widget child;
final MultiColor? backgroundColors;
final MultiColor? borderColors;
final BoxShadow? shadow;
final Size? minSize;
final Size? maxSize;
final double? padding;
final GlobalKey _key = GlobalKey(); final GlobalKey _key = GlobalKey();
Widget _buildChild(BuildContext context, Widget child) { Widget _buildChild(Widget child) => (background != null)
final themePadding =
ThemeHelper.getElement<EdgeInsetsGeometry, EdgeInsetsGeometry>(
[
padding,
Theme.of(context).extension<CardThemeExtension>()?.padding,
CardThemeExtensionDefault.from(Theme.of(context)).padding,
],
);
return (background != null)
? Stack( ? Stack(
alignment: Alignment.center, alignment: Alignment.center,
children: [ children: [
@ -110,131 +52,95 @@ class CardWrapper extends StatelessWidget {
background: background, background: background,
), ),
Padding( Padding(
padding: themePadding, padding: EdgeInsets.all(
padding ?? 25,
),
child: child, child: child,
), ),
], ],
) )
: Padding( : Padding(
padding: themePadding, padding: EdgeInsets.all(
padding ?? 25,
),
child: child, child: child,
); );
}
List<BoxShadow> _shadow(BuildContext context) { List<BoxShadow> _shadow(BuildContext context) {
final themeShadow = ThemeHelper.maybeGetElement<BoxShadow, BoxShadow>( final themeShadow = ThemeHelper.getThemeElement<BoxShadow, BoxShadow>(
[ [
shadow, shadow,
Theme.of(context).extension<CardThemeExtension>()?.shadow, Theme.of(context).extension<CardThemeExtension>()?.shadowColor,
CardThemeExtensionDefault.from(Theme.of(context)).shadow,
], ],
valueValidator: (shadow) => shadow != null,
transform: (shadow) => shadow,
); );
return (themeShadow != null) ? [themeShadow] : []; return (themeShadow != null) ? [themeShadow] : [];
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) => SelectionArea(
final themeBorderStroke = ThemeHelper.getElement<double, double>(
[
stroke,
Theme.of(context).extension<CardThemeExtension>()?.stroke,
CardThemeExtensionDefault.from(Theme.of(context)).stroke,
],
);
final themeBorderRadius =
ThemeHelper.getElement<BorderRadiusGeometry, BorderRadiusGeometry>(
[
radius,
Theme.of(context).extension<CardThemeExtension>()?.radius,
CardThemeExtensionDefault.from(Theme.of(context)).radius
],
);
final themeMinSize = ThemeHelper.maybeGetElement<Size, Size>(
[
minSize,
Theme.of(context).extension<CardThemeExtension>()?.minSize,
CardThemeExtensionDefault.from(Theme.of(context)).minSize
],
);
final themeMaxSize = ThemeHelper.maybeGetElement<Size, Size>(
[
maxSize,
Theme.of(context).extension<CardThemeExtension>()?.maxSize,
CardThemeExtensionDefault.from(Theme.of(context)).maxSize
],
);
return SelectionArea(
child: DecoratedBox( child: DecoratedBox(
key: _key, key: _key,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: themeBorderRadius, borderRadius: const BorderRadius.all(Radius.circular(12)),
gradient: ThemeHelper.maybeGetElement<MultiColor, Gradient>( gradient: ThemeHelper.getThemeElement<MultiColor, Gradient>(
[ [
backgroundColors, backgroundColors,
Theme.of(context) Theme.of(context)
.extension<CardThemeExtension>() .extension<CardThemeExtension>()
?.backgroundColors, ?.backgroundColors,
CardThemeExtensionDefault.from(Theme.of(context)).backgroundColors
], ],
valueValidator: (multiColor) => multiColor?.isGradient, valueValidator: (multiColor) => multiColor?.isGradient,
transform: (multiColor) => transform: (multiColor) =>
GradientHelper.linearFromMultiColor(multiColor!), LinearGradientHelper.fromMultiColor(multiColor!),
), ),
color: ThemeHelper.maybeGetElement<MultiColor, Color>( color: ThemeHelper.getThemeElement<MultiColor, Color>(
[ [
backgroundColors, backgroundColors,
Theme.of(context) Theme.of(context)
.extension<CardThemeExtension>() .extension<CardThemeExtension>()
?.backgroundColors, ?.backgroundColors,
CardThemeExtensionDefault.from(Theme.of(context)) MultiColor.single(Theme.of(context).cardColor),
.backgroundColors,
], ],
valueValidator: (multiColor) => valueValidator: (multiColor) =>
multiColor != null && multiColor.isColor, multiColor != null && multiColor.isColor,
transform: (multiColor) => multiColor?.color, transform: (multiColor) => multiColor?.color,
), ),
border: ThemeHelper.maybeGetElement<MultiColor, BoxBorder>( border: ThemeHelper.getThemeElement<MultiColor, BoxBorder>(
[ [
borderColors, borderColors,
Theme.of(context).extension<CardThemeExtension>()?.borderColors, Theme.of(context).extension<CardThemeExtension>()?.borderColors,
Theme.of(context) Theme.of(context)
.extension<CardThemeExtension>() .extension<CardThemeExtension>()
?.backgroundColors, ?.backgroundColors,
CardThemeExtensionDefault.from(Theme.of(context)).borderColors,
], ],
valueValidator: (multiColor) => valueValidator: (multiColor) =>
multiColor != null && multiColor.isColor, multiColor != null && multiColor.isColor,
transform: (multiColor) { transform: (multiColor) {
if (multiColor!.isGradient) { if (multiColor!.isGradient) {
return GradientBoxBorder( return GradientBoxBorder(
gradient: GradientHelper.linearFromMultiColor(multiColor), gradient: LinearGradientHelper.fromMultiColor(multiColor),
width: themeBorderStroke,
); );
} }
return Border.all( return Border.all(
color: multiColor.color, color: multiColor.color,
width: themeBorderStroke,
); );
}, },
), ),
boxShadow: _shadow(context), boxShadow: _shadow(context),
), ),
child: (themeMinSize != null || themeMaxSize != null) child: (minSize != null && maxSize != null)
? ConstrainedBox( ? ConstrainedBox(
constraints: BoxConstraints( constraints: BoxConstraints(
minWidth: themeMinSize?.width ?? 0, minWidth: minSize!.width,
minHeight: themeMinSize?.height ?? 0, minHeight: minSize!.height,
maxWidth: themeMaxSize?.width ?? double.infinity, maxWidth: maxSize!.width,
maxHeight: themeMaxSize?.height ?? double.infinity, maxHeight: maxSize!.height,
), ),
child: _buildChild(context, child), child: _buildChild(child),
) )
: _buildChild(context, child), : _buildChild(child),
), ),
); );
} }
}

View File

@ -44,7 +44,7 @@ class Loader extends LoaderComponent with $LoaderCWMixin {
child: RepaintBoundary( child: RepaintBoundary(
child: CustomPaint( child: CustomPaint(
painter: _LoaderPainter( painter: _LoaderPainter(
ThemeHelper.getElement<MultiColor, MultiColor>( ThemeHelper.getThemeElement<MultiColor, MultiColor>(
[ [
colors, colors,
Theme.of(context).extension<LoaderThemeExtension>()?.colors, Theme.of(context).extension<LoaderThemeExtension>()?.colors,
@ -61,9 +61,9 @@ class Loader extends LoaderComponent with $LoaderCWMixin {
valueValidator: (multiColor) => valueValidator: (multiColor) =>
multiColor != null && multiColor.isColor, multiColor != null && multiColor.isColor,
transform: (multiColor) => multiColor, transform: (multiColor) => multiColor,
), )!,
dimension / 2, dimension / 2,
ThemeHelper.getElement<double, double>( ThemeHelper.getThemeElement<double, double>(
[ [
stroke, stroke,
Theme.of(context).extension<LoaderThemeExtension>()?.stroke, Theme.of(context).extension<LoaderThemeExtension>()?.stroke,
@ -71,7 +71,7 @@ class Loader extends LoaderComponent with $LoaderCWMixin {
], ],
valueValidator: (stroke) => stroke != null, valueValidator: (stroke) => stroke != null,
transform: (stroke) => stroke, transform: (stroke) => stroke,
), )!,
flip: flip ?? false, flip: flip ?? false,
), ),
) )

View File

@ -39,7 +39,7 @@ class RichTextBuilder extends RichTextBuilderComponent
text ?? '', text ?? '',
regex, regex,
RichTextStyleParameter( RichTextStyleParameter(
ThemeHelper.getElement<TextStyle, TextStyle>( ThemeHelper.getThemeElement<TextStyle, TextStyle>(
[ [
defaultStyle, defaultStyle,
Theme.of(context) Theme.of(context)
@ -50,7 +50,8 @@ class RichTextBuilder extends RichTextBuilderComponent
valueValidator: (style) => style != null, valueValidator: (style) => style != null,
transform: (style) => style, transform: (style) => style,
), ),
ThemeHelper.getElement<Map<String, TextStyle>, Map<String, TextStyle>>( ThemeHelper.getThemeElement<Map<String, TextStyle>,
Map<String, TextStyle>>(
[ [
styles, styles,
Theme.of(context) Theme.of(context)
@ -60,7 +61,7 @@ class RichTextBuilder extends RichTextBuilderComponent
], ],
valueValidator: (styles) => styles != null, valueValidator: (styles) => styles != null,
transform: (styles) => styles, transform: (styles) => styles,
), )!,
null, null,
), ),
); );
@ -70,10 +71,7 @@ class RichTextBuilder extends RichTextBuilderComponent
if (style is GradientTextStyle?) { if (style is GradientTextStyle?) {
return WidgetSpan( return WidgetSpan(
child: GradientText( child: GradientText(
data: content, content,
gradientColors:
(style as GradientTextStyle?)?.gradientColors ??
const MultiColor([]),
style: style, style: style,
softWrap: true, softWrap: true,
textHeightBehavior: const TextHeightBehavior( textHeightBehavior: const TextHeightBehavior(

View File

@ -33,13 +33,6 @@ class TextInputState extends Equatable {
final String? statusMessage; final String? statusMessage;
bool get isDisabled => controlState.isDisabled();
bool get isEnabled => controlState.isEnabled();
bool get isFocused => controlState.isFocused();
bool get isHovered => controlState.isHovered();
bool get isTapped => controlState.isTapped();
bool get isInvalid => statusState == StatusState.error;
@override @override
List<Object?> get props => [controlState, statusState, statusMessage]; List<Object?> get props => [controlState, statusState, statusMessage];

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