[FIX] Action field longer padding.

This commit is contained in:
2025-12-20 21:26:35 +02:00
parent 655a405ac1
commit 47c85b3149
3 changed files with 632 additions and 1 deletions

View File

@@ -422,7 +422,33 @@ class _AstromicFieldBaseState extends State<AstromicFieldBase> {
);
},
),
widget.fieldStackedWidget != null ? widget.fieldStackedWidget!(_finalVerticalPadding(_style(), forceRespectBorder: true).vertical * 2, _finalBorderShape(_style())) : Container(),
widget.fieldStackedWidget != null
? Builder(builder: (c) {
// Calculate the actual height of the TextFormField including padding and border
double contentHeight = _getTextHeight(
_textController.text.isNotEmpty
? _textController.text
: (widget.hint?.isNotEmpty ?? false)
? widget.hint!
: '',
_style().textStyle ?? Theme.of(c).textTheme.titleMedium!,
_finalTextDirection(),
);
double verticalPadding = _finalVerticalPadding(_style()).vertical * 2;
double borderWidth = _style().borderWidth ?? 0; // Default to 0 if null
double totalFieldHeight;
if (_config.isFixedHeight && !_config.isTextArea) {
totalFieldHeight = _style().fixedHeight ?? contentHeight + verticalPadding + (borderWidth * 2);
} else if (_config.isFixedHeight && _config.isTextArea) {
totalFieldHeight = _style().fixedHeight ?? contentHeight + verticalPadding + (borderWidth * 2);
} else {
totalFieldHeight = contentHeight + verticalPadding + (borderWidth * 2);
}
return widget.fieldStackedWidget!(totalFieldHeight, _finalBorderShape(_style()));
})
: Container(),
],
),
),

View File

@@ -0,0 +1,152 @@
// //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 'base.dart';
// import 'dropdown_field_base.dart';
// import 'models/models.exports.dart';
// //s1 Exports
// class AstromicDropdownField<T> extends StatefulWidget {
// //!SECTION
// //
// const AstromicDropdownField({
// super.key,
// //
// this.stateKey,
// required this.textController,
// required this.items,
// this.initialValue,
// this.onChanged,
// //
// this.configuration,
// this.style,
// //
// this.hint,
// this.prefixWidget,
// this.suffixWidget,
// this.messageBuilder,
// });
// //SECTION - Widget Arguments
// //s1 -- Functionality
// final Key? stateKey;
// final TextEditingController textController;
// final (T item, String label)? initialValue;
// final List<(T item, String label)> items;
// final void Function((T item, String label) newValue)? onChanged;
// //
// //s1 -- Configurations
// final AstromicFieldConfiguration? configuration;
// //
// //s1 -- Style
// final AstromicFieldStyle Function(bool isEnabled)? style;
// //
// //s1 -- Content
// final String? hint;
// //
// final Widget? Function(bool isEnabled, VoidCallback stateSetter)? prefixWidget;
// final Widget? Function(bool isEnabled, VoidCallback stateSetter)? suffixWidget;
// final Widget? Function(bool isEnabled)? messageBuilder;
// @override
// State<AstromicDropdownField<T>> createState() => _AstromicDropdownFieldState<T>();
// }
// class _AstromicDropdownFieldState<T> extends State<AstromicDropdownField<T>> {
// //
// //SECTION - State Variables
// //s1 --State
// (T item, String label)? _currentValue;
// //s1 --State
// //
// //s1 --Controllers
// late TextEditingController _textController;
// //s1 --Controllers
// //
// //s1 --Constants
// //s1 --Constants
// //!SECTION
// @override
// void initState() {
// super.initState();
// //
// //SECTION - State Variables initializations & Listeners
// //s1 --State
// //s1 --State
// //
// //s1 --Controllers & Listeners
// _currentValue = widget.initialValue;
// _textController = widget.textController;
// _textController.text = _currentValue?.$2 ?? '';
// //s1 --Controllers & Listeners
// //
// //s1 --Late & Async Initializers
// //s1 --Late & Async Initializers
// //!SECTION
// }
// @override
// void didChangeDependencies() {
// super.didChangeDependencies();
// //
// //SECTION - State Variables initializations & Listeners
// //s1 --State
// //s1 --State
// //
// //s1 --Controllers & Listeners
// //s1 --Controllers & Listeners
// //
// //!SECTION
// }
// //SECTION - Dumb Widgets
// //!SECTION
// //SECTION - Stateless functions
// //!SECTION
// //SECTION - Action Callbacks
// //!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 --Contexted Widgets
// //s1 --Contexted Widgets
// //!SECTION
// //SECTION - Build Return
// return AstromicDropdownFieldBase(
// key: widget.key,
// textController: _textController,
// stateKey: widget.stateKey,
// onChanged: (v) => widget.onChanged?.call(v),
// configuration: widget.configuration,
// style: widget.style == null ? null : (bool enabled, bool focused) => widget.style!(enabled),
// hint: widget.hint,
// 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),
// );
// //!SECTION
// }
// @override
// void dispose() {
// //SECTION - Disposable variables
// //!SECTION
// super.dispose();
// }
// }

