This commit is contained in:
2025-02-12 14:20:11 +02:00
parent 7d3920bb95
commit 2f77d5d813
28 changed files with 448 additions and 420 deletions

View File

@@ -79,7 +79,7 @@ class AstromicButtons {
onTap: onTap,
onHold: onHold,
configuration: configuration,
isUnderlined: isUnderlined ?? (e) => e,
isUnderlined: isUnderlined ?? (bool e) => e,
contentPadding: contentPadding,
style: style,
text: text,

View File

@@ -12,16 +12,6 @@ import 'models/models.exports.dart';
//s1 Exports
class AstromicButtonBase extends StatefulWidget {
//SECTION - Widget Arguments
//s1 -- Functionality
final VoidCallback? onTap;
final VoidCallback? onHold;
//s1 -- Configurations
final AstromicButtonConfiguration? configuration;
//s1 -- Style
final AstromicButtonStyle Function(bool isEnabled, bool isHighlighted)? style;
//s1 -- Content
final Widget Function(bool isEnabled, bool isHighlighted) child;
//!SECTION
//
const AstromicButtonBase({
@@ -38,6 +28,16 @@ class AstromicButtonBase extends StatefulWidget {
}) : super(
key: key,
);
//SECTION - Widget Arguments
//s1 -- Functionality
final VoidCallback? onTap;
final VoidCallback? onHold;
//s1 -- Configurations
final AstromicButtonConfiguration? configuration;
//s1 -- Style
final AstromicButtonStyle Function(bool isEnabled, bool isHighlighted)? style;
//s1 -- Content
final Widget Function(bool isEnabled, bool isHighlighted) child;
@override
State<AstromicButtonBase> createState() => _AstromicButtonBaseState();
@@ -121,7 +121,7 @@ class _AstromicButtonBaseState extends State<AstromicButtonBase> {
onTap: _config.isEnabled && widget.onTap != null ? widget.onTap : null,
onLongPress: _config.isEnabled && widget.onHold != null ? widget.onHold : null,
onHighlightChanged: _config.withHighlightChange
? (v) {
? (bool v) {
setState(() {
_isHighlighted = v;
});

View File

@@ -12,18 +12,6 @@ import 'models/models.exports.dart';
//s1 Exports
class AstromicIconButton extends StatefulWidget {
//SECTION - Widget Arguments
//s1 -- Functionality
final void Function(VoidCallback start, VoidCallback stop)? onTap;
final Function(VoidCallback start, VoidCallback stop)? onHold;
//s1 -- Configurations
final AstromicButtonConfiguration? configuration;
//s1 -- Style
final bool isCircular;
final AstromicButtonStyle Function(bool isEnabled, bool isHighlighted, bool isLoading)? style;
//s1 -- Content
final Widget? loadingContent;
final Widget Function(bool isEnabled, bool isHighlighted) icon;
//!SECTION
//
const AstromicIconButton({
@@ -40,6 +28,18 @@ class AstromicIconButton extends StatefulWidget {
this.loadingContent,
required this.icon,
});
//SECTION - Widget Arguments
//s1 -- Functionality
final void Function(VoidCallback start, VoidCallback stop)? onTap;
final Function(VoidCallback start, VoidCallback stop)? onHold;
//s1 -- Configurations
final AstromicButtonConfiguration? configuration;
//s1 -- Style
final bool isCircular;
final AstromicButtonStyle Function(bool isEnabled, bool isHighlighted, bool isLoading)? style;
//s1 -- Content
final Widget? loadingContent;
final Widget Function(bool isEnabled, bool isHighlighted) icon;
@override
State<AstromicIconButton> createState() => _AstromicIconButtonState();
@@ -117,10 +117,10 @@ class _AstromicIconButtonState extends State<AstromicIconButton> {
: null,
style: widget.style == null
? null
: (enabled, highlighted) => widget.style!.call(enabled, highlighted, isLoading).copyWith(
: (bool enabled, bool highlighted) => widget.style!.call(enabled, highlighted, isLoading).copyWith(
borderRadius: widget.isCircular ? BorderRadiusDirectional.circular(100000000000) : null,
),
child: (enabled, highlighted) => isLoading && widget.loadingContent != null ? widget.loadingContent! : widget.icon(enabled, highlighted),
child: (bool enabled, bool highlighted) => isLoading && widget.loadingContent != null ? widget.loadingContent! : widget.icon(enabled, highlighted),
);
//s1 -Widgets

View File

@@ -12,22 +12,6 @@ import 'models/models.exports.dart';
//s1 Exports
class AstromicLinkButton extends StatelessWidget {
//SECTION - Widget Arguments
//s1 -- Functionality
final VoidCallback? onTap;
final VoidCallback? onHold;
//s1 -- Configurations
final AstromicButtonConfiguration? configuration;
//s1 -- Style
final bool Function(bool isEnabled) isUnderlined;
final EdgeInsetsGeometry? contentPadding;
final TextStyle Function(bool isEnabled)? style;
//
//s1 -- Content
final String? text;
final Widget? textWidget;
final Widget? prefix;
final Widget? suffix;
//!SECTION
//
const AstromicLinkButton({
@@ -50,6 +34,22 @@ class AstromicLinkButton extends StatelessWidget {
super(
key: key,
);
//SECTION - Widget Arguments
//s1 -- Functionality
final VoidCallback? onTap;
final VoidCallback? onHold;
//s1 -- Configurations
final AstromicButtonConfiguration? configuration;
//s1 -- Style
final bool Function(bool isEnabled) isUnderlined;
final EdgeInsetsGeometry? contentPadding;
final TextStyle Function(bool isEnabled)? style;
//
//s1 -- Content
final String? text;
final Widget? textWidget;
final Widget? prefix;
final Widget? suffix;
@override
Widget build(BuildContext context) {
@@ -64,27 +64,24 @@ class AstromicLinkButton extends StatelessWidget {
//SECTION - Build Return
return Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
textDirection: configuration?.textDirection,
children: [
children: <Widget>[
AstromicButtonBase(
onTap: onTap,
onHold: onHold,
//
configuration: configuration,
//
style: (isEnabled, isHighlighted) => AstromicButtonStyle(
style: (bool isEnabled, bool isHighlighted) => AstromicButtonStyle(
contentPadding: contentPadding,
borderWidth: 0,
borderRadius: BorderRadius.zero,
borderColor: Colors.transparent,
),
//
child: (isEnabled, isHighlighted) => Row(
child: (bool isEnabled, bool isHighlighted) => Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
children: <Widget>[
if (prefix != null) prefix!,
textWidget != null
? textWidget!

View File

@@ -2,23 +2,6 @@ import 'package:flutter/material.dart';
/// Styling model for the button element.
class AstromicButtonStyle {
//s1 -- Colors
final Color? backgroundColor;
final Gradient? backgroundGradient;
final Color? hoverColor;
final Color? splashColor;
final Color? highlightColor;
final Color? borderColor;
final Gradient? borderGradient;
//
//s1 -- Spacing & Insets
final double? fixedHeight;
final double? fixedWidth;
final EdgeInsetsGeometry? contentPadding;
final BorderRadiusGeometry? borderRadius;
final double? borderWidth;
//s1 -- Interactions
final InteractiveInkFeatureFactory? splashFactory;
const AstromicButtonStyle({
this.backgroundColor = Colors.transparent,
this.backgroundGradient,
@@ -37,6 +20,23 @@ class AstromicButtonStyle {
this.splashFactory,
//
});
//s1 -- Colors
final Color? backgroundColor;
final Gradient? backgroundGradient;
final Color? hoverColor;
final Color? splashColor;
final Color? highlightColor;
final Color? borderColor;
final Gradient? borderGradient;
//
//s1 -- Spacing & Insets
final double? fixedHeight;
final double? fixedWidth;
final EdgeInsetsGeometry? contentPadding;
final BorderRadiusGeometry? borderRadius;
final double? borderWidth;
//s1 -- Interactions
final InteractiveInkFeatureFactory? splashFactory;
AstromicButtonStyle copyWith({
Color? backgroundColor,

View File

@@ -13,20 +13,6 @@ import 'models/models.exports.dart';
//s1 Exports
class AstromicStateButton extends StatefulWidget {
//SECTION - Widget Arguments
//s1 -- Functionality
final void Function(VoidCallback start, VoidCallback stop)? onTap;
final Function(VoidCallback start, VoidCallback stop)? onHold;
//s1 -- Configurations
final AstromicButtonConfiguration? configuration;
//s1 -- Style
final AstromicSizingStrategy? widthSizingStrategy;
final AstromicSizingStrategy? heightSizingStrategy;
final AstromicButtonStyle Function(bool isEnabled, bool isHighlighted, bool isLoading)? style;
//s1 -- Content
final Widget? loadingContent;
final Widget Function(bool isEnabled, bool isHighlighted) content;
//!SECTION
//
const AstromicStateButton({
@@ -44,6 +30,20 @@ class AstromicStateButton extends StatefulWidget {
this.loadingContent,
required this.content,
}) : assert(heightSizingStrategy != AstromicSizingStrategy.fill, 'Height strategy cannot be fill');
//SECTION - Widget Arguments
//s1 -- Functionality
final void Function(VoidCallback start, VoidCallback stop)? onTap;
final Function(VoidCallback start, VoidCallback stop)? onHold;
//s1 -- Configurations
final AstromicButtonConfiguration? configuration;
//s1 -- Style
final AstromicSizingStrategy? widthSizingStrategy;
final AstromicSizingStrategy? heightSizingStrategy;
final AstromicButtonStyle Function(bool isEnabled, bool isHighlighted, bool isLoading)? style;
//s1 -- Content
final Widget? loadingContent;
final Widget Function(bool isEnabled, bool isHighlighted) content;
@override
State<AstromicStateButton> createState() => _AstromicStateButtonState();
@@ -119,22 +119,20 @@ class _AstromicStateButtonState extends State<AstromicStateButton> {
});
}
: null,
style: (enabled, highlighted) => widget.style!(enabled, highlighted, isLoading).copyWith(
style: (bool enabled, bool highlighted) => widget.style!(enabled, highlighted, isLoading).copyWith(
contentPadding: widget.heightSizingStrategy == AstromicSizingStrategy.fixed && widget.widthSizingStrategy == AstromicSizingStrategy.fixed
? EdgeInsets.zero
: widget.heightSizingStrategy == AstromicSizingStrategy.fixed && widget.widthSizingStrategy != AstromicSizingStrategy.fixed
? EdgeInsets.symmetric(
horizontal: widget.style!(enabled, highlighted, isLoading).contentPadding?.horizontal ?? 0,
vertical: 0,
)
: widget.widthSizingStrategy == AstromicSizingStrategy.fixed && widget.heightSizingStrategy != AstromicSizingStrategy.fixed
? EdgeInsets.symmetric(
vertical: widget.style!(enabled, highlighted, isLoading).contentPadding?.vertical ?? 0,
horizontal: 0,
)
: null,
),
child: (enabled, highlighted) => isLoading && widget.loadingContent != null ? widget.loadingContent! : widget.content(enabled, highlighted),
child: (bool enabled, bool highlighted) => isLoading && widget.loadingContent != null ? widget.loadingContent! : widget.content(enabled, highlighted),
);
//s1 -Widgets
@@ -143,7 +141,7 @@ class _AstromicStateButtonState extends State<AstromicStateButton> {
//SECTION - Build Return
return Row(
mainAxisSize: widget.widthSizingStrategy == AstromicSizingStrategy.hug ? MainAxisSize.min : MainAxisSize.max,
children: [
children: <Widget>[
widget.widthSizingStrategy == AstromicSizingStrategy.fill
? Expanded(
child: SizedBox(

View File

@@ -30,7 +30,7 @@ class AstromicFields {
Iterable<ContextMenuButtonItem>? contextButtons,
}) =>
Column(
children: [
children: <Widget>[
AstromicTextField(
textController: controller,
stateKey: stateKey,
@@ -64,8 +64,8 @@ class AstromicFields {
Widget? Function(bool isEnabled, VoidCallback stateSetter)? suffixWidget,
Widget? Function(bool isEnabled)? messageBuilder}) =>
Column(
children: [
AstromicActionField(
children: <Widget>[
AstromicActionField<T>(
stateKey: stateKey,
textController: controller,
initialValue: initialValue,

View File

@@ -12,6 +12,26 @@ import 'models/models.exports.dart';
//s1 Exports
class AstromicActionField<T> extends StatefulWidget {
//!SECTION
//
const AstromicActionField({
super.key,
//
this.initialValue,
this.stateKey,
required this.textController,
required this.onValueChangedMapper,
this.onTap,
this.onHold,
//
this.configuration,
this.style,
//
this.hint,
this.prefixWidget,
this.suffixWidget,
this.messageBuilder,
});
//SECTION - Widget Arguments
//s1 -- Functionality
final Key? stateKey;
@@ -33,26 +53,6 @@ class AstromicActionField<T> extends StatefulWidget {
final Widget? Function(bool isEnabled, VoidCallback stateSetter)? prefixWidget;
final Widget? Function(bool isEnabled, VoidCallback stateSetter)? suffixWidget;
final Widget? Function(bool isEnabled)? messageBuilder;
//!SECTION
//
const AstromicActionField({
super.key,
//
this.initialValue,
this.stateKey,
required this.textController,
required this.onValueChangedMapper,
this.onTap,
this.onHold,
//
this.configuration,
this.style,
//
this.hint,
this.prefixWidget,
this.suffixWidget,
this.messageBuilder,
});
@override
State<AstromicActionField<T>> createState() => _AstromicActionFieldState<T>();
@@ -136,12 +136,12 @@ class _AstromicActionFieldState<T> extends State<AstromicActionField<T>> {
// onChanged: (v) {},
// onSubmited: (v) {},
configuration: widget.configuration,
style: widget.style == null ? null : (enabled, focused) => widget.style!(enabled),
style: widget.style == null ? null : (bool enabled, bool focused) => widget.style!(enabled),
hint: widget.hint,
prefixWidget: widget.prefixWidget == null ? null : (enabled, focused, stateSetter) => widget.prefixWidget!(enabled, stateSetter),
suffixWidget: widget.suffixWidget == null ? null : (enabled, focused, stateSetter) => widget.suffixWidget!(enabled, stateSetter),
messageBuilder: widget.messageBuilder == null ? null : (enabled, focused) => widget.messageBuilder!(enabled),
fieldStackedWidget: (finalHeight, border) => SizedBox(
prefixWidget: widget.prefixWidget == null ? null : (bool enabled, bool focused, void Function() stateSetter) => widget.prefixWidget!(enabled, stateSetter),
suffixWidget: widget.suffixWidget == null ? null : (bool enabled, bool focused, void Function() stateSetter) => widget.suffixWidget!(enabled, stateSetter),
messageBuilder: widget.messageBuilder == null ? null : (bool enabled, bool focused) => widget.messageBuilder!(enabled),
fieldStackedWidget: (double finalHeight, ShapeBorder? border) => SizedBox(
width: double.infinity,
height: finalHeight,
child: Material(

View File

@@ -17,6 +17,27 @@ import 'models/models.exports.dart';
//s1 Exports
class AstromicFieldBase extends StatefulWidget {
//!SECTION
//
const AstromicFieldBase({
super.key,
//
required this.textController,
this.stateKey,
this.onChanged,
this.onSubmited,
//
this.configuration,
//
this.style,
//
this.fieldStackedWidget,
this.hint,
this.prefixWidget,
this.suffixWidget,
this.messageBuilder,
this.contextButtons,
});
//SECTION - Widget Arguments
//s1 -- Functionality
final TextEditingController textController;
@@ -40,27 +61,6 @@ class AstromicFieldBase extends StatefulWidget {
final Widget? Function(bool isEnabled, bool isFocused)? messageBuilder;
//
final Iterable<ContextMenuButtonItem>? contextButtons;
//!SECTION
//
const AstromicFieldBase({
super.key,
//
required this.textController,
this.stateKey,
this.onChanged,
this.onSubmited,
//
this.configuration,
//
this.style,
//
this.fieldStackedWidget,
this.hint,
this.prefixWidget,
this.suffixWidget,
this.messageBuilder,
this.contextButtons,
});
@override
State<AstromicFieldBase> createState() => _AstromicFieldBaseState();
@@ -128,9 +128,9 @@ class _AstromicFieldBaseState extends State<AstromicFieldBase> {
//SECTION - Stateless functions
_getTextHeight(String text, TextStyle style, ui.TextDirection direction) {
final span = TextSpan(text: text, style: style);
final tp = TextPainter(text: span, textDirection: direction);
tp.layout(maxWidth: double.infinity);
final TextSpan span = TextSpan(text: text, style: style);
final TextPainter tp = TextPainter(text: span, textDirection: direction);
tp.layout();
return tp.height;
}
@@ -167,7 +167,7 @@ class _AstromicFieldBaseState extends State<AstromicFieldBase> {
? widget.textController.text
: (widget.hint?.isNotEmpty ?? false)
? widget.hint!
: "",
: '',
widget.textController.text.isNotEmpty && _style().textStyle != null
? _style().textStyle!
: _style().hintStyle != null
@@ -213,7 +213,7 @@ class _AstromicFieldBaseState extends State<AstromicFieldBase> {
) ??
BorderRadius.circular(0))
: OutlineInputBorder(
borderSide: BorderSide(color: style.borderColor ?? Colors.grey, width: style.borderWidth ?? 2.0, style: BorderStyle.solid),
borderSide: BorderSide(color: style.borderColor ?? Colors.grey, width: style.borderWidth ?? 2.0),
borderRadius: style.borderRadius?.resolve(
_config.textDirection,
) ??
@@ -229,7 +229,7 @@ class _AstromicFieldBaseState extends State<AstromicFieldBase> {
) ??
BorderRadius.circular(0))
: UnderlineInputBorder(
borderSide: BorderSide(color: style.borderColor ?? Colors.grey, width: style.borderWidth ?? 2.0, style: BorderStyle.solid),
borderSide: BorderSide(color: style.borderColor ?? Colors.grey, width: style.borderWidth ?? 2.0),
borderRadius: style.borderRadius?.resolve(
_config.textDirection,
) ??
@@ -334,7 +334,7 @@ class _AstromicFieldBaseState extends State<AstromicFieldBase> {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Directionality(
textDirection: _finalTextDirection(),
child: Container(
@@ -345,7 +345,7 @@ class _AstromicFieldBaseState extends State<AstromicFieldBase> {
: null,
alignment: _style().textAlignVertical.toAlignment(),
child: Stack(
children: [
children: <Widget>[
TextFormField(
//s1 -- Functionality
key: widget.stateKey,
@@ -353,7 +353,7 @@ class _AstromicFieldBaseState extends State<AstromicFieldBase> {
focusNode: _focusNode,
textInputAction: _config.inputAction,
//
onChanged: (v) {
onChanged: (String v) {
setState(() {
if (widget.onChanged != null) {
widget.onChanged!(v);
@@ -361,7 +361,7 @@ class _AstromicFieldBaseState extends State<AstromicFieldBase> {
});
},
//
onFieldSubmitted: (v) {
onFieldSubmitted: (String v) {
//
if (_config.inputAction == TextInputAction.next) {
_focusNode.nextFocus();
@@ -371,7 +371,7 @@ class _AstromicFieldBaseState extends State<AstromicFieldBase> {
}
},
//
onTapOutside: (tapEvent) {
onTapOutside: (PointerDownEvent tapEvent) {
if (_config.unfocusOnTapOutside) {
_focusNode.unfocus();
}
@@ -398,7 +398,7 @@ class _AstromicFieldBaseState extends State<AstromicFieldBase> {
//
expands: _config.isFixedHeight && _config.isTextArea ? true : false,
// - Validation
validator: _config.validator != null ? (s) => _config.validator!(_config.isEnabled, _isFocused, s) : null,
validator: _config.validator != null ? (String? s) => _config.validator!(_config.isEnabled, _isFocused, s) : null,
// - Validation
//s1 -- Style
style: _style().textStyle,
@@ -409,7 +409,7 @@ class _AstromicFieldBaseState extends State<AstromicFieldBase> {
//s1 -- Input Decoration
decoration: inputDecoration,
//s1 -- Content
contextMenuBuilder: (_, state) {
contextMenuBuilder: (_, EditableTextState state) {
List<ContextMenuButtonItem> baseContextButtons = state.contextMenuButtonItems;
if (widget.contextButtons != null) {
baseContextButtons.addAll(widget.contextButtons!);

View File

@@ -1,34 +1,9 @@
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
/// Configuration model for the field element.
class AstromicFieldConfiguration {
//
final bool isEnabled;
final bool? isTextObscured;
final bool isFixedHeight;
final bool isTextArea;
//
final bool withAutofocus;
final bool respectBorderWidthPadding;
final bool withObscurity;
final bool withAutomaticDirectionalitySwitching;
final bool unfocusOnTapOutside;
//
final ui.TextDirection? hintDirection;
final ui.TextDirection? textDirection;
final ui.TextDirection? messageDirection;
//
final TextInputType inputType;
final TextInputAction inputAction;
//
final MaxLengthEnforcement maxLengthEnforcement;
//
final AutovalidateMode? validatingMode;
final String? Function(bool isEnabled, bool isFocused, String? text)? validator;
final List<TextInputFormatter>? inputFormatters;
//
const AstromicFieldConfiguration({
this.isEnabled = true,
@@ -55,6 +30,30 @@ class AstromicFieldConfiguration {
//
});
//
final bool isEnabled;
final bool? isTextObscured;
final bool isFixedHeight;
final bool isTextArea;
//
final bool withAutofocus;
final bool respectBorderWidthPadding;
final bool withObscurity;
final bool withAutomaticDirectionalitySwitching;
final bool unfocusOnTapOutside;
//
final ui.TextDirection? hintDirection;
final ui.TextDirection? textDirection;
final ui.TextDirection? messageDirection;
//
final TextInputType inputType;
final TextInputAction inputAction;
//
final MaxLengthEnforcement maxLengthEnforcement;
//
final AutovalidateMode? validatingMode;
final String? Function(bool isEnabled, bool isFocused, String? text)? validator;
final List<TextInputFormatter>? inputFormatters;
//
AstromicFieldConfiguration copyWith({
bool? isEnabled,

View File

@@ -3,6 +3,37 @@ import '../enums/border_type.enum.dart';
/// Styling model for the field element.
class AstromicFieldStyle {
const AstromicFieldStyle({
this.isFilled = true,
//
this.minLines = 1,
this.maxLines = 1,
this.maxLength,
this.textAlign = TextAlign.start,
this.textAlignVertical = TextAlignVertical.center,
//
this.fixedHeight,
//
this.borderRadius,
this.borderWidth,
this.borderType = AstromicFieldBorderType.underlined,
this.customBorder,
//
this.contentPadding = EdgeInsets.zero,
this.messagePadding = EdgeInsets.zero,
this.prefixSpacing = 4,
this.prefixSize = 24,
this.suffixSpacing = 4,
this.suffixSize = 24,
//
this.fillColor = const Color(0xffffffff),
this.borderColor,
this.borderGradient,
this.cursorColor,
this.hintStyle,
this.textStyle,
});
//s1 - Styling Configs
final bool isFilled;
//s1 - Sizing & Spacing
@@ -38,37 +69,6 @@ class AstromicFieldStyle {
//s1 - Styling
final TextStyle? hintStyle;
final TextStyle? textStyle;
const AstromicFieldStyle({
this.isFilled = true,
//
this.minLines = 1,
this.maxLines = 1,
this.maxLength,
this.textAlign = TextAlign.start,
this.textAlignVertical = TextAlignVertical.center,
//
this.fixedHeight,
//
this.borderRadius,
this.borderWidth,
this.borderType = AstromicFieldBorderType.underlined,
this.customBorder,
//
this.contentPadding = EdgeInsets.zero,
this.messagePadding = EdgeInsets.zero,
this.prefixSpacing = 4,
this.prefixSize = 24,
this.suffixSpacing = 4,
this.suffixSize = 24,
//
this.fillColor = const Color(0xffffffff),
this.borderColor,
this.borderGradient,
this.cursorColor,
this.hintStyle,
this.textStyle,
});
//
AstromicFieldStyle copyWith({
bool? isFilled,

View File

@@ -12,6 +12,26 @@ import 'models/models.exports.dart';
//s1 Exports
class AstromicTextField extends StatelessWidget {
//!SECTION
//
const AstromicTextField({
super.key,
//
required this.textController,
this.stateKey,
this.onChanged,
this.onSubmited,
//
this.configuration,
//
this.style,
//
this.hint,
this.prefixWidget,
this.suffixWidget,
this.messageBuilder,
this.contextButtons,
});
//SECTION - Widget Arguments
//s1 -- Functionality
final TextEditingController textController;
@@ -34,26 +54,6 @@ class AstromicTextField extends StatelessWidget {
final Widget? Function(bool isEnabled, bool isFocused)? messageBuilder;
//
final Iterable<ContextMenuButtonItem>? contextButtons;
//!SECTION
//
const AstromicTextField({
super.key,
//
required this.textController,
this.stateKey,
this.onChanged,
this.onSubmited,
//
this.configuration,
//
this.style,
//
this.hint,
this.prefixWidget,
this.suffixWidget,
this.messageBuilder,
this.contextButtons,
});
@override
Widget build(BuildContext context) {

View File

@@ -45,7 +45,7 @@ class AstromicSelectors {
required Widget Function(T item, bool isEnabled, bool isSelected, VoidCallback? onTap, VoidCallback? onClearTapped) itemBuilder,
Widget Function(List<Widget> items)? groupBuilder,
}) =>
AstromicChipSelector(
AstromicChipSelector<T>(
initialSelectedValues: initialSelectedValues,
onChanged: onChanged,
configuration: configuration,
@@ -53,6 +53,6 @@ class AstromicSelectors {
runSpacing: runSpacing,
items: items,
itemBuilder: itemBuilder,
groupBuilder: groupBuilder!,
groupBuilder: groupBuilder,
);
}

View File

@@ -13,20 +13,6 @@ import 'models/models.exports.dart';
/// 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 AstromicChipSelectorConfiguration? configuration;
//s1 -- Style
final double? itemSpacing;
final double? runSpacing;
//
//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
//
AstromicChipSelector({
@@ -44,12 +30,26 @@ class AstromicChipSelector<T> extends StatefulWidget {
required this.itemBuilder,
this.groupBuilder,
}) : assert(
(configuration?.isNullable ?? true) || (initialSelectedValues != null && items.map((i) => i.$1).toList().containsAll(initialSelectedValues)),
"Initial values are not all present in the items!",
(configuration?.isNullable ?? true) || (initialSelectedValues != null && items.map(((T, bool) i) => i.$1).toList().containsAll(initialSelectedValues)),
'Initial values are not all present in the items!',
),
super(
key: key,
);
//SECTION - Widget Arguments
//s1 -- Functionality
final List<T>? initialSelectedValues;
final Function(List<T> selectedItems)? onChanged;
//s1 -- Configuration
final AstromicChipSelectorConfiguration? configuration;
//s1 -- Style
final double? itemSpacing;
final double? runSpacing;
//
//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;
@override
State<AstromicChipSelector<T>> createState() => _AstromicChipSelectorState<T>();
@@ -80,7 +80,7 @@ class _AstromicChipSelectorState<T> extends State<AstromicChipSelector<T>> {
//s1 --Controllers & Listeners
//
//s1 --State
selectedItems = widget.initialSelectedValues ?? [];
selectedItems = widget.initialSelectedValues ?? <T>[];
//s1 --State
//
//s1 --Late & Async Initializers
@@ -126,7 +126,7 @@ class _AstromicChipSelectorState<T> extends State<AstromicChipSelector<T>> {
//s1 -Values
//
//s1 -Widgets
List<Widget> baseChildren = widget.items.map((currentItem) {
List<Widget> baseChildren = widget.items.map(((T, bool) currentItem) {
//
AstromicChipSelectorConfiguration configuration = widget.configuration ?? const AstromicChipSelectorConfiguration();
//

View File

@@ -3,15 +3,6 @@ import 'package:flutter/widgets.dart';
/// Configuration model for the chip selector element.
class AstromicChipSelectorConfiguration {
final bool isNullable;
final bool isWrap;
final WrapAlignment wrapMainAllignment;
final WrapCrossAlignment wrapCrossAllignment;
final bool isConsequent;
final bool withClearButton;
final int maxSelectedItems;
final int crossAxisCount;
final double? fixedRowHeight;
const AstromicChipSelectorConfiguration({
this.isNullable = true,
//
@@ -24,6 +15,15 @@ class AstromicChipSelectorConfiguration {
this.crossAxisCount = 3,
this.fixedRowHeight,
});
final bool isNullable;
final bool isWrap;
final WrapAlignment wrapMainAllignment;
final WrapCrossAlignment wrapCrossAllignment;
final bool isConsequent;
final bool withClearButton;
final int maxSelectedItems;
final int crossAxisCount;
final double? fixedRowHeight;
AstromicChipSelectorConfiguration copyWith({
bool? isNullable,

View File

@@ -2,12 +2,6 @@ import 'package:flutter/widgets.dart';
/// Configuration model for the radio selector element.
class AstromicRadioSelectorConfiguration {
final Axis axis;
final bool isNullable;
//
final MainAxisAlignment? mainAxisAlignment;
final MainAxisSize? mainAxisSize;
final CrossAxisAlignment? crossAxisAlignment;
const AstromicRadioSelectorConfiguration({
this.axis = Axis.horizontal,
this.isNullable = true,
@@ -16,6 +10,12 @@ class AstromicRadioSelectorConfiguration {
this.mainAxisSize,
this.crossAxisAlignment,
});
final Axis axis;
final bool isNullable;
//
final MainAxisAlignment? mainAxisAlignment;
final MainAxisSize? mainAxisSize;
final CrossAxisAlignment? crossAxisAlignment;
AstromicRadioSelectorConfiguration copyWith({
Axis? axis,

View File

@@ -12,17 +12,6 @@ import 'models/models.exports.dart';
/// 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;
//s1 -- Style
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
//
AstromicRadioSelector({
@@ -42,16 +31,27 @@ class AstromicRadioSelector<T> extends StatefulWidget {
configuration!.isNullable ||
(items
.map(
(e) => e.$1,
((T, bool) e) => e.$1,
)
.toList()
.contains(initialSelectedValue) &&
items.where((e) => e.$1 == initialSelectedValue).first.$2),
"Initial value is not present in the items or is not enabled!",
items.where(((T, bool) e) => e.$1 == initialSelectedValue).first.$2),
'Initial value is not present in the items or is not enabled!',
),
super(
key: key,
);
//SECTION - Widget Arguments
//s1 -- Functionality
final T? initialSelectedValue;
final Function(T selectedItem)? onChanged;
//s1 -- Configuration
final AstromicRadioSelectorConfiguration? configuration;
//s1 -- Style
final double? itemSpacing;
//s1 -- Content
final List<(T item, bool isEnabled)> items;
final Widget Function(T item, bool isEnabled, bool isSelected, VoidCallback? onTap) itemBuilder;
@override
State<AstromicRadioSelector<T>> createState() => _AstromicRadioSelectorState<T>();
@@ -116,7 +116,7 @@ class _AstromicRadioSelectorState<T> extends State<AstromicRadioSelector<T>> {
//s1 -Values
//
//s1 -Widgets
List<Widget> baseChildren = widget.items.map((currentItem) {
List<Widget> baseChildren = widget.items.map(((T, bool) currentItem) {
T item = currentItem.$1;
bool isEnabled = currentItem.$2;
bool isSelected = item == selectedItem;

View File

@@ -12,20 +12,6 @@ import '../models/models.exports.dart';
//s1 Exports
class AstromicCheckboxToggle 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 AstromicToggleConfiguration? configuration;
//s1 -- Style
final AstromicCheckboxToggleStyle Function(bool isEnabled, bool isSelected)? style;
//
//s1 -- Content
final Widget Function(bool isEnabled, bool isSelected)? innerWidget;
final Widget Function(bool isEnabled, bool isSelected)? label;
//!SECTION
//
const AstromicCheckboxToggle({
@@ -42,6 +28,20 @@ class AstromicCheckboxToggle extends StatefulWidget {
this.innerWidget,
this.label,
}) : assert(stateVariable == null || initialState == null, "Can't define both the state variable and the initial state");
//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 AstromicToggleConfiguration? configuration;
//s1 -- Style
final AstromicCheckboxToggleStyle Function(bool isEnabled, bool isSelected)? style;
//
//s1 -- Content
final Widget Function(bool isEnabled, bool isSelected)? innerWidget;
final Widget Function(bool isEnabled, bool isSelected)? label;
@override
State<AstromicCheckboxToggle> createState() => _AstromicCheckboxToggleState();
@@ -129,7 +129,7 @@ class _AstromicCheckboxToggleState extends State<AstromicCheckboxToggle> {
textDirection: _config.textDirection,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
children: <Widget>[
//Item
SizedBox(
width: _style.itemSize,

View File

@@ -2,6 +2,14 @@ import 'package:flutter/material.dart';
/// Styling model for the CheckBox Toggle element.
class AstromicCheckboxToggleStyle {
AstromicCheckboxToggleStyle({
this.itemSize = 24.0,
this.labelSpacing = 8.0,
this.border = const Border.fromBorderSide(BorderSide(width: 2)),
this.borderRadius = const BorderRadius.all(Radius.circular(4)),
this.backgroundColor = Colors.transparent,
});
final double? itemSize;
final double? labelSpacing;
//
@@ -9,14 +17,6 @@ class AstromicCheckboxToggleStyle {
final BorderRadius? borderRadius;
final Color? backgroundColor;
AstromicCheckboxToggleStyle({
this.itemSize = 24.0,
this.labelSpacing = 8.0,
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({
double? itemSize,
double? labelSpacing,

View File

@@ -2,24 +2,6 @@ import 'package:flutter/widgets.dart';
/// Styling model for the Switcher Toggle element.
class AstromicSwitcherToggleStyle {
final double width;
final double height;
final double labelSpacing;
final double toggleSize;
final double togglePadding;
final double borderRadius;
//
final Color activeColor;
final Color? activeToggleColor;
final BoxBorder? activeToggleBorder;
final BoxBorder? activeSwitchBorder;
final Widget? innerActiveWidget;
//
final Color inactiveColor;
final Color? inactiveToggleColor;
final BoxBorder? inactiveSwitchBorder;
final BoxBorder? inactiveToggleBorder;
final Widget? innerInactiveWidget;
//
const AstromicSwitcherToggleStyle({
this.width = 70,
@@ -39,4 +21,22 @@ class AstromicSwitcherToggleStyle {
this.innerActiveWidget,
this.innerInactiveWidget,
});
final double width;
final double height;
final double labelSpacing;
final double toggleSize;
final double togglePadding;
final double borderRadius;
//
final Color activeColor;
final Color? activeToggleColor;
final BoxBorder? activeToggleBorder;
final BoxBorder? activeSwitchBorder;
final Widget? innerActiveWidget;
//
final Color inactiveColor;
final Color? inactiveToggleColor;
final BoxBorder? inactiveSwitchBorder;
final BoxBorder? inactiveToggleBorder;
final Widget? innerInactiveWidget;
}

View File

@@ -13,18 +13,6 @@ import '../models/models.exports.dart';
//s1 Exports
class AstromicSwitcherToggle 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 AstromicToggleConfiguration? configuration;
//s1 -- Style
final AstromicSwitcherToggleStyle Function(bool isEnabled, bool isSelected)? style;
//s1 -- Content
final Widget Function(bool isEnabled, bool isSelected)? label;
//!SECTION
//
const AstromicSwitcherToggle({
@@ -39,6 +27,18 @@ class AstromicSwitcherToggle extends StatefulWidget {
//
this.label,
});
//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 AstromicToggleConfiguration? configuration;
//s1 -- Style
final AstromicSwitcherToggleStyle Function(bool isEnabled, bool isSelected)? style;
//s1 -- Content
final Widget Function(bool isEnabled, bool isSelected)? label;
@override
State<AstromicSwitcherToggle> createState() => AstromicSwitcherToggleState();
@@ -111,7 +111,7 @@ class AstromicSwitcherToggleState extends State<AstromicSwitcherToggle> {
textDirection: _config.textDirection,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
children: <Widget>[
//S1 -- Item
FlutterSwitch(
width: _style.width,
@@ -119,7 +119,6 @@ class AstromicSwitcherToggleState extends State<AstromicSwitcherToggle> {
borderRadius: _style.borderRadius,
value: _currentState,
toggleSize: _style.toggleSize,
disabled: false,
//
activeColor: _style.activeColor,
activeToggleColor: _style.activeToggleColor,
@@ -134,8 +133,7 @@ class AstromicSwitcherToggleState extends State<AstromicSwitcherToggle> {
inactiveIcon: _style.innerInactiveWidget,
//
padding: _style.togglePadding,
showOnOff: false,
onToggle: (s) => _onTap(s),
onToggle: (bool s) => _onTap(s),
),
//S1 -- Label Spacing
if (_config.withLabel) SizedBox(width: _style.labelSpacing),

View File

@@ -2,16 +2,16 @@ 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,
});
final bool isEnabled;
final bool withLabel;
final bool isLabelTapable;
final TextDirection textDirection;
AstromicToggleConfiguration copyWith({
bool? isEnabled,

View File

@@ -11,15 +11,6 @@ import 'package:flutter/material.dart';
//s1 Exports
class AstromicBlur extends StatelessWidget {
//SECTION - Widget Arguments
final Widget child;
final (double x, double y)? sigma;
final TileMode? tileMode;
final Color? overlayColor;
final Gradient? overlayGradient;
final BorderRadius? radius;
final List<BoxShadow>? shadow;
final Widget? childOnTop;
//!SECTION
//
const AstromicBlur({
@@ -33,6 +24,15 @@ class AstromicBlur extends StatelessWidget {
this.shadow,
this.childOnTop,
});
//SECTION - Widget Arguments
final Widget child;
final (double x, double y)? sigma;
final TileMode? tileMode;
final Color? overlayColor;
final Gradient? overlayGradient;
final BorderRadius? radius;
final List<BoxShadow>? shadow;
final Widget? childOnTop;
@override
Widget build(BuildContext context) {
@@ -56,7 +56,7 @@ class AstromicBlur extends StatelessWidget {
borderRadius: radius ?? BorderRadius.zero,
child: Stack(
fit: StackFit.expand,
children: [
children: <Widget>[
child, // The main widget goes under the blurred background
BackdropFilter(
filter: ImageFilter.blur(sigmaX: sigma!.$1, sigmaY: sigma!.$2),

View File

@@ -47,42 +47,6 @@ _DeclaredAssetType _parseAssetType(
}
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
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
final Color? svgColor;
//S1 -- STATE WIDGETS
final Widget Function(int? loadedBytes, int? totalBytesToLoad)? loadingWidget;
final Widget Function(dynamic error, StackTrace? stackTrace)? errorWidget;
//!SECTION
//
AstromicImage({
@@ -121,16 +85,52 @@ class AstromicImage extends StatelessWidget {
}) :
// 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."),
'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"),
'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");
'Please provide the correct sizing configurations based on the SizingMaster choosen');
//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
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
final Color? svgColor;
//S1 -- STATE WIDGETS
final Widget Function(int? loadedBytes, int? totalBytesToLoad)? loadingWidget;
final Widget Function(dynamic error, StackTrace? stackTrace)? errorWidget;
@override
Widget build(BuildContext context) {
@@ -152,7 +152,7 @@ class AstromicImage extends StatelessWidget {
Widget? finalSVGWidget(Size size, Widget? loadingWidget) => assetType == _DeclaredAssetType.path
? SvgPicture.asset(
assetRef,
key: ValueKey(assetRef),
key: ValueKey<String>(assetRef),
width: size.width,
height: size.height,
fit: fit!,
@@ -167,7 +167,7 @@ class AstromicImage extends StatelessWidget {
: assetType == _DeclaredAssetType.url
? SvgPicture.network(
assetRef,
key: ValueKey(assetRef),
key: ValueKey<String>(assetRef),
width: size.width,
height: size.height,
fit: fit!,
@@ -183,9 +183,9 @@ class AstromicImage extends StatelessWidget {
Widget buildImage(Size size) {
return Stack(
children: [
children: <Widget>[
OctoImage(
key: ValueKey(assetType == _DeclaredAssetType.bytes ? (assetRef as Uint8List).length.toString() : assetRef),
key: ValueKey<String>(assetType == _DeclaredAssetType.bytes ? (assetRef as Uint8List).length.toString() : assetRef),
//
width: size.width,
height: size.height,
@@ -195,8 +195,8 @@ class AstromicImage extends StatelessWidget {
color: svgColor,
colorBlendMode: blendMode ?? (isSVG ? BlendMode.srcATop : null),
//
errorBuilder: (context, error, stackTrace) {
debugPrint("AstromicImage Error: $error");
errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) {
debugPrint('AstromicImage Error: $error');
return errorWidget != null
? errorWidget!(error, stackTrace)
: assetFallback != null
@@ -204,15 +204,15 @@ class AstromicImage extends StatelessWidget {
: defaultErrorWidget(error);
},
//
progressIndicatorBuilder: (_, bytes) => SizedBox(
progressIndicatorBuilder: (_, ImageChunkEvent? 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,
placeholderBuilder: (BuildContext context) => loadingWidget != null ? loadingWidget!(null, null) : defaultLoadingWidget,
fadeInCurve: fadeInCurve,
fadeInDuration: fadeInDuration,
imageBuilder: (context, image) => Container(
imageBuilder: (BuildContext context, Widget image) => Container(
width: size.width,
height: size.height,
padding: borderPadding ?? EdgeInsets.zero,
@@ -220,7 +220,6 @@ class AstromicImage extends StatelessWidget {
decoration: BoxDecoration(
border: borderWidth != null
? Border.all(
strokeAlign: BorderSide.strokeAlignInside,
width: borderWidth!,
color: borderColor ?? const Color(0xff000000),
)
@@ -250,7 +249,7 @@ class AstromicImage extends StatelessWidget {
//!SECTION
//SECTION - Build Return
return LayoutBuilder(builder: (context, constraints) {
return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
Size size = _calculateSize(constraints);
return SizedBox(width: size.width, height: size.height, child: buildImage(size));
});