master #81

Closed
malo wants to merge 322 commits from master into feat/bloc_layout/new-package
32 changed files with 673 additions and 342 deletions
Showing only changes of commit 6c54689393 - Show all commits

View File

@ -14,6 +14,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/foundation.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
abstract class ButtonComponent extends Component { abstract class ButtonComponent extends Component {
@ -26,6 +27,7 @@ abstract class ButtonComponent extends Component {
this.selectedStyle, this.selectedStyle,
this.invalidStyle, this.invalidStyle,
this.onPressed, this.onPressed,
this.disabled,
super.themeResolver, super.themeResolver,
super.key, super.key,
}); });
@ -51,6 +53,12 @@ abstract class ButtonComponent extends Component {
/// Style of this button in invalid state /// Style of this button in invalid state
final ButtonStyle<dynamic>? invalidStyle; final ButtonStyle<dynamic>? invalidStyle;
/// Callback on button press /// Callback on button press,
///
/// [ControlState] is passed as argument and can be used to determine if the
/// button was pressed in disabled state or not.
final void Function(ControlState state)? onPressed; final void Function(ControlState state)? onPressed;
/// Current state of this button
final ValueNotifier<bool>? disabled;
} }

View File

@ -36,6 +36,7 @@ abstract class FileSelectionButtonComponent extends ButtonComponent
super.selectedStyle, super.selectedStyle,
super.invalidStyle, super.invalidStyle,
super.onPressed, super.onPressed,
super.disabled,
super.themeResolver, super.themeResolver,
super.key, super.key,
}); });

View File

@ -22,6 +22,7 @@ abstract class $FileSelectionButtonComponentCWProxy {
FileSelectionButtonComponent invalidStyle(ButtonStyle<dynamic>? invalidStyle); FileSelectionButtonComponent invalidStyle(ButtonStyle<dynamic>? invalidStyle);
FileSelectionButtonComponent onPressed( FileSelectionButtonComponent onPressed(
void Function(ControlState)? onPressed); void Function(ControlState)? onPressed);
FileSelectionButtonComponent disabled(ValueNotifier<bool>? disabled);
FileSelectionButtonComponent themeResolver( FileSelectionButtonComponent themeResolver(
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver); ThemeResolver<dynamic, dynamic, dynamic>? themeResolver);
FileSelectionButtonComponent key(Key? key); FileSelectionButtonComponent key(Key? key);
@ -38,6 +39,7 @@ abstract class $FileSelectionButtonComponentCWProxy {
ButtonStyle<dynamic>? selectedStyle, ButtonStyle<dynamic>? selectedStyle,
ButtonStyle<dynamic>? invalidStyle, ButtonStyle<dynamic>? invalidStyle,
void Function(ControlState)? onPressed, void Function(ControlState)? onPressed,
ValueNotifier<bool>? disabled,
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver, ThemeResolver<dynamic, dynamic, dynamic>? themeResolver,
Key? key, Key? key,
}); });

View File

@ -34,6 +34,7 @@ abstract class FlatButtonComponent extends ButtonComponent
super.focusedStyle, super.focusedStyle,
super.tappedStyle, super.tappedStyle,
super.onPressed, super.onPressed,
super.disabled,
super.themeResolver, super.themeResolver,
super.key, super.key,
}); });

View File

@ -17,6 +17,7 @@ abstract class $FlatButtonComponentCWProxy {
FlatButtonComponent focusedStyle(ButtonStyle<dynamic>? focusedStyle); FlatButtonComponent focusedStyle(ButtonStyle<dynamic>? focusedStyle);
FlatButtonComponent tappedStyle(ButtonStyle<dynamic>? tappedStyle); FlatButtonComponent tappedStyle(ButtonStyle<dynamic>? tappedStyle);
FlatButtonComponent onPressed(void Function(ControlState)? onPressed); FlatButtonComponent onPressed(void Function(ControlState)? onPressed);
FlatButtonComponent disabled(ValueNotifier<bool>? disabled);
FlatButtonComponent themeResolver( FlatButtonComponent themeResolver(
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver); ThemeResolver<dynamic, dynamic, dynamic>? themeResolver);
FlatButtonComponent key(Key? key); FlatButtonComponent key(Key? key);
@ -31,6 +32,7 @@ abstract class $FlatButtonComponentCWProxy {
ButtonStyle<dynamic>? focusedStyle, ButtonStyle<dynamic>? focusedStyle,
ButtonStyle<dynamic>? tappedStyle, ButtonStyle<dynamic>? tappedStyle,
void Function(ControlState)? onPressed, void Function(ControlState)? onPressed,
ValueNotifier<bool>? disabled,
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver, ThemeResolver<dynamic, dynamic, dynamic>? themeResolver,
Key? key, Key? key,
}); });

View File

@ -31,6 +31,7 @@ abstract class SimpleIconButtonComponent extends ButtonComponent
super.focusedStyle, super.focusedStyle,
super.tappedStyle, super.tappedStyle,
super.onPressed, super.onPressed,
super.disabled,
super.themeResolver, super.themeResolver,
super.key, super.key,
}); });

View File

@ -14,6 +14,7 @@ abstract class $SimpleIconButtonComponentCWProxy {
SimpleIconButtonComponent focusedStyle(ButtonStyle<dynamic>? focusedStyle); SimpleIconButtonComponent focusedStyle(ButtonStyle<dynamic>? focusedStyle);
SimpleIconButtonComponent tappedStyle(ButtonStyle<dynamic>? tappedStyle); SimpleIconButtonComponent tappedStyle(ButtonStyle<dynamic>? tappedStyle);
SimpleIconButtonComponent onPressed(void Function(ControlState)? onPressed); SimpleIconButtonComponent onPressed(void Function(ControlState)? onPressed);
SimpleIconButtonComponent disabled(ValueNotifier<bool>? disabled);
SimpleIconButtonComponent themeResolver( SimpleIconButtonComponent themeResolver(
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver); ThemeResolver<dynamic, dynamic, dynamic>? themeResolver);
SimpleIconButtonComponent key(Key? key); SimpleIconButtonComponent key(Key? key);
@ -25,6 +26,7 @@ abstract class $SimpleIconButtonComponentCWProxy {
ButtonStyle<dynamic>? focusedStyle, ButtonStyle<dynamic>? focusedStyle,
ButtonStyle<dynamic>? tappedStyle, ButtonStyle<dynamic>? tappedStyle,
void Function(ControlState)? onPressed, void Function(ControlState)? onPressed,
ValueNotifier<bool>? disabled,
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver, ThemeResolver<dynamic, dynamic, dynamic>? themeResolver,
Key? key, Key? key,
}); });

View File

@ -34,6 +34,7 @@ abstract class SymbolButtonComponent extends ButtonComponent
super.tappedStyle, super.tappedStyle,
super.selectedStyle, super.selectedStyle,
super.onPressed, super.onPressed,
super.disabled,
super.themeResolver, super.themeResolver,
super.key, super.key,
}); });

View File

@ -17,6 +17,7 @@ abstract class $SymbolButtonComponentCWProxy {
SymbolButtonComponent tappedStyle(ButtonStyle<dynamic>? tappedStyle); SymbolButtonComponent tappedStyle(ButtonStyle<dynamic>? tappedStyle);
SymbolButtonComponent selectedStyle(ButtonStyle<dynamic>? selectedStyle); SymbolButtonComponent selectedStyle(ButtonStyle<dynamic>? selectedStyle);
SymbolButtonComponent onPressed(void Function(ControlState)? onPressed); SymbolButtonComponent onPressed(void Function(ControlState)? onPressed);
SymbolButtonComponent disabled(ValueNotifier<bool>? disabled);
SymbolButtonComponent themeResolver( SymbolButtonComponent themeResolver(
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver); ThemeResolver<dynamic, dynamic, dynamic>? themeResolver);
SymbolButtonComponent key(Key? key); SymbolButtonComponent key(Key? key);
@ -31,6 +32,7 @@ abstract class $SymbolButtonComponentCWProxy {
ButtonStyle<dynamic>? tappedStyle, ButtonStyle<dynamic>? tappedStyle,
ButtonStyle<dynamic>? selectedStyle, ButtonStyle<dynamic>? selectedStyle,
void Function(ControlState)? onPressed, void Function(ControlState)? onPressed,
ValueNotifier<bool>? disabled,
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver, ThemeResolver<dynamic, dynamic, dynamic>? themeResolver,
Key? key, Key? key,
}); });

