ui/refactor/coherence-1 #187
@ -121,4 +121,11 @@ class TextWrapper {
 | 
			
		||||
  /// that, the selection color defaults to [DefaultSelectionStyle.defaultColor]
 | 
			
		||||
  /// (semi-transparent grey).
 | 
			
		||||
  final Color? selectionColor;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  String toString() => 'TextWrapper(data: $data, style: $style, '
 | 
			
		||||
      'gradientColors: $gradientColors, textAlign: $textAlign, '
 | 
			
		||||
      'textDirection: $textDirection, softWrap: $softWrap, '
 | 
			
		||||
      'overflow: $overflow, maxLines: $maxLines, '
 | 
			
		||||
      'selectionColor: $selectionColor)';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -40,8 +40,7 @@ class SymbolButtonThemeExtensionDefault extends SymbolButtonThemeExtension {
 | 
			
		||||
    final textColor = MultiColor.single(theme.textTheme.bodyMedium?.color);
 | 
			
		||||
 | 
			
		||||
    final style = SymbolButtonStyle(
 | 
			
		||||
      labelStyle:
 | 
			
		||||
          theme.textTheme.labelLarge?.copyWith(color: textColor.color),
 | 
			
		||||
      labelStyle: theme.textTheme.labelLarge?.copyWith(color: textColor.color),
 | 
			
		||||
      dimension: theme.buttonTheme.height * 1.5,
 | 
			
		||||
      radius: (theme.buttonTheme.shape is RoundedRectangleBorder)
 | 
			
		||||
          ? (theme.buttonTheme.shape as RoundedRectangleBorder).borderRadius
 | 
			
		||||
 | 
			
		||||
@ -17,5 +17,6 @@
 | 
			
		||||
export './card_component.dart';
 | 
			
		||||
export './information_card_component.dart';
 | 
			
		||||
export './portfolio_card_component.dart';
 | 
			
		||||
export './pricing_card_component.dart';
 | 
			
		||||
export './quote_card_component.dart';
 | 
			
		||||
export './skill_card_component.dart';
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,99 @@
 | 
			
		||||
// Copyright (C) 2023 WYATT GROUP
 | 
			
		||||
// Please see the AUTHORS file for details.
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
import 'package:flutter/widgets.dart';
 | 
			
		||||
import 'package:wyatt_component_copy_with_extension/wyatt_component_copy_with_extension.dart';
 | 
			
		||||
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
 | 
			
		||||
 | 
			
		||||
part 'pricing_card_component.g.dart';
 | 
			
		||||
 | 
			
		||||
class PricingLine {
 | 
			
		||||
  const PricingLine({
 | 
			
		||||
    required this.data,
 | 
			
		||||
    this.icon,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  final TextWrapper data;
 | 
			
		||||
  final Widget? icon;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  String toString() => 'PricingLine(data: $data, icon: $icon)';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Pricing {
 | 
			
		||||
  const Pricing({
 | 
			
		||||
    required this.price,
 | 
			
		||||
    this.period,
 | 
			
		||||
    this.hasAsterisk = false,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  final TextWrapper price;
 | 
			
		||||
  final TextWrapper? period;
 | 
			
		||||
 | 
			
		||||
  /// If [hasAsterisk] is true then the price will be displayed with
 | 
			
		||||
  /// an asterisk to emphasize that it is a special price.
 | 
			
		||||
  final bool hasAsterisk;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ComponentProxyExtension()
 | 
			
		||||
abstract class PricingCardComponent extends CardComponent
 | 
			
		||||
    with CopyWithMixin<$PricingCardComponentCWProxy> {
 | 
			
		||||
  const PricingCardComponent({
 | 
			
		||||
    this.axis,
 | 
			
		||||
    this.title,
 | 
			
		||||
    this.pricing,
 | 
			
		||||
    this.description,
 | 
			
		||||
    this.features,
 | 
			
		||||
    this.cta,
 | 
			
		||||
    super.radius,
 | 
			
		||||
    super.padding,
 | 
			
		||||
    super.borderColors,
 | 
			
		||||
    super.backgroundColors,
 | 
			
		||||
    super.stroke,
 | 
			
		||||
    super.minSize,
 | 
			
		||||
    super.maxSize,
 | 
			
		||||
    super.shadow,
 | 
			
		||||
    super.titleStyle,
 | 
			
		||||
    super.subtitleStyle,
 | 
			
		||||
    super.bodyStyle,
 | 
			
		||||
    super.background,
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  /// Axis of the card
 | 
			
		||||
  ///
 | 
			
		||||
  /// If [axis] is [Axis.horizontal] then only the first icon will be displayed.
 | 
			
		||||
  /// Used in header of the card.
 | 
			
		||||
  final Axis? axis;
 | 
			
		||||
 | 
			
		||||
  /// Title of the card
 | 
			
		||||
  ///
 | 
			
		||||
  /// If [axis] is [Axis.vertical] then icon of the title will be displayed
 | 
			
		||||
  /// above the title.
 | 
			
		||||
  final PricingLine? title;
 | 
			
		||||
 | 
			
		||||
  /// Pricing of the card
 | 
			
		||||
  final Pricing? pricing;
 | 
			
		||||
 | 
			
		||||
  /// Description of the card
 | 
			
		||||
  final TextWrapper? description;
 | 
			
		||||
 | 
			
		||||
  /// List of special features of the card
 | 
			
		||||
  final List<PricingLine>? features;
 | 
			
		||||
 | 
			
		||||
  /// CTA of the card
 | 
			
		||||
  final Widget? cta;
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,50 @@
 | 
			
		||||
// GENERATED CODE - DO NOT MODIFY BY HAND
 | 
			
		||||
 | 
			
		||||
part of 'pricing_card_component.dart';
 | 
			
		||||
 | 
			
		||||
// **************************************************************************
 | 
			
		||||
// ComponentProxyGenerator
 | 
			
		||||
// **************************************************************************
 | 
			
		||||
 | 
			
		||||
abstract class $PricingCardComponentCWProxy {
 | 
			
		||||
  PricingCardComponent axis(Axis? axis);
 | 
			
		||||
  PricingCardComponent title(PricingLine? title);
 | 
			
		||||
  PricingCardComponent pricing(Pricing? pricing);
 | 
			
		||||
  PricingCardComponent description(TextWrapper? description);
 | 
			
		||||
  PricingCardComponent features(List<PricingLine>? features);
 | 
			
		||||
  PricingCardComponent cta(Widget? cta);
 | 
			
		||||
  PricingCardComponent radius(BorderRadiusGeometry? radius);
 | 
			
		||||
  PricingCardComponent padding(EdgeInsetsGeometry? padding);
 | 
			
		||||
  PricingCardComponent borderColors(MultiColor? borderColors);
 | 
			
		||||
  PricingCardComponent backgroundColors(MultiColor? backgroundColors);
 | 
			
		||||
  PricingCardComponent stroke(double? stroke);
 | 
			
		||||
  PricingCardComponent minSize(Size? minSize);
 | 
			
		||||
  PricingCardComponent maxSize(Size? maxSize);
 | 
			
		||||
  PricingCardComponent shadow(BoxShadow? shadow);
 | 
			
		||||
  PricingCardComponent titleStyle(TextStyle? titleStyle);
 | 
			
		||||
  PricingCardComponent subtitleStyle(TextStyle? subtitleStyle);
 | 
			
		||||
  PricingCardComponent bodyStyle(TextStyle? bodyStyle);
 | 
			
		||||
  PricingCardComponent background(Widget? background);
 | 
			
		||||
  PricingCardComponent key(Key? key);
 | 
			
		||||
  PricingCardComponent call({
 | 
			
		||||
    Axis? axis,
 | 
			
		||||
    PricingLine? title,
 | 
			
		||||
    Pricing? pricing,
 | 
			
		||||
    TextWrapper? description,
 | 
			
		||||
    List<PricingLine>? features,
 | 
			
		||||
    Widget? cta,
 | 
			
		||||
    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,
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:gap/gap.dart';
 | 
			
		||||
import 'package:wyatt_ui_kit_example/cards/information_card/information_cards.dart';
 | 
			
		||||
import 'package:wyatt_ui_kit_example/cards/portfolio_card/portfolio_cards.dart';
 | 
			
		||||
import 'package:wyatt_ui_kit_example/cards/pricing_card/pricing_cards.dart';
 | 
			
		||||
import 'package:wyatt_ui_kit_example/cards/quote_card/quote_cards.dart';
 | 
			
		||||
import 'package:wyatt_ui_kit_example/cards/skill_card/skill_cards.dart';
 | 
			
		||||
import 'package:wyatt_ui_kit_example/demo_page.dart';
 | 
			
		||||
@ -24,6 +25,8 @@ class Cards extends DemoPage {
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
          const Gap(20),
 | 
			
		||||
          const PricingCards(),
 | 
			
		||||
          const Gap(20),
 | 
			
		||||
          const InformationCards(),
 | 
			
		||||
          const Gap(20),
 | 
			
		||||
          const PortfolioCards(),
 | 
			
		||||
 | 
			
		||||
@ -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:gap/gap.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 PricingCards extends StatelessWidget {
 | 
			
		||||
  const PricingCards({super.key});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) => Column(
 | 
			
		||||
        children: [
 | 
			
		||||
          Text(
 | 
			
		||||
            'Pricing Cards',
 | 
			
		||||
            style: Theme.of(context).textTheme.titleMedium,
 | 
			
		||||
          ),
 | 
			
		||||
          const Gap(20),
 | 
			
		||||
          Row(
 | 
			
		||||
            crossAxisAlignment: CrossAxisAlignment.start,
 | 
			
		||||
            mainAxisAlignment: MainAxisAlignment.center,
 | 
			
		||||
            children: [
 | 
			
		||||
              PricingCard(
 | 
			
		||||
                title: const PricingLine(
 | 
			
		||||
                  data: TextWrapper('Lorem Ipsum'),
 | 
			
		||||
                  icon: Icon(
 | 
			
		||||
                    Icons.ac_unit_rounded,
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
                pricing: const Pricing(
 | 
			
		||||
                  price: TextWrapper('450€'),
 | 
			
		||||
                  period: TextWrapper('/ jour'),
 | 
			
		||||
                  hasAsterisk: true,
 | 
			
		||||
                ),
 | 
			
		||||
                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 '),
 | 
			
		||||
                features: const [
 | 
			
		||||
                  PricingLine(
 | 
			
		||||
                    icon: Icon(
 | 
			
		||||
                      Icons.ac_unit_rounded,
 | 
			
		||||
                    ),
 | 
			
		||||
                    data: TextWrapper(
 | 
			
		||||
                      'Nulla labore aliquip dolor aliqua elit anim quis non officia laboris ad.',
 | 
			
		||||
                    ),
 | 
			
		||||
                  ),
 | 
			
		||||
                  PricingLine(
 | 
			
		||||
                    icon: Icon(
 | 
			
		||||
                      Icons.ac_unit_rounded,
 | 
			
		||||
                    ),
 | 
			
		||||
                    data: TextWrapper(
 | 
			
		||||
                      'Eu pariatur non et sint minim aute pariatur amet officia.',
 | 
			
		||||
                    ),
 | 
			
		||||
                  ),
 | 
			
		||||
                ],
 | 
			
		||||
                cta: context.components.flatButtonComponent.call(
 | 
			
		||||
                  label: const TextWrapper(
 | 
			
		||||
                    'Contactez-nous',
 | 
			
		||||
                    style: TextStyle(color: Colors.white),
 | 
			
		||||
                  ),
 | 
			
		||||
                  normalStyle: FlatButtonThemeExtensionImpl.dark(
 | 
			
		||||
                    theme: Theme.of(context),
 | 
			
		||||
                  ).normalStyle?.copyWith(
 | 
			
		||||
                        backgroundColors:
 | 
			
		||||
                            const MultiColor(Constants.blueBtnGradient),
 | 
			
		||||
                        borderColors:
 | 
			
		||||
                            const MultiColor(Constants.blueBtnGradient),
 | 
			
		||||
                      ),
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
              const Gap(20),
 | 
			
		||||
              PricingCard(
 | 
			
		||||
                title: const PricingLine(
 | 
			
		||||
                  data: TextWrapper('Lorem Ipsum'),
 | 
			
		||||
                  icon: Icon(
 | 
			
		||||
                    Icons.ac_unit_rounded,
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
                pricing: const Pricing(
 | 
			
		||||
                  price: TextWrapper('350€'),
 | 
			
		||||
                  period: TextWrapper('/ jour'),
 | 
			
		||||
                  hasAsterisk: true,
 | 
			
		||||
                ),
 | 
			
		||||
                features: const [
 | 
			
		||||
                  PricingLine(
 | 
			
		||||
                    icon: Icon(
 | 
			
		||||
                      Icons.ac_unit_rounded,
 | 
			
		||||
                    ),
 | 
			
		||||
                    data: TextWrapper(
 | 
			
		||||
                      'Nulla labore aliquip dolor aliqua elit anim quis non officia laboris ad.',
 | 
			
		||||
                    ),
 | 
			
		||||
                  ),
 | 
			
		||||
                  PricingLine(
 | 
			
		||||
                    icon: Icon(
 | 
			
		||||
                      Icons.ac_unit_rounded,
 | 
			
		||||
                    ),
 | 
			
		||||
                    data: TextWrapper(
 | 
			
		||||
                      'Eu pariatur non et sint minim aute pariatur amet officia.',
 | 
			
		||||
                    ),
 | 
			
		||||
                  ),
 | 
			
		||||
                  PricingLine(
 | 
			
		||||
                    icon: Icon(
 | 
			
		||||
                      Icons.ac_unit_rounded,
 | 
			
		||||
                    ),
 | 
			
		||||
                    data: TextWrapper(
 | 
			
		||||
                      'Nulla labore aliquip dolor aliqua elit anim quis non officia laboris ad.',
 | 
			
		||||
                    ),
 | 
			
		||||
                  ),
 | 
			
		||||
                ],
 | 
			
		||||
                cta: context.components.flatButtonComponent.call(
 | 
			
		||||
                  label: const TextWrapper(
 | 
			
		||||
                    'Contactez-nous',
 | 
			
		||||
                    style: TextStyle(color: Colors.white),
 | 
			
		||||
                  ),
 | 
			
		||||
                  normalStyle: FlatButtonThemeExtensionImpl.dark(
 | 
			
		||||
                    theme: Theme.of(context),
 | 
			
		||||
                  ).normalStyle?.copyWith(
 | 
			
		||||
                        backgroundColors:
 | 
			
		||||
                            const MultiColor(Constants.purpleGradient),
 | 
			
		||||
                        borderColors:
 | 
			
		||||
                            const MultiColor(Constants.purpleGradient),
 | 
			
		||||
                      ),
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
            ],
 | 
			
		||||
          ),
 | 
			
		||||
          const Gap(20),
 | 
			
		||||
        ],
 | 
			
		||||
      );
 | 
			
		||||
}
 | 
			
		||||
@ -25,6 +25,9 @@ abstract class Constants {
 | 
			
		||||
  static const blue3 = Color(0xFF1A84F7);
 | 
			
		||||
  static const blue4 = Color(0xFF1344E4);
 | 
			
		||||
 | 
			
		||||
  static const blue1Btn = Color(0xFF3C97FB);
 | 
			
		||||
  static const blue2Btn = Color(0xFF446DF4);
 | 
			
		||||
 | 
			
		||||
  static const grey1 = Color(0xFF60656A);
 | 
			
		||||
  static const grey2 = Color(0xFF383C40);
 | 
			
		||||
 | 
			
		||||
@ -37,10 +40,15 @@ abstract class Constants {
 | 
			
		||||
  static const red1 = Color(0xFFFB5E3C);
 | 
			
		||||
  static const red2 = Color(0xFFF44464);
 | 
			
		||||
 | 
			
		||||
  static const purple1 = Color(0xFFB79EFF);
 | 
			
		||||
  static const purple2 = Color(0xFF6865F2);
 | 
			
		||||
 | 
			
		||||
  static const blueGradient = [blue1, blue2];
 | 
			
		||||
  static const blueBtnGradient = [blue1Btn, blue2Btn];
 | 
			
		||||
  static const blueDarkGradient = [blue3, blue4];
 | 
			
		||||
  static const greyGradient = [grey1, grey2];
 | 
			
		||||
  static const greyDarkGradient = [grey3, grey4];
 | 
			
		||||
  static const greenGradient = [green1, green2];
 | 
			
		||||
  static const redGradient = [red1, red2];
 | 
			
		||||
  static const purpleGradient = [purple1, purple2];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -16,5 +16,6 @@
 | 
			
		||||
 | 
			
		||||
export './information_card/information_card.dart';
 | 
			
		||||
export './portfolio_card/portfolio_card.dart';
 | 
			
		||||
export './pricing_card/pricing_card.dart';
 | 
			
		||||
export './quote_card/quote_card.dart';
 | 
			
		||||
export './skill_card/skill_card.dart';
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,136 @@
 | 
			
		||||
// 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_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/pricing_card/widgets/pricing_card_features.dart';
 | 
			
		||||
import 'package:wyatt_ui_kit/src/components/cards/pricing_card/widgets/pricing_card_titles.dart';
 | 
			
		||||
import 'package:wyatt_ui_kit/src/components/cards/widgets/card_text.dart';
 | 
			
		||||
import 'package:wyatt_ui_kit/src/components/cards/widgets/card_wrapper.dart';
 | 
			
		||||
import 'package:wyatt_ui_kit/src/core/design_system/colors.dart';
 | 
			
		||||
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
 | 
			
		||||
 | 
			
		||||
part 'pricing_card.g.dart';
 | 
			
		||||
 | 
			
		||||
const _bodyTopSpacing = 25.0;
 | 
			
		||||
 | 
			
		||||
@ComponentCopyWithExtension()
 | 
			
		||||
class PricingCard extends PricingCardComponent with $PricingCardCWMixin {
 | 
			
		||||
  const PricingCard({
 | 
			
		||||
    super.axis,
 | 
			
		||||
    super.title,
 | 
			
		||||
    super.pricing,
 | 
			
		||||
    super.description,
 | 
			
		||||
    super.features,
 | 
			
		||||
    super.cta,
 | 
			
		||||
    super.radius,
 | 
			
		||||
    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) {
 | 
			
		||||
    final themeTitleStyle = ThemeHelper.maybeGetElement<TextStyle, TextStyle>(
 | 
			
		||||
      [
 | 
			
		||||
        titleStyle,
 | 
			
		||||
        Theme.of(context).extension<CardThemeExtension>()?.titleStyle,
 | 
			
		||||
        CardThemeExtensionDefault.from(Theme.of(context)).titleStyle,
 | 
			
		||||
      ],
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    final themePricingStyle = ThemeHelper.maybeGetElement<TextStyle, TextStyle>(
 | 
			
		||||
      [
 | 
			
		||||
        pricing?.price.style,
 | 
			
		||||
        context.textTheme.bodyMedium
 | 
			
		||||
            ?.copyWith(fontSize: 50, fontWeight: FontWeight.bold),
 | 
			
		||||
      ],
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    final themePeriodStyle = ThemeHelper.maybeGetElement<TextStyle, TextStyle>(
 | 
			
		||||
      [
 | 
			
		||||
        subtitleStyle,
 | 
			
		||||
        context.textTheme.bodyMedium?.copyWith(
 | 
			
		||||
          fontSize: 20,
 | 
			
		||||
          fontWeight: FontWeight.w600,
 | 
			
		||||
          color: WyattColors.gray1,
 | 
			
		||||
        ),
 | 
			
		||||
      ],
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    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: [
 | 
			
		||||
          PricingCardTitles(
 | 
			
		||||
            axis: axis,
 | 
			
		||||
            title: title,
 | 
			
		||||
            pricing: pricing,
 | 
			
		||||
            titleStyle: themeTitleStyle,
 | 
			
		||||
            pricingStyle: themePricingStyle,
 | 
			
		||||
            periodStyle: themePeriodStyle,
 | 
			
		||||
          ),
 | 
			
		||||
          const Gap(_bodyTopSpacing),
 | 
			
		||||
          if (description != null) ...[
 | 
			
		||||
            CardText.fromWrapper(
 | 
			
		||||
              description!,
 | 
			
		||||
              style: themeBodyStyle,
 | 
			
		||||
            ),
 | 
			
		||||
            const Gap(_bodyTopSpacing),
 | 
			
		||||
          ],
 | 
			
		||||
          if (features != null) ...[
 | 
			
		||||
            PricingCardFeatures(
 | 
			
		||||
              features: features,
 | 
			
		||||
              bodyStyle: themeBodyStyle,
 | 
			
		||||
            ),
 | 
			
		||||
            const Gap(_bodyTopSpacing),
 | 
			
		||||
          ],
 | 
			
		||||
          if (cta != null) ...[
 | 
			
		||||
            SelectionContainer.disabled(child: cta!),
 | 
			
		||||
          ],
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,102 @@
 | 
			
		||||
// GENERATED CODE - DO NOT MODIFY BY HAND
 | 
			
		||||
 | 
			
		||||
part of 'pricing_card.dart';
 | 
			
		||||
 | 
			
		||||
// **************************************************************************
 | 
			
		||||
// ComponentCopyWithGenerator
 | 
			
		||||
// **************************************************************************
 | 
			
		||||
 | 
			
		||||
class $PricingCardCWProxyImpl implements $PricingCardComponentCWProxy {
 | 
			
		||||
  const $PricingCardCWProxyImpl(this._value);
 | 
			
		||||
  final PricingCard _value;
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard axis(Axis? axis) => this(axis: axis);
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard title(PricingLine? title) => this(title: title);
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard pricing(Pricing? pricing) => this(pricing: pricing);
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard description(TextWrapper? description) =>
 | 
			
		||||
      this(description: description);
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard features(List<PricingLine>? features) => this(features: features);
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard cta(Widget? cta) => this(cta: cta);
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard radius(BorderRadiusGeometry? radius) => this(radius: radius);
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard padding(EdgeInsetsGeometry? padding) => this(padding: padding);
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard borderColors(MultiColor? borderColors) =>
 | 
			
		||||
      this(borderColors: borderColors);
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard backgroundColors(MultiColor? backgroundColors) =>
 | 
			
		||||
      this(backgroundColors: backgroundColors);
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard stroke(double? stroke) => this(stroke: stroke);
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard minSize(Size? minSize) => this(minSize: minSize);
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard maxSize(Size? maxSize) => this(maxSize: maxSize);
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard shadow(BoxShadow? shadow) => this(shadow: shadow);
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard titleStyle(TextStyle? titleStyle) => this(titleStyle: titleStyle);
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard subtitleStyle(TextStyle? subtitleStyle) =>
 | 
			
		||||
      this(subtitleStyle: subtitleStyle);
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard bodyStyle(TextStyle? bodyStyle) => this(bodyStyle: bodyStyle);
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard background(Widget? background) => this(background: background);
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard key(Key? key) => this(key: key);
 | 
			
		||||
  @override
 | 
			
		||||
  PricingCard call({
 | 
			
		||||
    Axis? axis,
 | 
			
		||||
    PricingLine? title,
 | 
			
		||||
    Pricing? pricing,
 | 
			
		||||
    TextWrapper? description,
 | 
			
		||||
    List<PricingLine>? features,
 | 
			
		||||
    Widget? cta,
 | 
			
		||||
    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,
 | 
			
		||||
  }) =>
 | 
			
		||||
      PricingCard(
 | 
			
		||||
        axis: axis ?? _value.axis,
 | 
			
		||||
        title: title ?? _value.title,
 | 
			
		||||
        pricing: pricing ?? _value.pricing,
 | 
			
		||||
        description: description ?? _value.description,
 | 
			
		||||
        features: features ?? _value.features,
 | 
			
		||||
        cta: cta ?? _value.cta,
 | 
			
		||||
        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,
 | 
			
		||||
      );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
mixin $PricingCardCWMixin on Component {
 | 
			
		||||
  $PricingCardComponentCWProxy get copyWith =>
 | 
			
		||||
      $PricingCardCWProxyImpl(this as PricingCard);
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,61 @@
 | 
			
		||||
// 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 PricingCardFeatures extends StatelessWidget {
 | 
			
		||||
  const PricingCardFeatures({
 | 
			
		||||
    super.key,
 | 
			
		||||
    this.features,
 | 
			
		||||
    this.bodyStyle,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  /// List of special features of the card
 | 
			
		||||
  final List<PricingLine>? features;
 | 
			
		||||
 | 
			
		||||
  /// Body style of the card.
 | 
			
		||||
  final TextStyle? bodyStyle;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) => Column(
 | 
			
		||||
        children: features!
 | 
			
		||||
            .map(
 | 
			
		||||
              (feature) => Padding(
 | 
			
		||||
                padding: EdgeInsets.only(
 | 
			
		||||
                  top: features?.indexOf(feature) == 0 ? 0 : 10,
 | 
			
		||||
                ),
 | 
			
		||||
                child: Row(
 | 
			
		||||
                  children: [
 | 
			
		||||
                    if (feature.icon != null) ...[
 | 
			
		||||
                      feature.icon!,
 | 
			
		||||
                    ],
 | 
			
		||||
                    const Gap(10),
 | 
			
		||||
                    Expanded(
 | 
			
		||||
                      child: CardText.fromWrapper(
 | 
			
		||||
                        feature.data,
 | 
			
		||||
                        style: bodyStyle,
 | 
			
		||||
                      ),
 | 
			
		||||
                    ),
 | 
			
		||||
                  ],
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
            )
 | 
			
		||||
            .toList(),
 | 
			
		||||
      );
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,139 @@
 | 
			
		||||
// Copyright (C) 2023 WYATT GROUP
 | 
			
		||||
// Please see the AUTHORS file for details.
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:gap/gap.dart';
 | 
			
		||||
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
 | 
			
		||||
import 'package:wyatt_ui_kit/src/components/cards/widgets/card_text.dart';
 | 
			
		||||
 | 
			
		||||
const _titlesLineSpacing = 5.0;
 | 
			
		||||
const _bodyTopSpacing = 25.0;
 | 
			
		||||
 | 
			
		||||
class PricingCardTitles extends StatelessWidget {
 | 
			
		||||
  const PricingCardTitles({
 | 
			
		||||
    this.axis,
 | 
			
		||||
    this.title,
 | 
			
		||||
    this.pricing,
 | 
			
		||||
    this.titleStyle,
 | 
			
		||||
    this.pricingStyle,
 | 
			
		||||
    this.periodStyle,
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  /// The axis of the card header.
 | 
			
		||||
  final Axis? axis;
 | 
			
		||||
 | 
			
		||||
  /// Title of the card
 | 
			
		||||
  ///
 | 
			
		||||
  /// If [axis] is [Axis.vertical] then icon of the title will be displayed
 | 
			
		||||
  /// above the title.
 | 
			
		||||
  final PricingLine? title;
 | 
			
		||||
 | 
			
		||||
  /// Pricing of the card
 | 
			
		||||
  final Pricing? pricing;
 | 
			
		||||
 | 
			
		||||
  /// Styles the title of the card.
 | 
			
		||||
  final TextStyle? titleStyle;
 | 
			
		||||
 | 
			
		||||
  /// Styles the pricing of the card.
 | 
			
		||||
  final TextStyle? pricingStyle;
 | 
			
		||||
 | 
			
		||||
  /// Styles the period of the card.
 | 
			
		||||
  final TextStyle? periodStyle;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    final price = (pricing != null)
 | 
			
		||||
        ? CardText.fromWrapper(
 | 
			
		||||
            pricing!.price,
 | 
			
		||||
            style: pricingStyle,
 | 
			
		||||
            textType: TextType.title,
 | 
			
		||||
          )
 | 
			
		||||
        : null;
 | 
			
		||||
 | 
			
		||||
    final period = ((pricing != null) && (pricing?.period != null))
 | 
			
		||||
        ? CardText.fromWrapper(
 | 
			
		||||
            pricing!.period!,
 | 
			
		||||
            style: periodStyle,
 | 
			
		||||
            textType: TextType.subtitle,
 | 
			
		||||
          )
 | 
			
		||||
        : null;
 | 
			
		||||
 | 
			
		||||
    return Column(
 | 
			
		||||
      children: [
 | 
			
		||||
        if (title != null) ...[
 | 
			
		||||
          if (axis == Axis.vertical) ...[
 | 
			
		||||
            if (title?.icon != null) ...[
 | 
			
		||||
              title!.icon!,
 | 
			
		||||
              const Gap(_titlesLineSpacing),
 | 
			
		||||
            ],
 | 
			
		||||
            CardText.fromWrapper(
 | 
			
		||||
              title!.data,
 | 
			
		||||
              style: titleStyle,
 | 
			
		||||
              textType: TextType.title,
 | 
			
		||||
            ),
 | 
			
		||||
            const Gap(_bodyTopSpacing),
 | 
			
		||||
          ] else ...[
 | 
			
		||||
            Row(
 | 
			
		||||
              mainAxisAlignment: MainAxisAlignment.center,
 | 
			
		||||
              children: [
 | 
			
		||||
                if (title?.icon != null) ...[
 | 
			
		||||
                  title!.icon!,
 | 
			
		||||
                  const Gap(_titlesLineSpacing),
 | 
			
		||||
                ],
 | 
			
		||||
                CardText.fromWrapper(
 | 
			
		||||
                  title!.data,
 | 
			
		||||
                  style: titleStyle,
 | 
			
		||||
                  textType: TextType.title,
 | 
			
		||||
                ),
 | 
			
		||||
              ],
 | 
			
		||||
            ),
 | 
			
		||||
            const Gap(_bodyTopSpacing),
 | 
			
		||||
          ]
 | 
			
		||||
        ],
 | 
			
		||||
        RichText(
 | 
			
		||||
          text: TextSpan(
 | 
			
		||||
            children: [
 | 
			
		||||
              if (price != null) ...[
 | 
			
		||||
                TextSpan(
 | 
			
		||||
                  text: price.text.data,
 | 
			
		||||
                  style: price.text.style,
 | 
			
		||||
                )
 | 
			
		||||
              ],
 | 
			
		||||
              if (pricing?.hasAsterisk ?? false) ...[
 | 
			
		||||
                WidgetSpan(
 | 
			
		||||
                  child: Transform.translate(
 | 
			
		||||
                    offset: const Offset(5, -15),
 | 
			
		||||
                    child: const Text(
 | 
			
		||||
                      '*  ',
 | 
			
		||||
                      style: TextStyle(fontSize: 18),
 | 
			
		||||
                    ),
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
              ],
 | 
			
		||||
              if (period != null) ...[
 | 
			
		||||
                TextSpan(
 | 
			
		||||
                  text: period.text.data,
 | 
			
		||||
                  style: period.text.style,
 | 
			
		||||
                )
 | 
			
		||||
              ],
 | 
			
		||||
            ],
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
      ],
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -50,7 +50,10 @@ class CardThemeExtensionImpl extends CardThemeExtension {
 | 
			
		||||
      stroke: 1,
 | 
			
		||||
      backgroundColors: const MultiColor.single(WyattColors.light),
 | 
			
		||||
      borderColors: WyattColors.lightGradient,
 | 
			
		||||
      titleStyle: theme.textTheme.titleLarge,
 | 
			
		||||
      titleStyle: theme.textTheme.titleLarge?.copyWith(
 | 
			
		||||
        fontSize: 26,
 | 
			
		||||
        fontWeight: FontWeight.w600,
 | 
			
		||||
      ),
 | 
			
		||||
      subtitleStyle: theme.textTheme.titleMedium,
 | 
			
		||||
      bodyStyle: theme.textTheme.bodyMedium?.copyWith(
 | 
			
		||||
        height: 1.5,
 | 
			
		||||
@ -76,7 +79,10 @@ class CardThemeExtensionImpl extends CardThemeExtension {
 | 
			
		||||
      stroke: 1,
 | 
			
		||||
      backgroundColors: WyattColors.grayBgOpacityGradient,
 | 
			
		||||
      borderColors: WyattColors.grayGradient,
 | 
			
		||||
      titleStyle: theme.textTheme.titleLarge,
 | 
			
		||||
      titleStyle: theme.textTheme.titleLarge?.copyWith(
 | 
			
		||||
        fontSize: 26,
 | 
			
		||||
        fontWeight: FontWeight.w600,
 | 
			
		||||
      ),
 | 
			
		||||
      subtitleStyle: theme.textTheme.titleMedium,
 | 
			
		||||
      bodyStyle: theme.textTheme.bodyMedium?.copyWith(
 | 
			
		||||
        height: 1.5,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user