[SYNC]
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1 +1 @@
|
||||
export './sizing_strategy.enum.dart';
|
||||
export 'sizing_strategy.enum.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<ContextMenuButtonItem>? 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}) =>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1 +1 @@
|
||||
export './border_type.enum.dart';
|
||||
export 'border_type.enum.dart';
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export './style.model.dart';
|
||||
export './configuration.model.dart';
|
||||
export 'style.model.dart';
|
||||
export 'configuration.model.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>({
|
||||
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<T>(
|
||||
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<T>({
|
||||
List<T>? initialSelectedValues,
|
||||
void Function(List<T> 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<Widget> 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!,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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<T> extends StatefulWidget {
|
||||
//SECTION - Widget Arguments
|
||||
//s1 -- Functionality
|
||||
final List<T>? initialSelectedValues;
|
||||
final Function(List<T> selectedItems)? onChanged;
|
||||
//s1 -- Configuration
|
||||
final bool isCustom;
|
||||
final AstromicChipSelectorConfiguration? configuration;
|
||||
//s1 -- Style
|
||||
final double? itemSpacing;
|
||||
@@ -33,7 +25,6 @@ class AstromicChipSelector<T> 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<Widget> items)? groupBuilder;
|
||||
//!SECTION
|
||||
@@ -45,7 +36,6 @@ class AstromicChipSelector<T> 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<T> 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<T>({
|
||||
Key? key,
|
||||
//s1 -- Functionality
|
||||
final List<T>? initialSelectedValues,
|
||||
final Function(List<T> 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<Widget> 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<T>(
|
||||
key: key,
|
||||
isCustom: true,
|
||||
//
|
||||
initialSelectedValues: initialSelectedValues,
|
||||
onChanged: onChanged,
|
||||
//
|
||||
configuration: configuration,
|
||||
//
|
||||
items: items,
|
||||
itemBuilder: itemBuilder,
|
||||
groupBuilder: groupBuilder,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
State<AstromicChipSelector<T>> createState() => _AstromicChipSelectorState<T>();
|
||||
}
|
||||
@@ -141,13 +95,11 @@ class _AstromicChipSelectorState<T> extends State<AstromicChipSelector<T>> {
|
||||
_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<T> extends State<AstromicChipSelector<T>> {
|
||||
}
|
||||
}
|
||||
|
||||
// ----
|
||||
_onTapClear(T value) {
|
||||
setState(() {
|
||||
if (selectedItems.contains(value)) {
|
||||
@@ -216,7 +167,7 @@ class _AstromicChipSelectorState<T> extends State<AstromicChipSelector<T>> {
|
||||
//s1 -Widgets
|
||||
//!SECTION
|
||||
//SECTION - Build Return
|
||||
return widget.isCustom && widget.groupBuilder != null
|
||||
return widget.groupBuilder != null
|
||||
? widget.groupBuilder!(baseChildren)
|
||||
: (widget.configuration?.isWrap ?? true)
|
||||
? Wrap(
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
/// Configuration model for the chip selector element.
|
||||
|
||||
class AstromicChipSelectorConfiguration {
|
||||
final bool isNullable;
|
||||
final bool isWrap;
|
||||
|
||||
1
lib/src/Selectors/src/Chip/models/models.exports.dart
Normal file
1
lib/src/Selectors/src/Chip/models/models.exports.dart
Normal file
@@ -0,0 +1 @@
|
||||
export '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,
|
||||
);
|
||||
}
|
||||
|
||||
1
lib/src/Selectors/src/Radio/models/models.exports.dart
Normal file
1
lib/src/Selectors/src/Radio/models/models.exports.dart
Normal file
@@ -0,0 +1 @@
|
||||
export 'configuration.model.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<T> 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<T> 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<T> extends State<AstromicRadioSelector<T>> {
|
||||
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<T> extends State<AstromicRadioSelector<T>> {
|
||||
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<T> extends State<AstromicRadioSelector<T>> {
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
Widget separatedRow(
|
||||
List<Widget> children,
|
||||
Widget separator, {
|
||||
MainAxisAlignment? mainAxisAlignment,
|
||||
CrossAxisAlignment? crossAxisAlignment,
|
||||
}) {
|
||||
List<Widget> 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<Widget> children,
|
||||
Widget separator,
|
||||
bool withExpandedSpace, {
|
||||
MainAxisAlignment? mainAxisAlignment,
|
||||
CrossAxisAlignment? crossAxisAlignment,
|
||||
}) {
|
||||
List<Widget> 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,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -51,3 +51,8 @@ class AstromicSpacing {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension SizedBoxExtension on num {
|
||||
Widget hsb() => AstromicSpacing.hsb(toDouble());
|
||||
Widget vsb() => AstromicSpacing.vsb(toDouble());
|
||||
}
|
||||
|
||||
@@ -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<AstromicCheckboxToggle> {
|
||||
//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<AstromicCheckboxToggle> {
|
||||
//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<AstromicCheckboxToggle> {
|
||||
@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<AstromicCheckboxToggle> {
|
||||
//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<AstromicCheckboxToggle> {
|
||||
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<AstromicCheckboxToggle> {
|
||||
|
||||
//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)),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
1
lib/src/Toggles/Checkbox/models/models.exports.dart
Normal file
1
lib/src/Toggles/Checkbox/models/models.exports.dart
Normal file
@@ -0,0 +1 @@
|
||||
export './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,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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<AstromicCustomToggle> createState() => _AstromicCustomToggleState();
|
||||
}
|
||||
|
||||
class _AstromicCustomToggleState extends State<AstromicCustomToggle> {
|
||||
//
|
||||
//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
|
||||
}
|
||||
}
|
||||
1
lib/src/Toggles/Switcher/models/models.exports.dart
Normal file
1
lib/src/Toggles/Switcher/models/models.exports.dart
Normal file
@@ -0,0 +1 @@
|
||||
export './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;
|
||||
@@ -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<AstromicSwitcherToggle> {
|
||||
//
|
||||
//s1 --State
|
||||
late bool _currentState;
|
||||
late AstromicSwitcherToggleStyle _style;
|
||||
late AstromicToggleConfiguration _config;
|
||||
//s1 --State
|
||||
//
|
||||
//s1 --Constants
|
||||
@@ -100,6 +98,8 @@ class AstromicSwitcherToggleState extends State<AstromicSwitcherToggle> {
|
||||
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<AstromicSwitcherToggle> {
|
||||
|
||||
//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)),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
29
lib/src/Toggles/models/configuration.model.dart
Normal file
29
lib/src/Toggles/models/configuration.model.dart
Normal file
@@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
1
lib/src/Toggles/models/models.exports.dart
Normal file
1
lib/src/Toggles/models/models.exports.dart
Normal file
@@ -0,0 +1 @@
|
||||
export './configuration.model.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,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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<BoxShadow>? shadow,
|
||||
final bool? isCircular;
|
||||
final double? borderWidth;
|
||||
final Color? borderColor;
|
||||
final EdgeInsetsGeometry? borderPadding;
|
||||
final BorderRadiusGeometry? radius;
|
||||
final List<BoxShadow>? 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('<svg') : (ref?.endsWith('.svg') ?? false);
|
||||
|
||||
// Get image provider based on type
|
||||
ImageProvider _imageProvider(_DeclaredAssetType type, dynamic ref) {
|
||||
switch (type) {
|
||||
case _DeclaredAssetType.fallback:
|
||||
return AssetImage(ref);
|
||||
case _DeclaredAssetType.path:
|
||||
return AssetImage(ref);
|
||||
case _DeclaredAssetType.bytes:
|
||||
return MemoryImage(ref);
|
||||
case _DeclaredAssetType.url:
|
||||
return CachedNetworkImageProvider(ref, cacheKey: ref);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the sizing of the image...
|
||||
Size _calculateSize(BoxConstraints constraints) {
|
||||
double? maxAvailablewidth = constraints.maxWidth;
|
||||
double? maxAvailableheight = constraints.maxHeight;
|
||||
Size finalSize;
|
||||
switch (sizingMaster!) {
|
||||
case ImageSizingMaster.w:
|
||||
{
|
||||
finalSize = Size(fixedWidth ?? (widthSizing!.$1 * maxAvailablewidth).clamp(widthSizing!.$2 ?? 0, widthSizing!.$3 ?? double.infinity), fixedHeight ?? maxAvailableheight);
|
||||
}
|
||||
case ImageSizingMaster.h:
|
||||
{
|
||||
finalSize = Size(fixedWidth ?? maxAvailablewidth, fixedHeight ?? (heightSizing!.$1 * maxAvailableheight).clamp(heightSizing!.$2 ?? 0, heightSizing!.$3 ?? double.infinity));
|
||||
}
|
||||
}
|
||||
return finalSize;
|
||||
}
|
||||
//!SECTION
|
||||
}
|
||||
|
||||
final Uint8List kTransparentImage = Uint8List.fromList(<int>[
|
||||
|
||||
@@ -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<BoxShadow>? 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,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user