View File

@ -15,14 +15,23 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
import 'package:wyatt_ui_kit_example/theme/constants.dart'; import 'package:wyatt_ui_kit_example/theme/constants.dart';
class FileSelectionButtons extends StatelessWidget { class FileSelectionButtons extends StatefulWidget {
const FileSelectionButtons({super.key}); const FileSelectionButtons({super.key});
@override
State<FileSelectionButtons> createState() => _FileSelectionButtonsState();
}
class _FileSelectionButtonsState extends State<FileSelectionButtons> {
final _disabled = ValueNotifier(true);
final _dynamic = ValueNotifier(false);
Widget _leading() => const DecoratedBox( Widget _leading() => const DecoratedBox(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Constants.grey2, color: Constants.grey2,
@ -48,6 +57,7 @@ class FileSelectionButtons extends StatelessWidget {
style: Theme.of(context).textTheme.titleMedium, style: Theme.of(context).textTheme.titleMedium,
), ),
const Gap(20), const Gap(20),
// Default
FileSelectionButton( FileSelectionButton(
leading: _leading(), leading: _leading(),
title: const TextWrapper( title: const TextWrapper(
@ -56,65 +66,99 @@ class FileSelectionButtons extends StatelessWidget {
subTitle: const TextWrapper('Taille max: 20 Mo'), subTitle: const TextWrapper('Taille max: 20 Mo'),
), ),
const Gap(20), const Gap(20),
FileSelectionButton( BlocProvider(
leading: _leading(), create: (context) => InvalidButtonCubit()..freeze(),
title: const TextWrapper( child: FileSelectionButton(
'Enabled', leading: _leading(),
title: const TextWrapper(
'Enabled',
),
subTitle: const TextWrapper('Subtitle'),
), ),
subTitle: const TextWrapper('Subtitle'), ),
)
..bloc.enable()
..bloc.freeze(),
const Gap(20), const Gap(20),
// Using a ValueNotifier to disable the button
FileSelectionButton( FileSelectionButton(
leading: _leading(), leading: _leading(),
title: const TextWrapper( title: const TextWrapper(
'Disabled', 'Disabled',
), ),
subTitle: const TextWrapper('Subtitle'), subTitle: const TextWrapper('Subtitle'),
) disabled: _disabled,
..bloc.disable() ),
..bloc.freeze(),
const Gap(20), const Gap(20),
FileSelectionButton( BlocProvider(
leading: _leading(), create: (context) => InvalidButtonCubit()..hover(),
title: const TextWrapper( child: FileSelectionButton(
'Hovered', leading: _leading(),
title: const TextWrapper(
'Hovered',
),
subTitle: const TextWrapper('Subtitle'),
), ),
subTitle: const TextWrapper('Subtitle'), ),
)
..bloc.onMouseEnter()
..bloc.freeze(),
const Gap(20), const Gap(20),
FileSelectionButton( BlocProvider(
leading: _leading(), create: (context) => InvalidButtonCubit()..focus(),
title: const TextWrapper( child: FileSelectionButton(
'Focused', leading: _leading(),
title: const TextWrapper(
'Focused',
),
subTitle: const TextWrapper('Subtitle'),
), ),
subTitle: const TextWrapper('Subtitle'), ),
)
..bloc.onFocus()
..bloc.freeze(),
const Gap(20), const Gap(20),
FileSelectionButton( BlocProvider(
leading: _leading(), create: (context) => InvalidButtonCubit()..tap(),
title: const TextWrapper( child: FileSelectionButton(
'Tapped', leading: _leading(),
title: const TextWrapper(
'Tapped',
),
subTitle: const TextWrapper('Subtitle'),
), ),
subTitle: const TextWrapper('Subtitle'), ),
)
..bloc.onClickDown()
..bloc.freeze(),
const Gap(20), const Gap(20),
FileSelectionButton( BlocProvider(
leading: _leading(), create: (context) => InvalidButtonCubit()..invalidate(),
title: const TextWrapper( child: FileSelectionButton(
'Invalid', leading: _leading(),
title: const TextWrapper(
'Invalid',
),
subTitle: const TextWrapper('Subtitle'),
), ),
subTitle: const TextWrapper('Subtitle'), ),
) const Gap(20),
..bloc.invalidate() // Dynamic, disabled with ValueNotifier and invalid with BlocProvider.
..bloc.freeze(), // Keep the state when the button is disabled.
Column(
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
const Text('Enabled'),
Checkbox(
value: !_dynamic.value,
onChanged: (value) {
setState(() {
_dynamic.value = !_dynamic.value;
});
},
),
],
),
FileSelectionButton(
leading: _leading(),
title: const TextWrapper(
'Dynamic',
),
subTitle: const TextWrapper('Subtitle'),
disabled: _dynamic,
),
],
),
const Gap(20), const Gap(20),
], ],
); );

View File

