master #81
| @ -16,28 +16,17 @@ | |||||||
| 
 | 
 | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:gap/gap.dart'; | import 'package:gap/gap.dart'; | ||||||
| import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; | import 'package:wyatt_ui_kit_example/buttons/file_selection_button/file_selection_buttons.dart'; | ||||||
| import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; | import 'package:wyatt_ui_kit_example/buttons/flat_button/flat_buttons.dart'; | ||||||
| 
 | import 'package:wyatt_ui_kit_example/buttons/simple_icon_button/simple_icon_buttons.dart'; | ||||||
| const _color1 = Color(0xFF3C97FB); | import 'package:wyatt_ui_kit_example/buttons/symbol_button/symbol_buttons.dart'; | ||||||
| const _color2 = Color(0xFF446DF4); |  | ||||||
| const _color3 = Color.fromARGB(255, 26, 132, 247); |  | ||||||
| const _color4 = Color.fromARGB(255, 19, 68, 228); |  | ||||||
| const _colors = [_color1, _color2]; |  | ||||||
| const _colorsDarken = [_color3, _color4]; |  | ||||||
| const _disabled = Color(0xFF6B7280); |  | ||||||
| const _background = Color(0xFF16191D); |  | ||||||
| const _disabledBackground = Color(0xFF16191D + 0x66FFFFFF); |  | ||||||
| const _disabledColors = [Color(0xFF60656A), Color(0xFF383C40)]; |  | ||||||
| const _selectedColors = [Color(0xFF50CE99), Color(0xFF339572)]; |  | ||||||
| const _invalidColor = Color(0xFFFB5E3C); |  | ||||||
| 
 | 
 | ||||||
