master #81

Closed
malo wants to merge 322 commits from master into feat/bloc_layout/new-package
92 changed files with 3303 additions and 2212 deletions
Showing only changes of commit 8f5e3923d6 - Show all commits

View File

@ -99,6 +99,12 @@ 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
> Common to this, and Wyatt UI Kit packages.

View File

@ -37,38 +37,67 @@ abstract class ThemeResolver<Style extends ThemeStyle<Style>, Extension,
/// {@macro theme_resolver}
const ThemeResolver();
/// 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.
/// Compute extension value from a given extension.
Style? computeExtensionValueFn(
BuildContext context,
Extension? themeExtension, {
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.
Style negotiate(BuildContext context, {Extra? extra}) {
// 1) Custom style passed in constructor (cannot be null)
final style = computeDefaultValue(context, extra: extra);
return ThemeHelper.getElement<Style, Style>(
[
// 1) Custom style passed in constructor
customStyleFn(context, extra: extra),
// 3) Default
style,
// -> then, try to find better style, and merge it with the default
// 2) Theme extension
computeExtensionValueFn(
context,
Theme.of(context).extension<Extension>(),
extra: extra,
),
// 3) Default
style,
// -> then, try to find better style, and merge it with the one above
// 1) Custom style passed in constructor
customStyleFn(context, extra: extra),
],
transform: (value) => value,
combine: (value, element) => value?.mergeWith(element),

View File

@ -14,28 +14,4 @@
// 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';
abstract class CardThemeExtension extends ThemeExtension<CardThemeExtension> {
const CardThemeExtension({
this.backgroundColors,
this.secondaryBackgroundColor,
this.borderColors,
this.shadowColor,
this.body,
this.title,
this.subtitle,
});
// Colors
final MultiColor? backgroundColors;
final Color? secondaryBackgroundColor;
final MultiColor? borderColors;
final BoxShadow? shadowColor;
// TextStyles
final TextStyle? body;
final TextStyle? title;
final TextStyle? subtitle;
}
export 'theme_extensions/theme_extensions.dart';

View File

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

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

@ -0,0 +1,78 @@
// 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

@ -0,0 +1,78 @@
// 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

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

@ -0,0 +1,67 @@
// 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

@ -0,0 +1,97 @@
// 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

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

View File

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

View File

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

@ -0,0 +1,83 @@
// 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

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

View File

@ -0,0 +1,91 @@
// 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

@ -0,0 +1,143 @@
// 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

@ -0,0 +1,69 @@
// 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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,127 +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: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

@ -1,172 +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: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

@ -1,153 +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: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

@ -1,157 +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: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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -16,7 +16,6 @@
import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
class SimpleIconButtonThemeResolver extends ThemeResolver<SimpleIconButtonStyle,
SimpleIconButtonThemeExtension, ControlState> {
@ -25,70 +24,41 @@ class SimpleIconButtonThemeResolver extends ThemeResolver<SimpleIconButtonStyle,
});
@override
SimpleIconButtonStyle computeDefaultValue(
BuildContext context, {
SimpleIconButtonStyle? computeExtensionValueFn(
BuildContext context,
SimpleIconButtonThemeExtension? themeExtension, {
ControlState? extra,
}) {
MultiColor backgroundColor = MultiColor.single(context.colorScheme.primary);
MultiColor foregroundColor =
MultiColor.single(context.colorScheme.onPrimary);
SimpleIconButtonStyle? style;
switch (extra) {
case ControlState.disabled:
backgroundColor =
MultiColor.single(context.colorScheme.onSurface.withOpacity(0.12));
foregroundColor =
MultiColor.single(context.colorScheme.onSurface.withOpacity(0.38));
style = themeExtension?.disabledStyle;
break;
case ControlState.focused:
style = themeExtension?.focusedStyle;
break;
case ControlState.hovered:
backgroundColor =
MultiColor.single(context.colorScheme.primary.withOpacity(0.92));
style = themeExtension?.hoveredStyle;
break;
case ControlState.tapped:
backgroundColor =
MultiColor.single(context.colorScheme.primary.withOpacity(0.92));
style = themeExtension?.tappedStyle;
break;
case null:
case ControlState.normal:
case ControlState.focused:
style = themeExtension?.normalStyle;
break;
}
return SimpleIconButtonStyle(
dimension: context.buttonTheme.height,
radius: (context.buttonTheme.shape is RoundedRectangleBorder)
? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius
: null,
padding: EdgeInsets.zero,
foregroundColors: foregroundColor,
backgroundColors: backgroundColor,
);
return style;
}
@override
SimpleIconButtonThemeExtension? getDefaultExtension(BuildContext context) =>
SimpleIconButtonThemeExtensionDefault.from(Theme.of(context));
@override
final SimpleIconButtonStyle? Function(
BuildContext context, {
ControlState? extra,
}) 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,12 +18,9 @@ import 'package:flutter/material.dart' hide ButtonStyle;
import 'package:flutter/services.dart';
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
import 'package:wyatt_ui_components/wyatt_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/simple_icon_button/simple_icon_button_theme_resolver.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_icon.dart';
import 'package:wyatt_ui_kit/src/core/helpers/linear_gradient_helper.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
class SimpleIconButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
const SimpleIconButtonScreen({
@ -39,7 +36,7 @@ class SimpleIconButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
super.key,
});
final Icon? icon;
final Widget? icon;
final SimpleIconButtonStyle? disabledStyle;
final SimpleIconButtonStyle? normalStyle;
@ -171,25 +168,23 @@ class SimpleIconButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
/// context.buttonTheme.onPrimary
child: Builder(
builder: (context) {
if (icon?.color != null) {
if (icon != null) {
if (icon is GradientIcon) {
return icon!;
}
if (!(style.foregroundColors?.isGradient ?? false)) {
return ColorFiltered(
colorFilter: ColorFilter.mode(
style.foregroundColors!.color,
BlendMode.srcIn,
),
child: icon,
if (icon is Icon) {
return GradientIcon.fromIcon(
(icon as Icon?)!,
gradientColors: style.foregroundColors,
);
}
return GradientIcon.fromWidget(
icon!,
gradientColors: style.foregroundColors,
);
}
return icon!.toGradient(
LinearGradientHelper.fromMultiColor(
style.foregroundColors!,
),
);
return const SizedBox.shrink();
},
),
),

View File

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

View File

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

View File

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

View File

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

View File

@ -23,18 +23,33 @@ const _avatarAndTitlesSpacing = 25.0;
class InformationCardHorizontalHeader extends StatelessWidget {
const InformationCardHorizontalHeader({
this.icons,
this.axis,
this.title,
this.subtitle,
this.axis,
this.icons,
this.titleStyle,
this.subtitleStyle,
super.key,
});
final TextWrapper? title;
final TextWrapper? subtitle;
final Axis? axis;
/// 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: [
@ -44,9 +59,11 @@ class InformationCardHorizontalHeader extends StatelessWidget {
],
Expanded(
child: InformationCardTitles(
axis: axis,
title: title,
subtitle: subtitle,
axis: axis,
titleStyle: titleStyle,
subtitleStyle: subtitleStyle,
),
),
],

View File

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

View File

@ -23,16 +23,29 @@ const _titlesLineSpacing = 5.0;
class InformationCardTitles extends StatelessWidget {
const InformationCardTitles({
this.axis,
this.title,
this.subtitle,
this.axis,
this.titleStyle,
this.subtitleStyle,
super.key,
});
final TextWrapper? title;
final TextWrapper? subtitle;
/// 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
@ -40,20 +53,18 @@ class InformationCardTitles extends StatelessWidget {
: CrossAxisAlignment.center,
children: [
if (title != null) ...[
CardText(
CardText.fromWrapper(
title!,
style: titleStyle,
textType: TextType.title,
style: title!.style,
gradientColors: title!.gradientColors,
),
],
if (subtitle != null) ...[
const Gap(_titlesLineSpacing),
CardText(
CardText.fromWrapper(
subtitle!,
style: subtitleStyle,
textType: TextType.subtitle,
style: subtitle!.style,
gradientColors: subtitle!.gradientColors,
),
],
],

View File

@ -24,18 +24,33 @@ const _avatarAndTitlesSpacing = 25.0;
class InformationCardVerticalHeader extends StatelessWidget {
const InformationCardVerticalHeader({
this.icons,
this.axis,
this.title,
this.subtitle,
this.axis,
this.icons,
this.titleStyle,
this.subtitleStyle,
super.key,
});
final TextWrapper? title;
final TextWrapper? subtitle;
final Axis? axis;
/// 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: [
@ -46,9 +61,11 @@ class InformationCardVerticalHeader extends StatelessWidget {
const Gap(_avatarAndTitlesSpacing),
],
InformationCardTitles(
axis: axis,
title: title,
subtitle: subtitle,
axis: axis,
titleStyle: titleStyle,
subtitleStyle: subtitleStyle,
),
],
);

View File

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

View File

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

View File

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

View File

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

View File

@ -20,7 +20,6 @@ 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_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/wyatt_ui_kit.dart';
part 'quote_card.g.dart';
@ -30,7 +29,6 @@ class QuoteCard extends QuoteCardComponent with $QuoteCardCWMixin {
super.avatar,
super.name,
super.subtitle,
super.gradient,
super.quote,
super.leftQuote,
super.rightQuote,
@ -38,56 +36,76 @@ class QuoteCard extends QuoteCardComponent with $QuoteCardCWMixin {
super.padding,
super.borderColors,
super.backgroundColors,
super.stroke,
super.minSize,
super.maxSize,
super.shadow,
super.titleStyle,
super.subtitleStyle,
super.bodyStyle,
super.background,
super.key,
});
@override
Widget build(BuildContext context) => CardWrapper(
Widget build(BuildContext context) {
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,
padding: padding,
radius: radius,
backgroundColors: backgroundColors,
borderColors: borderColors,
shadow: shadow,
stroke: stroke,
maxSize: maxSize,
minSize: minSize,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
leftQuote ??
Align(
const Align(
alignment: Alignment.topLeft,
child: GradientText(
child: Text(
'',
style: GradientTextStyle.from(
context.textTheme.titleLarge
?.copyWith(fontWeight: FontWeight.bold),
MultiColor(gradient?.colors),
),
),
),
if (quote != null) ...[
CardText(
CardText.fromWrapper(
quote!,
textType: TextType.body,
style: quote!.style,
gradientColors: quote!.gradientColors,
style: themeBodyStyle,
),
],
const Gap(15),
rightQuote ??
Align(
const Align(
alignment: Alignment.bottomRight,
child: GradientText(
child: Text(
'',
style: GradientTextStyle.from(
context.textTheme.titleLarge
?.copyWith(fontWeight: FontWeight.bold),
MultiColor(gradient?.colors),
),
),
),
Row(
@ -101,19 +119,17 @@ class QuoteCard extends QuoteCardComponent with $QuoteCardCWMixin {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (name != null) ...[
CardText(
CardText.fromWrapper(
name!,
textType: TextType.body,
style: name!.style,
gradientColors: name!.gradientColors,
style: themeTitleStyle,
textType: TextType.title,
),
],
if (subtitle != null) ...[
CardText(
CardText.fromWrapper(
subtitle!,
style: themeSubtitleStyle,
textType: TextType.subtitle,
style: subtitle!.style,
gradientColors: subtitle!.gradientColors,
),
],
],
@ -124,4 +140,5 @@ class QuoteCard extends QuoteCardComponent with $QuoteCardCWMixin {
],
),
);
}
}

View File

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

View File

@ -18,68 +18,118 @@ import 'package:flutter/material.dart';
import 'package:gap/gap.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_kit/src/components/cards/skill_card/widgets/skill_card_header.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_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_wrapper.dart';
part 'skill_card.g.dart';
const _bodyTopSpacing = 25.0;
@ComponentCopyWithExtension()
class SkillCard extends SkillCardComponent with $SkillCardCWMixin {
const SkillCard({
super.icon,
super.gradient,
super.secondaryBackgroundColors,
super.axis,
super.icons,
super.title,
super.subtitle,
super.description,
super.skills,
super.leadingIcon,
super.bulletColors,
super.bulletIcon,
super.radius,
super.padding,
super.borderColors,
super.backgroundColors,
super.stroke,
super.minSize,
super.maxSize = const Size(330, double.infinity),
super.maxSize,
super.shadow,
super.titleStyle,
super.subtitleStyle,
super.bodyStyle,
super.background,
super.key,
});
@override
Widget build(BuildContext context) => CardWrapper(
Widget build(BuildContext context) {
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,
padding: padding,
radius: radius,
backgroundColors: backgroundColors,
borderColors: borderColors,
shadow: shadow,
stroke: stroke,
maxSize: maxSize,
minSize: minSize,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SkillCardHeader(
secondaryBackgroundColors: secondaryBackgroundColors,
icon: icon,
if (axis == Axis.horizontal) ...[
SkillCardHorizontalHeader(
icons: icons,
axis: axis,
title: title,
subtitle: subtitle,
titleStyle: themeTitleStyle,
subtitleStyle: themeSubtitleStyle,
),
const Gap(25),
] else ...[
SkillCardVerticalHeader(
icons: icons,
axis: axis,
title: title,
subtitle: subtitle,
titleStyle: themeTitleStyle,
subtitleStyle: themeSubtitleStyle,
),
],
const Gap(_bodyTopSpacing),
if (description != null) ...[
CardText(
CardText.fromWrapper(
description!,
textType: TextType.body,
style: description!.style,
gradientColors: description!.gradientColors,
style: themeBodyStyle,
),
const Gap(25),
const Gap(_bodyTopSpacing),
],
if (skills != null)
SkillCardSkills(
gradient: gradient,
skills: skills,
leadingIcon: leadingIcon,
bulletColors: bulletColors,
bulletIcon: bulletIcon,
bodyStyle: themeBodyStyle,
),
],
),
);
}
}

View File

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

View File

@ -1,55 +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';
class SkillCardHeader extends StatelessWidget {
const SkillCardHeader({
super.key,
this.icon,
this.title,
this.secondaryBackgroundColors,
});
final Widget? icon;
final TextWrapper? title;
final Color? secondaryBackgroundColors;
@override
Widget build(BuildContext context) => Column(
children: [
if (icon != null) ...[
icon!,
const Gap(25),
],
Column(
children: [
if (title != null) ...[
CardText(
title!,
textType: TextType.title,
style: title!.style,
gradientColors: title!.gradientColors,
),
],
],
)
],
);
}

View File

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

View File

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

View File

@ -24,46 +24,67 @@ enum TextType {
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 {
/// {@macro card_text}
const CardText(
this.text, {
required this.textType,
this.style,
this.gradientColors,
this.textType = TextType.body,
super.key,
});
final TextWrapper text;
/// Creates a [CardText] from a [TextWrapper].
///
/// 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 TextStyle? style;
final MultiColor? gradientColors;
TextStyle? _getStyle(BuildContext context) {
if (style != null) {
return style;
if (text.style != null) {
return text.style;
} else {
final cardThemeExtension =
Theme.of(context).extension<CardThemeExtension>();
Theme.of(context).extension<CardThemeExtension>() ??
CardThemeExtensionDefault.from(Theme.of(context));
switch (textType) {
case TextType.title:
return cardThemeExtension?.title ?? context.textTheme.titleLarge;
return cardThemeExtension.titleStyle ??
CardThemeExtensionDefault.from(Theme.of(context)).titleStyle;
case TextType.subtitle:
return cardThemeExtension?.subtitle ?? context.textTheme.titleMedium;
return cardThemeExtension.subtitleStyle ??
CardThemeExtensionDefault.from(Theme.of(context)).subtitleStyle;
case TextType.body:
return cardThemeExtension?.body ?? context.textTheme.bodyMedium;
return cardThemeExtension.bodyStyle ??
CardThemeExtensionDefault.from(Theme.of(context)).bodyStyle;
}
}
}
@override
Widget build(BuildContext context) => Text(
text.data,
Widget build(BuildContext context) => text.copyWith
.call(
style: _getStyle(context),
textAlign: text.textAlign,
textDirection: text.textDirection,
softWrap: text.softWrap,
overflow: text.overflow,
maxLines: text.maxLines,
selectionColor: text.selectionColor,
).toGradient(gradientColors: gradientColors);
)
.build(context);
}

View File

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

View File

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

View File

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

View File

@ -33,6 +33,13 @@ class TextInputState extends Equatable {
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
List<Object?> get props => [controlState, statusState, statusMessage];

View File

@ -38,8 +38,8 @@ class TextInput extends TextInputComponent with $TextInputCWMixin {
super.hint,
super.normalStyle,
super.focusedStyle,
super.errorStyle,
super.disableStyle,
super.invalidStyle,
super.disabledStyle,
super.controller,
super.focusNode,
super.keyboardType,
@ -105,8 +105,8 @@ class TextInput extends TextInputComponent with $TextInputCWMixin {
hint: hint,
focusedStyle: focusedStyle,
normalStyle: normalStyle,
errorStyle: errorStyle,
disableStyle: disableStyle,
invalidStyle: invalidStyle,
disabledStyle: disabledStyle,
prefixIcon: prefixIcon,
prefixText: prefixText,
suffixIcon: suffixIcon,

View File

@ -35,11 +35,11 @@ class $TextInputCWProxyImpl implements $TextInputComponentCWProxy {
TextInput focusedStyle(TextInputStyle? focusedStyle) =>
this(focusedStyle: focusedStyle);
@override
TextInput errorStyle(TextInputStyle? errorStyle) =>
this(errorStyle: errorStyle);
TextInput invalidStyle(TextInputStyle? invalidStyle) =>
this(invalidStyle: invalidStyle);
@override
TextInput disableStyle(TextInputStyle? disableStyle) =>
this(disableStyle: disableStyle);
TextInput disabledStyle(TextInputStyle? disabledStyle) =>
this(disabledStyle: disabledStyle);
@override
TextInput controller(TextEditingController? controller) =>
this(controller: controller);
@ -206,8 +206,8 @@ class $TextInputCWProxyImpl implements $TextInputComponentCWProxy {
TextWrapper? hint,
TextInputStyle? normalStyle,
TextInputStyle? focusedStyle,
TextInputStyle? errorStyle,
TextInputStyle? disableStyle,
TextInputStyle? invalidStyle,
TextInputStyle? disabledStyle,
TextEditingController? controller,
FocusNode? focusNode,
TextInputType? keyboardType,
@ -277,8 +277,8 @@ class $TextInputCWProxyImpl implements $TextInputComponentCWProxy {
hint: hint ?? _value.hint,
normalStyle: normalStyle ?? _value.normalStyle,
focusedStyle: focusedStyle ?? _value.focusedStyle,
errorStyle: errorStyle ?? _value.errorStyle,
disableStyle: disableStyle ?? _value.disableStyle,
invalidStyle: invalidStyle ?? _value.invalidStyle,
disabledStyle: disabledStyle ?? _value.disabledStyle,
controller: controller ?? _value.controller,
focusNode: focusNode ?? _value.focusNode,
keyboardType: keyboardType ?? _value.keyboardType,

View File

@ -40,8 +40,8 @@ class TextInputScreen extends CubitScreen<TextInputCubit, TextInputState> {
this.hint,
this.normalStyle,
this.focusedStyle,
this.errorStyle,
this.disableStyle,
this.invalidStyle,
this.disabledStyle,
this.magnifierConfiguration,
this.controller,
this.focusNode,
@ -157,8 +157,8 @@ class TextInputScreen extends CubitScreen<TextInputCubit, TextInputState> {
final TextInputStyle? normalStyle;
final TextInputStyle? focusedStyle;
final TextInputStyle? errorStyle;
final TextInputStyle? disableStyle;
final TextInputStyle? invalidStyle;
final TextInputStyle? disabledStyle;
final TextWrapper? label;
final TextWrapper? hint;
@ -202,7 +202,7 @@ class TextInputScreen extends CubitScreen<TextInputCubit, TextInputState> {
textInputStyle = focusedStyle;
break;
case ControlState.disabled:
textInputStyle = disableStyle;
textInputStyle = disabledStyle;
break;
case ControlState.normal:
textInputStyle = normalStyle;
@ -216,7 +216,7 @@ class TextInputScreen extends CubitScreen<TextInputCubit, TextInputState> {
TextInputStyle? style;
switch (extra?.statusState) {
case StatusState.error:
style = errorStyle;
style = invalidStyle;
break;
case StatusState.initial:
case StatusState.success:
@ -262,7 +262,7 @@ class TextInputScreen extends CubitScreen<TextInputCubit, TextInputState> {
child: AnimatedContainer(
duration: const Duration(milliseconds: 600),
decoration: BoxDecoration(
boxShadow: style.boxShadow != null ? [style.boxShadow!] : null,
boxShadow: style.shadow != null ? [style.shadow!] : null,
gradient: style.backgroundColors?.isGradient ?? false
? LinearGradient(colors: style.backgroundColors!.colors)
: null,
@ -312,7 +312,7 @@ class TextInputScreen extends CubitScreen<TextInputCubit, TextInputState> {
focusNode: focusNode ?? _focusNode,
label: (state.statusState == StatusState.error &&
(state.statusMessage?.isNotEmpty ?? false))
? state.statusMessage?.wrap()
? TextWrapper(state.statusMessage!)
: label,
labelStyle: style.labelStyle,
)

View File

@ -17,8 +17,6 @@
import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/text_inputs/cubit/text_input_cubit.dart';
import 'package:wyatt_ui_kit/src/core/core.dart';
import 'package:wyatt_ui_kit/src/domain/text_input_theme_extension.dart';
class TextInputThemeResolver extends ThemeResolver<TextInputStyle,
TextInputThemeExtension, TextInputState> {
@ -26,130 +24,44 @@ class TextInputThemeResolver extends ThemeResolver<TextInputStyle,
required this.customStyleFn,
});
@override
final TextInputStyle? Function(
BuildContext context, {
TextInputState? extra,
}) customStyleFn;
@override
TextInputStyle computeDefaultValue(
BuildContext context, {
TextInputState? extra,
}) {
TextStyle? labelStyle = context.textTheme.labelLarge
?.copyWith(color: Theme.of(context).unselectedWidgetColor);
TextStyle? hintStyle = context.textTheme.labelLarge;
TextStyle? prefixStyle = context.textTheme.bodyMedium;
TextStyle? suffixStyle = context.textTheme.bodyMedium;
TextStyle? inputStyle = context.textTheme.bodyMedium;
Color? iconColor = context.colorScheme.inversePrimary;
Color? prefixIconColor = Theme.of(context).unselectedWidgetColor;
Color? suffixIconColor = Theme.of(context).unselectedWidgetColor;
Color? borderColors = Theme.of(context).unselectedWidgetColor;
MultiColor? backgroundColors;
BoxShadow? boxShadow;
final BorderRadiusGeometry radius = BorderRadius.circular(4);
switch (extra?.controlState) {
case ControlState.disabled:
labelStyle =
labelStyle?.copyWith(color: Theme.of(context).disabledColor);
hintStyle = hintStyle?.copyWith(color: Theme.of(context).disabledColor);
prefixStyle =
prefixStyle?.copyWith(color: Theme.of(context).disabledColor);
suffixStyle =
suffixStyle?.copyWith(color: Theme.of(context).disabledColor);
inputStyle =
inputStyle?.copyWith(color: Theme.of(context).disabledColor);
borderColors = Theme.of(context).disabledColor;
prefixIconColor = Theme.of(context).disabledColor;
suffixIconColor = Theme.of(context).disabledColor;
break;
case ControlState.focused:
prefixIconColor = context.colorScheme.primary;
suffixIconColor = context.colorScheme.primary;
iconColor = context.colorScheme.primary;
borderColors = context.colorScheme.primary;
labelStyle = labelStyle?.copyWith(color: context.colorScheme.primary);
break;
case ControlState.hovered:
case ControlState.tapped:
case ControlState.normal:
case null:
break;
}
switch (extra?.statusState) {
case StatusState.error:
labelStyle = context.textTheme.labelLarge
?.copyWith(color: context.colorScheme.error);
borderColors = context.colorScheme.error;
break;
case StatusState.initial:
case StatusState.success:
case StatusState.loading:
case null:
break;
}
return TextInputStyle(
labelStyle: labelStyle,
hintStyle: hintStyle,
iconColor: iconColor,
prefixIconColor: prefixIconColor,
prefixStyle: prefixStyle,
suffixStyle: suffixStyle,
suffixIconColor: suffixIconColor,
backgroundColors: backgroundColors,
borderColors: borderColors,
boxShadow: boxShadow,
radius: radius,
inputStyle: inputStyle,
);
}
@override
TextInputStyle? computeExtensionValueFn(
BuildContext context,
TextInputThemeExtension? themeExtension, {
TextInputState? extra,
}) {
TextInputStyle? textInputStyle;
TextInputStyle? style;
switch (extra?.controlState) {
case ControlState.focused:
textInputStyle = themeExtension?.focusedStyle;
break;
case ControlState.disabled:
textInputStyle = themeExtension?.disableStyle;
style = themeExtension?.disabledStyle;
break;
case ControlState.normal:
textInputStyle = themeExtension?.normalStyle;
case ControlState.focused:
style = themeExtension?.focusedStyle;
break;
case ControlState.hovered:
case ControlState.tapped:
case ControlState.normal:
case null:
style = themeExtension?.normalStyle;
break;
}
TextInputStyle? style;
switch (extra?.statusState) {
case StatusState.error:
style = themeExtension?.errorStyle;
break;
case StatusState.initial:
case StatusState.success:
case StatusState.loading:
case null:
break;
if (extra?.isInvalid ?? false) {
style = themeExtension?.invalidStyle;
}
return TextInputStyle.merge(textInputStyle, style);
return style;
}
@override
TextInputThemeExtension? getDefaultExtension(
BuildContext context,
) =>
TextInputThemeExtensionDefault.from(Theme.of(context));
@override
final TextInputStyle? Function(
BuildContext context, {
TextInputState? extra,
}) customStyleFn;
}

View File

@ -0,0 +1,17 @@
// 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

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

View File

@ -0,0 +1,141 @@
// 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';
class FileSelectionButtonThemeExtensionImpl
extends FileSelectionButtonThemeExtension {
const FileSelectionButtonThemeExtensionImpl({
super.disabledStyle,
super.focusedStyle,
super.hoveredStyle,
super.normalStyle,
super.tappedStyle,
super.selectedStyle,
super.invalidStyle,
});
factory FileSelectionButtonThemeExtensionImpl.light({ThemeData? theme}) {
theme ??= ThemeData.light();
final style = FileSelectionButtonStyle(
titleStyle: theme.textTheme.labelLarge,
subtitleStyle: theme.textTheme.labelSmall,
radius: BorderRadius.circular(12),
padding: const EdgeInsets.all(13),
foregroundColors: const MultiColor.single(Color(0xFF24262A)),
backgroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
borderColors: const MultiColor([
Color(0xFFDDE0E3),
Color(0xFFCACCD4),
]),
stroke: 2,
);
return FileSelectionButtonThemeExtensionImpl(
normalStyle: style,
disabledStyle: style.copyWith(
foregroundColors:
MultiColor.single(const Color(0xFF24262A).withOpacity(0.4)),
backgroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
borderColors:
MultiColor.single(const Color(0xFF24262A).withOpacity(0.4)),
),
hoveredStyle: style.copyWith(
backgroundColors:
MultiColor.single(const Color(0xFF24262A).withOpacity(0.4)),
),
focusedStyle: style.copyWith(stroke: 4),
tappedStyle: style.copyWith(
backgroundColors:
MultiColor.single(const Color(0xFF24262A).withOpacity(0.4)),
),
invalidStyle: style.copyWith(
subtitleStyle: theme.textTheme.labelSmall?.copyWith(
fontSize: 11,
fontWeight: FontWeight.w400,
color: const Color(0xFFF44464),
),
borderColors: const MultiColor([
Color(0xFFF44464),
Color(0xFFF44464),
]),
),
// Unused
selectedStyle: style.copyWith(
foregroundColors: const MultiColor.single(Color(0xFF24262A)),
borderColors: const MultiColor([
Color(0xFF00D16C),
Color(0xFF00D16C),
]),
),
);
}
factory FileSelectionButtonThemeExtensionImpl.dark({ThemeData? theme}) {
theme ??= ThemeData.dark();
final style = FileSelectionButtonStyle(
titleStyle: theme.textTheme.labelLarge,
subtitleStyle: theme.textTheme.labelSmall,
radius: BorderRadius.circular(12),
padding: const EdgeInsets.all(13),
foregroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
backgroundColors: const MultiColor.single(Color(0xFF24262A)),
borderColors: const MultiColor([
Color(0xFF24262A),
Color(0xFF24262A),
]),
stroke: 2,
);
return FileSelectionButtonThemeExtensionImpl(
normalStyle: style,
disabledStyle: style.copyWith(
foregroundColors:
MultiColor.single(const Color(0xFFDDE0E3).withOpacity(0.4)),
backgroundColors: const MultiColor.single(Color(0xFF24262A)),
borderColors:
MultiColor.single(const Color(0xFFDDE0E3).withOpacity(0.4)),
),
hoveredStyle: style.copyWith(
backgroundColors:
MultiColor.single(const Color(0xFFDDE0E3).withOpacity(0.4)),
),
focusedStyle: style.copyWith(stroke: 4),
tappedStyle: style.copyWith(
backgroundColors:
MultiColor.single(const Color(0xFFDDE0E3).withOpacity(0.4)),
),
invalidStyle: style.copyWith(
subtitleStyle: theme.textTheme.labelSmall?.copyWith(
fontSize: 11,
fontWeight: FontWeight.w400,
color: const Color(0xFFF44464),
),
borderColors: const MultiColor([
Color(0xFFF44464),
Color(0xFFF44464),
]),
),
// Unused
selectedStyle: style.copyWith(
foregroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
borderColors: const MultiColor([
Color(0xFF00D16C),
Color(0xFF00D16C),
]),
),
);
}
}

View File

@ -0,0 +1,133 @@
// 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';
class FlatButtonThemeExtensionImpl extends FlatButtonThemeExtension {
const FlatButtonThemeExtensionImpl({
super.disabledStyle,
super.focusedStyle,
super.hoveredStyle,
super.normalStyle,
super.tappedStyle,
});
factory FlatButtonThemeExtensionImpl.light({ThemeData? theme}) {
theme ??= ThemeData.light();
final style = FlatButtonStyle(
labelStyle: theme.textTheme.labelLarge,
radius: BorderRadius.circular(15),
padding: const EdgeInsets.all(10),
foregroundColors: const MultiColor([
Color(0xFF3C97FB),
Color(0xFF436EF4),
]),
backgroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
borderColors: const MultiColor([
Color(0xFF3C97FB),
Color(0xFF436EF4),
]),
stroke: 3,
);
return FlatButtonThemeExtensionImpl(
normalStyle: style,
disabledStyle: style.copyWith(
labelStyle: theme.textTheme.labelLarge?.copyWith(
color: const Color(0xFF3C97FB).withOpacity(0.4),
),
foregroundColors:
MultiColor.single(const Color(0xFF3C97FB).withOpacity(0.4)),
backgroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
borderColors:
MultiColor.single(const Color(0xFF3C97FB).withOpacity(0.4)),
stroke: 1,
),
hoveredStyle: style.copyWith(
labelStyle: theme.textTheme.labelLarge?.copyWith(
color: const Color(0xFFDDE0E3),
),
foregroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
backgroundColors: const MultiColor([
Color(0xFF3C97FB),
Color(0xFF436EF4),
]),
),
focusedStyle: style.copyWith(stroke: 5),
tappedStyle: style.copyWith(
labelStyle: theme.textTheme.labelLarge?.copyWith(
color: const Color(0xFFDDE0E3),
),
foregroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
backgroundColors: const MultiColor([
Color(0xFF4B68FF),
Color(0xFF3531F5),
]),
borderColors: const MultiColor([
Color(0xFF4B68FF),
Color(0xFF3531F5),
]),
),
);
}
factory FlatButtonThemeExtensionImpl.dark({ThemeData? theme}) {
theme ??= ThemeData.dark();
final style = FlatButtonStyle(
labelStyle: theme.textTheme.labelLarge,
radius: BorderRadius.circular(15),
padding: const EdgeInsets.all(10),
foregroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
backgroundColors: const MultiColor.single(Color(0xFF24262A)),
borderColors: const MultiColor([
Color(0xFF3C97FB),
Color(0xFF436EF4),
]),
stroke: 3,
);
return FlatButtonThemeExtensionImpl(
normalStyle: style,
disabledStyle: style.copyWith(
labelStyle: theme.textTheme.labelLarge?.copyWith(
color: const Color(0xFF60656A),
),
foregroundColors: const MultiColor.single(Color(0xFF60656A)),
backgroundColors: const MultiColor.single(Color(0xFF33373E)),
borderColors: const MultiColor([Color(0xFF60656A), Color(0xFF383C40)]),
stroke: 1,
),
hoveredStyle: style.copyWith(
foregroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
backgroundColors: const MultiColor([
Color(0xFF3C97FB),
Color(0xFF436EF4),
]),
),
focusedStyle: style.copyWith(stroke: 5),
tappedStyle: style.copyWith(
foregroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
backgroundColors: const MultiColor([
Color(0xFF4B68FF),
Color(0xFF3531F5),
]),
borderColors: const MultiColor([
Color(0xFF4B68FF),
Color(0xFF3531F5),
]),
),
);
}
}

View File

@ -0,0 +1,121 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
class SimpleIconButtonThemeExtensionImpl
extends SimpleIconButtonThemeExtension {
const SimpleIconButtonThemeExtensionImpl({
super.disabledStyle,
super.focusedStyle,
super.hoveredStyle,
super.normalStyle,
super.tappedStyle,
});
factory SimpleIconButtonThemeExtensionImpl.light({ThemeData? theme}) {
theme ??= ThemeData.light();
final style = SimpleIconButtonStyle(
dimension: 30,
radius: BorderRadius.circular(15),
padding: const EdgeInsets.all(10),
foregroundColors: const MultiColor([
Color(0xFF3C97FB),
Color(0xFF436EF4),
]),
backgroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
borderColors: const MultiColor([
Color(0xFF3C97FB),
Color(0xFF436EF4),
]),
stroke: 3,
);
return SimpleIconButtonThemeExtensionImpl(
normalStyle: style,
disabledStyle: style.copyWith(
foregroundColors:
MultiColor.single(const Color(0xFF3C97FB).withOpacity(0.4)),
backgroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
borderColors:
MultiColor.single(const Color(0xFF3C97FB).withOpacity(0.4)),
stroke: 1,
),
hoveredStyle: style.copyWith(
foregroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
backgroundColors: const MultiColor([
Color(0xFF3C97FB),
Color(0xFF436EF4),
]),
),
focusedStyle: style.copyWith(stroke: 5),
tappedStyle: style.copyWith(
foregroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
backgroundColors: const MultiColor([
Color(0xFF4B68FF),
Color(0xFF3531F5),
]),
borderColors: const MultiColor([
Color(0xFF4B68FF),
Color(0xFF3531F5),
]),
),
);
}
factory SimpleIconButtonThemeExtensionImpl.dark({ThemeData? theme}) {
theme ??= ThemeData.dark();
final style = SimpleIconButtonStyle(
radius: BorderRadius.circular(15),
padding: const EdgeInsets.all(10),
foregroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
backgroundColors: const MultiColor.single(Color(0xFF24262A)),
borderColors: const MultiColor([
Color(0xFF3C97FB),
Color(0xFF436EF4),
]),
stroke: 3,
);
return SimpleIconButtonThemeExtensionImpl(
normalStyle: style,
disabledStyle: style.copyWith(
foregroundColors: const MultiColor.single(Color(0xFF60656A)),
backgroundColors: const MultiColor.single(Color(0xFF33373E)),
borderColors: const MultiColor([Color(0xFF60656A), Color(0xFF383C40)]),
stroke: 1,
),
hoveredStyle: style.copyWith(
foregroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
backgroundColors: const MultiColor([
Color(0xFF3C97FB),
Color(0xFF436EF4),
]),
),
focusedStyle: style.copyWith(stroke: 5),
tappedStyle: style.copyWith(
foregroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
backgroundColors: const MultiColor([
Color(0xFF4B68FF),
Color(0xFF3531F5),
]),
borderColors: const MultiColor([
Color(0xFF4B68FF),
Color(0xFF3531F5),
]),
),
);
}
}

View File

@ -0,0 +1,148 @@
// 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';
class SymbolButtonThemeExtensionImpl extends SymbolButtonThemeExtension {
const SymbolButtonThemeExtensionImpl({
super.disabledStyle,
super.focusedStyle,
super.hoveredStyle,
super.normalStyle,
super.tappedStyle,
super.selectedStyle,
});
factory SymbolButtonThemeExtensionImpl.light({ThemeData? theme}) {
theme ??= ThemeData.light();
final style = SymbolButtonStyle(
labelStyle: theme.textTheme.labelLarge,
radius: BorderRadius.circular(15),
padding: const EdgeInsets.all(10),
foregroundColors: const MultiColor([
Color(0xFF3C97FB),
Color(0xFF436EF4),
]),
backgroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
borderColors: const MultiColor([
Color(0xFF3C97FB),
Color(0xFF436EF4),
]),
stroke: 3,
);
return SymbolButtonThemeExtensionImpl(
normalStyle: style,
disabledStyle: style.copyWith(
labelStyle: theme.textTheme.labelLarge?.copyWith(
color: const Color(0xFF3C97FB).withOpacity(0.4),
),
foregroundColors:
MultiColor.single(const Color(0xFF3C97FB).withOpacity(0.4)),
backgroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
borderColors:
MultiColor.single(const Color(0xFF3C97FB).withOpacity(0.4)),
stroke: 1,
),
hoveredStyle: style.copyWith(
labelStyle: theme.textTheme.labelLarge?.copyWith(
color: const Color(0xFFDDE0E3),
),
foregroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
backgroundColors: const MultiColor([
Color(0xFF3C97FB),
Color(0xFF436EF4),
]),
),
focusedStyle: style.copyWith(stroke: 5),
tappedStyle: style.copyWith(
labelStyle: theme.textTheme.labelLarge?.copyWith(
color: const Color(0xFFDDE0E3),
),
foregroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
backgroundColors: const MultiColor([
Color(0xFF4B68FF),
Color(0xFF3531F5),
]),
borderColors: const MultiColor([
Color(0xFF4B68FF),
Color(0xFF3531F5),
]),
),
selectedStyle: style.copyWith(
foregroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
borderColors: const MultiColor([
Color(0xFF00D16C),
Color(0xFF00D16C),
]),
),
);
}
factory SymbolButtonThemeExtensionImpl.dark({ThemeData? theme}) {
theme ??= ThemeData.dark();
final style = SymbolButtonStyle(
labelStyle: theme.textTheme.labelLarge,
radius: BorderRadius.circular(15),
padding: const EdgeInsets.all(10),
foregroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
backgroundColors: const MultiColor.single(Color(0xFF24262A)),
borderColors: const MultiColor([
Color(0xFF3C97FB),
Color(0xFF436EF4),
]),
stroke: 3,
);
return SymbolButtonThemeExtensionImpl(
normalStyle: style,
disabledStyle: style.copyWith(
labelStyle: theme.textTheme.labelLarge?.copyWith(
color: const Color(0xFF60656A),
),
foregroundColors: const MultiColor.single(Color(0xFF60656A)),
backgroundColors: const MultiColor.single(Color(0xFF33373E)),
borderColors: const MultiColor([Color(0xFF60656A), Color(0xFF383C40)]),
stroke: 1,
),
hoveredStyle: style.copyWith(
foregroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
backgroundColors: const MultiColor([
Color(0xFF3C97FB),
Color(0xFF436EF4),
]),
),
focusedStyle: style.copyWith(stroke: 5),
tappedStyle: style.copyWith(
foregroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
backgroundColors: const MultiColor([
Color(0xFF4B68FF),
Color(0xFF3531F5),
]),
borderColors: const MultiColor([
Color(0xFF4B68FF),
Color(0xFF3531F5),
]),
),
selectedStyle: style.copyWith(
foregroundColors: const MultiColor.single(Color(0xFFDDE0E3)),
borderColors: const MultiColor([
Color(0xFF00D16C),
Color(0xFF00D16C),
]),
),
);
}
}

View File

@ -0,0 +1,95 @@
// 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 card_theme_extension_impl}
/// Card theme extension that implements Wyatt Theme.
/// {@endtemplate}
class CardThemeExtensionImpl extends CardThemeExtension {
/// {@macro card_theme_extension_impl}
const CardThemeExtensionImpl({
super.radius,
super.padding,
super.backgroundColors,
super.borderColors,
super.stroke,
super.shadow,
super.minSize,
super.maxSize,
super.titleStyle,
super.subtitleStyle,
super.bodyStyle,
});
/// {@macro card_theme_extension_impl}
///
/// You can pass a [ThemeData] to use its text styles.
///
/// This is the default light theme.
factory CardThemeExtensionImpl.light({ThemeData? theme}) {
theme ??= ThemeData.light();
return CardThemeExtensionImpl(
radius: const BorderRadius.all(Radius.circular(12)),
padding: const EdgeInsets.all(25),
stroke: 1,
backgroundColors: const MultiColor.single(Color(0xFFF6F6F6)),
borderColors: const MultiColor([
Color(0xFFDDE0E3),
Color(0xFFCACCD4),
]),
titleStyle: theme.textTheme.titleLarge,
subtitleStyle: theme.textTheme.titleMedium,
bodyStyle: theme.textTheme.bodyMedium,
minSize: const Size(330, 0),
maxSize: const Size(390, double.infinity),
shadow: BoxShadow(
color: const Color(0xFF24262A).withOpacity(0.05),
blurRadius: 30,
offset: const Offset(0, 5),
),
);
}
/// {@macro card_theme_extension_impl}
///
/// This is the default dark theme.
factory CardThemeExtensionImpl.dark({ThemeData? theme}) {
theme ??= ThemeData.dark();
return CardThemeExtensionImpl(
radius: const BorderRadius.all(Radius.circular(12)),
padding: const EdgeInsets.all(25),
stroke: 1,
backgroundColors:
const MultiColor([Color(0xFF26292D), Color(0xFF202327)]),
borderColors: const MultiColor([
Color(0xFF60656A),
Color(0xFF383C40),
]),
titleStyle: theme.textTheme.titleLarge,
subtitleStyle: theme.textTheme.titleMedium,
bodyStyle: theme.textTheme.bodyMedium,
minSize: const Size(330, 0),
maxSize: const Size(390, double.infinity),
shadow: BoxShadow(
color: const Color(0xFF24262A).withOpacity(0.15),
blurRadius: 30,
offset: const Offset(0, 5),
),
);
}
}

View File

@ -0,0 +1,123 @@
// 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 text_input_theme_extension}
/// Text input theme extension that implements Wyatt Theme
/// {@endtemplate}
class TextInputThemeExtensionImpl extends TextInputThemeExtension {
/// {@macro text_input_theme_extension}
const TextInputThemeExtensionImpl({
super.normalStyle,
super.focusedStyle,
super.disabledStyle,
super.invalidStyle,
});
factory TextInputThemeExtensionImpl.light({ThemeData? theme}) {
theme ??= ThemeData.light();
return TextInputThemeExtensionImpl(
normalStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const Color.fromRGBO(221, 224, 227, 1),
labelStyle: theme.textTheme.labelLarge?.copyWith(
color: const Color.fromRGBO(55, 65, 81, 1),
),
inputStyle: theme.textTheme.bodyMedium?.copyWith(
color: const Color.fromRGBO(55, 65, 81, 1),
),
),
focusedStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const Color.fromRGBO(60, 125, 251, 1),
labelStyle: theme.textTheme.labelLarge?.copyWith(
color: const Color.fromRGBO(55, 65, 81, 1),
),
inputStyle: theme.textTheme.bodyMedium?.copyWith(
color: const Color.fromRGBO(55, 65, 81, 1),
),
),
invalidStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const Color.fromRGBO(244, 68, 100, 1),
labelStyle: theme.textTheme.labelLarge?.copyWith(
color: const Color.fromRGBO(244, 68, 100, 1),
),
inputStyle: theme.textTheme.bodyMedium?.copyWith(
color: const Color.fromRGBO(55, 65, 81, 1),
),
),
disabledStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const Color.fromRGBO(229, 231, 235, 1),
labelStyle: theme.textTheme.labelLarge?.copyWith(
color: const Color.fromRGBO(156, 163, 175, 1),
),
inputStyle: theme.textTheme.bodyMedium?.copyWith(
color: const Color.fromRGBO(156, 163, 175, 1),
),
),
);
}
factory TextInputThemeExtensionImpl.dark({ThemeData? theme}) {
theme ??= ThemeData.dark();
return TextInputThemeExtensionImpl(
normalStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const Color.fromRGBO(96, 101, 106, 1),
labelStyle: theme.textTheme.labelLarge?.copyWith(
color: const Color.fromRGBO(204, 204, 204, 1),
),
inputStyle: theme.textTheme.bodyMedium?.copyWith(
color: const Color.fromRGBO(255, 255, 255, 1),
),
),
focusedStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const Color.fromRGBO(60, 125, 251, 1),
labelStyle: theme.textTheme.labelLarge?.copyWith(
color: const Color.fromRGBO(204, 204, 204, 1),
),
inputStyle: theme.textTheme.bodyMedium?.copyWith(
color: const Color.fromRGBO(255, 255, 255, 1),
),
),
invalidStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const Color.fromRGBO(244, 68, 100, 1),
labelStyle: theme.textTheme.labelLarge?.copyWith(
color: const Color.fromRGBO(244, 68, 100, 1),
),
inputStyle: theme.textTheme.bodyMedium?.copyWith(
color: const Color.fromRGBO(255, 255, 255, 1),
),
),
disabledStyle: TextInputStyle(
radius: BorderRadius.circular(12),
borderColors: const Color.fromRGBO(96, 101, 106, 1),
labelStyle: theme.textTheme.labelLarge?.copyWith(
color: const Color.fromRGBO(96, 101, 106, 1),
),
inputStyle: theme.textTheme.bodyMedium?.copyWith(
color: const Color.fromRGBO(255, 255, 255, 1),
),
),
);
}
}

View File

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

View File

@ -1,52 +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';
abstract class FileSelectionButtonThemeExtension
extends ThemeExtension<FileSelectionButtonThemeExtension> {
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;
}

View File

@ -1,44 +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';
abstract class FlatButtonThemeExtension
extends ThemeExtension<FlatButtonThemeExtension> {
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;
}

View File

@ -1,44 +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';
abstract class SimpleIconButtonThemeExtension
extends ThemeExtension<SimpleIconButtonThemeExtension> {
const SimpleIconButtonThemeExtension({
this.disabledStyle,
this.focusedStyle,
this.hoveredStyle,
this.normalStyle,
this.tappedStyle,
});
/// Style of this button in disabled state
final SimpleIconButtonStyle? disabledStyle;
/// Style of this button in focused state
final SimpleIconButtonStyle? focusedStyle;
/// Style of this button in hovered state
final SimpleIconButtonStyle? hoveredStyle;
/// Style of this button in normal state
final SimpleIconButtonStyle? normalStyle;
/// Style of this button in tapped state
final SimpleIconButtonStyle? tappedStyle;
}

View File

@ -1,48 +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';
abstract class SymbolButtonThemeExtension
extends ThemeExtension<SymbolButtonThemeExtension> {
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;
}

View File

@ -14,8 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export './button_theme_extension/button_theme_extension.dart';
export './card_theme_extension.dart';
export './loader_theme_extension.dart';
export './rich_text_builder_theme_extension.dart';
export './text_input_theme_extension.dart';

View File

@ -14,7 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export './components/components.dart';
export './core/core.dart';
export './domain/domain.dart';
export './features/wyatt_component_theme_data.dart';
export 'components/components.dart';
export 'core/core.dart';
export 'data/data.dart';
export 'domain/domain.dart';
export 'features/wyatt_component_theme_data.dart';

View File

@ -15,6 +15,8 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
/// UIKit and Design System used in Wyatt Studio.
///
/// Built using `wyatt_ui_components`.
library wyatt_ui_kit;
export 'package:wyatt_ui_components/src/core/extensions/build_context_extensions.dart';