@ -15,13 +15,22 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
class FlatButtons extends StatelessWidget { class FlatButtons extends StatefulWidget {
const FlatButtons({super.key}); const FlatButtons({super.key});
@override
State<FlatButtons> createState() => _FlatButtonsState();
}
class _FlatButtonsState extends State<FlatButtons> {
final _disabled = ValueNotifier(true);
final _dynamic = ValueNotifier(false);
@override @override
Widget build(BuildContext context) => Column( Widget build(BuildContext context) => Column(
children: [ children: [
@ -30,56 +39,80 @@ class FlatButtons extends StatelessWidget {
style: Theme.of(context).textTheme.titleMedium, style: Theme.of(context).textTheme.titleMedium,
), ),
const Gap(20), const Gap(20),
Center( // Default
const Center(
/// You can overwrite global textstyle of the label with [label], /// You can overwrite global textstyle of the label with [label],
/// but if you only want to override the color/gradient of the text /// but if you only want to override the color/gradient of the text
/// in a particular case you can override the style that will /// in a particular case you can override the style that will
/// be merge during the build. /// be merge during the build.
child: FlatButton( child: FlatButton(
label: const TextWrapper( label: TextWrapper(
'Voir notre savoir faire', 'Voir notre savoir faire',
), ),
), ),
), ),
const Gap(20), const Gap(20),
Center( Center(
child: FlatButton( child: BlocProvider(
label: const TextWrapper('Enabled'), create: (context) => ButtonCubit()..freeze(),
) child: const FlatButton(
..bloc.enable() label: TextWrapper('Enabled'),
..bloc.freeze(), ),
),
), ),
const Gap(20), const Gap(20),
// Disabled with ValueNotifier
Center( Center(
child: FlatButton( child: FlatButton(
label: const TextWrapper('Disabled'), label: const TextWrapper('Disabled'),
) disabled: _disabled,
..bloc.disable() ),
..bloc.freeze(),
), ),
const Gap(20), const Gap(20),
Center( Center(
child: FlatButton( child: BlocProvider(
label: const TextWrapper('Hovered'), create: (context) => ButtonCubit()..hover(),
) child: const FlatButton(
..bloc.onMouseEnter() label: TextWrapper('Hovered'),
..bloc.freeze(), ),
),
), ),
const Gap(20), const Gap(20),
Center( Center(
child: FlatButton( child: BlocProvider(
label: const TextWrapper('Focused'), create: (context) => ButtonCubit()..focus(),
) child: const FlatButton(
..bloc.onFocus() label: TextWrapper('Focused'),
..bloc.freeze(), ),
),
), ),
const Gap(20), const Gap(20),
Center( Center(
child: FlatButton( child: BlocProvider(
label: const TextWrapper('Tapped'), create: (context) => ButtonCubit()..tap(),
) child: const FlatButton(
..bloc.onClickDown() label: TextWrapper('Tapped'),
..bloc.freeze(), ),
),
),
const Gap(20),
// Dynamic, disabled with ValueNotifier and
// keep the state when the button is disabled
Row(
children: [
Checkbox(
value: !_dynamic.value,
onChanged: (value) {
setState(() {
_dynamic.value = !_dynamic.value;
});
},
),
FlatButton(
label: const TextWrapper('Dynamic'),
disabled: _dynamic,
),
],
), ),
const Gap(20), const Gap(20),
], ],

View File

@ -15,12 +15,21 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:gap/gap.dart'; import 'package:gap/gap.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
class SimpleIconButtons extends StatelessWidget { class SimpleIconButtons extends StatefulWidget {
const SimpleIconButtons({super.key}); const SimpleIconButtons({super.key});
@override
State<SimpleIconButtons> createState() => _SimpleIconButtonsState();
}
class _SimpleIconButtonsState extends State<SimpleIconButtons> {
final _disabled = ValueNotifier(true);
final _dynamic = ValueNotifier(false);
@override @override
Widget build(BuildContext context) => Column( Widget build(BuildContext context) => Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -30,8 +39,9 @@ class SimpleIconButtons extends StatelessWidget {
style: Theme.of(context).textTheme.titleMedium, style: Theme.of(context).textTheme.titleMedium,
), ),
const Gap(20), const Gap(20),
SimpleIconButton( // Default
icon: const Icon( const SimpleIconButton(
icon: Icon(
Icons.storm_outlined, Icons.storm_outlined,
size: 17, size: 17,
), ),
@ -42,71 +52,101 @@ class SimpleIconButtons extends StatelessWidget {
style: Theme.of(context).textTheme.labelMedium, style: Theme.of(context).textTheme.labelMedium,
), ),
const Gap(10), const Gap(10),
SimpleIconButton( BlocProvider(
icon: const Icon( create: (context) => ButtonCubit()..freeze(),
Icons.storm_outlined, child: const SimpleIconButton(
size: 17, icon: Icon(
Icons.storm_outlined,
size: 17,
),
), ),
) ),
..bloc.enable()
..bloc.freeze(),
const Gap(20), const Gap(20),
Text( Text(
'Disabled', 'Disabled',
style: Theme.of(context).textTheme.labelMedium, style: Theme.of(context).textTheme.labelMedium,
), ),
const Gap(10), const Gap(10),
// Disabled using ValueNotifier
SimpleIconButton( SimpleIconButton(
icon: const Icon( icon: const Icon(
Icons.storm_outlined, Icons.storm_outlined,
size: 17, size: 17,
), ),
) disabled: _disabled,
..bloc.disable() ),
..bloc.freeze(),
const Gap(20), const Gap(20),
Text( Text(
'Hovered', 'Hovered',
style: Theme.of(context).textTheme.labelMedium, style: Theme.of(context).textTheme.labelMedium,
), ),
const Gap(10), const Gap(10),
SimpleIconButton( BlocProvider(
icon: const Icon( create: (context) => ButtonCubit()..hover(),
Icons.storm_outlined, child: const SimpleIconButton(
size: 17, icon: Icon(
Icons.storm_outlined,
size: 17,
),
), ),
) ),
..bloc.onMouseEnter()
..bloc.freeze(),
const Gap(20), const Gap(20),
Text( Text(
'Focused', 'Focused',
style: Theme.of(context).textTheme.labelMedium, style: Theme.of(context).textTheme.labelMedium,
), ),
const Gap(10), const Gap(10),
SimpleIconButton( BlocProvider(
icon: const Icon( create: (context) => ButtonCubit()..focus(),
Icons.storm_outlined, child: const SimpleIconButton(
size: 17, icon: Icon(
Icons.storm_outlined,
size: 17,
),
), ),
) ),
..bloc.onFocus()
..bloc.freeze(),
const Gap(20), const Gap(20),
Text( Text(
'Tapped', 'Tapped',
style: Theme.of(context).textTheme.labelMedium, style: Theme.of(context).textTheme.labelMedium,
), ),
const Gap(10), const Gap(10),
SimpleIconButton( BlocProvider(
icon: const Icon( create: (context) => ButtonCubit()..tap(),
Icons.storm_outlined, child: const SimpleIconButton(
size: 17, icon: Icon(
Icons.storm_outlined,
size: 17,
),
), ),
) ),
..bloc.onClickDown()
..bloc.freeze(),
const Gap(20), const Gap(20),
Text(
'Dynamic',
style: Theme.of(context).textTheme.labelMedium,
),
const Gap(10),
// Dynamic, disabled with ValueNotifier and
// keep the state when the button is disabled
Row(
children: [
Checkbox(
value: !_dynamic.value,
onChanged: (value) {
setState(() {
_dynamic.value = !_dynamic.value;
});
},
),
SimpleIconButton(
icon: const Icon(
Icons.storm_outlined,
size: 17,
),
disabled: _dynamic,
),
],
),
], ],
); );
} }

View File