| class Buttons extends StatelessWidget { | class Buttons extends StatelessWidget { | ||||||
|   const Buttons({super.key}); |   const Buttons({super.key}); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) => ListView( |   Widget build(BuildContext context) => ListView( | ||||||
|         cacheExtent: 2000, |         cacheExtent: 1000, | ||||||
|         children: [ |         children: [ | ||||||
|           const Gap(20), |           const Gap(20), | ||||||
|           Align( |           Align( | ||||||
| @ -47,337 +36,19 @@ class Buttons extends StatelessWidget { | |||||||
|             ), |             ), | ||||||
|           ), |           ), | ||||||
|           const Gap(20), |           const Gap(20), | ||||||
|           Center( |  | ||||||
|             child: FlatButton( |  | ||||||
|               label: const TextWrapper('Voir notre savoir faire'), |  | ||||||
|               normalStyle: const FlatButtonStyle( |  | ||||||
|                 foregroundColors: MultiColor(_colors), |  | ||||||
|                 backgroundColors: MultiColor.single(Colors.transparent), |  | ||||||
|                 borderColors: MultiColor(_colors), |  | ||||||
|                 stroke: 3, |  | ||||||
|               ), |  | ||||||
|               hoveredStyle: const FlatButtonStyle( |  | ||||||
|                 foregroundColors: MultiColor.single(Colors.white), |  | ||||||
|                 backgroundColors: MultiColor(_colors), |  | ||||||
|                 borderColors: MultiColor(_colors), |  | ||||||
|                 stroke: 3, |  | ||||||
|               ), |  | ||||||
|               tappedStyle: const FlatButtonStyle( |  | ||||||
|                 foregroundColors: MultiColor.single(Colors.white), |  | ||||||
|                 backgroundColors: MultiColor(_colorsDarken), |  | ||||||
|                 borderColors: MultiColor(_colorsDarken), |  | ||||||
|                 stroke: 3, |  | ||||||
|               ), |  | ||||||
|               prefix: const Icon( |  | ||||||
|                 Icons.arrow_forward_rounded, |  | ||||||
|               ), |  | ||||||
|               suffix: const Icon( |  | ||||||
|                 Icons.arrow_forward_rounded, |  | ||||||
|               ), |  | ||||||
|             ), |  | ||||||
|           ), |  | ||||||
|           const Gap(20), |  | ||||||
|           FlatButton( |  | ||||||
|             label: TextWrapper( |  | ||||||
|               'Voir notre savoir faire', |  | ||||||
|               style: |  | ||||||
|                   context.textTheme.titleLarge?.copyWith(color: Colors.white), |  | ||||||
|             ), |  | ||||||
|             normalStyle: const FlatButtonStyle( |  | ||||||
|               backgroundColors: MultiColor(_colors), |  | ||||||
|             ), |  | ||||||
|             prefix: const Icon( |  | ||||||
|               Icons.arrow_forward_rounded, |  | ||||||
|               color: Colors.white, |  | ||||||
|             ), |  | ||||||
|             suffix: const Icon( |  | ||||||
|               Icons.arrow_forward_rounded, |  | ||||||
|               color: Colors.white, |  | ||||||
|             ), |  | ||||||
|           ), |  | ||||||
|           const Gap(20), |  | ||||||
|           ColoredBox( |  | ||||||
|             color: _background, |  | ||||||
|             child: Center( |  | ||||||
|               child: Row( |  | ||||||
|                 mainAxisAlignment: MainAxisAlignment.center, |  | ||||||
|                 children: [ |  | ||||||
|                   Column( |  | ||||||
|                     children: [ |  | ||||||
|                       const Gap(20), |  | ||||||
|                       FlatButton( |  | ||||||
|                         label: TextWrapper( |  | ||||||
|                           'Démarrer mon projet', |  | ||||||
|                           style: context.textTheme.titleLarge |  | ||||||
|                               ?.copyWith(color: _disabled), |  | ||||||
|                         ), |  | ||||||
|                         normalStyle: const FlatButtonStyle( |  | ||||||
|                           borderColors: MultiColor(_disabledColors), |  | ||||||
|                           backgroundColors: |  | ||||||
|                               MultiColor.single(_disabledBackground), |  | ||||||
|                           stroke: 1, |  | ||||||
|                         ), |  | ||||||
|                       ), |  | ||||||
|                       const Gap(20), |  | ||||||
|                       FlatButton( |  | ||||||
|                         label: TextWrapper( |  | ||||||
|                           'Démarrer mon projet', |  | ||||||
|                           style: context.textTheme.titleLarge |  | ||||||
|                               ?.copyWith(color: Colors.white), |  | ||||||
|                         ), |  | ||||||
|                         normalStyle: const FlatButtonStyle( |  | ||||||
|                           backgroundColors: MultiColor(_colors), |  | ||||||
|                         ), |  | ||||||
|                       ), |  | ||||||
|                       const Gap(20), |  | ||||||
|                     ], |  | ||||||
|                   ), |  | ||||||
|                   const Gap(20), |  | ||||||
|                   Column( |  | ||||||
|                     children: [ |  | ||||||
|                       const Gap(20), |  | ||||||
|                       FlatButton( |  | ||||||
|                         label: TextWrapper( |  | ||||||
|                           'Aller voir nos réalisations', |  | ||||||
|                           style: context.textTheme.titleLarge |  | ||||||
|                               ?.copyWith(color: Colors.white), |  | ||||||
|                         ), |  | ||||||
|                         normalStyle: const FlatButtonStyle( |  | ||||||
|                           borderColors: MultiColor(_colors), |  | ||||||
|                           backgroundColors: |  | ||||||
|                               MultiColor.single(_disabledBackground), |  | ||||||
|                           stroke: 3, |  | ||||||
|                         ), |  | ||||||
|                         suffix: const Icon( |  | ||||||
|                           Icons.arrow_forward_rounded, |  | ||||||
|                           color: Colors.white, |  | ||||||
|                         ), |  | ||||||
|                       ), |  | ||||||
|                       const Gap(20), |  | ||||||
|                       FlatButton( |  | ||||||
|                         label: TextWrapper( |  | ||||||
|                           'Aller voir nos réalisations', |  | ||||||
|                           style: context.textTheme.titleLarge |  | ||||||
|                               ?.copyWith(color: Colors.white), |  | ||||||
|                         ), |  | ||||||
|                         normalStyle: const FlatButtonStyle( |  | ||||||
|                           backgroundColors: MultiColor(_colors), |  | ||||||
|                         ), |  | ||||||
|                         suffix: const Icon( |  | ||||||
|                           Icons.arrow_forward_rounded, |  | ||||||
|                           color: Colors.white, |  | ||||||
|                         ), |  | ||||||
|                       ), |  | ||||||
|                       const Gap(20), |  | ||||||
|                     ], |  | ||||||
|                   ), |  | ||||||
|                 ], |  | ||||||
|               ), |  | ||||||
|             ), |  | ||||||
|           ), |  | ||||||
|           const Gap(20), |  | ||||||
|           FlatButton( |  | ||||||
|             label: TextWrapper( |  | ||||||
|               'Démarrer mon projet', |  | ||||||
|               style: |  | ||||||
|                   context.textTheme.titleLarge?.copyWith(color: Colors.white), |  | ||||||
|             ), |  | ||||||
|             disabledStyle: const FlatButtonStyle( |  | ||||||
|               backgroundColors: MultiColor.single(Colors.blue), |  | ||||||
|             ), |  | ||||||
|             normalStyle: const FlatButtonStyle( |  | ||||||
|               backgroundColors: MultiColor(_colors), |  | ||||||
|             ), |  | ||||||
|             hoveredStyle: const FlatButtonStyle( |  | ||||||
|               backgroundColors: MultiColor.single(Colors.green), |  | ||||||
|             ), |  | ||||||
|             focusedStyle: const FlatButtonStyle( |  | ||||||
|               backgroundColors: MultiColor.single(Colors.yellow), |  | ||||||
|             ), |  | ||||||
|             tappedStyle: const FlatButtonStyle( |  | ||||||
|               backgroundColors: MultiColor.single(Colors.red), |  | ||||||
|             ), |  | ||||||
|           ), |  | ||||||
|           const Gap(20), |  | ||||||
|           ColoredBox( |  | ||||||
|             color: _background, |  | ||||||
|             child: Center( |  | ||||||
|               child: Row( |  | ||||||
|                 mainAxisAlignment: MainAxisAlignment.center, |  | ||||||
|                 children: [ |  | ||||||
|                   Column( |  | ||||||
|                     children: [ |  | ||||||
|                       const Gap(20), |  | ||||||
|                       SymbolButton( |  | ||||||
|                         icon: const Icon( |  | ||||||
|                           Icons.android, |  | ||||||
|                           size: 25, |  | ||||||
|                         ), |  | ||||||
|                         label: const TextWrapper('Texte'), |  | ||||||
|                         normalStyle: const SymbolButtonStyle( |  | ||||||
|                           borderColors: MultiColor(_disabledColors), |  | ||||||
|                           foregroundColors: MultiColor.single(Colors.white), |  | ||||||
|                           backgroundColors: |  | ||||||
|                               MultiColor.single(_disabledBackground), |  | ||||||
|                           stroke: 1, |  | ||||||
|                         ), |  | ||||||
|                         hoveredStyle: const SymbolButtonStyle( |  | ||||||
|                           borderColors: MultiColor(_disabledColors), |  | ||||||
|                           foregroundColors: MultiColor.single(Colors.white), |  | ||||||
|                           backgroundColors: MultiColor.single(_background), |  | ||||||
|                           stroke: 1, |  | ||||||
|                         ), |  | ||||||
|                         selectedStyle: const SymbolButtonStyle( |  | ||||||
|                           borderColors: MultiColor(_selectedColors), |  | ||||||
|                           foregroundColors: MultiColor.single(Colors.white), |  | ||||||
|                           backgroundColors: |  | ||||||
|                               MultiColor.single(_disabledBackground), |  | ||||||
|                           stroke: 1, |  | ||||||
|                         ), |  | ||||||
|                       ) |  | ||||||
|                         ..bloc.onClickUpIn() |  | ||||||
|                         ..bloc.freeze(), |  | ||||||
|                       const Gap(20), |  | ||||||
|                       SymbolButton( |  | ||||||
|                         icon: const Icon( |  | ||||||
|                           Icons.android, |  | ||||||
|                           size: 25, |  | ||||||
|                         ), |  | ||||||
|                         label: const TextWrapper('Texte'), |  | ||||||
|                         normalStyle: const SymbolButtonStyle( |  | ||||||
|                           borderColors: MultiColor(_disabledColors), |  | ||||||
|                           foregroundColors: MultiColor.single(Colors.white), |  | ||||||
|                           backgroundColors: |  | ||||||
|                               MultiColor.single(_disabledBackground), |  | ||||||
|                           stroke: 1, |  | ||||||
|                         ), |  | ||||||
|                         hoveredStyle: const SymbolButtonStyle( |  | ||||||
|                           borderColors: MultiColor(_disabledColors), |  | ||||||
|                           foregroundColors: MultiColor.single(Colors.white), |  | ||||||
|                           backgroundColors: MultiColor.single(_background), |  | ||||||
|                           stroke: 1, |  | ||||||
|                         ), |  | ||||||
|                         selectedStyle: const SymbolButtonStyle( |  | ||||||
|                           borderColors: MultiColor(_selectedColors), |  | ||||||
|                           foregroundColors: MultiColor.single(Colors.white), |  | ||||||
|                           backgroundColors: |  | ||||||
|                               MultiColor.single(_disabledBackground), |  | ||||||
|                           stroke: 1, |  | ||||||
|                         ), |  | ||||||
|                       )..bloc.freeze(), |  | ||||||
|                       const Gap(20), |  | ||||||
|                     ], |  | ||||||
|                   ), |  | ||||||
|                   const Gap(20), |  | ||||||
|           Row( |           Row( | ||||||
|                     children: [ |             mainAxisAlignment: MainAxisAlignment.center, | ||||||
|                       SimpleIconButton( |             crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|                         icon: const Icon( |             children: const [ | ||||||
|                           Icons.storm_outlined, |               FlatButtons(), | ||||||
|                           size: 17, |               Gap(20), | ||||||
|                         ), |               SymbolButtons(), | ||||||
|                         normalStyle: const SimpleIconButtonStyle( |               Gap(20), | ||||||
|                           backgroundColors: MultiColor.single(_disabled), |               SimpleIconButtons(), | ||||||
|                         ), |  | ||||||
|                         hoveredStyle: SimpleIconButtonStyle( |  | ||||||
|                           backgroundColors: |  | ||||||
|                               MultiColor.single(_disabledColors.last), |  | ||||||
|                         ), |  | ||||||
|                       ), |  | ||||||
|                       const Gap(10), |  | ||||||
|                       SimpleIconButton( |  | ||||||
|                         icon: const Icon( |  | ||||||
|                           Icons.sunny, |  | ||||||
|                           size: 17, |  | ||||||
|                         ), |  | ||||||
|                         normalStyle: const SimpleIconButtonStyle( |  | ||||||
|                           backgroundColors: MultiColor.single(_disabled), |  | ||||||
|                         ), |  | ||||||
|                         hoveredStyle: SimpleIconButtonStyle( |  | ||||||
|                           backgroundColors: |  | ||||||
|                               MultiColor.single(_disabledColors.last), |  | ||||||
|                         ), |  | ||||||
|                       ), |  | ||||||
|                       const Gap(10), |  | ||||||
|                       SimpleIconButton( |  | ||||||
|                         icon: const Icon( |  | ||||||
|                           Icons.wechat, |  | ||||||
|                           size: 17, |  | ||||||
|                         ), |  | ||||||
|                         normalStyle: const SimpleIconButtonStyle( |  | ||||||
|                           backgroundColors: MultiColor.single(_disabled), |  | ||||||
|                         ), |  | ||||||
|                         hoveredStyle: SimpleIconButtonStyle( |  | ||||||
|                           backgroundColors: |  | ||||||
|                               MultiColor.single(_disabledColors.last), |  | ||||||
|                         ), |  | ||||||
|                       ) |  | ||||||
|             ], |             ], | ||||||
|           ), |           ), | ||||||
|           const Gap(20), |           const Gap(20), | ||||||
|                   Row( |           const Align(child: FileSelectionButtons()), | ||||||
|                     children: [ |  | ||||||
|                       SymbolButton( |  | ||||||
|                         icon: const FlutterLogo( |  | ||||||
|                           size: 50, |  | ||||||
|                         ), |  | ||||||
|                         normalStyle: const SymbolButtonStyle( |  | ||||||
|                           dimension: 73, |  | ||||||
|                           backgroundColors: MultiColor.single(Colors.white), |  | ||||||
|                         ), |  | ||||||
|                         hoveredStyle: SymbolButtonStyle( |  | ||||||
|                           dimension: 73, |  | ||||||
|                           backgroundColors: MultiColor.single(Colors.grey[300]), |  | ||||||
|                         ), |  | ||||||
|                       ), |  | ||||||
|                     ], |  | ||||||
|                   ), |  | ||||||
|                   const Gap(20), |  | ||||||
|                   FileSelectionButton( |  | ||||||
|                     leading: const DecoratedBox( |  | ||||||
|                       decoration: BoxDecoration( |  | ||||||
|                         color: _disabled, |  | ||||||
|                         borderRadius: BorderRadius.all( |  | ||||||
|                           Radius.circular(5), |  | ||||||
|                         ), |  | ||||||
|                       ), |  | ||||||
|                       child: Padding( |  | ||||||
|                         padding: EdgeInsets.all(8), |  | ||||||
|                         child: Icon( |  | ||||||
|                           Icons.file_upload_outlined, |  | ||||||
|                           color: Colors.white, |  | ||||||
|                         ), |  | ||||||
|                       ), |  | ||||||
|                     ), |  | ||||||
|                     title: TextWrapper( |  | ||||||
|                       'Ajouter un fichier', |  | ||||||
|                       style: Theme.of(context) |  | ||||||
|                           .textTheme |  | ||||||
|                           .titleLarge |  | ||||||
|                           ?.copyWith(color: _disabled), |  | ||||||
|                     ), |  | ||||||
|                     subTitle: TextWrapper.text('Taille max: 20 Mo'), |  | ||||||
|                     normalStyle: const FileSelectionButtonStyle( |  | ||||||
|                       backgroundColors: MultiColor.single(_disabledBackground), |  | ||||||
|                       foregroundColors: MultiColor.single(_disabled), |  | ||||||
|                       borderColors: MultiColor.single(_disabled), |  | ||||||
|                     ), |  | ||||||
|                     hoveredStyle: const FileSelectionButtonStyle( |  | ||||||
|                       backgroundColors: MultiColor.single(_disabledBackground), |  | ||||||
|                       foregroundColors: MultiColor.single(_disabled), |  | ||||||
|                       borderColors: MultiColor.single(Colors.white), |  | ||||||
|                     ), |  | ||||||
|                     invalidStyle: const FileSelectionButtonStyle( |  | ||||||
|                       backgroundColors: MultiColor.single(_disabledBackground), |  | ||||||
|                       foregroundColors: MultiColor.single(_invalidColor), |  | ||||||
|                       borderColors: MultiColor.single(_invalidColor), |  | ||||||
|                     ), |  | ||||||
|                   ) |  | ||||||
|                 ], |  | ||||||
|               ), |  | ||||||
|             ), |  | ||||||
|           ), |  | ||||||
|           const Gap(20), |  | ||||||
|         ], |         ], | ||||||
|       ); |       ); | ||||||
| } | } | ||||||
|  | |||||||
| @ -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:gap/gap.dart'; | ||||||
|  | import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; | ||||||
|  | import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; | ||||||
|  | import 'package:wyatt_ui_kit_example/theme/constants.dart'; | ||||||
|  | 
 | ||||||