View File

@@ -0,0 +1,453 @@
// //s1 Imports
// //s2 Core Package Imports
// import 'package:flutter/material.dart';
// import 'package:intl/intl.dart' as intl;
// import 'dart:ui' as ui;
// //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 '../../../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
// class AstromicDropdownFieldBase extends StatefulWidget {
// //!SECTION
// //
// const AstromicDropdownFieldBase({
// super.key,
// this.stateKey,
// //
// required this.textController,
// this.onChanged,
// //
// this.configuration,
// //
// this.style,
// //
// this.hint,
// this.prefixWidget,
// this.suffixWidget,
// this.messageBuilder,
// this.contextButtons,
// });
// //SECTION - Widget Arguments
// //s1 -- Functionality
// final TextEditingController textController;
// final Key? stateKey;
// //
// final void Function(String v)? onChanged;
// //
// //s1 -- Configurations
// final AstromicFieldConfiguration? configuration;
// //
// //s1 -- Style
// final AstromicFieldStyle Function(bool isEnabled, bool isFocused)? style;
// //
// //s1 -- Content
// final String? hint;
// //
// final Widget? Function(bool isEnabled, bool isFocused, VoidCallback stateSetter)? prefixWidget;
// final Widget? Function(bool isEnabled, bool isFocused, VoidCallback stateSetter)? suffixWidget;
// final Widget? Function(bool isEnabled, bool isFocused)? messageBuilder;
// //
// final Iterable<ContextMenuButtonItem>? contextButtons;
// @override
// State<AstromicDropdownFieldBase> createState() => _AstromicDropdownFieldBaseState();
// }
// class _AstromicDropdownFieldBaseState extends State<AstromicDropdownFieldBase> {
// //
// //SECTION - State Variables
// //s1 --Controllers
// late TextEditingController _textController;
// //s1 --Controllers
// //
// //s1 --State
// // late bool widget.configuration.isEnabled;
// final FocusNode _focusNode = FocusNode();
// late bool _isFocused;
// //
// late AstromicFieldStyle Function([bool isFocused]) _style;
// late AstromicFieldConfiguration _config;
// //
// //s1 --State
// //
// //s1 --Constants
// //s1 --Constants
// //!SECTION
// @override
// void initState() {
// super.initState();
// //
// //SECTION - State Variables initializations & Listeners
// //s1 --Controllers & Listeners
// _textController = widget.textController;
// //s1 --Controllers & Listeners
// //
// //s1 --State
// // widget.configuration.isEnabled = widget.configuration.isEnabled;
// _isFocused = false;
// //s1 --State
// //
// //s1 --Late & Async Initializers
// //s1 --Late & Async Initializers
// //!SECTION
// }
// @override
// void didChangeDependencies() {
// super.didChangeDependencies();
// //
// //SECTION - State Variables initializations & Listeners
// //s1 --State
// _focusNode.addListener(() {
// if (mounted) {
// setState(() {
// _isFocused = _focusNode.hasFocus;
// });
// }
// });
// //s1 --State
// //!SECTION
// }
// //SECTION - Dumb Widgets
// //!SECTION
// //SECTION - Stateless functions
// _getTextHeight(String text, TextStyle style, ui.TextDirection direction) {
// final TextSpan span = TextSpan(text: text, style: style);
// final TextPainter tp = TextPainter(text: span, textDirection: direction);
// tp.layout();
// return tp.height;
// }
// ui.TextDirection _finalTextDirection() {
// ui.TextDirection fromLocale = intl.Bidi.isRtlLanguage(Localizations.localeOf(context).languageCode) ? ui.TextDirection.rtl : ui.TextDirection.ltr;
// //
// if (_config.textDirection != null) {
// // Get form Style
// return _config.textDirection!;
// } else {
// // Detect form Text
// return _textController.text != ''
// ? _config.withAutomaticDirectionalitySwitching
// ? intl.Bidi.startsWithLtr(_textController.text)
// ? ui.TextDirection.ltr
// : ui.TextDirection.rtl
// : fromLocale
// : fromLocale;
// }
// }
// EdgeInsetsGeometry _finalVerticalPadding(
// AstromicFieldStyle style, {
// bool? forceRespectBorder,
// }) {
// double desiredFixedHeight = style.fixedHeight ?? 0;
// //
// double providedPadding = style.contentPadding.vertical;
// //
// double borderOffset = (forceRespectBorder ?? _config.respectBorderWidthPadding) ? (_finalBorderShape(style)?.borderSide.strokeInset ?? 0.0) - (style.borderWidth ?? 0) : 0.0;
// //
// double fontOffset = _getTextHeight(
// widget.textController.text.isNotEmpty
// ? widget.textController.text
// : (widget.hint?.isNotEmpty ?? false)
// ? widget.hint!
// : '',
// widget.textController.text.isNotEmpty && _style().textStyle != null
// ? _style().textStyle!
// : _style().hintStyle != null
// ? _style().hintStyle!
// : const TextStyle(),
// _finalTextDirection(),
// );
// //
// double finalVertical =
// //-
// _config.isFixedHeight
// ?
// //-
// _config.isTextArea
// ?
// //s1 Fixed Height with Text Area
// borderOffset + providedPadding
// :
// //s1 Fixed Height and not Text Area
// desiredFixedHeight - (fontOffset + borderOffset)
// //s1 - Not Fixed Height
// : providedPadding + borderOffset;
// //
// return EdgeInsets.symmetric(
// vertical: finalVertical / 2,
// );
// }
// InputBorder? _finalBorderShape(AstromicFieldStyle style) {
// InputBorder defaultBorder = const UnderlineInputBorder(borderSide: BorderSide(color: Colors.grey, width: 2));
// switch (style.borderType) {
// case AstromicFieldBorderType.cusotm:
// return style.customBorder ?? defaultBorder;
// case AstromicFieldBorderType.outlined:
// return style.borderGradient != null
// ? GradientOutlineInputBorder(
// gradient: style.borderGradient!,
// gapPadding: 0,
// width: style.borderWidth ?? 2.0,
// borderRadius: style.borderRadius?.resolve(
// _config.textDirection,
// ) ??
// BorderRadius.circular(0))
// : OutlineInputBorder(
// borderSide: BorderSide(color: style.borderColor ?? Colors.grey, width: style.borderWidth ?? 2.0),
// borderRadius: style.borderRadius?.resolve(
// _config.textDirection,
// ) ??
// BorderRadius.circular(0));
// case AstromicFieldBorderType.underlined:
// return style.borderGradient != null
// ? GradientUnderlineInputBorder(
// gradient: style.borderGradient!,
// gapPadding: 0,
// width: style.borderWidth ?? 2.0,
// borderRadius: style.borderRadius?.resolve(
// _config.textDirection,
// ) ??
// BorderRadius.circular(0))
// : UnderlineInputBorder(
// borderSide: BorderSide(color: style.borderColor ?? Colors.grey, width: style.borderWidth ?? 2.0),
// borderRadius: style.borderRadius?.resolve(
// _config.textDirection,
// ) ??
// BorderRadius.circular(0));
// }
// }
// //!SECTION
// //SECTION - Action Callbacks
// //!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;
// _config = widget.configuration ?? const AstromicFieldConfiguration();
// _style = ([bool? isFocused]) => widget.style?.call(_config.isEnabled, isFocused ?? _isFocused) ?? const AstromicFieldStyle();
// //s1 --Values
// //
// //s1 --Contexted Widgets
// InputDecorationTheme inputDecoration = InputDecorationTheme(
// //s1 -- Functionality
// // enabled: _config.isEnabled,
// //s1 -- Configurations
// isDense: true,
// // hintTextDirection: _config.hintDirection ?? _finalTextDirection(),
// //s1 -- Style
// filled: _style().isFilled,
// fillColor: _style().fillColor,
// //
// hintStyle: _style().hintStyle,
// //
// enabledBorder: _finalBorderShape(_style(false)),
// focusedBorder: _finalBorderShape(_style(true)),
// disabledBorder: _finalBorderShape(_style()),
// errorBorder: _finalBorderShape(_style(false)),
// focusedErrorBorder: _finalBorderShape(_style(true)),
// //
// errorStyle: const TextStyle(height: 0.001, color: Colors.transparent),
// contentPadding: _finalVerticalPadding(_style()),
// //s1 -- Content
// // hintText: widget.hint,
// //
// prefixIcon: widget.prefixWidget != null &&
// widget.prefixWidget!(_config.isEnabled, _isFocused, () {
// setState(() {});
// }) !=
// null
// ? Container(
// margin: EdgeInsetsDirectional.fromSTEB(_style().prefixSpacing, 0, _style().contentPadding.resolveToDirectional(_finalTextDirection()).start, 0),
// child: widget.prefixWidget!(_config.isEnabled, _isFocused, () {
// setState(() {});
// }),
// )
// : SizedBox(width: _style().contentPadding.resolveToDirectional(_finalTextDirection()).start),
// //
// prefixIconConstraints: widget.prefixWidget != null &&
// widget.prefixWidget!(_config.isEnabled, _isFocused, () {
// setState(() {});
// }) !=
// null
// ? _style().prefixSize != 0
// ? BoxConstraints.expand(
// width: _style().prefixSize + _style().prefixSpacing + _style().contentPadding.resolveToDirectional(_finalTextDirection()).start,
// height: _style().prefixSize,
// )
// : const BoxConstraints.tightForFinite()
// : BoxConstraints.tightForFinite(width: _style().contentPadding.resolveToDirectional(_finalTextDirection()).start),
// //
// suffixIcon: widget.suffixWidget != null &&
// widget.suffixWidget!(_config.isEnabled, _isFocused, () {
// setState(() {});
// }) !=
// null
// ? Container(
// margin: EdgeInsetsDirectional.fromSTEB(_style().contentPadding.resolveToDirectional(_finalTextDirection()).end, 0, _style().suffixSpacing, 0),
// child: widget.suffixWidget!(_config.isEnabled, _isFocused, () {
// setState(() {});
// }),
// )
// : SizedBox(width: _style().contentPadding.resolveToDirectional(_finalTextDirection()).end),
// suffixIconConstraints: widget.suffixWidget != null &&
// widget.suffixWidget != null &&
// widget.suffixWidget!(_config.isEnabled, _isFocused, () {
// setState(() {});
// }) !=
// null
// ? _style().suffixSize != 0
// ? BoxConstraints.expand(
// width: _style().suffixSize + _style().suffixSpacing + _style().contentPadding.resolveToDirectional(_finalTextDirection()).end,
// height: _style().suffixSize,
// )
// : const BoxConstraints.tightForFinite()
// : BoxConstraints.tightForFinite(width: _style().contentPadding.resolveToDirectional(_finalTextDirection()).end),
// );
// //s1 --Contexted Widgets
// //!SECTION
// //
// //SECTION - Build Return
// return Column(
// mainAxisSize: MainAxisSize.min,
// crossAxisAlignment: CrossAxisAlignment.start,
// children: <Widget>[
// Directionality(
// textDirection: _finalTextDirection(),
// child: Container(
// height: _config.isFixedHeight
// ? !_config.isTextArea
// ? null
// : _style().fixedHeight
// : null,
// alignment: _style().textAlignVertical.toAlignment(),
// child: Stack(
// children: <Widget>[
// DropdownMenuFormField(
// //s1 -- Functionality
// key: widget.stateKey,
// dropdownMenuEntries: [DropdownMenuEntry(value: value, label: label)],
// controller: _textController,
// focusNode: _focusNode,
// textInputAction: _config.inputAction,
// //
// onSelected: (String v) {
// setState(() {
// if (widget.onChanged != null) {
// widget.onChanged!(v);
// }
// });
// },
// //
// // onFieldSubmitted: (String v) {
// // //
// // if (_config.inputAction == TextInputAction.next) {
// // _focusNode.nextFocus();
// // }
// // if (widget.onSubmited != null) {
// // widget.onSubmited!(v);
// // }
// // },
// //
// // onTapOutside: (PointerDownEvent tapEvent) {
// // if (_config.unfocusOnTapOutside) {
// // _focusNode.unfocus();
// // }
// // },
// //
// //s1 -- Configurations
// hintText: widget.hint,
// //
// // autofillHints: _config.autofillHints,
// autovalidateMode: _config.validatingMode ?? AutovalidateMode.disabled,
// // autofocus: _config.withAutofocus,
// keyboardType: _config.inputType,
// // textDirection: _finalTextDirection(),
// // obscureText: _config.withObscurity ? (_config.isTextObscured ?? false) : false,
// inputFormatters: _config.inputFormatters,
// //
// // minLines: _config.isFixedHeight && _config.isTextArea ? null : _style().minLines,
// maxLines: (_config.isFixedHeight
// ? _config.isTextArea
// ? null
// : _style().maxLines
// : _style().maxLines) ??
// 1,
// //
// // maxLength: _style().maxLength,
// // maxLengthEnforcement: _config.maxLengthEnforcement,
// //
// // expands: _config.isFixedHeight && _config.isTextArea ? true : false,
// // - Validation
// validator: _config.validator != null ? (String? s) => _config.validator!(_config.isEnabled, _isFocused, s) : null,
// // - Validation
// //s1 -- Style
// textStyle: _style().textStyle,
// // cursorColor: _style().cursorColor,
// // cursorErrorColor: _style().cursorColor,
// textAlign: _style().textAlign,
// // textAlignVertical: _style().textAlignVertical,
// //
// //s1 -- Input Decoration
// inputDecorationTheme: inputDecoration,
// //s1 -- Content
// // contextMenuBuilder: (_, EditableTextState state) {
// // List<ContextMenuButtonItem> baseContextButtons = state.contextMenuButtonItems;
// // if (widget.contextButtons != null) {
// // baseContextButtons.addAll(widget.contextButtons!);
// // }
// // return AdaptiveTextSelectionToolbar.buttonItems(
// // buttonItems: baseContextButtons,
// // anchors: state.contextMenuAnchors,
// // );
// // },
// ),
// widget.fieldStackedWidget != null ? widget.fieldStackedWidget!(_finalVerticalPadding(_style(), forceRespectBorder: true).vertical * 2, _finalBorderShape(_style())) : Container(),
// ],
// ),
// ),
// ),
// widget.messageBuilder != null &&
// widget.messageBuilder!(
// _config.isEnabled,
// _isFocused,
// ) !=
// null
// ? Padding(
// padding: _style().messagePadding,
// child: widget.messageBuilder!(_config.isEnabled, _isFocused) ?? Container(),
// )
// : Container()
// ],
// );
// //!SECTION
// }
// @override
// void dispose() {
// //SECTION - Disposable variables
// //!SECTION
// super.dispose();
// }
// }