From 40f17efd30c77dfd521f9caa431785a6e0302a12 Mon Sep 17 00:00:00 2001 From: "Michael W. Aziz" Date: Tue, 11 Feb 2025 15:26:44 +0200 Subject: [PATCH] [SYNC] --- lib/astromic_elements.dart | 12 +- lib/src/Buttons/buttons.astromic.dart | 22 - lib/src/Buttons/src/base.dart | 2 +- lib/src/Buttons/src/enums/enums.exports.dart | 2 +- lib/src/Fields/fields.astromic.dart | 22 +- lib/src/Fields/src/base.dart | 4 +- lib/src/Fields/src/enums/enums.exports.dart | 2 +- lib/src/Fields/src/models/models.exports.dart | 4 +- lib/src/Selectors/selectors.astromic.dart | 83 ++- lib/src/Selectors/src/Chip/chip.selector.dart | 79 +-- .../src/Chip/models/configuration.model.dart | 2 + .../src/Chip/models/models.exports.dart | 1 + .../src/Radio/models/configuration.model.dart | 9 +- .../src/Radio/models/models.exports.dart | 1 + .../Selectors/src/Radio/radio.selector.dart | 120 ++--- lib/src/Spacing/spacing.astromic.dart | 5 + lib/src/Toggles/Checkbox/checkbox.toggle.dart | 84 ++- .../Checkbox/models/models.exports.dart | 1 + .../{style.dart => models/style.model.dart} | 12 +- lib/src/Toggles/Custom/custom.toggle.dart | 128 ----- .../Switcher/models/models.exports.dart | 1 + .../{style.dart => models/style.model.dart} | 1 + lib/src/Toggles/Switcher/switcher.toggle.dart | 66 +-- .../Toggles/models/configuration.model.dart | 29 + lib/src/Toggles/models/models.exports.dart | 1 + lib/src/Toggles/toggles.astromic.dart | 84 +-- lib/src/Widgets/src/image.widget.dart | 498 +++++++++++------- lib/src/Widgets/widgets.astromic.dart | 86 ++- 28 files changed, 580 insertions(+), 781 deletions(-) create mode 100644 lib/src/Selectors/src/Chip/models/models.exports.dart create mode 100644 lib/src/Selectors/src/Radio/models/models.exports.dart create mode 100644 lib/src/Toggles/Checkbox/models/models.exports.dart rename lib/src/Toggles/Checkbox/{style.dart => models/style.model.dart} (75%) delete mode 100644 lib/src/Toggles/Custom/custom.toggle.dart create mode 100644 lib/src/Toggles/Switcher/models/models.exports.dart rename lib/src/Toggles/Switcher/{style.dart => models/style.model.dart} (95%) create mode 100644 lib/src/Toggles/models/configuration.model.dart create mode 100644 lib/src/Toggles/models/models.exports.dart diff --git a/lib/astromic_elements.dart b/lib/astromic_elements.dart index 9840125..883b99e 100644 --- a/lib/astromic_elements.dart +++ b/lib/astromic_elements.dart @@ -1,9 +1,9 @@ library astromic_elements; -export './src/Spacing/spacing.astromic.dart'; -export './src/Widgets/widgets.astromic.dart'; -export './src/Selectors/selectors.astromic.dart'; -export './src/Toggles/toggles.astromic.dart'; -export './src/Buttons/buttons.astromic.dart'; -export './src/Fields/fields.astromic.dart'; +export 'src/spacing/spacing.astromic.dart'; +export 'src/widgets/widgets.astromic.dart'; +export 'src/selectors/selectors.astromic.dart'; +export 'src/toggles/toggles.astromic.dart'; +export 'src/buttons/buttons.astromic.dart'; +export 'src/fields/fields.astromic.dart'; export 'package:flutter_svg/flutter_svg.dart' show SvgPicture, BytesLoader, SvgAssetLoader; //Needed for assets manipulation diff --git a/lib/src/Buttons/buttons.astromic.dart b/lib/src/Buttons/buttons.astromic.dart index 6dc3ce1..5042aa9 100644 --- a/lib/src/Buttons/buttons.astromic.dart +++ b/lib/src/Buttons/buttons.astromic.dart @@ -10,7 +10,6 @@ import 'package:flutter/material.dart'; import 'src/icon_button.dart'; import 'src/link_button.dart'; import 'src/state_button.dart'; -// import 'src/enums/enums.exports.dart'; import 'src/models/models.exports.dart'; //s1 Exports @@ -21,74 +20,56 @@ export 'src/models/models.exports.dart'; class AstromicButtons { /// an `AstromicStateButton` is a button whoose style is affected by it's state. static Widget state({ - // void Function(VoidCallback start, VoidCallback stop)? onTap, Function(VoidCallback start, VoidCallback stop)? onHold, - // AstromicButtonConfiguration? configuration, - // AstromicSizingStrategy? widthSizingStrategy, AstromicSizingStrategy? heightSizingStrategy, InteractiveInkFeatureFactory? splashFactory, required AstromicButtonStyle Function(bool isEnabled, bool isHighlighted, bool isLoading) style, - // Widget? loadingContent, required Widget Function(bool isEnabled, bool isHighlighted) content, }) => AstromicStateButton( onTap: onTap, onHold: onHold, - // configuration: configuration, - // widthSizingStrategy: widthSizingStrategy, heightSizingStrategy: heightSizingStrategy, style: style, - // loadingContent: loadingContent, content: content, ); /// an `AstromicIconButton` is a button specifically for mapping to an IconButton. static Widget icon({ - // void Function(VoidCallback start, VoidCallback stop)? onTap, Function(VoidCallback start, VoidCallback stop)? onHold, - // AstromicButtonConfiguration? configuration, - // bool? isCircular, InteractiveInkFeatureFactory? splashFactory, required AstromicButtonStyle Function(bool isEnabled, bool isHighlighted, bool isLoading) style, - // Widget? loadingContent, required Widget Function(bool isEnabled, bool isHighlighted) icon, }) => AstromicIconButton( onTap: onTap, onHold: onHold, - // configuration: configuration, - // isCircular: isCircular ?? true, style: style, - // loadingContent: loadingContent, icon: icon, ); /// an `AstromicLinkButton` is a button specifically for mapping to LinkButton. static Widget link({ - // VoidCallback? onTap, VoidCallback? onHold, - // AstromicButtonConfiguration? configuration, - // bool Function(bool isEnabled)? isUnderlined, EdgeInsetsGeometry? contentPadding, TextStyle Function(bool isEnabled)? style, - // String? text, Widget? textWidget, Widget? prefix, @@ -97,13 +78,10 @@ class AstromicButtons { AstromicLinkButton( onTap: onTap, onHold: onHold, - // configuration: configuration, - // isUnderlined: isUnderlined ?? (e) => e, contentPadding: contentPadding, style: style, - // text: text, textWidget: textWidget, prefix: prefix, diff --git a/lib/src/Buttons/src/base.dart b/lib/src/Buttons/src/base.dart index 123bea8..c5b18d4 100644 --- a/lib/src/Buttons/src/base.dart +++ b/lib/src/Buttons/src/base.dart @@ -2,7 +2,7 @@ //s2 Core Package Imports import 'package:flutter/material.dart'; //s2 1st-party Package Imports -import '../../../Dependencies/gradient_border/gradient_borders.dart'; +import '../../../dependencies/gradient_border/gradient_borders.dart'; //s2 3rd-party Package Imports //s2 Dependancies Imports //s3 Routes diff --git a/lib/src/Buttons/src/enums/enums.exports.dart b/lib/src/Buttons/src/enums/enums.exports.dart index 2c39c52..2b2f031 100644 --- a/lib/src/Buttons/src/enums/enums.exports.dart +++ b/lib/src/Buttons/src/enums/enums.exports.dart @@ -1 +1 @@ -export './sizing_strategy.enum.dart'; +export 'sizing_strategy.enum.dart'; diff --git a/lib/src/Fields/fields.astromic.dart b/lib/src/Fields/fields.astromic.dart index 7fd4f3d..a7eebfe 100644 --- a/lib/src/Fields/fields.astromic.dart +++ b/lib/src/Fields/fields.astromic.dart @@ -1,9 +1,16 @@ +//s1 Imports +//s2 Core Package Imports import 'package:flutter/widgets.dart'; -// +//s2 1st-party Package Imports +//s2 3rd-party Package Imports +//s2 Dependancies Imports +//s3 Routes +//s3 Services +//s3 Models import 'src/text_field.dart'; import 'src/action_field.dart'; import 'src/models/models.exports.dart'; -// +//s1 Exports export 'src/models/models.exports.dart'; export 'src/enums/enums.exports.dart'; @@ -12,20 +19,14 @@ class AstromicFields { static Widget text({ required TextEditingController controller, Key? stateKey, - // void Function(String v)? onChanged, void Function(String v)? onSubmited, - // AstromicFieldConfiguration? configuration, - // AstromicFieldStyle Function(bool isEnabled, bool isFocused)? style, - // String? hint, - // Widget? Function(bool isEnabled, bool isFocused, VoidCallback stateSetter)? prefixWidget, Widget? Function(bool isEnabled, bool isFocused, VoidCallback stateSetter)? suffixWidget, Widget? Function(bool isEnabled, bool isFocused)? messageBuilder, - // Iterable? contextButtons, }) => Column( @@ -51,19 +52,14 @@ class AstromicFields { {Key? stateKey, (T item, String label)? initialValue, required TextEditingController controller, - // Future<(T item, String label)?> Function((T item, String label)? currentValue)? onTap, Future<(T item, String label)?> Function((T item, String label)? currentValue)? onHold, /// Map the old controller value and the new selected value to how it will look in the field. e.g Adding a new choosen value as a list in the field. required String Function(String? oldValue, String newValue) onValueChangedMapper, - // AstromicFieldConfiguration? configuration, - // AstromicFieldStyle Function(bool isEnabled)? style, - // String? hint, - // Widget? Function(bool isEnabled, VoidCallback stateSetter)? prefixWidget, Widget? Function(bool isEnabled, VoidCallback stateSetter)? suffixWidget, Widget? Function(bool isEnabled)? messageBuilder}) => diff --git a/lib/src/Fields/src/base.dart b/lib/src/Fields/src/base.dart index 3703af6..5f0f3f4 100644 --- a/lib/src/Fields/src/base.dart +++ b/lib/src/Fields/src/base.dart @@ -10,8 +10,8 @@ import 'package:astromic_extensions/astromic_extensions.dart'; //s3 Routes //s3 Services //s3 Models -import '../../../Dependencies/gradient_border/gradient_borders.dart'; -import '../../../Dependencies/gradient_border/input_borders/gradient_underline_input_border.dart'; +import '../../../dependencies/gradient_border/gradient_borders.dart'; +import '../../../dependencies/gradient_border/input_borders/gradient_underline_input_border.dart'; import 'enums/enums.exports.dart'; import 'models/models.exports.dart'; //s1 Exports diff --git a/lib/src/Fields/src/enums/enums.exports.dart b/lib/src/Fields/src/enums/enums.exports.dart index ff95ce4..d49d036 100644 --- a/lib/src/Fields/src/enums/enums.exports.dart +++ b/lib/src/Fields/src/enums/enums.exports.dart @@ -1 +1 @@ -export './border_type.enum.dart'; +export 'border_type.enum.dart'; diff --git a/lib/src/Fields/src/models/models.exports.dart b/lib/src/Fields/src/models/models.exports.dart index be581d0..40d868b 100644 --- a/lib/src/Fields/src/models/models.exports.dart +++ b/lib/src/Fields/src/models/models.exports.dart @@ -1,2 +1,2 @@ -export './style.model.dart'; -export './configuration.model.dart'; +export 'style.model.dart'; +export 'configuration.model.dart'; diff --git a/lib/src/Selectors/selectors.astromic.dart b/lib/src/Selectors/selectors.astromic.dart index da20aa1..823742c 100644 --- a/lib/src/Selectors/selectors.astromic.dart +++ b/lib/src/Selectors/selectors.astromic.dart @@ -1,79 +1,58 @@ -//s2 Core Packages Imports +//s1 Imports +//s2 Core Package Imports import 'package:flutter/widgets.dart'; -import 'src/Radio/radio.selector.dart'; -import 'src/Chip/chip.selector.dart'; -import 'src/Radio/models/configuration.model.dart'; -import 'src/Chip/models/configuration.model.dart'; -// -export 'src/Radio/models/configuration.model.dart'; -export 'src/Chip/models/configuration.model.dart'; +//s2 1st-party Package Imports +//s2 3rd-party Package Imports +//s2 Dependancies Imports +//s3 Routes +//s3 Services +//s3 Models +import 'src/radio/radio.selector.dart'; +import 'src/chip/chip.selector.dart'; +import 'src/radio/models/models.exports.dart'; +import 'src/chip/models/models.exports.dart'; +//s1 Exports +export 'src/radio/models/models.exports.dart'; +export 'src/chip/models/models.exports.dart'; class AstromicSelectors { - //S1 -- Radio + /// A selector that allows only one item to be selected from a group of items. static Widget radio({ T? initialSelectedValue, Function(T selectedItem)? onChanged, - // AstromicRadioSelectorConfiguration? configurations, - // double? itemSpacing = 4, - // - required Widget Function(T item, bool isEnabled, bool isSelected, VoidCallback? onTap) itemBuilder, required List<(T item, bool isEnabled)> items, + required Widget Function(T item, bool isEnabled, bool isSelected, VoidCallback? onTap) itemBuilder, }) => AstromicRadioSelector( initialSelectedValue: initialSelectedValue, onChanged: onChanged, - // - configuration: configurations ?? const AstromicRadioSelectorConfiguration(), - // - itemSpacing: itemSpacing ?? 8.0, - // + configuration: configurations, + itemSpacing: itemSpacing, itemBuilder: itemBuilder, items: items, ); - //S1 -- Chip + /// A selector that allows multible items to be selected from a group of items with the option to unselect and clear. static Widget chip({ List? initialSelectedValues, void Function(List selectedItems)? onChanged, - // AstromicChipSelectorConfiguration? configuration, - bool isCustom = false, - // double? itemSpacing = 4, double? runSpacing = 8, - // required List<(T item, bool isEnabled)> items, required Widget Function(T item, bool isEnabled, bool isSelected, VoidCallback? onTap, VoidCallback? onClearTapped) itemBuilder, Widget Function(List items)? groupBuilder, - }) { - assert( - (!isCustom || groupBuilder != null), - "You have to provide the group builder in a custom constructor.", - ); - return isCustom - ? AstromicChipSelector.custom( - initialSelectedValues: initialSelectedValues, - onChanged: onChanged, - // - configuration: configuration, - // - items: items, - itemBuilder: itemBuilder, - groupBuilder: groupBuilder!, - ) - : AstromicChipSelector( - initialSelectedValues: initialSelectedValues, - onChanged: onChanged, - // - configuration: configuration, - // - itemSpacing: itemSpacing, - runSpacing: runSpacing, - // - items: items, - itemBuilder: itemBuilder, - ); - } + }) => + AstromicChipSelector( + initialSelectedValues: initialSelectedValues, + onChanged: onChanged, + configuration: configuration, + itemSpacing: itemSpacing, + runSpacing: runSpacing, + items: items, + itemBuilder: itemBuilder, + groupBuilder: groupBuilder!, + ); } diff --git a/lib/src/Selectors/src/Chip/chip.selector.dart b/lib/src/Selectors/src/Chip/chip.selector.dart index d892285..d83395f 100644 --- a/lib/src/Selectors/src/Chip/chip.selector.dart +++ b/lib/src/Selectors/src/Chip/chip.selector.dart @@ -1,31 +1,23 @@ -//SECTION - Imports -// -//s1 PACKAGES -//--------------- -//s2 CORE -import 'package:astromic_extensions/astromic_extensions.dart'; +//s1 Imports +//s2 Core Package Imports import 'package:flutter/material.dart'; -//s2 3RD-PARTY -// -//s1 DEPENDENCIES -//--------------- -//s2 SERVICES -//s2 MODELS -import 'models/configuration.model.dart'; +//s2 1st-party Package Imports +import 'package:astromic_extensions/astromic_extensions.dart'; +//s2 3rd-party Package Imports +//s2 Dependancies Imports +//s3 Routes +//s3 Services +//s3 Models +import 'models/models.exports.dart'; +//s1 Exports -//s2 MISC -//!SECTION - Imports -// -//SECTION - Exports -//!SECTION - Exports -// +/// Selector that allows multible items to be selected from a group of items with the option to unselect and clear. class AstromicChipSelector extends StatefulWidget { //SECTION - Widget Arguments //s1 -- Functionality final List? initialSelectedValues; final Function(List selectedItems)? onChanged; //s1 -- Configuration - final bool isCustom; final AstromicChipSelectorConfiguration? configuration; //s1 -- Style final double? itemSpacing; @@ -33,7 +25,6 @@ class AstromicChipSelector extends StatefulWidget { // //s1 -- Content final List<(T item, bool isEnabled)> items; - // final Widget Function(T item, bool isEnabled, bool isSelected, VoidCallback? onTap, VoidCallback? onClearTapped) itemBuilder; final Widget Function(List items)? groupBuilder; //!SECTION @@ -45,7 +36,6 @@ class AstromicChipSelector extends StatefulWidget { this.onChanged, //s1 -- Configuration this.configuration, - this.isCustom = false, //s1 -- Style this.itemSpacing = 8, this.runSpacing = 8, @@ -57,46 +47,10 @@ class AstromicChipSelector extends StatefulWidget { (configuration?.isNullable ?? true) || (initialSelectedValues != null && items.map((i) => i.$1).toList().containsAll(initialSelectedValues)), "Initial values are not all present in the items!", ), - assert( - (!isCustom || groupBuilder != null), - "You have to provide the group builder in a custom constructor.", - ), super( key: key, ); - static AstromicChipSelector custom({ - Key? key, - //s1 -- Functionality - final List? initialSelectedValues, - final Function(List selectedItems)? onChanged, - //s1 -- Configuration - final AstromicChipSelectorConfiguration? configuration, - //s1 -- Content - required final List<(T item, bool isEnabled)> items, - // - required final Widget Function(T item, bool isEnabled, bool isSelected, VoidCallback? onTap, VoidCallback? onClearTapped) itemBuilder, - required final Widget Function(List items) groupBuilder, - }) { - assert((configuration?.isNullable ?? true) || (initialSelectedValues != null && items.map((i) => i.$1).toList().containsAll(initialSelectedValues)), - "Initial values are not all present in the items!"); - - // - return AstromicChipSelector( - key: key, - isCustom: true, - // - initialSelectedValues: initialSelectedValues, - onChanged: onChanged, - // - configuration: configuration, - // - items: items, - itemBuilder: itemBuilder, - groupBuilder: groupBuilder, - ); - } - @override State> createState() => _AstromicChipSelectorState(); } @@ -141,13 +95,11 @@ class _AstromicChipSelectorState extends State> { _onTap(T value) { setState(() { if (selectedItems.contains(value)) { - //---- if item selected + // Item is selected selectedItems.remove(value); - //---- !if item selected } else { - //---- if item Not selected + // Item is NOT selected selectedItems.add(value); - //---- !if item Not selected } }); if (widget.onChanged != null) { @@ -155,7 +107,6 @@ class _AstromicChipSelectorState extends State> { } } - // ---- _onTapClear(T value) { setState(() { if (selectedItems.contains(value)) { @@ -216,7 +167,7 @@ class _AstromicChipSelectorState extends State> { //s1 -Widgets //!SECTION //SECTION - Build Return - return widget.isCustom && widget.groupBuilder != null + return widget.groupBuilder != null ? widget.groupBuilder!(baseChildren) : (widget.configuration?.isWrap ?? true) ? Wrap( diff --git a/lib/src/Selectors/src/Chip/models/configuration.model.dart b/lib/src/Selectors/src/Chip/models/configuration.model.dart index bd1bac3..cf496d5 100644 --- a/lib/src/Selectors/src/Chip/models/configuration.model.dart +++ b/lib/src/Selectors/src/Chip/models/configuration.model.dart @@ -1,5 +1,7 @@ import 'package:flutter/widgets.dart'; +/// Configuration model for the chip selector element. + class AstromicChipSelectorConfiguration { final bool isNullable; final bool isWrap; diff --git a/lib/src/Selectors/src/Chip/models/models.exports.dart b/lib/src/Selectors/src/Chip/models/models.exports.dart new file mode 100644 index 0000000..a30a0b3 --- /dev/null +++ b/lib/src/Selectors/src/Chip/models/models.exports.dart @@ -0,0 +1 @@ +export 'configuration.model.dart'; diff --git a/lib/src/Selectors/src/Radio/models/configuration.model.dart b/lib/src/Selectors/src/Radio/models/configuration.model.dart index a89474c..379d163 100644 --- a/lib/src/Selectors/src/Radio/models/configuration.model.dart +++ b/lib/src/Selectors/src/Radio/models/configuration.model.dart @@ -1,34 +1,35 @@ import 'package:flutter/widgets.dart'; +/// Configuration model for the radio selector element. class AstromicRadioSelectorConfiguration { final Axis axis; final bool isNullable; - final bool withExpandedSpace; // final MainAxisAlignment? mainAxisAlignment; + final MainAxisSize? mainAxisSize; final CrossAxisAlignment? crossAxisAlignment; const AstromicRadioSelectorConfiguration({ this.axis = Axis.horizontal, this.isNullable = true, - this.withExpandedSpace = false, // this.mainAxisAlignment, + this.mainAxisSize, this.crossAxisAlignment, }); AstromicRadioSelectorConfiguration copyWith({ Axis? axis, bool? isNullable, - bool? withExpandedSpace, // MainAxisAlignment? mainAxisAlignment, + MainAxisSize? mainAxisSize, CrossAxisAlignment? crossAxisAlignment, }) { return AstromicRadioSelectorConfiguration( axis: axis ?? this.axis, isNullable: isNullable ?? this.isNullable, - withExpandedSpace: withExpandedSpace ?? this.withExpandedSpace, mainAxisAlignment: mainAxisAlignment ?? this.mainAxisAlignment, + mainAxisSize: mainAxisSize ?? this.mainAxisSize, crossAxisAlignment: crossAxisAlignment ?? this.crossAxisAlignment, ); } diff --git a/lib/src/Selectors/src/Radio/models/models.exports.dart b/lib/src/Selectors/src/Radio/models/models.exports.dart new file mode 100644 index 0000000..a30a0b3 --- /dev/null +++ b/lib/src/Selectors/src/Radio/models/models.exports.dart @@ -0,0 +1 @@ +export 'configuration.model.dart'; diff --git a/lib/src/Selectors/src/Radio/radio.selector.dart b/lib/src/Selectors/src/Radio/radio.selector.dart index fdff460..69285a2 100644 --- a/lib/src/Selectors/src/Radio/radio.selector.dart +++ b/lib/src/Selectors/src/Radio/radio.selector.dart @@ -1,37 +1,27 @@ -//SECTION - Imports -// -//s1 PACKAGES -//--------------- -//s2 CORE +//s1 Imports +//s2 Core Package Imports import 'package:flutter/widgets.dart'; -//s2 3RD-PARTY -// -//s1 DEPENDENCIES -//--------------- -//s2 SERVICES -//s2 MODELS -import '../../../Spacing/spacing.astromic.dart'; -import 'models/configuration.model.dart'; -//s2 MISC -//!SECTION - Imports -// -//SECTION - Exports -//!SECTION - Exports -// +//s2 1st-party Package Imports +//s2 3rd-party Package Imports +//s2 Dependancies Imports +//s3 Routes +//s3 Services +//s3 Models +import 'models/models.exports.dart'; +//s1 Exports -// +/// Selector that allows only one item to be selected from a group of items. class AstromicRadioSelector extends StatefulWidget { //SECTION - Widget Arguments //s1 -- Functionality final T? initialSelectedValue; final Function(T selectedItem)? onChanged; //s1 -- Configuration - final AstromicRadioSelectorConfiguration configuration; + final AstromicRadioSelectorConfiguration? configuration; //s1 -- Style - final double itemSpacing; + final double? itemSpacing; //s1 -- Content final List<(T item, bool isEnabled)> items; - // final Widget Function(T item, bool isEnabled, bool isSelected, VoidCallback? onTap) itemBuilder; //!SECTION // @@ -42,14 +32,14 @@ class AstromicRadioSelector extends StatefulWidget { required this.items, this.onChanged, //s1 -- Configuration - required this.configuration, + this.configuration = const AstromicRadioSelectorConfiguration(), //s1 -- Style - required this.itemSpacing, + this.itemSpacing = 8.0, //s1 -- Content required this.itemBuilder, - }) : assert(configuration.isNullable || initialSelectedValue != null, 'You need to supply an initial value if not nullable!'), + }) : assert(configuration!.isNullable || initialSelectedValue != null, 'You need to supply an initial value if not nullable!'), assert( - configuration.isNullable || + configuration!.isNullable || (items .map( (e) => e.$1, @@ -123,8 +113,6 @@ class _AstromicRadioSelectorState extends State> { Widget build(BuildContext context) { //SECTION - Build Setup //s1 -Values - //double w = MediaQuery.of(context).size.width; - //double h = MediaQuery.of(context).size.height; //s1 -Values // //s1 -Widgets @@ -133,27 +121,26 @@ class _AstromicRadioSelectorState extends State> { bool isEnabled = currentItem.$2; bool isSelected = item == selectedItem; // - return widget.configuration.withExpandedSpace && widget.configuration.axis == Axis.horizontal - ? Expanded(child: widget.itemBuilder(item, isEnabled, isSelected, isEnabled ? () => _onTap(item) : null)) - : widget.itemBuilder(item, isEnabled, isSelected, isEnabled ? () => _onTap(item) : null); + return widget.itemBuilder(item, isEnabled, isSelected, isEnabled ? () => _onTap(item) : null); }).toList(); //s1 -Widgets //!SECTION //SECTION - Build Return - return widget.configuration.axis == Axis.horizontal - ? separatedRow( - baseChildren, - AstromicSpacing.hsb(widget.itemSpacing), - mainAxisAlignment: widget.configuration.mainAxisAlignment ?? MainAxisAlignment.start, - crossAxisAlignment: widget.configuration.crossAxisAlignment ?? CrossAxisAlignment.center, + return widget.configuration!.axis == Axis.horizontal + ? Row( + children: baseChildren, + spacing: widget.itemSpacing!, + mainAxisAlignment: widget.configuration!.mainAxisAlignment ?? MainAxisAlignment.start, + mainAxisSize: widget.configuration!.mainAxisSize ?? MainAxisSize.min, + crossAxisAlignment: widget.configuration!.crossAxisAlignment ?? CrossAxisAlignment.center, ) - : separatedColumn( - baseChildren, - AstromicSpacing.vsb(widget.itemSpacing), - widget.configuration.withExpandedSpace, - mainAxisAlignment: widget.configuration.mainAxisAlignment ?? MainAxisAlignment.center, - crossAxisAlignment: widget.configuration.crossAxisAlignment ?? CrossAxisAlignment.center, + : Column( + children: baseChildren, + spacing: widget.itemSpacing!, + mainAxisAlignment: widget.configuration!.mainAxisAlignment ?? MainAxisAlignment.center, + mainAxisSize: widget.configuration!.mainAxisSize ?? MainAxisSize.min, + crossAxisAlignment: widget.configuration!.crossAxisAlignment ?? CrossAxisAlignment.center, ); //!SECTION } @@ -165,48 +152,3 @@ class _AstromicRadioSelectorState extends State> { super.dispose(); } } - -Widget separatedRow( - List children, - Widget separator, { - MainAxisAlignment? mainAxisAlignment, - CrossAxisAlignment? crossAxisAlignment, -}) { - List finalChildren = []; - for (var e in children) { - if (children.indexOf(e) != children.length - 1) { - finalChildren.addAll([e, separator]); - } else { - finalChildren.add(e); - } - } - return Row( - mainAxisSize: MainAxisSize.max, - crossAxisAlignment: crossAxisAlignment!, - mainAxisAlignment: mainAxisAlignment!, - children: finalChildren, - ); -} - -Widget separatedColumn( - List children, - Widget separator, - bool withExpandedSpace, { - MainAxisAlignment? mainAxisAlignment, - CrossAxisAlignment? crossAxisAlignment, -}) { - List finalChildren = []; - for (var e in children) { - if (children.indexOf(e) != children.length - 1) { - finalChildren.addAll([e, separator]); - } else { - finalChildren.add(e); - } - } - return Column( - mainAxisSize: MainAxisSize.max, - crossAxisAlignment: withExpandedSpace ? CrossAxisAlignment.stretch : crossAxisAlignment!, - mainAxisAlignment: mainAxisAlignment!, - children: finalChildren, - ); -} diff --git a/lib/src/Spacing/spacing.astromic.dart b/lib/src/Spacing/spacing.astromic.dart index 8bf4082..63a48d5 100644 --- a/lib/src/Spacing/spacing.astromic.dart +++ b/lib/src/Spacing/spacing.astromic.dart @@ -51,3 +51,8 @@ class AstromicSpacing { ); } } + +extension SizedBoxExtension on num { + Widget hsb() => AstromicSpacing.hsb(toDouble()); + Widget vsb() => AstromicSpacing.vsb(toDouble()); +} diff --git a/lib/src/Toggles/Checkbox/checkbox.toggle.dart b/lib/src/Toggles/Checkbox/checkbox.toggle.dart index 1125b33..6e58194 100644 --- a/lib/src/Toggles/Checkbox/checkbox.toggle.dart +++ b/lib/src/Toggles/Checkbox/checkbox.toggle.dart @@ -1,24 +1,16 @@ -//SECTION - Imports -// -//s1 PACKAGES -//--------------- -//s2 CORE +//s1 Imports +//s2 Core Package Imports import 'package:flutter/material.dart'; +//s2 1st-party Package Imports +//s2 3rd-party Package Imports +//s2 Dependancies Imports +//s3 Routes +//s3 Services +//s3 Models +import 'models/models.exports.dart'; +import '../models/models.exports.dart'; +//s1 Exports -import 'style.dart'; - -//s2 3RD-PARTY -// -//s1 DEPENDENCIES -//--------------- -//s2 SERVICES -//s2 MODELS -//s2 MISC -//!SECTION - Imports -// -//SECTION - Exports -//!SECTION - Exports -// class AstromicCheckboxToggle extends StatefulWidget { //SECTION - Widget Arguments //s1 -- Functionality @@ -27,12 +19,9 @@ class AstromicCheckboxToggle extends StatefulWidget { final bool? initialState; final void Function(bool)? onStateChanged; //s1 -- Configuration - final bool? isEnabled; - final bool? withLabel; - final bool? isLabelTapable; - final TextDirection? textDirection; + final AstromicToggleConfiguration? configuration; //s1 -- Style - final AstromicCheckboxToggleStyle Function(bool isEnabled, bool isSelected) style; + final AstromicCheckboxToggleStyle Function(bool isEnabled, bool isSelected)? style; // //s1 -- Content final Widget Function(bool isEnabled, bool isSelected)? innerWidget; @@ -46,12 +35,9 @@ class AstromicCheckboxToggle extends StatefulWidget { this.initialState, this.onStateChanged, // - this.isEnabled = true, - this.withLabel = true, - this.isLabelTapable = true, - this.textDirection = TextDirection.ltr, + this.configuration, // - required this.style, + this.style, // this.innerWidget, this.label, @@ -68,7 +54,9 @@ class _AstromicCheckboxToggleState extends State { //s1 --Controllers // //s1 --State - late bool isChecked; + late bool _isChecked; + late AstromicCheckboxToggleStyle _style; + late AstromicToggleConfiguration _config; //s1 --State // //s1 --Constants @@ -84,7 +72,7 @@ class _AstromicCheckboxToggleState extends State { //s1 --Controllers & Listeners // //s1 --State - isChecked = widget.initialState ?? widget.stateVariable ?? false; + _isChecked = widget.initialState ?? widget.stateVariable ?? false; //s1 --State // //s1 --Late & Async Initializers @@ -105,7 +93,7 @@ class _AstromicCheckboxToggleState extends State { @override void didUpdateWidget(AstromicCheckboxToggle oldWidget) { if (widget.stateVariable != null && widget.stateVariable != oldWidget.stateVariable) { - isChecked = widget.stateVariable!; + _isChecked = widget.stateVariable!; } super.didUpdateWidget(oldWidget); } @@ -116,8 +104,8 @@ class _AstromicCheckboxToggleState extends State { //SECTION - Action Callbacks _onTap() { setState(() { - isChecked = !isChecked; - if (widget.onStateChanged != null) widget.onStateChanged!(isChecked); + _isChecked = !_isChecked; + if (widget.onStateChanged != null) widget.onStateChanged!(_isChecked); }); } //!SECTION @@ -126,6 +114,8 @@ class _AstromicCheckboxToggleState extends State { Widget build(BuildContext context) { //SECTION - Build Setup //s1 -Values + _config = widget.configuration ?? AstromicToggleConfiguration(); + _style = widget.style != null ? widget.style!(_config.isEnabled, _isChecked) : AstromicCheckboxToggleStyle(); //double w = MediaQuery.of(context).size.width; //double h = MediaQuery.of(context).size.height; //s1 -Values @@ -136,31 +126,31 @@ class _AstromicCheckboxToggleState extends State { //SECTION - Build Return return Directionality( - textDirection: widget.textDirection ?? TextDirection.ltr, + textDirection: _config.textDirection, child: Row( mainAxisSize: MainAxisSize.min, children: [ - //S1 -- Item + //Item SizedBox( - width: widget.style(widget.isEnabled!, isChecked).itemSize, - height: widget.style(widget.isEnabled!, isChecked).itemSize, + width: _style.itemSize, + height: _style.itemSize, child: Material( child: InkWell( - onTap: widget.isEnabled! ? () => _onTap() : null, + onTap: _config.isEnabled ? () => _onTap() : null, child: Container( decoration: BoxDecoration( - color: widget.style(widget.isEnabled!, isChecked).backgroundColor, - border: widget.style(widget.isEnabled!, isChecked).border, - borderRadius: widget.style(widget.isEnabled!, isChecked).borderRadius, + color: _style.backgroundColor, + border: _style.border, + borderRadius: _style.borderRadius, ), - child: widget.innerWidget != null ? widget.innerWidget!(widget.isEnabled!, isChecked) : Container(), + child: widget.innerWidget != null ? widget.innerWidget!(_config.isEnabled, _isChecked) : Container(), ), ), )), - //S1 -- Label Spacing - if (widget.withLabel!) SizedBox(width: widget.style(widget.isEnabled!, isChecked).labelSpacing), - //S1 -- Label - if (widget.withLabel! && widget.label != null) GestureDetector(onTap: widget.isLabelTapable! ? _onTap() : null, child: widget.label!(widget.isEnabled!, isChecked)), + //Label Spacing + if (_config.withLabel) SizedBox(width: _style.labelSpacing), + //Label + if (_config.withLabel && widget.label != null) GestureDetector(onTap: _config.isLabelTapable ? _onTap() : null, child: widget.label!(_config.isEnabled, _isChecked)), ], ), ); diff --git a/lib/src/Toggles/Checkbox/models/models.exports.dart b/lib/src/Toggles/Checkbox/models/models.exports.dart new file mode 100644 index 0000000..2db3ee0 --- /dev/null +++ b/lib/src/Toggles/Checkbox/models/models.exports.dart @@ -0,0 +1 @@ +export './style.model.dart'; diff --git a/lib/src/Toggles/Checkbox/style.dart b/lib/src/Toggles/Checkbox/models/style.model.dart similarity index 75% rename from lib/src/Toggles/Checkbox/style.dart rename to lib/src/Toggles/Checkbox/models/style.model.dart index d88c2f3..5a4464a 100644 --- a/lib/src/Toggles/Checkbox/style.dart +++ b/lib/src/Toggles/Checkbox/models/style.model.dart @@ -1,6 +1,6 @@ -// ignore_for_file: public_member_api_docs, sort_constructors_first import 'package:flutter/material.dart'; +/// Styling model for the CheckBox Toggle element. class AstromicCheckboxToggleStyle { final double? itemSize; final double? labelSpacing; @@ -8,15 +8,13 @@ class AstromicCheckboxToggleStyle { final Border? border; final BorderRadius? borderRadius; final Color? backgroundColor; - final TextStyle? labelStyle; AstromicCheckboxToggleStyle({ this.itemSize = 24.0, this.labelSpacing = 8.0, - this.border, - this.borderRadius, - this.backgroundColor, - this.labelStyle, + this.border = const Border.fromBorderSide(BorderSide(width: 2, color: Colors.black)), + this.borderRadius = const BorderRadius.all(Radius.circular(4)), + this.backgroundColor = Colors.transparent, }); AstromicCheckboxToggleStyle copyWith({ @@ -25,7 +23,6 @@ class AstromicCheckboxToggleStyle { Border? border, BorderRadius? borderRadius, Color? backgroundColor, - TextStyle? labelStyle, }) { return AstromicCheckboxToggleStyle( itemSize: itemSize ?? this.itemSize, @@ -33,7 +30,6 @@ class AstromicCheckboxToggleStyle { border: border ?? this.border, borderRadius: borderRadius ?? this.borderRadius, backgroundColor: backgroundColor ?? this.backgroundColor, - labelStyle: labelStyle ?? this.labelStyle, ); } } diff --git a/lib/src/Toggles/Custom/custom.toggle.dart b/lib/src/Toggles/Custom/custom.toggle.dart deleted file mode 100644 index d4eb2a1..0000000 --- a/lib/src/Toggles/Custom/custom.toggle.dart +++ /dev/null @@ -1,128 +0,0 @@ -//SECTION - Imports -// -//s1 PACKAGES -//--------------- -//s2 CORE -import 'package:flutter/material.dart'; - -//s2 3RD-PARTY -// -//s1 DEPENDENCIES -//--------------- -//s2 SERVICES -//s2 MODELS -//s2 MISC -//!SECTION - Imports -// -//SECTION - Exports -//!SECTION - Exports -// -class AstromicCustomToggle extends StatefulWidget { - //SECTION - Widget Arguments - //s1 -- Functionality - /// If provided, you have to change the variable yourself in the onStateChanged! - final bool? stateVariable; - final bool? initialState; - final void Function(bool)? onStateChanged; - //s1 -- Configuration - final bool? isEnabled; - // - //s1 -- Content - final Widget Function(bool isChecked, bool isEnabled, VoidCallback? onTap) itemBuilder; - //!SECTION - // - const AstromicCustomToggle({ - super.key, - //s1 -- Functionality - this.stateVariable, - this.initialState, - this.onStateChanged, - //s1 -- Configuration - this.isEnabled = true, - //s1 -- Content - required this.itemBuilder, - }) : assert(stateVariable == null || initialState == null, "Can't define both the state variable and the initial state"); - - @override - State createState() => _AstromicCustomToggleState(); -} - -class _AstromicCustomToggleState extends State { - // - //SECTION - State Variables - //s1 --Controllers - //s1 --Controllers - // - //s1 --State - late bool currentState; - //s1 --State - // - //s1 --Constants - //s1 --Constants - //!SECTION - - @override - void initState() { - super.initState(); - // - //SECTION - State Variables initializations & Listeners - //s1 --Controllers & Listeners - //s1 --Controllers & Listeners - // - //s1 --State - currentState = widget.initialState ?? widget.stateVariable ?? false; - //s1 --State - // - //s1 --Late & Async Initializers - //s1 --Late & Async Initializers - //!SECTION - } - - @override - void didChangeDependencies() { - super.didChangeDependencies(); - // - //SECTION - State Variables initializations & Listeners - //s1 --State - //s1 --State - //!SECTION - } - - @override - void didUpdateWidget(AstromicCustomToggle oldWidget) { - if (widget.stateVariable != null && widget.stateVariable != oldWidget.stateVariable) { - currentState = widget.stateVariable!; - } - super.didUpdateWidget(oldWidget); - } - - //SECTION - Stateless functions - //!SECTION - - //SECTION - Action Callbacks - _onTap() { - setState(() { - currentState = !currentState; - if (widget.onStateChanged != null) widget.onStateChanged!(currentState); - }); - } - //!SECTION - - @override - Widget build(BuildContext context) { - //SECTION - Build Setup - //s1 -Values - //double w = MediaQuery.of(context).size.width; - //double h = MediaQuery.of(context).size.height; - //s1 -Values - // - //s1 -Widgets - //s1 -Widgets - //!SECTION - - //SECTION - Build Return - return widget.itemBuilder(currentState, widget.isEnabled!, widget.isEnabled! ? () => _onTap() : null); - - //!SECTION - } -} diff --git a/lib/src/Toggles/Switcher/models/models.exports.dart b/lib/src/Toggles/Switcher/models/models.exports.dart new file mode 100644 index 0000000..2db3ee0 --- /dev/null +++ b/lib/src/Toggles/Switcher/models/models.exports.dart @@ -0,0 +1 @@ +export './style.model.dart'; diff --git a/lib/src/Toggles/Switcher/style.dart b/lib/src/Toggles/Switcher/models/style.model.dart similarity index 95% rename from lib/src/Toggles/Switcher/style.dart rename to lib/src/Toggles/Switcher/models/style.model.dart index 2a1aa36..1fe3d0c 100644 --- a/lib/src/Toggles/Switcher/style.dart +++ b/lib/src/Toggles/Switcher/models/style.model.dart @@ -1,5 +1,6 @@ import 'package:flutter/widgets.dart'; +/// Styling model for the Switcher Toggle element. class AstromicSwitcherToggleStyle { final double width; final double height; diff --git a/lib/src/Toggles/Switcher/switcher.toggle.dart b/lib/src/Toggles/Switcher/switcher.toggle.dart index 6befaad..00161a6 100644 --- a/lib/src/Toggles/Switcher/switcher.toggle.dart +++ b/lib/src/Toggles/Switcher/switcher.toggle.dart @@ -1,15 +1,17 @@ -// ignore_for_file: public_member_api_docs, sort_constructors_first -//s2 Core Packages Imports +//s1 Imports +//s2 Core Package Imports import 'package:flutter/material.dart'; +//s2 1st-party Package Imports +//s2 3rd-party Package Imports import 'package:flutter_switch/flutter_switch.dart'; //s2 Dependancies Imports +//s3 Routes //s3 Services //s3 Models -import 'style.dart'; +import 'models/models.exports.dart'; +import '../models/models.exports.dart'; //s1 Exports -// -// class AstromicSwitcherToggle extends StatefulWidget { //SECTION - Widget Arguments //s1 -- Functionality @@ -18,12 +20,9 @@ class AstromicSwitcherToggle extends StatefulWidget { final bool? initialState; final void Function(bool)? onStateChanged; //s1 -- Configuration - final bool? isEnabled; - final bool? withLabel; - final bool? isLabelTapable; - final TextDirection? textDirection; + final AstromicToggleConfiguration? configuration; //s1 -- Style - final AstromicSwitcherToggleStyle Function(bool isEnabled, bool isSelected) style; + final AstromicSwitcherToggleStyle Function(bool isEnabled, bool isSelected)? style; //s1 -- Content final Widget Function(bool isEnabled, bool isSelected)? label; //!SECTION @@ -34,12 +33,9 @@ class AstromicSwitcherToggle extends StatefulWidget { this.initialState, this.onStateChanged, // - this.isEnabled = true, - this.withLabel = true, - this.isLabelTapable = true, - this.textDirection = TextDirection.ltr, + this.configuration, // - required this.style, + this.style, // this.label, }); @@ -56,6 +52,8 @@ class AstromicSwitcherToggleState extends State { // //s1 --State late bool _currentState; + late AstromicSwitcherToggleStyle _style; + late AstromicToggleConfiguration _config; //s1 --State // //s1 --Constants @@ -100,6 +98,8 @@ class AstromicSwitcherToggleState extends State { Widget build(BuildContext context) { //SECTION - Build Setup //s1 -Values + _config = widget.configuration ?? AstromicToggleConfiguration(); + _style = widget.style != null ? widget.style!(_config.isEnabled, _currentState) : const AstromicSwitcherToggleStyle(); //s1 -Values // //s1 -Widgets @@ -108,39 +108,39 @@ class AstromicSwitcherToggleState extends State { //SECTION - Build Return return Directionality( - textDirection: widget.textDirection ?? TextDirection.ltr, + textDirection: _config.textDirection, child: Row( mainAxisSize: MainAxisSize.min, children: [ //S1 -- Item FlutterSwitch( - width: widget.style(widget.isEnabled!, _currentState).width, - height: widget.style(widget.isEnabled!, _currentState).height, - borderRadius: widget.style(widget.isEnabled!, _currentState).borderRadius, + width: _style.width, + height: _style.height, + borderRadius: _style.borderRadius, value: _currentState, - toggleSize: widget.style(widget.isEnabled!, _currentState).toggleSize, + toggleSize: _style.toggleSize, disabled: false, // - activeColor: widget.style(widget.isEnabled!, _currentState).activeColor, - activeToggleColor: widget.style(widget.isEnabled!, _currentState).activeToggleColor, - activeSwitchBorder: widget.style(widget.isEnabled!, _currentState).activeSwitchBorder, - activeToggleBorder: widget.style(widget.isEnabled!, _currentState).activeToggleBorder, - activeIcon: widget.style(widget.isEnabled!, _currentState).innerActiveWidget, + activeColor: _style.activeColor, + activeToggleColor: _style.activeToggleColor, + activeSwitchBorder: _style.activeSwitchBorder, + activeToggleBorder: _style.activeToggleBorder, + activeIcon: _style.innerActiveWidget, // - inactiveColor: widget.style(widget.isEnabled!, _currentState).inactiveColor, - inactiveToggleColor: widget.style(widget.isEnabled!, _currentState).inactiveToggleColor, - inactiveSwitchBorder: widget.style(widget.isEnabled!, _currentState).inactiveSwitchBorder, - inactiveToggleBorder: widget.style(widget.isEnabled!, _currentState).inactiveToggleBorder, - inactiveIcon: widget.style(widget.isEnabled!, _currentState).innerInactiveWidget, + inactiveColor: _style.inactiveColor, + inactiveToggleColor: _style.inactiveToggleColor, + inactiveSwitchBorder: _style.inactiveSwitchBorder, + inactiveToggleBorder: _style.inactiveToggleBorder, + inactiveIcon: _style.innerInactiveWidget, // - padding: widget.style(widget.isEnabled!, _currentState).togglePadding, + padding: _style.togglePadding, showOnOff: false, onToggle: (s) => _onTap(s), ), //S1 -- Label Spacing - if (widget.withLabel!) SizedBox(width: widget.style(widget.isEnabled!, _currentState).labelSpacing), + if (_config.withLabel) SizedBox(width: _style.labelSpacing), //S1 -- Label - if (widget.withLabel! && widget.label != null) GestureDetector(onTap: widget.isLabelTapable! ? () => _onTap(!_currentState) : null, child: widget.label!(widget.isEnabled!, _currentState)), + if (_config.withLabel && widget.label != null) GestureDetector(onTap: _config.isLabelTapable ? () => _onTap(!_currentState) : null, child: widget.label!(_config.isEnabled, _currentState)), ], ), ); diff --git a/lib/src/Toggles/models/configuration.model.dart b/lib/src/Toggles/models/configuration.model.dart new file mode 100644 index 0000000..cd32806 --- /dev/null +++ b/lib/src/Toggles/models/configuration.model.dart @@ -0,0 +1,29 @@ +import 'dart:ui'; + +/// SConfiguration model for the Toggles element group. +class AstromicToggleConfiguration { + final bool isEnabled; + final bool withLabel; + final bool isLabelTapable; + final TextDirection textDirection; + AstromicToggleConfiguration({ + this.isEnabled = true, + this.withLabel = false, + this.isLabelTapable = true, + this.textDirection = TextDirection.ltr, + }); + + AstromicToggleConfiguration copyWith({ + bool? isEnabled, + bool? withLabel, + bool? isLabelTapable, + TextDirection? textDirection, + }) { + return AstromicToggleConfiguration( + isEnabled: isEnabled ?? this.isEnabled, + withLabel: withLabel ?? this.withLabel, + isLabelTapable: isLabelTapable ?? this.isLabelTapable, + textDirection: textDirection ?? this.textDirection, + ); + } +} diff --git a/lib/src/Toggles/models/models.exports.dart b/lib/src/Toggles/models/models.exports.dart new file mode 100644 index 0000000..3873214 --- /dev/null +++ b/lib/src/Toggles/models/models.exports.dart @@ -0,0 +1 @@ +export './configuration.model.dart'; diff --git a/lib/src/Toggles/toggles.astromic.dart b/lib/src/Toggles/toggles.astromic.dart index 433ead2..8e568b5 100644 --- a/lib/src/Toggles/toggles.astromic.dart +++ b/lib/src/Toggles/toggles.astromic.dart @@ -1,92 +1,58 @@ -//s2 Core Packages Imports +//s1 Imports +//s2 Core Package Imports import 'package:flutter/widgets.dart'; -import 'Checkbox/checkbox.toggle.dart'; -import 'Switcher/switcher.toggle.dart'; -import 'Custom/custom.toggle.dart'; -// -import 'Switcher/style.dart'; -import 'Checkbox/style.dart'; -// -export 'Switcher/style.dart'; -export 'Checkbox/style.dart'; +//s2 1st-party Package Imports +//s2 3rd-party Package Imports +//s2 Dependancies Imports +//s3 Routes +//s3 Services +//s3 Models +import 'checkbox/checkbox.toggle.dart'; +import 'switcher/switcher.toggle.dart'; +import 'switcher/models/models.exports.dart'; +import 'checkbox/models/models.exports.dart'; +import 'models/models.exports.dart'; +//s1 Exports +export 'switcher/models/models.exports.dart'; +export 'checkbox/models/models.exports.dart'; +export 'models/models.exports.dart'; class AstromicToggles { - //S1 -- Checkbox + /// A CheckBox element that toggles state On and Off. static Widget checkBox({ - // bool? stateVariable, bool? initialState, void Function(bool)? onStateChanged, - // - bool? isEnabled, - bool? withLabel, - bool? isLabelTapable, - TextDirection? textDirection, - // - required AstromicCheckboxToggleStyle Function(bool isEnabled, bool isSelected) style, - // + AstromicToggleConfiguration? configuration, + AstromicCheckboxToggleStyle Function(bool isEnabled, bool isSelected)? style, Widget Function(bool isEnabled, bool isSelected)? innerWidget, Widget Function(bool isEnabled, bool isSelected)? label, - // }) => AstromicCheckboxToggle( stateVariable: stateVariable, initialState: initialState, onStateChanged: onStateChanged, - isEnabled: isEnabled ?? true, - withLabel: withLabel ?? false, - isLabelTapable: isLabelTapable ?? false, - textDirection: textDirection ?? TextDirection.ltr, + configuration: configuration, style: style, innerWidget: innerWidget, label: label, ); - //S1 -- Switcher + /// A Switch element that toggles state On and Off. static Widget switcher({ - // bool? stateVariable, bool? initialState, void Function(bool)? onStateChanged, - // - bool? isEnabled, - bool? withLabel, - bool? isLabelTapable, - TextDirection? textDirection, - // - required AstromicSwitcherToggleStyle Function(bool isEnabled, bool isSelected) style, - // + AstromicToggleConfiguration? configuration, + AstromicSwitcherToggleStyle Function(bool isEnabled, bool isSelected)? style, Widget Function(bool isEnabled, bool isSelected)? label, - // }) => AstromicSwitcherToggle( stateVariable: stateVariable, initialState: initialState, onStateChanged: onStateChanged, - isEnabled: isEnabled ?? true, - withLabel: withLabel ?? false, - isLabelTapable: isLabelTapable ?? false, - textDirection: textDirection ?? TextDirection.ltr, + configuration: configuration, style: style, label: label, ); - - //S1 -- Custom - static Widget custom({ - // - bool? stateVariable, - bool? initialState, - void Function(bool)? onStateChanged, - // - bool? isEnabled, - // - required Widget Function(bool isChecked, bool isEnabled, VoidCallback? onTap) itemBuilder, - }) => - AstromicCustomToggle( - stateVariable: stateVariable, - initialState: initialState, - onStateChanged: onStateChanged, - isEnabled: isEnabled ?? true, - itemBuilder: itemBuilder, - ); } diff --git a/lib/src/Widgets/src/image.widget.dart b/lib/src/Widgets/src/image.widget.dart index 0543f16..f7ce93f 100644 --- a/lib/src/Widgets/src/image.widget.dart +++ b/lib/src/Widgets/src/image.widget.dart @@ -1,217 +1,313 @@ -import 'dart:typed_data'; - -import 'package:cached_network_image/cached_network_image.dart'; +//s1 Imports +//s2 Core Package Imports import 'package:flutter/widgets.dart'; +import 'dart:convert'; +import 'dart:typed_data'; +//s2 1st-party Package Imports +//s2 3rd-party Package Imports +import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:octo_image/octo_image.dart'; +//s2 Dependancies Imports +//s3 Routes +//s3 Services +//s3 Models +//s1 Exports + +enum ImageSizingMaster { + w, + h, +} + +enum _DeclaredAssetType { + path, + url, + bytes, + fallback, +} + +_DeclaredAssetType _parseAssetType( + String? path, + String? url, + Uint8List? bytes, + String? fallback, +) { + bool fromPath = (path != null && path != ''); + bool fromBytes = (bytes != null && bytes.isNotEmpty); + bool fromNetwork = (url != null && url.isNotEmpty && Uri.tryParse(url)?.hasAbsolutePath == true && (url.startsWith('http://') || url.startsWith('https://'))); -Widget astromicImage( - BuildContext context, { - //S1 -- Asset - String? assetPath, - String? assetURL, - Uint8List? assetBytes, - String? assetFallback, // - //S1 -- Sizing | Width - double? wFactor, // variable width ratio - double? minW, // Min width allowed - double? maxW, // Max width allowed - double? fixedWidth, // Only used when uisng height variables - //S1 -- Sizing | Width - bool useHeight = false, // use height constrains - double? hFactor, // Variable height ratio - double? minH, // Min Height allowed - double? maxH, // Max height allowed - double? fixedHeight, // Only used when using width variables + return fromPath + ? _DeclaredAssetType.path + : fromBytes + ? _DeclaredAssetType.bytes + : fromNetwork + ? _DeclaredAssetType.url + : _DeclaredAssetType.fallback; +} + +class AstromicImage extends StatelessWidget { + //SECTION - Widget Arguments + //S1 -- Assets + final String? assetPath; + final String? assetURL; + final Uint8List? assetBytes; + final String? assetFallback; + //S1 -- Sizing + final ImageSizingMaster? sizingMaster; + final (double factor, double? min, double? max)? widthSizing; + + /// Used when the width is Master and want to set fixed width OR if height is Master and want to constraint the width + final double? fixedWidth; + final (double factor, double? min, double? max)? heightSizing; + + /// Used when the height is Master and want to set fixed height OR if width is Master and want to constraint the height + final double? fixedHeight; //S1 -- STYLING - bool circular = false, - double? border, - Color? borderColor, - EdgeInsetsGeometry? borderPadding, - BorderRadiusGeometry radius = BorderRadius.zero, - List? shadow, + final bool? isCircular; + final double? borderWidth; + final Color? borderColor; + final EdgeInsetsGeometry? borderPadding; + final BorderRadiusGeometry? radius; + final List? shadow; + final Color? overlayColor; + final Gradient? overlayGradient; + //S1 -- CONFIGURATIONS + final Alignment? alignment; + final BoxFit? fit; + final BlendMode? blendMode; + final Curve? fadeInCurve; + final Duration? fadeInDuration; //S1 -- SVG FILTERS - Color? color, - BlendMode? blend, - //S1 -- CONFIGS - BoxFit fit = BoxFit.cover, - Alignment alignment = Alignment.center, - LinearGradient? linearGradient, - //S1 -- STATE - Widget? loadingWidget, - Widget? errorWidget, -}) { + final Color? svgColor; + //S1 -- STATE WIDGETS + final Widget Function(int? loadedBytes, int? totalBytesToLoad)? loadingWidget; + final Widget Function(dynamic error, StackTrace? stackTrace)? errorWidget; + //!SECTION // - assert(minW == null || maxW == null, "Please specify only one width constrain"); - assert(minH == null || maxH == null, "Please specify only one height constrain"); - assert(!useHeight || (hFactor != null), "Please specify The height factor and constrains"); - assert( - (assetPath != null && assetBytes == null && assetURL == null) || - (assetPath == null && assetBytes != null && assetURL == null) || - (assetPath == null && assetBytes == null && assetURL != null) || - (assetFallback != null && assetFallback != ''), - "Please specify only one Asset Source"); - // - // - bool fromPath = (assetPath != null && assetPath != ''); - bool fromBytes = (assetBytes != null && assetBytes.isNotEmpty); - bool fromNetwork = (assetURL != null && assetURL != '' && Uri.tryParse(assetURL) != null); - // - String finalAssetKey = fromPath - ? assetPath - : fromNetwork - ? assetURL - : fromBytes - ? assetBytes.length.toString() - : 'N/A'; - // - bool isFallback = (assetBytes == null && assetURL == null && assetPath == null && assetFallback != null); - bool isSVG = fromPath - ? assetPath.endsWith('.svg') - : fromNetwork - ? assetURL.endsWith('.svg') - : isFallback - ? assetFallback.endsWith('.svg') - : false; - // - double h = MediaQuery.of(context).size.height; - double? fh = hFactor != null ? hFactor * h : null; - double w = MediaQuery.of(context).size.width; - double? fw = wFactor != null ? wFactor * w : null; + AstromicImage({ + super.key, + // + this.assetPath, + this.assetURL, + this.assetBytes, + this.assetFallback, + // + this.sizingMaster = ImageSizingMaster.w, + this.widthSizing, + this.heightSizing, + this.fixedWidth, + this.fixedHeight, + // + this.isCircular = false, + this.borderWidth, + this.borderColor, + this.borderPadding, + this.radius = BorderRadius.zero, + this.shadow, + this.overlayColor, + this.overlayGradient, + // + this.fit = BoxFit.cover, + this.alignment = Alignment.center, + this.blendMode, + this.fadeInCurve = Curves.ease, + this.fadeInDuration = const Duration(milliseconds: 250), + // + this.svgColor, + // + this.loadingWidget, + this.errorWidget, + }) : + // Assert that a source is provided, or provide a fallback source.. + assert(((assetPath?.isNotEmpty ?? false) || (assetURL?.isNotEmpty ?? false) || (assetBytes?.isNotEmpty ?? false)) || (assetFallback?.isNotEmpty ?? false), + "Please specify a source or provide a fallback."), + // Assert that only ONE source is provided... + assert( + (assetPath != null && assetBytes == null && assetURL == null) || + (assetPath == null && assetBytes != null && assetURL == null) || + (assetPath == null && assetBytes == null && assetURL != null), + "Please specify only ONE Asset Source"), + // Assert that correct sizing plan is provided... + assert((sizingMaster == ImageSizingMaster.w && (widthSizing != null || fixedWidth != null)) || (sizingMaster == ImageSizingMaster.h && (heightSizing != null || fixedHeight != null)), + "Please provide the correct sizing configurations based on the SizingMaster choosen"); - // - double? finalW = useHeight - ? fixedWidth - : fw != null - ? fw > (maxW ?? double.infinity) - ? maxW - : fw < (minW ?? 0) - ? minW - : fw - : null; - double? finalH = !useHeight - ? fixedHeight - : fh != null - ? fh > (maxH ?? double.infinity) - ? maxH - : fh < (minH ?? 0) - ? minH - : fh - : null; - // - Widget finalError = errorWidget ?? - const Center( - child: Text("Error has happened.."), - ); - // - Widget finalLoading = loadingWidget ?? Container(); - // - ImageProvider finalImageProvider = isFallback - ? AssetImage( - assetFallback, - ) - : fromPath - ? AssetImage( - assetPath, - ) - : fromBytes - ? MemoryImage(assetBytes) - : fromNetwork - ? CachedNetworkImageProvider( - assetURL, - cacheKey: assetURL, - ) - : MemoryImage(kTransparentImage) as ImageProvider; - // - Widget? finalSVGWidget = fromPath - ? SvgPicture.asset( - assetPath, - key: ValueKey(assetPath), - width: finalW, - height: finalH, - fit: fit, - placeholderBuilder: (_) => SizedBox( - width: finalW, - height: finalH, - child: finalLoading, - ), - alignment: alignment, - colorFilter: color != null ? ColorFilter.mode(color, blend ?? BlendMode.srcATop) : null, - ) - : fromNetwork - ? SvgPicture.network( - assetURL, - key: ValueKey(assetURL), - width: finalW, - height: finalH, - fit: fit, - placeholderBuilder: (_) => SizedBox( - width: finalW, - height: finalH, - child: finalLoading, + @override + Widget build(BuildContext context) { + //SECTION - Build Setup + //s1 -Values + _DeclaredAssetType assetType = _parseAssetType(assetPath, assetURL, assetBytes, assetFallback); + dynamic assetRef = _getAssetRef(assetType); + bool isSVG = _isSVG(assetType, assetRef); + //s1 -Values + // + //s1 -Widgets + // Default Loading Widget + Widget defaultLoadingWidget = const Text('Loading...'); + + // Default Error Widget + Widget defaultErrorWidget(dynamic error) => Text('An error has happened: $error'); + + // Get final svg widget + Widget? finalSVGWidget(Size size, Widget? loadingWidget) => assetType == _DeclaredAssetType.path + ? SvgPicture.asset( + assetRef, + key: ValueKey(assetRef), + width: size.width, + height: size.height, + fit: fit!, + placeholderBuilder: (_) => SizedBox( + width: size.width, + height: size.height, + child: loadingWidget, + ), + alignment: alignment!, + colorFilter: svgColor != null ? ColorFilter.mode(svgColor!, blendMode ?? BlendMode.srcATop) : null, + ) + : assetType == _DeclaredAssetType.url + ? SvgPicture.network( + assetRef, + key: ValueKey(assetRef), + width: size.width, + height: size.height, + fit: fit!, + placeholderBuilder: (_) => SizedBox( + width: size.width, + height: size.height, + child: loadingWidget, + ), + alignment: alignment!, + colorFilter: svgColor != null ? ColorFilter.mode(svgColor!, blendMode ?? BlendMode.srcATop) : null, + ) + : null; + + Widget buildImage(Size size) { + return Stack( + children: [ + OctoImage( + key: ValueKey(assetType == _DeclaredAssetType.bytes ? (assetRef as Uint8List).length.toString() : assetRef), + // + width: size.width, + height: size.height, + fit: fit, + alignment: alignment, + filterQuality: FilterQuality.none, + color: svgColor, + colorBlendMode: blendMode ?? (isSVG ? BlendMode.srcATop : null), + // + errorBuilder: (context, error, stackTrace) { + debugPrint("AstromicImage Error: $error"); + return errorWidget != null + ? errorWidget!(error, stackTrace) + : assetFallback != null + ? Image.asset(assetFallback!) + : defaultErrorWidget(error); + }, + // + progressIndicatorBuilder: (_, bytes) => SizedBox( + width: size.width, + height: size.height, + child: loadingWidget != null ? loadingWidget!(bytes?.cumulativeBytesLoaded, bytes?.expectedTotalBytes) : defaultLoadingWidget, + ), + placeholderBuilder: (context) => loadingWidget != null ? loadingWidget!(null, null) : defaultLoadingWidget, + fadeInCurve: fadeInCurve, + fadeInDuration: fadeInDuration, + imageBuilder: (context, image) => Container( + width: size.width, + height: size.height, + padding: borderPadding ?? EdgeInsets.zero, + margin: EdgeInsets.zero, + decoration: BoxDecoration( + border: borderWidth != null + ? Border.all( + strokeAlign: BorderSide.strokeAlignInside, + width: borderWidth!, + color: borderColor ?? const Color(0xff000000), + ) + : null, + borderRadius: isCircular! ? BorderRadius.circular(10000000) : radius, + boxShadow: shadow, ), - alignment: alignment, - colorFilter: color != null ? ColorFilter.mode(color, blend ?? BlendMode.srcATop) : null, - ) - : null; - // - return SizedBox( - width: finalW, - height: finalH, - child: Stack( - children: [ - OctoImage( - key: ValueKey(finalAssetKey), - // - width: finalW, - height: finalH, - fit: fit, - alignment: alignment, - filterQuality: FilterQuality.none, - color: color, - colorBlendMode: blend ?? (isSVG ? BlendMode.srcATop : null), - // - errorBuilder: (context, error, stackTrace) { - return finalError; - }, - // - progressIndicatorBuilder: (a, b) => SizedBox( - width: finalW, - height: finalH, - child: finalLoading, - ), - - imageBuilder: (context, image) => Container( - width: finalW, - height: finalH, - padding: borderPadding ?? EdgeInsets.zero, - margin: EdgeInsets.zero, - decoration: BoxDecoration( - border: border != null - ? Border.all( - strokeAlign: BorderSide.strokeAlignInside, - width: border, - color: borderColor ?? const Color(0xff000000), + child: isCircular! + ? ClipOval( + child: isSVG ? finalSVGWidget(size, loadingWidget != null ? loadingWidget!(null, null) : defaultLoadingWidget) : image, ) - : null, - borderRadius: circular ? BorderRadius.circular(10000) : radius, - boxShadow: shadow, + : ClipRRect( + borderRadius: isCircular! ? BorderRadius.circular(10000000) : radius!, + child: isSVG ? finalSVGWidget(size, loadingWidget != null ? loadingWidget!(null, null) : defaultLoadingWidget) : image, + ), ), - child: ClipRRect( - borderRadius: circular ? BorderRadius.circular(10000) : radius, - child: isSVG ? finalSVGWidget : image, + image: isSVG ? MemoryImage(kTransparentImage) : _imageProvider(assetType, assetRef), + ), + if (overlayColor != null || overlayGradient != null) + Container( + decoration: BoxDecoration(color: overlayGradient != null ? null : overlayColor, gradient: overlayGradient, borderRadius: radius), ), - ), - image: isSVG ? MemoryImage(kTransparentImage) : finalImageProvider, - ), - if (linearGradient != null) - Container( - decoration: BoxDecoration(gradient: linearGradient, borderRadius: radius), - ), - ], - ), - ); + ], + ); + } + //s1 -Widgets + //!SECTION + + //SECTION - Build Return + return LayoutBuilder(builder: (context, constraints) { + Size size = _calculateSize(constraints); + return SizedBox(width: size.width, height: size.height, child: buildImage(size)); + }); + //!SECTION + } + + //SECTION - Helper Functions + // Get asset reference based on asset type... + dynamic _getAssetRef(_DeclaredAssetType type) { + switch (type) { + case _DeclaredAssetType.path: + return assetPath; + case _DeclaredAssetType.bytes: + return assetBytes; + case _DeclaredAssetType.url: + return assetURL; + case _DeclaredAssetType.fallback: + return assetFallback; + } + } + + // Detect if asset is an SVG... + bool _isSVG(_DeclaredAssetType type, dynamic ref) => + type == _DeclaredAssetType.bytes ? utf8.decode(ref.sublist(0, ref.length > 10 ? 10 : ref.length), allowMalformed: true).trimLeft().startsWith('[ diff --git a/lib/src/Widgets/widgets.astromic.dart b/lib/src/Widgets/widgets.astromic.dart index eb0f5ac..5696455 100644 --- a/lib/src/Widgets/widgets.astromic.dart +++ b/lib/src/Widgets/widgets.astromic.dart @@ -58,75 +58,65 @@ class AstromicWidgets { ); //S1 -- IMAGE - static Widget image( - BuildContext context, { - //S1 -- Asset + static Widget image({ String? assetPath, String? assetURL, Uint8List? assetBytes, String? assetFallback, - //S1 -- Sizing | Width - double? wFactor, - double? minW, - double? maxW, + ImageSizingMaster? sizingMaster, + (double factor, double? min, double? max)? widthSizing, + + /// Used when the width is Master and want to set fixed width OR if height is Master and want to constraint the width double? fixedWidth, - //S1 -- Sizing | Width - bool useHeight = false, - double? hFactor, - double? minH, - double? maxH, + (double factor, double? min, double? max)? heightSizing, + + /// Used when the height is Master and want to set fixed height OR if width is Master and want to constraint the height double? fixedHeight, - //S1 -- STYLING - bool circular = false, - double? border, + bool? isCircular, + double? borderWidth, Color? borderColor, EdgeInsetsGeometry? borderPadding, - BorderRadiusGeometry radius = BorderRadius.zero, + BorderRadiusGeometry? radius, List? shadow, - //S1 -- SVG FILTERS - Color? color, - BlendMode? blend, - //S1 -- CONFIGS - BoxFit fit = BoxFit.cover, - Alignment alignment = Alignment.center, - LinearGradient? linearGradient, - //S1 -- STATE - Widget? loadingWidget, - Widget? errorWidget, + Color? overlayColor, + Gradient? overlayGradient, + Alignment? alignment, + BoxFit? fit, + BlendMode? blendMode, + Curve? fadeInCurve, + Duration? fadeInDuration, + Color? svgColor, + Widget Function(int? loadedBytes, int? totalBytesToLoad)? loadingWidget, + Widget Function(dynamic error, StackTrace? stackTrace)? errorWidget, }) => - astromicImage( - context, - // + AstromicImage( assetPath: assetPath, assetURL: assetURL, assetBytes: assetBytes, assetFallback: assetFallback, - // - wFactor: wFactor, - minW: minW, - maxW: maxW, + sizingMaster: sizingMaster, + widthSizing: widthSizing, + + /// Used when the width is Master and want to set fixed width OR if height is Master and want to constraint the width fixedWidth: fixedWidth, - // - useHeight: useHeight, - hFactor: hFactor, - minH: minH, - maxH: maxH, + heightSizing: heightSizing, + + /// Used when the height is Master and want to set fixed height OR if width is Master and want to constraint the height fixedHeight: fixedHeight, - // - circular: circular, - border: border, + isCircular: isCircular, + borderWidth: borderWidth, borderColor: borderColor, borderPadding: borderPadding, radius: radius, shadow: shadow, - // - color: color, - blend: blend, - // - fit: fit, + overlayColor: overlayColor, + overlayGradient: overlayGradient, alignment: alignment, - linearGradient: linearGradient, - // + fit: fit, + blendMode: blendMode, + fadeInCurve: fadeInCurve, + fadeInDuration: fadeInDuration, + svgColor: svgColor, loadingWidget: loadingWidget, errorWidget: errorWidget, );