|  | class FileSelectionButtons extends StatelessWidget { | ||||||
|  |   const FileSelectionButtons({super.key}); | ||||||
|  | 
 | ||||||
|  |   Widget _leading() => const DecoratedBox( | ||||||
|  |         decoration: BoxDecoration( | ||||||
|  |           color: Constants.grey3, | ||||||
|  |           borderRadius: BorderRadius.all( | ||||||
|  |             Radius.circular(5), | ||||||
|  |           ), | ||||||
|  |         ), | ||||||
|  |         child: Padding( | ||||||
|  |           padding: EdgeInsets.all(8), | ||||||
|  |           child: Icon( | ||||||
|  |             Icons.file_upload_outlined, | ||||||
|  |             color: Colors.white, | ||||||
|  |           ), | ||||||
|  |         ), | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) => Column( | ||||||
|  |         crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |         children: [ | ||||||
|  |           Text( | ||||||
|  |             'FileSelection Buttons', | ||||||
|  |             style: Theme.of(context).textTheme.titleMedium, | ||||||
|  |           ), | ||||||
|  |           const Gap(20), | ||||||
|  |           FileSelectionButton( | ||||||
|  |             leading: _leading(), | ||||||
|  |             title: const TextWrapper( | ||||||
|  |               'Ajouter un fichier', | ||||||
|  |             ), | ||||||
|  |             subTitle: const TextWrapper('Taille max: 20 Mo'), | ||||||
|  |           ), | ||||||
|  |           const Gap(20), | ||||||
|  |           FileSelectionButton( | ||||||
|  |             leading: _leading(), | ||||||
|  |             title: const TextWrapper( | ||||||
|  |               'Enabled', | ||||||
|  |             ), | ||||||
|  |             subTitle: const TextWrapper('Subtitle'), | ||||||
|  |           ) | ||||||
|  |             ..bloc.enable() | ||||||
|  |             ..bloc.freeze(), | ||||||
|  |           const Gap(20), | ||||||
|  |           FileSelectionButton( | ||||||
|  |             leading: _leading(), | ||||||
|  |             title: const TextWrapper( | ||||||
|  |               'Disabled', | ||||||
|  |             ), | ||||||
|  |             subTitle: const TextWrapper('Subtitle'), | ||||||
|  |           ) | ||||||
|  |             ..bloc.disable() | ||||||
|  |             ..bloc.freeze(), | ||||||
|  |           const Gap(20), | ||||||
|  |           FileSelectionButton( | ||||||
|  |             leading: _leading(), | ||||||
|  |             title: const TextWrapper( | ||||||
|  |               'Hovered', | ||||||
|  |             ), | ||||||
|  |             subTitle: const TextWrapper('Subtitle'), | ||||||
|  |           ) | ||||||
|  |             ..bloc.onMouseEnter() | ||||||
|  |             ..bloc.freeze(), | ||||||
|  |           const Gap(20), | ||||||
|  |           FileSelectionButton( | ||||||
|  |             leading: _leading(), | ||||||
|  |             title: const TextWrapper( | ||||||
|  |               'Focused', | ||||||
|  |             ), | ||||||
|  |             subTitle: const TextWrapper('Subtitle'), | ||||||
|  |           ) | ||||||
|  |             ..bloc.onFocus() | ||||||
|  |             ..bloc.freeze(), | ||||||
|  |           const Gap(20), | ||||||
|  |           FileSelectionButton( | ||||||
|  |             leading: _leading(), | ||||||
|  |             title: const TextWrapper( | ||||||
|  |               'Tapped', | ||||||
|  |             ), | ||||||
|  |             subTitle: const TextWrapper('Subtitle'), | ||||||
|  |           ) | ||||||
|  |             ..bloc.onClickDown() | ||||||
|  |             ..bloc.freeze(), | ||||||
|  |           const Gap(20), | ||||||
|  |           FileSelectionButton( | ||||||
|  |             leading: _leading(), | ||||||
|  |             title: const TextWrapper( | ||||||
|  |               'Invalid', | ||||||
|  |             ), | ||||||
|  |             subTitle: const TextWrapper('Subtitle'), | ||||||
|  |           ) | ||||||
|  |             ..bloc.invalidate() | ||||||
|  |             ..bloc.freeze(), | ||||||
|  |           const Gap(20), | ||||||
|  |         ], | ||||||
|  |       ); | ||||||
|  | } | ||||||
| @ -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:gap/gap.dart'; | ||||||
|  | import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; | ||||||
|  | import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; | ||||||
|  | 
 | ||||||
