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

@@ -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) {