diff --git a/lib/Infrastructure/misc_extensions.dart b/lib/Infrastructure/misc_extensions.dart new file mode 100644 index 0000000..f93cff4 --- /dev/null +++ b/lib/Infrastructure/misc_extensions.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; + +extension TextAlignVerticalExtension on TextAlignVertical { + toAlignment() { + switch (this) { + case TextAlignVertical.top: + return Alignment.topCenter; + case TextAlignVertical.center: + return Alignment.center; + case TextAlignVertical.bottom: + return Alignment.bottomCenter; + default: + return Alignment.center; + } + } +} diff --git a/lib/src/Fields/src/configuration.dart b/lib/src/Fields/src/configuration.dart index c3c4d5d..9419040 100644 --- a/lib/src/Fields/src/configuration.dart +++ b/lib/src/Fields/src/configuration.dart @@ -14,7 +14,6 @@ class AstromicFieldConfiguration { final bool withObscurity; final bool withAutomaticDirectionalitySwitching; final bool unfocusOnTapOutside; - final bool resetMessageOnChange; // final ui.TextDirection? hintDirection; final ui.TextDirection? textDirection; @@ -34,7 +33,6 @@ class AstromicFieldConfiguration { this.withObscurity = false, this.withAutomaticDirectionalitySwitching = false, this.unfocusOnTapOutside = false, - this.resetMessageOnChange = false, // this.hintDirection, this.textDirection, @@ -55,7 +53,6 @@ class AstromicFieldConfiguration { bool? withObscurity, bool? withAutomaticDirectionalitySwitching, bool? unfocusOnTapOutside, - bool? resetMessageOnChange, ui.TextDirection? hintDirection, ui.TextDirection? textDirection, ui.TextDirection? messageDirection, @@ -73,7 +70,6 @@ class AstromicFieldConfiguration { withObscurity: withObscurity ?? this.withObscurity, withAutomaticDirectionalitySwitching: withAutomaticDirectionalitySwitching ?? this.withAutomaticDirectionalitySwitching, unfocusOnTapOutside: unfocusOnTapOutside ?? this.unfocusOnTapOutside, - resetMessageOnChange: resetMessageOnChange ?? this.resetMessageOnChange, hintDirection: hintDirection ?? this.hintDirection, textDirection: textDirection ?? this.textDirection, messageDirection: messageDirection ?? this.messageDirection, diff --git a/lib/src/Fields/src/style.dart b/lib/src/Fields/src/style.dart index 469c853..d313a73 100644 --- a/lib/src/Fields/src/style.dart +++ b/lib/src/Fields/src/style.dart @@ -12,6 +12,8 @@ class AstromicFieldStyle { final int? maxLength; // final TextAlign textAlign; + + /// Only works when it's a Text Area. final TextAlignVertical textAlignVertical; // final EdgeInsetsGeometry contentPadding; @@ -28,7 +30,6 @@ class AstromicFieldStyle { //s1 - Styling final TextStyle? hintStyle; final TextStyle? textStyle; - final TextStyle? messageStyle; //s1 - MISC final InputBorder? border; @@ -53,7 +54,6 @@ class AstromicFieldStyle { this.cursorColor, this.hintStyle, this.textStyle, - this.messageStyle, // this.border, }); @@ -78,7 +78,6 @@ class AstromicFieldStyle { Color? cursorColor, TextStyle? hintStyle, TextStyle? textStyle, - TextStyle? messageStyle, InputBorder? border, }) { return AstromicFieldStyle( @@ -99,7 +98,6 @@ class AstromicFieldStyle { cursorColor: cursorColor ?? this.cursorColor, hintStyle: hintStyle ?? this.hintStyle, textStyle: textStyle ?? this.textStyle, - messageStyle: messageStyle ?? this.messageStyle, border: border ?? this.border, ); } diff --git a/lib/src/Fields/src/text_field.dart b/lib/src/Fields/src/text_field.dart index 20fbf64..748e6c6 100644 --- a/lib/src/Fields/src/text_field.dart +++ b/lib/src/Fields/src/text_field.dart @@ -19,6 +19,7 @@ import 'configuration.dart'; import 'style.dart'; //s2 MISC import '../../../Infrastructure/insets_extension.dart'; +import '../../../Infrastructure/misc_extensions.dart'; //!SECTION - Imports // @@ -47,9 +48,9 @@ class AstromicTextField extends StatefulWidget { //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 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? contextButtons; //!SECTION @@ -89,7 +90,7 @@ class _AstromicTextFieldState extends State { //s1 --Controllers // //s1 --State - late bool _isEnabled; + // late bool widget.configuration.isEnabled; final FocusNode _focusNode = FocusNode(); late bool _isFocused; // @@ -109,7 +110,7 @@ class _AstromicTextFieldState extends State { //s1 --Controllers & Listeners // //s1 --State - _isEnabled = widget.configuration.isEnabled; + // widget.configuration.isEnabled = widget.configuration.isEnabled; _isFocused = false; //s1 --State // @@ -139,6 +140,17 @@ class _AstromicTextFieldState extends State { //!SECTION //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); + return tp.height; + } + + //- + //---------------------------------------------------------------- + //- + ui.TextDirection finalTextDirection() { ui.TextDirection fromLocale = intl.Bidi.isRtlLanguage(Localizations.localeOf(context).languageCode) ? ui.TextDirection.rtl : ui.TextDirection.ltr; // @@ -169,9 +181,19 @@ class _AstromicTextFieldState extends State { // double borderOffset = widget.configuration.respectBorderWidthPadding ? style.border?.borderSide.strokeInset ?? 0.0 : 0.0; // - double fontOffset = - ((widget.textController.text.isNotEmpty ? widget.style(_isEnabled, _isFocused).textStyle : widget.style(_isEnabled, _isFocused).hintStyle) ?? const TextStyle(fontSize: 16)).fontSize! * - (((widget.textController.text.isNotEmpty ? widget.style(_isEnabled, _isFocused).textStyle : widget.style(_isEnabled, _isFocused).hintStyle) ?? const TextStyle(height: 1.0)).height!); + double fontOffset = getTextHeight( + widget.textController.text.isNotEmpty + ? widget.textController.text + : (widget.hint?.isNotEmpty ?? false) + ? widget.hint! + : "", + widget.textController.text.isNotEmpty && widget.style(widget.configuration.isEnabled, _isFocused).textStyle != null + ? widget.style(widget.configuration.isEnabled, _isFocused).textStyle! + : widget.style(widget.configuration.isEnabled, _isFocused).hintStyle != null + ? widget.style(widget.configuration.isEnabled, _isFocused).hintStyle! + : const TextStyle(), + finalTextDirection(), + ); // double finalVertical = //- @@ -213,62 +235,79 @@ class _AstromicTextFieldState extends State { isDense: true, hintTextDirection: widget.configuration.hintDirection ?? finalTextDirection(), //s1 -- Style - filled: widget.style(_isEnabled, _isFocused).isFilled, - fillColor: widget.style(_isEnabled, _isFocused).fillColor, + filled: widget.style(widget.configuration.isEnabled, _isFocused).isFilled, + fillColor: widget.style(widget.configuration.isEnabled, _isFocused).fillColor, // - hintStyle: widget.style(_isEnabled, _isFocused).hintStyle, + hintStyle: widget.style(widget.configuration.isEnabled, _isFocused).hintStyle, // - enabledBorder: widget.style(_isEnabled, false).border, - focusedBorder: widget.style(_isEnabled, true).border, - disabledBorder: widget.style(_isEnabled, _isFocused).border, - errorBorder: widget.style(_isEnabled, false).border, - focusedErrorBorder: widget.style(_isEnabled, true).border, + enabledBorder: widget.style(widget.configuration.isEnabled, false).border, + focusedBorder: widget.style(widget.configuration.isEnabled, true).border, + disabledBorder: widget.style(widget.configuration.isEnabled, _isFocused).border, + errorBorder: widget.style(widget.configuration.isEnabled, false).border, + focusedErrorBorder: widget.style(widget.configuration.isEnabled, true).border, // errorStyle: const TextStyle(height: 0), - contentPadding: finalVerticalPadding(widget.style(_isEnabled, _isFocused)), + contentPadding: finalVerticalPadding(widget.style(widget.configuration.isEnabled, _isFocused)), //s1 -- Content hintText: widget.hint, // - prefixIcon: widget.prefixWidget != null + prefixIcon: widget.prefixWidget != null && + widget.prefixWidget!(widget.configuration.isEnabled, _isFocused, () { + setState(() {}); + }) != + null ? Container( - margin: EdgeInsetsDirectional.fromSTEB( - widget.style(_isEnabled, _isFocused).prefixSpacing, 0, widget.style(_isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).start, 0), - child: widget.prefixWidget!(_isEnabled, _isFocused, () { + margin: EdgeInsetsDirectional.fromSTEB(widget.style(widget.configuration.isEnabled, _isFocused).prefixSpacing, 0, + widget.style(widget.configuration.isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).start, 0), + child: widget.prefixWidget!(widget.configuration.isEnabled, _isFocused, () { setState(() {}); }), ) - : SizedBox(width: widget.style(_isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).start), + : SizedBox(width: widget.style(widget.configuration.isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).start), // - prefixIconConstraints: widget.prefixWidget != null - ? widget.style(_isEnabled, _isFocused).prefixSize != 0 + prefixIconConstraints: widget.prefixWidget != null && + widget.prefixWidget!(widget.configuration.isEnabled, _isFocused, () { + setState(() {}); + }) != + null + ? widget.style(widget.configuration.isEnabled, _isFocused).prefixSize != 0 ? BoxConstraints.expand( - width: widget.style(_isEnabled, _isFocused).prefixSize + - widget.style(_isEnabled, _isFocused).prefixSpacing + - widget.style(_isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).start, - height: widget.style(_isEnabled, _isFocused).prefixSize, + width: widget.style(widget.configuration.isEnabled, _isFocused).prefixSize + + widget.style(widget.configuration.isEnabled, _isFocused).prefixSpacing + + widget.style(widget.configuration.isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).start, + height: widget.style(widget.configuration.isEnabled, _isFocused).prefixSize, ) : const BoxConstraints.tightForFinite() - : BoxConstraints.tightForFinite(width: widget.style(_isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).start), + : BoxConstraints.tightForFinite(width: widget.style(widget.configuration.isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).start), // - suffixIcon: widget.suffixWidget != null + suffixIcon: widget.suffixWidget != null && + widget.suffixWidget!(widget.configuration.isEnabled, _isFocused, () { + setState(() {}); + }) != + null ? Container( - margin: EdgeInsetsDirectional.fromSTEB( - widget.style(_isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).end, 0, widget.style(_isEnabled, _isFocused).suffixSpacing, 0), - child: widget.suffixWidget!(_isEnabled, _isFocused, () { + margin: EdgeInsetsDirectional.fromSTEB(widget.style(widget.configuration.isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).end, 0, + widget.style(widget.configuration.isEnabled, _isFocused).suffixSpacing, 0), + child: widget.suffixWidget!(widget.configuration.isEnabled, _isFocused, () { setState(() {}); }), ) - : SizedBox(width: widget.style(_isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).end), - suffixIconConstraints: widget.suffixWidget != null - ? widget.style(_isEnabled, _isFocused).suffixSize != 0 + : SizedBox(width: widget.style(widget.configuration.isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).end), + suffixIconConstraints: widget.suffixWidget != null && + widget.suffixWidget != null && + widget.suffixWidget!(widget.configuration.isEnabled, _isFocused, () { + setState(() {}); + }) != + null + ? widget.style(widget.configuration.isEnabled, _isFocused).suffixSize != 0 ? BoxConstraints.expand( - width: widget.style(_isEnabled, _isFocused).suffixSize + - widget.style(_isEnabled, _isFocused).suffixSpacing + - widget.style(_isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).end, - height: widget.style(_isEnabled, _isFocused).suffixSize, + width: widget.style(widget.configuration.isEnabled, _isFocused).suffixSize + + widget.style(widget.configuration.isEnabled, _isFocused).suffixSpacing + + widget.style(widget.configuration.isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).end, + height: widget.style(widget.configuration.isEnabled, _isFocused).suffixSize, ) : const BoxConstraints.tightForFinite() - : BoxConstraints.tightForFinite(width: widget.style(_isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).end), + : BoxConstraints.tightForFinite(width: widget.style(widget.configuration.isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).end), ); //s1 --Contexted Widgets //!SECTION @@ -284,9 +323,9 @@ class _AstromicTextFieldState extends State { height: widget.configuration.isFixedHeight ? !widget.configuration.isTextArea ? null - : widget.style(_isEnabled, _isFocused).fixedHeight + : widget.style(widget.configuration.isEnabled, _isFocused).fixedHeight : null, - alignment: Alignment.center, + alignment: widget.style(widget.configuration.isEnabled, _isFocused).textAlignVertical.toAlignment(), child: TextFormField( //s1 -- Functionality controller: _textController, @@ -325,26 +364,26 @@ class _AstromicTextFieldState extends State { obscureText: widget.configuration.withObscurity ? (widget.obscureText ?? false) : false, inputFormatters: widget.inputFormatters, // - minLines: widget.configuration.isFixedHeight && widget.configuration.isTextArea ? null : widget.style(_isEnabled, _isFocused).minLines, + minLines: widget.configuration.isFixedHeight && widget.configuration.isTextArea ? null : widget.style(widget.configuration.isEnabled, _isFocused).minLines, maxLines: widget.configuration.isFixedHeight ? widget.configuration.isTextArea ? null - : widget.style(_isEnabled, _isFocused).maxLines - : widget.style(_isEnabled, _isFocused).maxLines, + : widget.style(widget.configuration.isEnabled, _isFocused).maxLines + : widget.style(widget.configuration.isEnabled, _isFocused).maxLines, // - maxLength: widget.style(_isEnabled, _isFocused).maxLength, + maxLength: widget.style(widget.configuration.isEnabled, _isFocused).maxLength, maxLengthEnforcement: widget.configuration.maxLengthEnforcement, // expands: widget.configuration.isFixedHeight && widget.configuration.isTextArea ? true : false, // - Validation - validator: widget.validator != null ? (s) => widget.validator!(_isEnabled, _isFocused, s) : null, + validator: widget.validator != null ? (s) => widget.validator!(widget.configuration.isEnabled, _isFocused, s) : null, // - Validation //s1 -- Style - style: widget.style(_isEnabled, _isFocused).textStyle, - cursorColor: widget.style(_isEnabled, _isFocused).cursorColor, - textAlign: widget.style(_isEnabled, _isFocused).textAlign, - textAlignVertical: widget.style(_isEnabled, _isFocused).textAlignVertical, + style: widget.style(widget.configuration.isEnabled, _isFocused).textStyle, + cursorColor: widget.style(widget.configuration.isEnabled, _isFocused).cursorColor, + textAlign: widget.style(widget.configuration.isEnabled, _isFocused).textAlign, + textAlignVertical: widget.style(widget.configuration.isEnabled, _isFocused).textAlignVertical, // //s1 -- Input Decoration decoration: inputDecoration, @@ -362,7 +401,17 @@ class _AstromicTextFieldState extends State { ), ), ), - widget.messageBuilder != null ? widget.messageBuilder!(_isEnabled, _isFocused) : Container() + widget.messageBuilder != null && + widget.messageBuilder!( + widget.configuration.isEnabled, + _isFocused, + ) != + null + ? Padding( + padding: widget.style(widget.configuration.isEnabled, _isFocused).messagePadding, + child: widget.messageBuilder!(widget.configuration.isEnabled, _isFocused) ?? Container(), + ) + : Container() ], ); //!SECTION