|  | class FlatButtons extends StatelessWidget { | ||||||
|  |   const FlatButtons({super.key}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) => Column( | ||||||
|  |         children: [ | ||||||
|  |           Text( | ||||||
|  |             'Flat Buttons', | ||||||
|  |             style: Theme.of(context).textTheme.titleMedium, | ||||||
|  |           ), | ||||||
|  |           const Gap(20), | ||||||
|  |           Center( | ||||||
|  |             child: FlatButton( | ||||||
|  |               label: const TextWrapper('Voir notre savoir faire'), | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |           const Gap(20), | ||||||
|  |           Center( | ||||||
|  |             child: FlatButton( | ||||||
|  |               label: const TextWrapper('Enabled'), | ||||||
|  |             ) | ||||||
|  |               ..bloc.enable() | ||||||
|  |               ..bloc.freeze(), | ||||||
|  |           ), | ||||||
|  |           const Gap(20), | ||||||
|  |           Center( | ||||||
|  |             child: FlatButton( | ||||||
|  |               label: const TextWrapper('Disabled'), | ||||||
|  |             ) | ||||||
|  |               ..bloc.disable() | ||||||
|  |               ..bloc.freeze(), | ||||||
|  |           ), | ||||||
|  |           const Gap(20), | ||||||
|  |           Center( | ||||||
|  |             child: FlatButton( | ||||||
|  |               label: const TextWrapper('Hovered'), | ||||||
|  |             ) | ||||||
|  |               ..bloc.onMouseEnter() | ||||||
|  |               ..bloc.freeze(), | ||||||
|  |           ), | ||||||
|  |           const Gap(20), | ||||||
|  |           Center( | ||||||
|  |             child: FlatButton( | ||||||
|  |               label: const TextWrapper('Focused'), | ||||||
|  |             ) | ||||||
|  |               ..bloc.onFocus() | ||||||
|  |               ..bloc.freeze(), | ||||||
|  |           ), | ||||||
|  |           const Gap(20), | ||||||
|  |           Center( | ||||||
|  |             child: FlatButton( | ||||||
|  |               label: const TextWrapper('Tapped'), | ||||||
|  |             ) | ||||||
|  |               ..bloc.onClickDown() | ||||||
|  |               ..bloc.freeze(), | ||||||
|  |           ), | ||||||
|  |           const Gap(20), | ||||||
|  |         ], | ||||||
|  |       ); | ||||||
|  | } | ||||||
| @ -0,0 +1,112 @@ | |||||||
|  | // Copyright (C) 2023 WYATT GROUP | ||||||
|  | // Please see the AUTHORS file for details. | ||||||
|  | // | ||||||
|  | // This program is free software: you can redistribute it and/or modify | ||||||
|  | // it under the terms of the GNU General Public License as published by | ||||||
|  | // the Free Software Foundation, either version 3 of the License, or | ||||||
|  | // any later version. | ||||||
|  | // | ||||||
|  | // This program is distributed in the hope that it will be useful, | ||||||
|  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||||
|  | // GNU General Public License for more details. | ||||||
|  | // | ||||||
|  | // You should have received a copy of the GNU General Public License | ||||||
|  | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
|  | 
 | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:gap/gap.dart'; | ||||||
|  | import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; | ||||||
|  | 
 | ||||||
|  | class SimpleIconButtons extends StatelessWidget { | ||||||
|  |   const SimpleIconButtons({super.key}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) => Column( | ||||||
|  |         crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |         children: [ | ||||||
|  |           Text( | ||||||
|  |             'SimpleIcon Buttons', | ||||||
|  |             style: Theme.of(context).textTheme.titleMedium, | ||||||
|  |           ), | ||||||
|  |           const Gap(20), | ||||||
|  |           SimpleIconButton( | ||||||
|  |             icon: const Icon( | ||||||
|  |               Icons.storm_outlined, | ||||||
|  |               size: 17, | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |           const Gap(20), | ||||||
|  |           Text( | ||||||
|  |             'Enabled', | ||||||
|  |             style: Theme.of(context).textTheme.labelMedium, | ||||||
|  |           ), | ||||||
|  |           const Gap(10), | ||||||
|  |           SimpleIconButton( | ||||||
|  |             icon: const Icon( | ||||||
|  |               Icons.storm_outlined, | ||||||
|  |               size: 17, | ||||||
|  |             ), | ||||||
|  |           ) | ||||||
|  |             ..bloc.enable() | ||||||
|  |             ..bloc.freeze(), | ||||||
|  |           const Gap(20), | ||||||
|  |           Text( | ||||||
|  |             'Disabled', | ||||||
|  |             style: Theme.of(context).textTheme.labelMedium, | ||||||
|  |           ), | ||||||
|  |           const Gap(10), | ||||||
|  |           SimpleIconButton( | ||||||
|  |             icon: const Icon( | ||||||
|  |               Icons.storm_outlined, | ||||||
|  |               size: 17, | ||||||
|  |             ), | ||||||
|  |           ) | ||||||
|  |             ..bloc.disable() | ||||||
|  |             ..bloc.freeze(), | ||||||
|  |           const Gap(20), | ||||||
|  |           Text( | ||||||
|  |             'Hovered', | ||||||
|  |             style: Theme.of(context).textTheme.labelMedium, | ||||||
|  |           ), | ||||||
|  |           const Gap(10), | ||||||
|  |           SimpleIconButton( | ||||||
|  |             icon: const Icon( | ||||||
|  |               Icons.storm_outlined, | ||||||
|  |               size: 17, | ||||||
|  |             ), | ||||||
|  |           ) | ||||||
|  |             ..bloc.onMouseEnter() | ||||||
|  |             ..bloc.freeze(), | ||||||
|  |           const Gap(20), | ||||||
|  |           Text( | ||||||
|  |             'Focused', | ||||||
|  |             style: Theme.of(context).textTheme.labelMedium, | ||||||
|  |           ), | ||||||
|  |           const Gap(10), | ||||||
|  |           SimpleIconButton( | ||||||
|  |             icon: const Icon( | ||||||
|  |               Icons.storm_outlined, | ||||||
|  |               size: 17, | ||||||
|  |             ), | ||||||
|  |           ) | ||||||
|  |             ..bloc.onFocus() | ||||||
|  |             ..bloc.freeze(), | ||||||
|  |           const Gap(20), | ||||||
|  |           Text( | ||||||
|  |             'Tapped', | ||||||
|  |             style: Theme.of(context).textTheme.labelMedium, | ||||||
|  |           ), | ||||||
|  |           const Gap(10), | ||||||
|  |           SimpleIconButton( | ||||||
|  |             icon: const Icon( | ||||||
|  |               Icons.storm_outlined, | ||||||
|  |               size: 17, | ||||||
|  |             ), | ||||||
|  |           ) | ||||||
|  |             ..bloc.onClickDown() | ||||||
|  |             ..bloc.freeze(), | ||||||
|  |           const Gap(20), | ||||||
|  |         ], | ||||||
|  |       ); | ||||||
|  | } | ||||||
| @ -0,0 +1,126 @@ | |||||||
|  | // 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_wyatt_ui_components.dart'; | ||||||
|  | import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; | ||||||
|  | import 'package:wyatt_ui_kit_example/theme/constants.dart'; | ||||||
|  | 
 | ||||||
|  | class SymbolButtons extends StatelessWidget { | ||||||
|  |   const SymbolButtons({super.key}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) => Column( | ||||||
|  |         crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |         children: [ | ||||||
|  |           Text( | ||||||
|  |             'Symbol Buttons', | ||||||
|  |             style: Theme.of(context).textTheme.titleMedium, | ||||||
|  |           ), | ||||||
|  |           const Gap(20), | ||||||
|  |           SymbolButton( | ||||||
|  |             label: const TextWrapper('Text'), | ||||||
|  |             icon: const Icon( | ||||||
|  |               Icons.android, | ||||||
|  |               size: 25, | ||||||
|  |               color: Constants.white, | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |           const Gap(20), | ||||||
|  |           SymbolButton( | ||||||
|  |             label: const TextWrapper('Enabled'), | ||||||
|  |             icon: const Icon( | ||||||
|  |               Icons.android, | ||||||
|  |               size: 25, | ||||||
|  |               color: Constants.white, | ||||||
|  |             ), | ||||||
|  |           ) | ||||||
|  |             ..bloc.enable() | ||||||
|  |             ..bloc.freeze(), | ||||||
|  |           const Gap(20), | ||||||
|  |           SymbolButton( | ||||||
|  |             label: const TextWrapper('Disabled'), | ||||||
|  |             icon: const Icon( | ||||||
|  |               Icons.android, | ||||||
|  |               size: 25, | ||||||
|  |               color: Constants.white, | ||||||
|  |             ), | ||||||
|  |           ) | ||||||
|  |             ..bloc.disable() | ||||||
|  |             ..bloc.freeze(), | ||||||
|  |           const Gap(20), | ||||||
|  |           SymbolButton( | ||||||
|  |             label: const TextWrapper('Hovered'), | ||||||
|  |             icon: const Icon( | ||||||
|  |               Icons.android, | ||||||
|  |               size: 25, | ||||||
|  |               color: Constants.white, | ||||||
|  |             ), | ||||||
|  |           ) | ||||||
|  |             ..bloc.onMouseEnter() | ||||||
|  |             ..bloc.freeze(), | ||||||
|  |           const Gap(20), | ||||||
|  |           SymbolButton( | ||||||
|  |             label: const TextWrapper('Focused'), | ||||||
|  |             icon: const Icon( | ||||||
|  |               Icons.android, | ||||||
|  |               size: 25, | ||||||
|  |               color: Constants.white, | ||||||
|  |             ), | ||||||
|  |           ) | ||||||
|  |             ..bloc.onFocus() | ||||||
|  |             ..bloc.freeze(), | ||||||
|  |           const Gap(20), | ||||||
|  |           SymbolButton( | ||||||
|  |             label: const TextWrapper('Tapped'), | ||||||
|  |             icon: const Icon( | ||||||
|  |               Icons.android, | ||||||
|  |               size: 25, | ||||||
|  |               color: Constants.white, | ||||||
|  |             ), | ||||||
|  |           ) | ||||||
|  |             ..bloc.onClickDown() | ||||||
|  |             ..bloc.freeze(), | ||||||
|  |           const Gap(20), | ||||||
|  |           SymbolButton( | ||||||
|  |             label: const TextWrapper('Selected'), | ||||||
|  |             icon: const Icon( | ||||||
|  |               Icons.android, | ||||||
|  |               size: 25, | ||||||
|  |               color: Constants.white, | ||||||
|  |             ), | ||||||
|  |           ) | ||||||
|  |             ..bloc.select() | ||||||
|  |             ..bloc.freeze(), | ||||||
|  |           const Gap(20), | ||||||
|  |           DecoratedBox( | ||||||
|  |             decoration: BoxDecoration( | ||||||
|  |               border: Border.all(color: Constants.red1), | ||||||
|  |             ), | ||||||
|  |             child: SymbolButton( | ||||||
|  |               label: const TextWrapper('Trigger zone'), | ||||||
|  |               icon: const Icon( | ||||||
|  |                 Icons.android, | ||||||
|  |                 size: 25, | ||||||
|  |                 color: Constants.white, | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |           const Gap(20), | ||||||
|  |         ], | ||||||
|  |       ); | ||||||
|  | } | ||||||
| @ -23,9 +23,11 @@ import 'package:wyatt_ui_kit_example/theme_extension.dart'; | |||||||
| 
 | 
 | ||||||
| void main(List<String> args) { | void main(List<String> args) { | ||||||
|   const forcePage = int.fromEnvironment('PAGE'); |   const forcePage = int.fromEnvironment('PAGE'); | ||||||
|   runApp(const App( |   runApp( | ||||||
|  |     const App( | ||||||
|       defaultPage: forcePage, |       defaultPage: forcePage, | ||||||
|   ),); |     ), | ||||||
|  |   ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class App extends StatelessWidget { | class App extends StatelessWidget { | ||||||
| @ -74,6 +76,8 @@ class App extends StatelessWidget { | |||||||
|                 color: const Color.fromRGBO(36, 38, 42, 1), |                 color: const Color.fromRGBO(36, 38, 42, 1), | ||||||
|               ), |               ), | ||||||
|             ), |             ), | ||||||
|  |             // FlatButtonTheme.light(), | ||||||
|  |             // SymbolButtonTheme.light(), | ||||||
|           ], |           ], | ||||||
|         ), |         ), | ||||||
|         dark: ThemeData.dark().copyWith( |         dark: ThemeData.dark().copyWith( | ||||||
| @ -114,6 +118,8 @@ class App extends StatelessWidget { | |||||||
|                 color: Colors.white, |                 color: Colors.white, | ||||||
|               ), |               ), | ||||||
|             ), |             ), | ||||||
|  |             // FlatButtonTheme.dark(), | ||||||
|  |             // SymbolButtonTheme.dark(), | ||||||
|           ], |           ], | ||||||
|         ), |         ), | ||||||
|         builder: (light, dark) => MaterialApp( |         builder: (light, dark) => MaterialApp( | ||||||
|  | |||||||
							
								
								
									
										46
									
								
								packages/wyatt_ui_kit/example/lib/theme/constants.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								packages/wyatt_ui_kit/example/lib/theme/constants.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | |||||||
|  | // Copyright (C) 2023 WYATT GROUP | ||||||
|  | // Please see the AUTHORS file for details. | ||||||
|  | // | ||||||
|  | // This program is free software: you can redistribute it and/or modify | ||||||
|  | // it under the terms of the GNU General Public License as published by | ||||||
|  | // the Free Software Foundation, either version 3 of the License, or | ||||||
|  | // any later version. | ||||||
|  | // | ||||||
|  | // This program is distributed in the hope that it will be useful, | ||||||
|  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||||
|  | // GNU General Public License for more details. | ||||||
|  | // | ||||||
|  | // You should have received a copy of the GNU General Public License | ||||||
|  | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
|  | 
 | ||||||
|  | import 'package:flutter/widgets.dart'; | ||||||
|  | 
 | ||||||
|  | abstract class Constants { | ||||||
|  |   static const white = Color(0xFFFFFFFF); | ||||||
|  |   static const dark = Color(0xFF383C40); | ||||||
|  | 
 | ||||||
|  |   static const blue1 = Color(0xFF3C97FB); | ||||||
|  |   static const blue2 = Color(0xFF446DF4); | ||||||
|  |   static const blue3 = Color(0xFF1A84F7); | ||||||
|  |   static const blue4 = Color(0xFF1344E4); | ||||||
|  | 
 | ||||||
|  |   static const grey1 = Color(0xFF60656A); | ||||||
|  |   static const grey2 = Color(0xFF383C40); | ||||||
|  | 
 | ||||||
|  |   static const grey3 = Color(0xFF16191D); | ||||||
|  |   static const grey4 = Color(0xFF33373E); | ||||||
|  | 
 | ||||||
|  |   static const green1 = Color(0xFF50CE99); | ||||||
|  |   static const green2 = Color(0xFF339572); | ||||||
|  | 
 | ||||||
|  |   static const red1 = Color(0xFFFB5E3C); | ||||||
|  |   static const red2 = Color(0xFFF44464); | ||||||
|  | 
 | ||||||
|  |   static const blueGradient = [blue1, blue2]; | ||||||
|  |   static const blueDarkGradient = [blue3, blue4]; | ||||||
|  |   static const greyGradient = [grey1, grey2]; | ||||||
|  |   static const greyDarkGradient = [grey3, grey4]; | ||||||
|  |   static const greenGradient = [green1, green2]; | ||||||
|  |   static const redGradient = [red1, red2]; | ||||||
|  | } | ||||||
							
								
								
									
										151
									
								
								packages/wyatt_ui_kit/example/lib/theme/flat_button_theme.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								packages/wyatt_ui_kit/example/lib/theme/flat_button_theme.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,151 @@ | |||||||
|  | // 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_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), | ||||||
|  |       ), | ||||||
|  |       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), | ||||||
|  |       ), | ||||||
|  |       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), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										155
									
								
								packages/wyatt_ui_kit/example/lib/theme/symbol_button_theme.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								packages/wyatt_ui_kit/example/lib/theme/symbol_button_theme.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,155 @@ | |||||||
