From 6042b3a619e060e587913fe163aa510a8caa48a5 Mon Sep 17 00:00:00 2001 From: Vitalij Vascenko Date: Wed, 26 Jun 2024 17:09:35 +0200 Subject: [PATCH 1/5] feat: [DX-1920] Add auto collapse option --- optimus/lib/src/form/input_field.dart | 3 +++ storybook/lib/stories/input.dart | 2 ++ 2 files changed, 5 insertions(+) diff --git a/optimus/lib/src/form/input_field.dart b/optimus/lib/src/form/input_field.dart index 589a9e7e..01f5bf11 100644 --- a/optimus/lib/src/form/input_field.dart +++ b/optimus/lib/src/form/input_field.dart @@ -52,6 +52,7 @@ class OptimusInputField extends StatefulWidget { this.enableIMEPersonalizedLearning = true, this.enableSuggestions = true, this.inline = false, + this.autoCollapse = false, this.statusBarState, }); @@ -161,6 +162,8 @@ class OptimusInputField extends StatefulWidget { /// the vertical direction. final bool inline; + final bool autoCollapse; + final OptimusStatusBarState? statusBarState; bool get hasError { diff --git a/storybook/lib/stories/input.dart b/storybook/lib/stories/input.dart index 21bda504..ede884c8 100644 --- a/storybook/lib/stories/input.dart +++ b/storybook/lib/stories/input.dart @@ -44,6 +44,7 @@ final Story inputStory = Story( k.sliderInt(label: 'Max Characters', max: 100, min: 1, initial: 30); } final inline = k.boolean(label: 'Inline', initial: false); + final autoCollapse = k.boolean(label: 'Auto Collapse', initial: true); final statusBar = k.options( label: 'Status Bar', @@ -74,6 +75,7 @@ final Story inputStory = Story( options: sizeOptions, ), inline: inline, + autoCollapse: autoCollapse, label: k.text(label: 'Label', initial: 'Optimus input field'), placeholder: k.text(label: 'Placeholder', initial: 'Put some hint here...'), From ca8a99ec9e13697755009772a1bdd351a4726797 Mon Sep 17 00:00:00 2001 From: Vitalij Vascenko Date: Wed, 26 Jun 2024 17:55:01 +0200 Subject: [PATCH 2/5] upd --- optimus/lib/src/form/input_field.dart | 31 +++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/optimus/lib/src/form/input_field.dart b/optimus/lib/src/form/input_field.dart index 01f5bf11..570da7f7 100644 --- a/optimus/lib/src/form/input_field.dart +++ b/optimus/lib/src/form/input_field.dart @@ -181,6 +181,8 @@ class _OptimusInputFieldState extends State FocusNode? _focusNode; bool _isShowPasswordEnabled = false; TextEditingController? _controller; + late int? _minLines = widget.minLines; + late int _maxLines = widget.maxLines; TextEditingController get _effectiveController => widget.controller ?? (_controller ??= TextEditingController()); @@ -191,19 +193,27 @@ class _OptimusInputFieldState extends State @override void initState() { super.initState(); - _effectiveFocusNode.addListener(_handleStateUpdate); + _effectiveFocusNode.addListener(_handleFocusUpdate); _effectiveController.addListener(_handleStateUpdate); } @override void dispose() { - _effectiveFocusNode.removeListener(_handleStateUpdate); + _effectiveFocusNode.removeListener(_handleFocusUpdate); _effectiveController.removeListener(_handleStateUpdate); _focusNode?.dispose(); _controller?.dispose(); super.dispose(); } + @override + void didUpdateWidget(OptimusInputField oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.autoCollapse != oldWidget.autoCollapse) { + _updateLines(); + } + } + bool get _shouldShowInlineError => (widget.errorVariant == OptimusInputErrorVariant.inlineTooltip || widget.inline) && @@ -231,6 +241,19 @@ class _OptimusInputFieldState extends State bool get _isPasswordToggleVisible => widget.isPasswordField && !widget.showLoader; + bool get _shouldCollapse => + widget.autoCollapse && !_effectiveFocusNode.hasFocus; + + void _handleFocusUpdate() => setState(() { + if (!widget.autoCollapse) return; + _updateLines(); + }); + + void _updateLines() { + _maxLines = _shouldCollapse ? 1 : widget.maxLines; + _minLines = _shouldCollapse ? 1 : widget.minLines; + } + void _handleStateUpdate() => setState(() {}); void _handlePasswordTap() => setState( @@ -305,8 +328,8 @@ class _OptimusInputFieldState extends State autofocus: widget.autofocus, enableInteractiveSelection: widget.enableInteractiveSelection, controller: _effectiveController, - maxLines: widget.maxLines, - minLines: widget.minLines, + maxLines: _maxLines, + minLines: _minLines, onSubmitted: widget.onSubmitted, textInputAction: widget.textInputAction, placeholder: widget.placeholder, From e2cf5c067ac1a1a049d72194cac4de2976ca4e6c Mon Sep 17 00:00:00 2001 From: Vitalij Vascenko Date: Thu, 27 Jun 2024 13:43:36 +0200 Subject: [PATCH 3/5] upd --- optimus/lib/src/form/input_field.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/optimus/lib/src/form/input_field.dart b/optimus/lib/src/form/input_field.dart index 570da7f7..5af4c407 100644 --- a/optimus/lib/src/form/input_field.dart +++ b/optimus/lib/src/form/input_field.dart @@ -209,7 +209,9 @@ class _OptimusInputFieldState extends State @override void didUpdateWidget(OptimusInputField oldWidget) { super.didUpdateWidget(oldWidget); - if (widget.autoCollapse != oldWidget.autoCollapse) { + if (widget.autoCollapse != oldWidget.autoCollapse || + widget.minLines != oldWidget.minLines || + widget.maxLines != oldWidget.maxLines) { _updateLines(); } } From f832fda3fb450611779a2fb95ca2f384b3eac919 Mon Sep 17 00:00:00 2001 From: Vitalij Vascenko Date: Fri, 28 Jun 2024 10:39:41 +0200 Subject: [PATCH 4/5] upd --- optimus/lib/src/form/input_field.dart | 4 ++++ storybook/lib/stories/input.dart | 21 ++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/optimus/lib/src/form/input_field.dart b/optimus/lib/src/form/input_field.dart index 881d0971..b648098b 100644 --- a/optimus/lib/src/form/input_field.dart +++ b/optimus/lib/src/form/input_field.dart @@ -83,6 +83,10 @@ class OptimusInputField extends StatefulWidget { final int? maxCharacters; /// {@macro flutter.widgets.editableText.minLines} + /// + /// If the input is multi-lined we recommend you to set the [keyboardType] to + /// [TextInputType.multiline] otherwise the move to the next line won't work + /// properly. final int? minLines; final TextEditingController? controller; final String? error; diff --git a/storybook/lib/stories/input.dart b/storybook/lib/stories/input.dart index 11cd677b..5cb925e3 100644 --- a/storybook/lib/stories/input.dart +++ b/storybook/lib/stories/input.dart @@ -1,4 +1,4 @@ -import 'package:flutter/widgets.dart'; +import 'package:flutter/material.dart'; import 'package:optimus/optimus.dart'; import 'package:storybook/utils.dart'; import 'package:storybook_flutter/storybook_flutter.dart'; @@ -45,6 +45,11 @@ final Story inputStory = Story( } final minLines = k.sliderInt(label: 'Min lines', initial: 1, min: 1, max: 10); + final keyboardType = k.options( + label: 'Keyboard Type:', + initial: null, + options: KeyboardType.values.toOptions().withEmpty(), + ); final inline = k.boolean(label: 'Inline', initial: false); final autoCollapse = k.boolean(label: 'Auto Collapse', initial: true); @@ -65,6 +70,7 @@ final Story inputStory = Story( maxCharacters: maxChars, minLines: minLines, maxLines: minLines, + keyboardType: keyboardType?.inputType, prefix: prefix.isNotEmpty ? Text(prefix) : null, suffix: suffix.isNotEmpty ? Text(suffix) : null, leading: leadingIcon == null ? null : Icon(leadingIcon), @@ -92,3 +98,16 @@ final Story inputStory = Story( ); }, ); + +enum KeyboardType { + text(TextInputType.text), + multiline(TextInputType.multiline), + number(TextInputType.number), + phone(TextInputType.phone), + datetime(TextInputType.datetime), + emailAddress(TextInputType.emailAddress), + url(TextInputType.url); + + const KeyboardType(this.inputType); + final TextInputType inputType; +} From ce20e966f9d1c4364378680ffa2ad3cc17d3db7d Mon Sep 17 00:00:00 2001 From: Vitalij Vascenko Date: Fri, 28 Jun 2024 10:41:29 +0200 Subject: [PATCH 5/5] upd --- optimus/lib/src/form/input_field.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/optimus/lib/src/form/input_field.dart b/optimus/lib/src/form/input_field.dart index b648098b..5aff589f 100644 --- a/optimus/lib/src/form/input_field.dart +++ b/optimus/lib/src/form/input_field.dart @@ -166,6 +166,8 @@ class OptimusInputField extends StatefulWidget { /// the vertical direction. final bool inline; + /// Controls whether the input should collapse to one line height if not + /// focused. final bool autoCollapse; final OptimusStatusBarState? statusBarState;