@ -15,14 +15,23 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart'; import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
import 'package:wyatt_ui_kit_example/theme/constants.dart'; import 'package:wyatt_ui_kit_example/theme/constants.dart';
class SymbolButtons extends StatelessWidget { class SymbolButtons extends StatefulWidget {
const SymbolButtons({super.key}); const SymbolButtons({super.key});
@override
State<SymbolButtons> createState() => _SymbolButtonsState();
}
class _SymbolButtonsState extends State<SymbolButtons> {
final _disabled = ValueNotifier(true);
final _dynamic = ValueNotifier(false);
Icon _icon(BuildContext context) => Icon( Icon _icon(BuildContext context) => Icon(
Icons.android, Icons.android,
size: 25, size: 25,
@ -45,47 +54,70 @@ class SymbolButtons extends StatelessWidget {
icon: _icon(context), icon: _icon(context),
), ),
const Gap(20), const Gap(20),
SymbolButton( BlocProvider(
label: const TextWrapper('Enabled'), create: (context) => SelectableButtonCubit()..freeze(),
icon: _icon(context), child: SymbolButton(
) label: const TextWrapper('Enabled'),
..bloc.enable() icon: _icon(context),
..bloc.freeze(), ),
),
const Gap(20), const Gap(20),
// Disabled
SymbolButton( SymbolButton(
label: const TextWrapper('Disabled'), label: const TextWrapper('Disabled'),
icon: _icon(context), icon: _icon(context),
) disabled: _disabled,
..bloc.disable() ),
..bloc.freeze(),
const Gap(20), const Gap(20),
SymbolButton( BlocProvider(
label: const TextWrapper('Hovered'), create: (context) => SelectableButtonCubit()..hover(),
icon: _icon(context), child: SymbolButton(
) label: const TextWrapper('Hovered'),
..bloc.onMouseEnter() icon: _icon(context),
..bloc.freeze(), ),
),
const Gap(20), const Gap(20),
SymbolButton( BlocProvider(
label: const TextWrapper('Focused'), create: (context) => SelectableButtonCubit()..focus(),
icon: _icon(context), child: SymbolButton(
) label: const TextWrapper('Focused'),
..bloc.onFocus() icon: _icon(context),
..bloc.freeze(), ),
),
const Gap(20), const Gap(20),
SymbolButton( BlocProvider(
label: const TextWrapper('Tapped'), create: (context) => SelectableButtonCubit()..tap(),
icon: _icon(context), child: SymbolButton(
) label: const TextWrapper('Tapped'),
..bloc.onClickDown() icon: _icon(context),
..bloc.freeze(), ),
),
const Gap(20), const Gap(20),
SymbolButton( BlocProvider(
label: const TextWrapper('Selected'), create: (context) => SelectableButtonCubit()..select(),
icon: _icon(context), child: SymbolButton(
) label: const TextWrapper('Selected'),
..bloc.select() icon: _icon(context),
..bloc.freeze(), ),
),
const Gap(20),
Row(
children: [
Checkbox(
value: !_dynamic.value,
onChanged: (value) {
setState(() {
_dynamic.value = !_dynamic.value;
});
},
),
SymbolButton(
label: const TextWrapper('Dynamic'),
icon: _icon(context),
disabled: _dynamic,
),
],
),
const Gap(20), const Gap(20),
DecoratedBox( DecoratedBox(
decoration: BoxDecoration( decoration: BoxDecoration(

View File

@ -10,6 +10,7 @@ environment:
dependencies: dependencies:
flutter: { sdk: flutter } flutter: { sdk: flutter }
flutter_bloc: ^8.1.2
flutter_localizations: { sdk: flutter } flutter_localizations: { sdk: flutter }
gap: ^2.0.1 gap: ^2.0.1

View File

@ -14,6 +14,9 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
export './cubit/button_cubit.dart';
export './cubit/invalid_button_cubit.dart';
export './cubit/selectable_button_cubit.dart';
export './file_selection_button/file_selection_button.dart'; export './file_selection_button/file_selection_button.dart';
export './flat_button/flat_button.dart'; export './flat_button/flat_button.dart';
export './simple_icon_button/simple_icon_button.dart'; export './simple_icon_button/simple_icon_button.dart';

View File

@ -23,8 +23,19 @@ import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
part 'button_state.dart'; part 'button_state.dart';
class ButtonCubit extends Cubit<ButtonState> { class ButtonCubit extends Cubit<ButtonState> {
ButtonCubit() : super(const ButtonState.initial(ControlState.normal)); ButtonCubit() : super(const ButtonState.initial(ControlState.normal)) {
_previousState = state.copyWith();
}
/// The previous state of the button.
/// This is used to restore the state of the button when
/// the button is enabled again.
ButtonState? _previousState;
/// When the mouse enters the button. The button will change
/// its state to [ControlState.hovered].
///
/// If the button is disabled or freezed, this method does nothing.
FutureOr<void> onMouseEnter() async { FutureOr<void> onMouseEnter() async {
if (state.isDisabled || state.isFreezed) { if (state.isDisabled || state.isFreezed) {
return; return;
@ -32,6 +43,10 @@ class ButtonCubit extends Cubit<ButtonState> {
emit(state.copyWith(state: ControlState.hovered)); emit(state.copyWith(state: ControlState.hovered));
} }
/// When the mouse leaves the button. The button will change
/// its state to [ControlState.normal].
///
/// If the button is disabled or freezed, this method does nothing.
FutureOr<void> onMouseLeave() async { FutureOr<void> onMouseLeave() async {
if (state.isDisabled || state.isFreezed) { if (state.isDisabled || state.isFreezed) {
return; return;
@ -40,6 +55,10 @@ class ButtonCubit extends Cubit<ButtonState> {
emit(state.copyWith(state: ControlState.normal)); emit(state.copyWith(state: ControlState.normal));
} }
/// When the button is focused. The button will change
/// its state to [ControlState.focused].
///
/// If the button is disabled or freezed, this method does nothing.
FutureOr<void> onFocus() async { FutureOr<void> onFocus() async {
if (state.isDisabled || state.isFreezed) { if (state.isDisabled || state.isFreezed) {
return; return;
@ -47,6 +66,10 @@ class ButtonCubit extends Cubit<ButtonState> {
emit(state.copyWith(state: ControlState.focused)); emit(state.copyWith(state: ControlState.focused));
} }
/// When the button is unfocused. The button will change
/// its state to [ControlState.normal].
///
/// If the button is disabled or freezed, this method does nothing.
FutureOr<void> onUnfocus() async { FutureOr<void> onUnfocus() async {
if (state.isDisabled || state.isFreezed) { if (state.isDisabled || state.isFreezed) {
return; return;
@ -54,6 +77,10 @@ class ButtonCubit extends Cubit<ButtonState> {
emit(state.copyWith(state: ControlState.normal)); emit(state.copyWith(state: ControlState.normal));
} }
/// When the mouse is pressed on the button. The button will change
/// its state to [ControlState.tapped].
///
/// If the button is disabled or freezed, this method does nothing.
FutureOr<void> onClickDown() async { FutureOr<void> onClickDown() async {
if (state.isDisabled || state.isFreezed) { if (state.isDisabled || state.isFreezed) {
return; return;
@ -61,39 +88,127 @@ class ButtonCubit extends Cubit<ButtonState> {
emit(state.copyWith(state: ControlState.tapped)); emit(state.copyWith(state: ControlState.tapped));
} }
/// When the mouse is released on the button. The button will change
/// its state to [ControlState.hovered].
///
/// If the button is disabled or freezed, this method does nothing.
FutureOr<void> onClickUpIn() async { FutureOr<void> onClickUpIn() async {
if (state.isDisabled) { if (state.isDisabled || state.isFreezed) {
return; return;
} }
emit(state.copyWith(state: ControlState.hovered)); emit(state.copyWith(state: ControlState.hovered));
} }
/// When the mouse is released outside the button. The button will change
/// its state to [ControlState.normal].
///
/// If the button is disabled or freezed, this method does nothing.
FutureOr<void> onClickUpOut() async { FutureOr<void> onClickUpOut() async {
if (state.isDisabled) { if (state.isDisabled || state.isFreezed) {
return; return;
} }
emit(state.copyWith(state: ControlState.normal)); emit(state.copyWith(state: ControlState.normal));
} }
/// Programmatically change the state or extra states of the button.
FutureOr<void> setState({
ControlState? state,
List<ExtraState>? extraStates,
}) async {
emit(this.state.copyWith(state: state, extraStates: extraStates));
}
/// Disable the button.
///
/// This will remove all extra states and set
/// the state to [ControlState.disabled] and add [ExtraState.freezed].
FutureOr<void> disable() async { FutureOr<void> disable() async {
if (state.isFreezed) { /// Save the previous state.
return; /// copyWith() is used to make sure the previous state is not
} /// affected by any changes to the current state.
emit(state.copyWith(state: ControlState.disabled)); _previousState = state.copyWith();
emit(
const ButtonState(
state: ControlState.disabled,
extraStates: [ExtraState.freezed],
),
);
} }
/// Enable the button.
///
/// This will restore the previous state of the button.
FutureOr<void> enable() async { FutureOr<void> enable() async {
if (state.isFreezed) { if (_previousState == null) {
return; return;
} }
emit(state.copyWith(state: ControlState.normal));
emit(_previousState!);
_previousState = null;
} }
/// Set the button to hovered state and freeze it.
///
/// Use this method to programmatically set the button to hovered state.
FutureOr<void> hover() async {
emit(
state.copyWith(
state: ControlState.hovered,
extraStates: state.extraStates + [ExtraState.freezed],
),
);
}
/// Set the button to focused state and freeze it.
///
/// Use this method to programmatically set the button to focused state.
FutureOr<void> focus() async {
emit(
state.copyWith(
state: ControlState.focused,
extraStates: state.extraStates + [ExtraState.freezed],
),
);
}
/// Set the button to tapped state and freeze it.
///
/// Use this method to programmatically set the button to tapped state.
FutureOr<void> tap() async {
emit(
state.copyWith(
state: ControlState.tapped,
extraStates: state.extraStates + [ExtraState.freezed],
),
);
}
/// Freeze the button in its current state.
///
/// Shortcut for [setState] with extra state [ExtraState.freezed].
///
/// Use this method to programmatically freeze the button.
FutureOr<void> freeze() async { FutureOr<void> freeze() async {
emit(state.copyWith(freezed: true)); emit(
state.copyWith(
extraStates: state.extraStates + [ExtraState.freezed],
),
);
} }
/// Unfreeze the button.
///
/// Shortcut for [setState] without extra state [ExtraState.freezed].
///
/// Use this method to programmatically unfreeze the button.
FutureOr<void> unfreeze() async { FutureOr<void> unfreeze() async {
emit(state.copyWith(freezed: false)); emit(
state.copyWith(
extraStates: state.extraStates
.where((element) => element != ExtraState.freezed)
.toList(),
),
);
} }
} }

View File

@ -18,54 +18,41 @@
part of 'button_cubit.dart'; part of 'button_cubit.dart';
class ButtonState extends Equatable { class ButtonState extends Equatable {
const ButtonState({ const ButtonState({required this.state, required this.extraStates});
required this.state,
required this.selected,
required this.invalid,
required this.freezed,
});
const ButtonState.initial(this.state) const ButtonState.initial(this.state) : extraStates = const [];
: selected = false,
invalid = false,
freezed = false;
/// The control state of the button
final ControlState state; final ControlState state;
// Not in control state, because a button state can be /// Not in control state, because a button state can be
// a control state + extra state /// a control state + extra state
// e.g : hover + invalid, or selected + tapped /// e.g :
final bool selected; /// - ControlState.hover + [ExtraState.invalid]
final bool invalid; /// - ControlState.tapped + [ExtraState.invalid + ExtraState.freezed]
final bool freezed; final List<ExtraState> extraStates;
bool get isDisabled => state.isDisabled(); bool get isDisabled => state.isDisabled();
bool get isEnabled => state.isEnabled(); bool get isEnabled => state.isEnabled();
bool get isFocused => state.isFocused(); bool get isFocused => state.isFocused();
bool get isHovered => state.isHovered(); bool get isHovered => state.isHovered();
bool get isTapped => state.isTapped(); bool get isTapped => state.isTapped();
bool get isSelected => extraStates.contains(ExtraState.selected);
// only for consistence bool get isInvalid => extraStates.contains(ExtraState.invalid);
bool get isSelected => selected; bool get isFreezed => extraStates.contains(ExtraState.freezed);
bool get isInvalid => invalid;
bool get isFreezed => freezed;
@override @override
List<Object?> get props => [state, selected, invalid, freezed]; List<Object?> get props => [state, extraStates];
@override @override
bool? get stringify => true; bool? get stringify => true;
ButtonState copyWith({ ButtonState copyWith({
ControlState? state, ControlState? state,
bool? selected, List<ExtraState>? extraStates,
bool? invalid,
bool? freezed,
}) => }) =>
ButtonState( ButtonState(
state: state ?? this.state, state: state ?? this.state,
selected: selected ?? this.selected, extraStates: extraStates ?? this.extraStates,
invalid: invalid ?? this.invalid,
freezed: freezed ?? this.freezed,
); );
} }

View File

@ -20,49 +20,29 @@ 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';
class InvalidButtonCubit extends ButtonCubit { class InvalidButtonCubit extends ButtonCubit {
@override /// When the button is invalid. The button will add the
FutureOr<void> onClickUpIn() async { /// [ExtraState.invalid] to its extra states.
if (state.isDisabled || state.isFreezed) { ///
return; /// Use [validate] to remove the [ExtraState.invalid] from the extra states.
} ///
/// Use this method to invalidate the button programmatically.
emit(
state.copyWith(
state: ControlState.hovered,
),
);
}
@override
FutureOr<void> onClickUpOut() async {
if (state.isDisabled || state.isFreezed) {
return;
}
emit(
state.copyWith(
state: ControlState.normal,
),
);
}
FutureOr<void> invalidate() async { FutureOr<void> invalidate() async {
if (state.isDisabled || state.isFreezed) { emit(state.copyWith(extraStates: state.extraStates + [ExtraState.invalid]));
return;
}
emit(
state.copyWith(invalid: true),
);
} }
FutureOr<void> fix() async { /// When the button is valid. The button will remove the
if (state.isDisabled || state.isFreezed) { /// [ExtraState.invalid] from its extra states.
return; ///
} /// Use [invalidate] to add the [ExtraState.invalid] to the extra states.
///
/// Use this method to validate the button programmatically.
FutureOr<void> validate() async {
emit( emit(
state.copyWith(invalid: false), state.copyWith(
extraStates: state.extraStates
.where((element) => element != ExtraState.invalid)
.toList(),
),
); );
} }
} }

View File

@ -20,14 +20,32 @@ 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';
class SelectableButtonCubit extends ButtonCubit { class SelectableButtonCubit extends ButtonCubit {
ButtonState _toggle(ButtonState state) {
if (state.isSelected) {
return state.copyWith(
extraStates: state.extraStates
.where((element) => element != ExtraState.selected)
.toList(),
);
} else {
return state.copyWith(
extraStates: state.extraStates + [ExtraState.selected],
);
}
}
/// When the mouse is released on the button, the button will
/// add the [ExtraState.selected] if it is selected, or remove
/// the [ExtraState.selected] if it is not selected.
///
/// If the button is disabled or freezed, this method does nothing.
@override @override
FutureOr<void> onClickUpIn() async { FutureOr<void> onClickUpIn() async {
if (state.isDisabled || state.isFreezed) { if (state.isDisabled || state.isFreezed) {
return; return;
} }
emit(
state.copyWith(state: ControlState.hovered, selected: !state.selected), emit(_toggle(state).copyWith(state: ControlState.hovered));
);
} }
@override @override
@ -35,26 +53,31 @@ class SelectableButtonCubit extends ButtonCubit {
if (state.isDisabled || state.isFreezed) { if (state.isDisabled || state.isFreezed) {
return; return;
} }
emit(state.copyWith(state: ControlState.normal, selected: !state.selected));
emit(_toggle(state).copyWith(state: ControlState.normal));
} }
/// When the button is selected. The button will add the
/// [ExtraState.selected] to its extra states.
///
/// Use this method to select the button programmatically.
FutureOr<void> select() async { FutureOr<void> select() async {
if (state.isDisabled || state.isFreezed) {
return;
}
emit( emit(
state.copyWith(selected: true), state.copyWith(extraStates: state.extraStates + [ExtraState.selected]),
); );
} }
/// When the button is unselected. The button will remove the
/// [ExtraState.selected] from its extra states.
///
/// Use this method to unselect the button programmatically.
FutureOr<void> unselect() async { FutureOr<void> unselect() async {
if (state.isDisabled || state.isFreezed) {
return;
}
emit( emit(
state.copyWith(selected: false), state.copyWith(
extraStates: state.extraStates
.where((element) => element != ExtraState.selected)
.toList(),
),
); );
} }
} }

View File

@ -14,23 +14,22 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
class ExportableBloc<T extends StateStreamableSource<Object?>> /// A class that listens to the state of a [ValueNotifier] and
extends StatelessWidget { /// changes the state of a [ButtonCubit] accordingly.
const ExportableBloc({ abstract class StateListener {
required this.bloc, /// Listens to the state of the [ValueNotifier] and
required this.child, /// changes the state of the [ButtonCubit] accordingly.
super.key, static void listen<B extends ButtonCubit>(
}); ValueNotifier<bool>? state,
B bloc,
final T bloc; ) {
final Widget child; if (state!.value) {
bloc.disable();
@override } else {
Widget build(BuildContext context) => BlocProvider<T>.value( bloc.enable();
value: bloc, }
child: child, }
);
} }

View File

@ -17,8 +17,6 @@
import 'package:flutter/material.dart' hide ButtonStyle; import 'package:flutter/material.dart' hide ButtonStyle;
import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart'; import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/invalid_button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/exportable_bloc.dart';
import 'package:wyatt_ui_kit/src/components/buttons/file_selection_button/file_selection_button_screen.dart'; import 'package:wyatt_ui_kit/src/components/buttons/file_selection_button/file_selection_button_screen.dart';
import 'package:wyatt_ui_kit/src/components/buttons/file_selection_button/file_selection_button_theme_resolver.dart'; import 'package:wyatt_ui_kit/src/components/buttons/file_selection_button/file_selection_button_theme_resolver.dart';
@ -27,7 +25,7 @@ part 'file_selection_button.g.dart';
@ComponentCopyWithExtension() @ComponentCopyWithExtension()
class FileSelectionButton extends FileSelectionButtonComponent class FileSelectionButton extends FileSelectionButtonComponent
with $FileSelectionButtonCWMixin { with $FileSelectionButtonCWMixin {
FileSelectionButton({ const FileSelectionButton({
super.leading, super.leading,
super.title, super.title,
super.subTitle, super.subTitle,
@ -39,15 +37,12 @@ class FileSelectionButton extends FileSelectionButtonComponent
super.selectedStyle, super.selectedStyle,
super.invalidStyle, super.invalidStyle,
super.onPressed, super.onPressed,
super.disabled,
super.mainAxisSize, super.mainAxisSize,
super.themeResolver, super.themeResolver,
super.key, super.key,
}); });
final InvalidButtonCubit _cubit = InvalidButtonCubit();
InvalidButtonCubit get bloc => _cubit;
@override @override
FileSelectionButtonStyle? get disabledStyle => FileSelectionButtonStyle? get disabledStyle =>
super.disabledStyle as FileSelectionButtonStyle?; super.disabledStyle as FileSelectionButtonStyle?;
@ -81,23 +76,21 @@ class FileSelectionButton extends FileSelectionButtonComponent
super.themeResolver as FileSelectionButtonThemeResolver?; super.themeResolver as FileSelectionButtonThemeResolver?;
@override @override
Widget build(BuildContext context) => ExportableBloc( Widget build(BuildContext context) => FileSelectionButtonScreen(
bloc: _cubit, leading: leading,
child: FileSelectionButtonScreen( title: title,
leading: leading, subTitle: subTitle,
title: title, disabledStyle: disabledStyle,
subTitle: subTitle, normalStyle: normalStyle,
disabledStyle: disabledStyle, hoveredStyle: hoveredStyle,
normalStyle: normalStyle, focusedStyle: focusedStyle,
hoveredStyle: hoveredStyle, tappedStyle: tappedStyle,
focusedStyle: focusedStyle, selectedStyle: selectedStyle,
tappedStyle: tappedStyle, invalidStyle: invalidStyle,
selectedStyle: selectedStyle, onPressed: onPressed,
invalidStyle: invalidStyle, disabled: disabled,
onPressed: onPressed, mainAxisSize: mainAxisSize,
mainAxisSize: mainAxisSize, themeResolver: themeResolver,
themeResolver: themeResolver, key: key,
key: key,
),
); );
} }

View File

@ -45,6 +45,9 @@ class $FileSelectionButtonCWProxyImpl
FileSelectionButton onPressed(void Function(ControlState)? onPressed) => FileSelectionButton onPressed(void Function(ControlState)? onPressed) =>
this(onPressed: onPressed); this(onPressed: onPressed);
@override @override
FileSelectionButton disabled(ValueNotifier<bool>? disabled) =>
this(disabled: disabled);
@override
FileSelectionButton themeResolver( FileSelectionButton themeResolver(
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver) => ThemeResolver<dynamic, dynamic, dynamic>? themeResolver) =>
this(themeResolver: themeResolver); this(themeResolver: themeResolver);
@ -64,6 +67,7 @@ class $FileSelectionButtonCWProxyImpl
ButtonStyle<dynamic>? selectedStyle, ButtonStyle<dynamic>? selectedStyle,
ButtonStyle<dynamic>? invalidStyle, ButtonStyle<dynamic>? invalidStyle,
void Function(ControlState)? onPressed, void Function(ControlState)? onPressed,
ValueNotifier<bool>? disabled,
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver, ThemeResolver<dynamic, dynamic, dynamic>? themeResolver,
Key? key, Key? key,
}) => }) =>
@ -79,6 +83,7 @@ class $FileSelectionButtonCWProxyImpl
selectedStyle: selectedStyle ?? _value.selectedStyle, selectedStyle: selectedStyle ?? _value.selectedStyle,
invalidStyle: invalidStyle ?? _value.invalidStyle, invalidStyle: invalidStyle ?? _value.invalidStyle,
onPressed: onPressed ?? _value.onPressed, onPressed: onPressed ?? _value.onPressed,
disabled: disabled ?? _value.disabled,
mainAxisSize: mainAxisSize ?? _value.mainAxisSize, mainAxisSize: mainAxisSize ?? _value.mainAxisSize,
themeResolver: themeResolver ?? _value.themeResolver, themeResolver: themeResolver ?? _value.themeResolver,
key: key ?? _value.key, key: key ?? _value.key,

View File

@ -21,6 +21,7 @@ import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart'; import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/invalid_button_cubit.dart'; import 'package:wyatt_ui_kit/src/components/buttons/cubit/invalid_button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/state_listener.dart';
import 'package:wyatt_ui_kit/src/components/buttons/file_selection_button/dotter_border_child.dart'; import 'package:wyatt_ui_kit/src/components/buttons/file_selection_button/dotter_border_child.dart';
import 'package:wyatt_ui_kit/src/components/buttons/file_selection_button/file_selection_button_theme_resolver.dart'; import 'package:wyatt_ui_kit/src/components/buttons/file_selection_button/file_selection_button_theme_resolver.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart'; import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart';
@ -39,6 +40,7 @@ class FileSelectionButtonScreen
this.selectedStyle, this.selectedStyle,
this.invalidStyle, this.invalidStyle,
this.onPressed, this.onPressed,
this.disabled,
this.mainAxisSize, this.mainAxisSize,
this.themeResolver, this.themeResolver,
super.key, super.key,
@ -58,11 +60,26 @@ class FileSelectionButtonScreen
final FileSelectionButtonStyle? invalidStyle; final FileSelectionButtonStyle? invalidStyle;
final void Function(ControlState state)? onPressed; final void Function(ControlState state)? onPressed;
final ValueNotifier<bool>? disabled;
final FileSelectionButtonThemeResolver? themeResolver; final FileSelectionButtonThemeResolver? themeResolver;
@override @override
InvalidButtonCubit create(BuildContext context) => InvalidButtonCubit(); InvalidButtonCubit create(BuildContext context) => InvalidButtonCubit();
@override
InvalidButtonCubit init(BuildContext context, InvalidButtonCubit bloc) {
disabled?.addListener(
() => StateListener.listen<InvalidButtonCubit>(disabled, bloc),
);
/// Set the initial state depending on the disabled value
/// after adding the listener.
if (disabled?.value ?? false) {
bloc.disable();
}
return bloc;
}
/// Negotiate the theme to get a complete style. /// Negotiate the theme to get a complete style.
FileSelectionButtonStyle _resolve(BuildContext context, ButtonState state) { FileSelectionButtonStyle _resolve(BuildContext context, ButtonState state) {
final FileSelectionButtonThemeResolver resolver = themeResolver ?? final FileSelectionButtonThemeResolver resolver = themeResolver ??

View File

@ -17,8 +17,6 @@
import 'package:flutter/material.dart' hide ButtonStyle; import 'package:flutter/material.dart' hide ButtonStyle;
import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart'; import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/exportable_bloc.dart';
import 'package:wyatt_ui_kit/src/components/buttons/flat_button/flat_button_screen.dart'; import 'package:wyatt_ui_kit/src/components/buttons/flat_button/flat_button_screen.dart';
import 'package:wyatt_ui_kit/src/components/buttons/flat_button/flat_button_theme_resolver.dart'; import 'package:wyatt_ui_kit/src/components/buttons/flat_button/flat_button_theme_resolver.dart';
@ -26,7 +24,7 @@ part 'flat_button.g.dart';
@ComponentCopyWithExtension() @ComponentCopyWithExtension()
class FlatButton extends FlatButtonComponent with $FlatButtonCWMixin { class FlatButton extends FlatButtonComponent with $FlatButtonCWMixin {
FlatButton({ const FlatButton({
super.prefix, super.prefix,
super.suffix, super.suffix,
super.label, super.label,
@ -36,15 +34,12 @@ class FlatButton extends FlatButtonComponent with $FlatButtonCWMixin {
super.focusedStyle, super.focusedStyle,
super.tappedStyle, super.tappedStyle,
super.onPressed, super.onPressed,
super.disabled,
super.mainAxisSize, super.mainAxisSize,
super.themeResolver, super.themeResolver,
super.key, super.key,
}); });
final ButtonCubit _cubit = ButtonCubit();
ButtonCubit get bloc => _cubit;
@override @override
FlatButtonStyle? get disabledStyle => super.disabledStyle as FlatButtonStyle?; FlatButtonStyle? get disabledStyle => super.disabledStyle as FlatButtonStyle?;
@ -65,21 +60,19 @@ class FlatButton extends FlatButtonComponent with $FlatButtonCWMixin {
super.themeResolver as FlatButtonThemeResolver?; super.themeResolver as FlatButtonThemeResolver?;
@override @override
Widget build(BuildContext context) => ExportableBloc( Widget build(BuildContext context) => FlatButtonScreen(
bloc: _cubit, prefix: prefix,
child: FlatButtonScreen( suffix: suffix,
prefix: prefix, label: label,
suffix: suffix, disabledStyle: disabledStyle,
label: label, normalStyle: normalStyle,
disabledStyle: disabledStyle, hoveredStyle: hoveredStyle,
normalStyle: normalStyle, focusedStyle: focusedStyle,
hoveredStyle: hoveredStyle, tappedStyle: tappedStyle,
focusedStyle: focusedStyle, onPressed: onPressed,
tappedStyle: tappedStyle, disabled: disabled,
onPressed: onPressed, mainAxisSize: mainAxisSize,
mainAxisSize: mainAxisSize, themeResolver: themeResolver,
themeResolver: themeResolver, key: key,
key: key,
),
); );
} }

View File

@ -37,6 +37,9 @@ class $FlatButtonCWProxyImpl implements $FlatButtonComponentCWProxy {
FlatButton onPressed(void Function(ControlState)? onPressed) => FlatButton onPressed(void Function(ControlState)? onPressed) =>
this(onPressed: onPressed); this(onPressed: onPressed);
@override @override
FlatButton disabled(ValueNotifier<bool>? disabled) =>
this(disabled: disabled);
@override
FlatButton themeResolver( FlatButton themeResolver(
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver) => ThemeResolver<dynamic, dynamic, dynamic>? themeResolver) =>
this(themeResolver: themeResolver); this(themeResolver: themeResolver);
@ -54,6 +57,7 @@ class $FlatButtonCWProxyImpl implements $FlatButtonComponentCWProxy {
ButtonStyle<dynamic>? focusedStyle, ButtonStyle<dynamic>? focusedStyle,
ButtonStyle<dynamic>? tappedStyle, ButtonStyle<dynamic>? tappedStyle,
void Function(ControlState)? onPressed, void Function(ControlState)? onPressed,
ValueNotifier<bool>? disabled,
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver, ThemeResolver<dynamic, dynamic, dynamic>? themeResolver,
Key? key, Key? key,
}) => }) =>
@ -67,6 +71,7 @@ class $FlatButtonCWProxyImpl implements $FlatButtonComponentCWProxy {
focusedStyle: focusedStyle ?? _value.focusedStyle, focusedStyle: focusedStyle ?? _value.focusedStyle,
tappedStyle: tappedStyle ?? _value.tappedStyle, tappedStyle: tappedStyle ?? _value.tappedStyle,
onPressed: onPressed ?? _value.onPressed, onPressed: onPressed ?? _value.onPressed,
disabled: disabled ?? _value.disabled,
mainAxisSize: mainAxisSize ?? _value.mainAxisSize, mainAxisSize: mainAxisSize ?? _value.mainAxisSize,
themeResolver: themeResolver ?? _value.themeResolver, themeResolver: themeResolver ?? _value.themeResolver,
key: key ?? _value.key, key: key ?? _value.key,

View File

@ -20,6 +20,7 @@ import 'package:gap/gap.dart';
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart'; import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart'; import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/state_listener.dart';
import 'package:wyatt_ui_kit/src/components/buttons/flat_button/flat_button_theme_resolver.dart'; import 'package:wyatt_ui_kit/src/components/buttons/flat_button/flat_button_theme_resolver.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart'; import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart'; import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart';
@ -35,6 +36,7 @@ class FlatButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
this.focusedStyle, this.focusedStyle,
this.tappedStyle, this.tappedStyle,
this.onPressed, this.onPressed,
this.disabled,
this.mainAxisSize, this.mainAxisSize,
this.themeResolver, this.themeResolver,
super.key, super.key,
@ -52,11 +54,23 @@ class FlatButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
final FlatButtonStyle? tappedStyle; final FlatButtonStyle? tappedStyle;
final void Function(ControlState state)? onPressed; final void Function(ControlState state)? onPressed;
final ValueNotifier<bool>? disabled;
final FlatButtonThemeResolver? themeResolver; final FlatButtonThemeResolver? themeResolver;
@override @override
ButtonCubit create(BuildContext context) => ButtonCubit(); ButtonCubit create(BuildContext context) => ButtonCubit();
@override
ButtonCubit init(BuildContext context, ButtonCubit bloc) {
disabled?.addListener(() => StateListener.listen(disabled, bloc));
/// Set the initial state depending on the disabled value
/// after adding the listener.
if (disabled?.value ?? false) {
bloc.disable();
}
return bloc;
}
/// Negotiate the theme to get a complete style. /// Negotiate the theme to get a complete style.
FlatButtonStyle _resolve(BuildContext context, ControlState state) { FlatButtonStyle _resolve(BuildContext context, ControlState state) {
final FlatButtonThemeResolver resolver = themeResolver ?? final FlatButtonThemeResolver resolver = themeResolver ??

View File

@ -17,8 +17,6 @@
import 'package:flutter/material.dart' hide ButtonStyle; import 'package:flutter/material.dart' hide ButtonStyle;
import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart'; import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/exportable_bloc.dart';
import 'package:wyatt_ui_kit/src/components/buttons/simple_icon_button/simple_icon_button_theme_resolver.dart'; import 'package:wyatt_ui_kit/src/components/buttons/simple_icon_button/simple_icon_button_theme_resolver.dart';
import 'package:wyatt_ui_kit/src/components/buttons/simple_icon_button/simple_icon_screen.dart'; import 'package:wyatt_ui_kit/src/components/buttons/simple_icon_button/simple_icon_screen.dart';
@ -27,7 +25,7 @@ part 'simple_icon_button.g.dart';
@ComponentCopyWithExtension() @ComponentCopyWithExtension()
class SimpleIconButton extends SimpleIconButtonComponent class SimpleIconButton extends SimpleIconButtonComponent
with $SimpleIconButtonCWMixin { with $SimpleIconButtonCWMixin {
SimpleIconButton({ const SimpleIconButton({
super.icon, super.icon,
super.disabledStyle, super.disabledStyle,
super.normalStyle, super.normalStyle,
@ -35,14 +33,11 @@ class SimpleIconButton extends SimpleIconButtonComponent
super.focusedStyle, super.focusedStyle,
super.tappedStyle, super.tappedStyle,
super.onPressed, super.onPressed,
super.disabled,
super.themeResolver, super.themeResolver,
super.key, super.key,
}); });
final ButtonCubit _cubit = ButtonCubit();
ButtonCubit get bloc => _cubit;
@override @override
SimpleIconButtonStyle? get disabledStyle => SimpleIconButtonStyle? get disabledStyle =>
super.disabledStyle as SimpleIconButtonStyle?; super.disabledStyle as SimpleIconButtonStyle?;
@ -68,18 +63,16 @@ class SimpleIconButton extends SimpleIconButtonComponent
super.themeResolver as SimpleIconButtonThemeResolver?; super.themeResolver as SimpleIconButtonThemeResolver?;
@override @override
Widget build(BuildContext context) => ExportableBloc( Widget build(BuildContext context) => SimpleIconButtonScreen(
bloc: _cubit, icon: icon,
child: SimpleIconButtonScreen( disabledStyle: disabledStyle,
icon: icon, normalStyle: normalStyle,
disabledStyle: disabledStyle, hoveredStyle: hoveredStyle,
normalStyle: normalStyle, focusedStyle: focusedStyle,
hoveredStyle: hoveredStyle, tappedStyle: tappedStyle,
focusedStyle: focusedStyle, onPressed: onPressed,
tappedStyle: tappedStyle, disabled: disabled,
onPressed: onPressed, themeResolver: themeResolver,
themeResolver: themeResolver, key: key,
key: key,
),
); );
} }

View File

@ -31,6 +31,9 @@ class $SimpleIconButtonCWProxyImpl
SimpleIconButton onPressed(void Function(ControlState)? onPressed) => SimpleIconButton onPressed(void Function(ControlState)? onPressed) =>
this(onPressed: onPressed); this(onPressed: onPressed);
@override @override
SimpleIconButton disabled(ValueNotifier<bool>? disabled) =>
this(disabled: disabled);
@override
SimpleIconButton themeResolver( SimpleIconButton themeResolver(
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver) => ThemeResolver<dynamic, dynamic, dynamic>? themeResolver) =>
this(themeResolver: themeResolver); this(themeResolver: themeResolver);
@ -45,6 +48,7 @@ class $SimpleIconButtonCWProxyImpl
ButtonStyle<dynamic>? focusedStyle, ButtonStyle<dynamic>? focusedStyle,
ButtonStyle<dynamic>? tappedStyle, ButtonStyle<dynamic>? tappedStyle,
void Function(ControlState)? onPressed, void Function(ControlState)? onPressed,
ValueNotifier<bool>? disabled,
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver, ThemeResolver<dynamic, dynamic, dynamic>? themeResolver,
Key? key, Key? key,
}) => }) =>
@ -56,6 +60,7 @@ class $SimpleIconButtonCWProxyImpl
focusedStyle: focusedStyle ?? _value.focusedStyle, focusedStyle: focusedStyle ?? _value.focusedStyle,
tappedStyle: tappedStyle ?? _value.tappedStyle, tappedStyle: tappedStyle ?? _value.tappedStyle,
onPressed: onPressed ?? _value.onPressed, onPressed: onPressed ?? _value.onPressed,
disabled: disabled ?? _value.disabled,
themeResolver: themeResolver ?? _value.themeResolver, themeResolver: themeResolver ?? _value.themeResolver,
key: key ?? _value.key, key: key ?? _value.key,
); );

View File

@ -19,6 +19,7 @@ import 'package:flutter/services.dart';
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart'; import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart'; import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/state_listener.dart';
import 'package:wyatt_ui_kit/src/components/buttons/simple_icon_button/simple_icon_button_theme_resolver.dart'; import 'package:wyatt_ui_kit/src/components/buttons/simple_icon_button/simple_icon_button_theme_resolver.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart'; import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_icon.dart'; import 'package:wyatt_ui_kit/src/components/gradients/gradient_icon.dart';
@ -33,6 +34,7 @@ class SimpleIconButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
this.focusedStyle, this.focusedStyle,
this.tappedStyle, this.tappedStyle,
this.onPressed, this.onPressed,
this.disabled,
this.themeResolver, this.themeResolver,
super.key, super.key,
}); });
@ -46,11 +48,24 @@ class SimpleIconButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
final SimpleIconButtonStyle? tappedStyle; final SimpleIconButtonStyle? tappedStyle;
final void Function(ControlState state)? onPressed; final void Function(ControlState state)? onPressed;
final ValueNotifier<bool>? disabled;
final SimpleIconButtonThemeResolver? themeResolver; final SimpleIconButtonThemeResolver? themeResolver;
@override @override
ButtonCubit create(BuildContext context) => ButtonCubit(); ButtonCubit create(BuildContext context) => ButtonCubit();
@override
ButtonCubit init(BuildContext context, ButtonCubit bloc) {
disabled?.addListener(() => StateListener.listen(disabled, bloc));
/// Set the initial state depending on the disabled value
/// after adding the listener.
if (disabled?.value ?? false) {
bloc.disable();
}
return bloc;
}
/// Negotiate the theme to get a complete style. /// Negotiate the theme to get a complete style.
SimpleIconButtonStyle _resolve(BuildContext context, ControlState state) { SimpleIconButtonStyle _resolve(BuildContext context, ControlState state) {
final SimpleIconButtonThemeResolver resolver = themeResolver ?? final SimpleIconButtonThemeResolver resolver = themeResolver ??

View File

@ -17,17 +17,14 @@
import 'package:flutter/material.dart' hide ButtonStyle; import 'package:flutter/material.dart' hide ButtonStyle;
import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart'; import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/selectable_button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/exportable_bloc.dart';
import 'package:wyatt_ui_kit/src/components/buttons/symbol_button/symbol_button_screen.dart'; import 'package:wyatt_ui_kit/src/components/buttons/symbol_button/symbol_button_screen.dart';
import 'package:wyatt_ui_kit/src/components/buttons/symbol_button/symbol_button_theme_resolver.dart'; import 'package:wyatt_ui_kit/src/components/buttons/symbol_button/symbol_button_theme_resolver.dart';
part 'symbol_button.g.dart'; part 'symbol_button.g.dart';
@ComponentCopyWithExtension() @ComponentCopyWithExtension()
class SymbolButton extends SymbolButtonComponent class SymbolButton extends SymbolButtonComponent with $SymbolButtonCWMixin {
with $SymbolButtonCWMixin{ const SymbolButton({
SymbolButton({
super.icon, super.icon,
super.label, super.label,
super.disabledStyle, super.disabledStyle,
@ -39,13 +36,10 @@ class SymbolButton extends SymbolButtonComponent
super.mainAxisSize, super.mainAxisSize,
super.themeResolver, super.themeResolver,
super.onPressed, super.onPressed,
super.disabled,
super.key, super.key,
}); });
final SelectableButtonCubit _cubit = SelectableButtonCubit();
SelectableButtonCubit get bloc => _cubit;
@override @override
SymbolButtonStyle? get disabledStyle => SymbolButtonStyle? get disabledStyle =>
super.disabledStyle as SymbolButtonStyle?; super.disabledStyle as SymbolButtonStyle?;
@ -73,21 +67,19 @@ class SymbolButton extends SymbolButtonComponent
super.themeResolver as SymbolButtonThemeResolver?; super.themeResolver as SymbolButtonThemeResolver?;
@override @override
Widget build(BuildContext context) => ExportableBloc( Widget build(BuildContext context) => SymbolButtonScreen(
bloc: _cubit, icon: icon,
child: SymbolButtonScreen( label: label,
icon: icon, disabledStyle: disabledStyle,
label: label, normalStyle: normalStyle,
disabledStyle: disabledStyle, hoveredStyle: hoveredStyle,
normalStyle: normalStyle, focusedStyle: focusedStyle,
hoveredStyle: hoveredStyle, tappedStyle: tappedStyle,
focusedStyle: focusedStyle, selectedStyle: selectedStyle,
tappedStyle: tappedStyle, onPressed: onPressed,
selectedStyle: selectedStyle, disabled: disabled,
onPressed: onPressed, mainAxisSize: mainAxisSize,
mainAxisSize: mainAxisSize, themeResolver: themeResolver,
themeResolver: themeResolver, key: key,
key: key,
),
); );
} }

View File

@ -38,6 +38,9 @@ class $SymbolButtonCWProxyImpl implements $SymbolButtonComponentCWProxy {
SymbolButton onPressed(void Function(ControlState)? onPressed) => SymbolButton onPressed(void Function(ControlState)? onPressed) =>
this(onPressed: onPressed); this(onPressed: onPressed);
@override @override
SymbolButton disabled(ValueNotifier<bool>? disabled) =>
this(disabled: disabled);
@override
SymbolButton themeResolver( SymbolButton themeResolver(
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver) => ThemeResolver<dynamic, dynamic, dynamic>? themeResolver) =>
this(themeResolver: themeResolver); this(themeResolver: themeResolver);
@ -55,6 +58,7 @@ class $SymbolButtonCWProxyImpl implements $SymbolButtonComponentCWProxy {
ButtonStyle<dynamic>? tappedStyle, ButtonStyle<dynamic>? tappedStyle,
ButtonStyle<dynamic>? selectedStyle, ButtonStyle<dynamic>? selectedStyle,
void Function(ControlState)? onPressed, void Function(ControlState)? onPressed,
ValueNotifier<bool>? disabled,
ThemeResolver<dynamic, dynamic, dynamic>? themeResolver, ThemeResolver<dynamic, dynamic, dynamic>? themeResolver,
Key? key, Key? key,
}) => }) =>
@ -70,6 +74,7 @@ class $SymbolButtonCWProxyImpl implements $SymbolButtonComponentCWProxy {
mainAxisSize: mainAxisSize ?? _value.mainAxisSize, mainAxisSize: mainAxisSize ?? _value.mainAxisSize,
themeResolver: themeResolver ?? _value.themeResolver, themeResolver: themeResolver ?? _value.themeResolver,
onPressed: onPressed ?? _value.onPressed, onPressed: onPressed ?? _value.onPressed,
disabled: disabled ?? _value.disabled,
key: key ?? _value.key, key: key ?? _value.key,
); );
} }

View File

@ -21,6 +21,7 @@ import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart'; import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/selectable_button_cubit.dart'; import 'package:wyatt_ui_kit/src/components/buttons/cubit/selectable_button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/state_listener.dart';
import 'package:wyatt_ui_kit/src/components/buttons/symbol_button/symbol_button_theme_resolver.dart'; import 'package:wyatt_ui_kit/src/components/buttons/symbol_button/symbol_button_theme_resolver.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart'; import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart'; import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart';
@ -37,6 +38,7 @@ class SymbolButtonScreen
this.tappedStyle, this.tappedStyle,
this.selectedStyle, this.selectedStyle,
this.onPressed, this.onPressed,
this.disabled,
this.mainAxisSize, this.mainAxisSize,
this.themeResolver, this.themeResolver,
super.key, super.key,
@ -54,11 +56,26 @@ class SymbolButtonScreen
final SymbolButtonStyle? selectedStyle; final SymbolButtonStyle? selectedStyle;
final void Function(ControlState state)? onPressed; final void Function(ControlState state)? onPressed;
final ValueNotifier<bool>? disabled;
final SymbolButtonThemeResolver? themeResolver; final SymbolButtonThemeResolver? themeResolver;
@override @override
SelectableButtonCubit create(BuildContext context) => SelectableButtonCubit(); SelectableButtonCubit create(BuildContext context) => SelectableButtonCubit();
@override
SelectableButtonCubit init(BuildContext context, SelectableButtonCubit bloc) {
disabled?.addListener(
() => StateListener.listen<SelectableButtonCubit>(disabled, bloc),
);
/// Set the initial state depending on the disabled value
/// after adding the listener.
if (disabled?.value ?? false) {
bloc.disable();
}
return bloc;
}
/// Negotiate the theme to get a complete style. /// Negotiate the theme to get a complete style.
SymbolButtonStyle _resolve(BuildContext context, ButtonState state) { SymbolButtonStyle _resolve(BuildContext context, ButtonState state) {
final SymbolButtonThemeResolver resolver = themeResolver ?? final SymbolButtonThemeResolver resolver = themeResolver ??