|  | // 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_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)), | ||||||
|  |       ), | ||||||
|  |       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), | ||||||
|  |       ), | ||||||
|  |       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), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -15,7 +15,6 @@ | |||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
| import 'dart:async'; | import 'dart:async'; | ||||||
| import 'dart:math'; |  | ||||||
| 
 | 
 | ||||||
| import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; | import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; | ||||||
| import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart'; | import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart'; | ||||||
| @ -30,8 +29,6 @@ class InvalidButtonCubit extends ButtonCubit { | |||||||
|     emit( |     emit( | ||||||
|       state.copyWith( |       state.copyWith( | ||||||
|         state: ControlState.hovered, |         state: ControlState.hovered, | ||||||
|         // TODO(hpcl): change this |  | ||||||
|         invalid: Random().nextBool(), |  | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| @ -45,8 +42,6 @@ class InvalidButtonCubit extends ButtonCubit { | |||||||
|     emit( |     emit( | ||||||
|       state.copyWith( |       state.copyWith( | ||||||
|         state: ControlState.normal, |         state: ControlState.normal, | ||||||
|         // TODO(hpcl): change this |  | ||||||
|         invalid: Random().nextBool(), |  | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -218,7 +218,6 @@ class FileSelectionButtonScreen | |||||||
|                   padding: style.padding ?? EdgeInsets.zero, |                   padding: style.padding ?? EdgeInsets.zero, | ||||||
|                   child: Row( |                   child: Row( | ||||||
|                     mainAxisSize: mainAxisSize ?? MainAxisSize.min, |                     mainAxisSize: mainAxisSize ?? MainAxisSize.min, | ||||||
|                     mainAxisAlignment: MainAxisAlignment.spaceBetween, |  | ||||||
|                     children: [ |                     children: [ | ||||||
|                       if (leading != null) ...[ |                       if (leading != null) ...[ | ||||||
|                         leading ?? const SizedBox.shrink(), |                         leading ?? const SizedBox.shrink(), | ||||||
| @ -240,7 +239,7 @@ class FileSelectionButtonScreen | |||||||
|                           /// |                           /// | ||||||
|                           /// More infos in `negociate()` method |                           /// More infos in `negociate()` method | ||||||
|                           if (title != null) ...[ |                           if (title != null) ...[ | ||||||
|                             Gap(style.padding?.horizontal ?? 10), |                             Gap(style.padding?.vertical ?? 10), | ||||||
|                             Text( |                             Text( | ||||||
|                               title!.text, |                               title!.text, | ||||||
|                               style: title!.style ?? style.title, |                               style: title!.style ?? style.title, | ||||||
| @ -267,7 +266,7 @@ class FileSelectionButtonScreen | |||||||
|                           /// |                           /// | ||||||
|                           /// More infos in `negociate()` method |                           /// More infos in `negociate()` method | ||||||
|                           if (subTitle != null) ...[ |                           if (subTitle != null) ...[ | ||||||
|                             Gap(style.padding?.horizontal ?? 10), |                             Gap(style.padding?.vertical ?? 10), | ||||||
|                             Text( |                             Text( | ||||||
|                               subTitle!.text, |                               subTitle!.text, | ||||||
|                               style: subTitle!.style ?? style.subTitle, |                               style: subTitle!.style ?? style.subTitle, | ||||||
|  | |||||||
| @ -30,17 +30,48 @@ class FileSelectionButtonThemeResolver extends ThemeResolver< | |||||||
|   FileSelectionButtonStyle computeDefaultValue( |   FileSelectionButtonStyle computeDefaultValue( | ||||||
|     BuildContext context, { |     BuildContext context, { | ||||||
|     ButtonState? extra, |     ButtonState? extra, | ||||||
|   }) => |   }) { | ||||||
|       FileSelectionButtonStyle( |     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, |       title: context.textTheme.labelLarge, | ||||||
|       subTitle: context.textTheme.labelSmall, |       subTitle: context.textTheme.labelSmall, | ||||||
|       radius: (context.buttonTheme.shape is RoundedRectangleBorder) |       radius: (context.buttonTheme.shape is RoundedRectangleBorder) | ||||||
|           ? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius |           ? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius | ||||||
|           : null, |           : null, | ||||||
|         padding: context.buttonTheme.padding, |       padding: const EdgeInsets.symmetric(horizontal: 10), | ||||||
|         foregroundColors: MultiColor.single(context.colorScheme.onPrimary), |       foregroundColors: foregroundColor, | ||||||
|         backgroundColors: MultiColor.single(context.colorScheme.primary), |       backgroundColors: backgroundColor, | ||||||
|     ); |     ); | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   final FileSelectionButtonStyle? Function( |   final FileSelectionButtonStyle? Function( | ||||||
|  | |||||||
| @ -29,16 +29,42 @@ class SimpleIconButtonThemeResolver extends ThemeResolver<SimpleIconButtonStyle, | |||||||
|   SimpleIconButtonStyle computeDefaultValue( |   SimpleIconButtonStyle computeDefaultValue( | ||||||
|     BuildContext context, { |     BuildContext context, { | ||||||
|     ControlState? extra, |     ControlState? extra, | ||||||
|   }) => |   }) { | ||||||
|       SimpleIconButtonStyle( |     MultiColor backgroundColor = MultiColor.single(context.colorScheme.primary); | ||||||
|  |     MultiColor foregroundColor = | ||||||
|  |         MultiColor.single(context.colorScheme.onPrimary); | ||||||
|  | 
 | ||||||
|  |     switch (extra) { | ||||||
|  |       case ControlState.disabled: | ||||||
|  |         backgroundColor = | ||||||
|  |             MultiColor.single(context.colorScheme.onSurface.withOpacity(0.12)); | ||||||
|  |         foregroundColor = | ||||||
|  |             MultiColor.single(context.colorScheme.onSurface.withOpacity(0.38)); | ||||||
|  |         break; | ||||||
|  |       case ControlState.hovered: | ||||||
|  |         backgroundColor = | ||||||
|  |             MultiColor.single(context.colorScheme.primary.withOpacity(0.92)); | ||||||
|  |         break; | ||||||
|  |       case ControlState.tapped: | ||||||
|  |         backgroundColor = | ||||||
|  |             MultiColor.single(context.colorScheme.primary.withOpacity(0.92)); | ||||||
|  |         break; | ||||||
|  |       case null: | ||||||
|  |       case ControlState.normal: | ||||||
|  |       case ControlState.focused: | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return SimpleIconButtonStyle( | ||||||
|       dimension: context.buttonTheme.height, |       dimension: context.buttonTheme.height, | ||||||
|       radius: (context.buttonTheme.shape is RoundedRectangleBorder) |       radius: (context.buttonTheme.shape is RoundedRectangleBorder) | ||||||
|           ? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius |           ? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius | ||||||
|           : null, |           : null, | ||||||
|         padding: context.buttonTheme.padding, |       padding: EdgeInsets.zero, | ||||||
|         foregroundColors: MultiColor.single(context.colorScheme.onPrimary), |       foregroundColors: foregroundColor, | ||||||
|         backgroundColors: MultiColor.single(context.colorScheme.primary), |       backgroundColors: backgroundColor, | ||||||
|     ); |     ); | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   final SimpleIconButtonStyle? Function( |   final SimpleIconButtonStyle? Function( | ||||||
|  | |||||||
| @ -58,7 +58,7 @@ class SymbolButtonThemeResolver extends ThemeResolver<SymbolButtonStyle, | |||||||
| 
 | 
 | ||||||
|     return SymbolButtonStyle( |     return SymbolButtonStyle( | ||||||
|       label: context.textTheme.labelLarge, |       label: context.textTheme.labelLarge, | ||||||
|       dimension: context.buttonTheme.height, |       dimension: context.buttonTheme.height*1.5, | ||||||
|       radius: (context.buttonTheme.shape is RoundedRectangleBorder) |       radius: (context.buttonTheme.shape is RoundedRectangleBorder) | ||||||
|           ? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius |           ? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius | ||||||
|           : null, |           : null, | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user