From 8f39cf74c146c94a3a846fa86859b30fab5cebea Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 10:16:55 +0000 Subject: [PATCH 1/8] Initial plan From 174ec00cb3c4f1d314d864f45578918cf09ee86d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 10:22:32 +0000 Subject: [PATCH 2/8] feat: add VirtualKeypadStandaloneScope for scoped standalone keyboard Co-authored-by: Masum-MSNR <70331283+Masum-MSNR@users.noreply.github.com> --- lib/src/standalone_scope.dart | 51 +++++++++++++++++++++++++ lib/src/widgets/keyboard.dart | 46 ++++++++++++++++++++--- lib/virtual_keypad.dart | 2 + test/virtual_keypad_test.dart | 71 +++++++++++++++++++++++++++++++++++ 4 files changed, 165 insertions(+), 5 deletions(-) create mode 100644 lib/src/standalone_scope.dart diff --git a/lib/src/standalone_scope.dart b/lib/src/standalone_scope.dart new file mode 100644 index 0000000..1a12fa9 --- /dev/null +++ b/lib/src/standalone_scope.dart @@ -0,0 +1,51 @@ +import 'package:flutter/widgets.dart'; + +/// Scopes a [VirtualKeypad] in standalone mode to only respond to text fields +/// within its subtree. +/// +/// Wrap both your text fields and [VirtualKeypad] with this widget to prevent +/// the keyboard from appearing when a text field outside the scope gains focus. +/// This is especially useful in tools like Widgetbook where multiple widget +/// previews are shown simultaneously. +/// +/// ```dart +/// VirtualKeypadStandaloneScope( +/// child: Column( +/// children: [ +/// TextField(controller: myController), +/// VirtualKeypad(standalone: true), +/// ], +/// ), +/// ) +/// ``` +/// +/// Without this wrapper, [VirtualKeypad] in standalone mode responds to any +/// focused text field in the application. +class VirtualKeypadStandaloneScope extends StatefulWidget { + /// Creates a standalone scope for [VirtualKeypad]. + const VirtualKeypadStandaloneScope({ + super.key, + required this.child, + }); + + /// The child widget tree containing text fields and the keyboard. + final Widget child; + + /// Returns the nearest [VirtualKeypadStandaloneScopeState] ancestor, or + /// null if there is none. + static VirtualKeypadStandaloneScopeState? maybeOf(BuildContext context) { + return context + .findAncestorStateOfType(); + } + + @override + State createState() => + VirtualKeypadStandaloneScopeState(); +} + +/// State for [VirtualKeypadStandaloneScope]. +class VirtualKeypadStandaloneScopeState + extends State { + @override + Widget build(BuildContext context) => widget.child; +} diff --git a/lib/src/widgets/keyboard.dart b/lib/src/widgets/keyboard.dart index f16ca8f..a4fe93a 100644 --- a/lib/src/widgets/keyboard.dart +++ b/lib/src/widgets/keyboard.dart @@ -8,6 +8,7 @@ import '../layouts/keyboard_layout_provider.dart'; import '../models.dart'; import '../scope.dart'; import '../standalone_input_control.dart'; +import '../standalone_scope.dart'; import '../theme.dart'; /// A customizable virtual on-screen keyboard widget. @@ -133,11 +134,7 @@ class _VirtualKeypadState extends State { void _initStandalone() { _inputControl = StandaloneInputControl( - onShow: () { - if (!mounted) return; - setState(() => _standaloneVisible = true); - _onStandaloneFieldChanged(); - }, + onShow: _onStandaloneShow, onHide: () { if (!mounted) return; setState(() => _standaloneVisible = false); @@ -163,9 +160,48 @@ class _VirtualKeypadState extends State { if (_standaloneVisible) { setState(() => _standaloneVisible = false); } + return; + } + + // If wrapped in a scope, hide when focus moves outside that scope + final myScope = VirtualKeypadStandaloneScope.maybeOf(context); + if (myScope != null && _standaloneVisible) { + final focusedScope = + VirtualKeypadStandaloneScope.maybeOf(focus.context!); + if (focusedScope != myScope) { + setState(() => _standaloneVisible = false); + } } } + /// Called when the [StandaloneInputControl] requests the keyboard to show. + /// + /// If the keyboard is wrapped in a [VirtualKeypadStandaloneScope], the + /// focused text field must be within the same scope for the keyboard to + /// appear. This prevents the keyboard from responding to text fields that + /// belong to a different part of the widget tree. + void _onStandaloneShow() { + if (!mounted) return; + + // If this keyboard is inside a VirtualKeypadStandaloneScope, only show + // when the focused widget is in the same scope. + final myScope = VirtualKeypadStandaloneScope.maybeOf(context); + if (myScope != null) { + final focusedContext = FocusManager.instance.primaryFocus?.context; + final focusedScope = focusedContext != null + ? VirtualKeypadStandaloneScope.maybeOf(focusedContext) + : null; + if (focusedScope != myScope) { + // The focused field is outside our scope – hide the keyboard. + if (_standaloneVisible) setState(() => _standaloneVisible = false); + return; + } + } + + setState(() => _standaloneVisible = true); + _onStandaloneFieldChanged(); + } + void _onStandaloneFieldChanged() { if (!mounted || _inputControl == null) return; final newType = _inputControl!.keyboardType; diff --git a/lib/virtual_keypad.dart b/lib/virtual_keypad.dart index 323b8fb..6a1c644 100644 --- a/lib/virtual_keypad.dart +++ b/lib/virtual_keypad.dart @@ -45,6 +45,7 @@ /// /// - [VirtualKeypad] - Customizable on-screen keyboard widget /// - [VirtualKeypadScope] - Manages keyboard-to-textfield connections (scope mode) +/// - [VirtualKeypadStandaloneScope] - Restricts standalone keyboard to a widget subtree /// - [VirtualKeypadTextField] - Text field optimized for virtual keyboard input (scope mode) /// - [VirtualKeypadController] - Controller with text manipulation methods /// - [VirtualKeypadTheme] - Theming for keyboard appearance @@ -57,6 +58,7 @@ export 'src/enums.dart'; export 'src/models.dart'; export 'src/scope.dart'; export 'src/standalone_input_control.dart'; +export 'src/standalone_scope.dart'; export 'src/theme.dart'; export 'src/widgets/keyboard.dart'; export 'src/widgets/text_field.dart'; diff --git a/test/virtual_keypad_test.dart b/test/virtual_keypad_test.dart index 623e39c..a5cc7f1 100644 --- a/test/virtual_keypad_test.dart +++ b/test/virtual_keypad_test.dart @@ -135,4 +135,75 @@ void main() { expect(key.isCharacter, false); }); }); + + group('VirtualKeypadStandaloneScope', () { + testWidgets('maybeOf returns null when no scope in tree', (tester) async { + late BuildContext capturedContext; + await tester.pumpWidget( + MaterialApp( + home: Builder( + builder: (ctx) { + capturedContext = ctx; + return const SizedBox.shrink(); + }, + ), + ), + ); + expect( + VirtualKeypadStandaloneScope.maybeOf(capturedContext), + isNull, + ); + }); + + testWidgets('maybeOf returns state when scope is ancestor', (tester) async { + late BuildContext capturedContext; + await tester.pumpWidget( + MaterialApp( + home: VirtualKeypadStandaloneScope( + child: Builder( + builder: (ctx) { + capturedContext = ctx; + return const SizedBox.shrink(); + }, + ), + ), + ), + ); + expect( + VirtualKeypadStandaloneScope.maybeOf(capturedContext), + isA(), + ); + }); + + testWidgets('two sibling scopes return different state instances', + (tester) async { + late BuildContext contextA; + late BuildContext contextB; + await tester.pumpWidget( + MaterialApp( + home: Column( + children: [ + VirtualKeypadStandaloneScope( + child: Builder(builder: (ctx) { + contextA = ctx; + return const SizedBox.shrink(); + }), + ), + VirtualKeypadStandaloneScope( + child: Builder(builder: (ctx) { + contextB = ctx; + return const SizedBox.shrink(); + }), + ), + ], + ), + ), + ); + final scopeA = VirtualKeypadStandaloneScope.maybeOf(contextA); + final scopeB = VirtualKeypadStandaloneScope.maybeOf(contextB); + expect(scopeA, isNotNull); + expect(scopeB, isNotNull); + expect(scopeA, isNot(same(scopeB))); + }); + }); } From e39c98e91e807016ba7c08e39eb41bec2bffc93d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 11:06:04 +0000 Subject: [PATCH 3/8] fix: apply dart format to all changed files per contributing guidelines Co-authored-by: Masum-MSNR <70331283+Masum-MSNR@users.noreply.github.com> --- example/lib/main.dart | 6 +- .../screens/auto_hide_keyboard_example.dart | 19 +++-- example/lib/screens/custom_theme_example.dart | 18 ++--- example/lib/screens/email_url_example.dart | 6 +- .../screens/language_switching_example.dart | 24 +++++- example/lib/screens/multi_field_example.dart | 10 ++- .../lib/screens/numeric_input_example.dart | 3 +- .../lib/screens/password_entry_example.dart | 3 +- example/lib/screens/standalone_example.dart | 10 ++- lib/src/layouts/languages/french.dart | 77 +++++++++++++++---- lib/src/standalone_input_control.dart | 12 +-- lib/src/standalone_scope.dart | 3 +- lib/src/widgets/keyboard.dart | 6 +- 13 files changed, 128 insertions(+), 69 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 6ed75f8..f9ada75 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -160,8 +160,7 @@ class HomePage extends StatelessWidget { title: 'Auto-Hide Keyboard', subtitle: 'Focus-aware animated transitions', gradient: const [Color(0xFF30cfd0), Color(0xFF330867)], - onTap: () => - _navigate(context, const AutoHideKeyboardExample()), + onTap: () => _navigate(context, const AutoHideKeyboardExample()), ), _ExampleCard( icon: Icons.palette_rounded, @@ -175,8 +174,7 @@ class HomePage extends StatelessWidget { title: 'Language Switching', subtitle: 'Toggle English ↔ Bengali ↔ French', gradient: const [Color(0xFF89f7fe), Color(0xFF66a6ff)], - onTap: () => - _navigate(context, const LanguageSwitchingExample()), + onTap: () => _navigate(context, const LanguageSwitchingExample()), ), ], ), diff --git a/example/lib/screens/auto_hide_keyboard_example.dart b/example/lib/screens/auto_hide_keyboard_example.dart index a9ecf19..b7a9db4 100644 --- a/example/lib/screens/auto_hide_keyboard_example.dart +++ b/example/lib/screens/auto_hide_keyboard_example.dart @@ -108,8 +108,7 @@ class _AutoHideKeyboardExampleState extends State { child: Row( children: [ AnimatedContainer( - duration: - const Duration(milliseconds: 300), + duration: const Duration(milliseconds: 300), width: 10, height: 10, decoration: BoxDecoration( @@ -163,8 +162,7 @@ class _AutoHideKeyboardExampleState extends State { ), ), AnimatedSwitcher( - duration: - const Duration(milliseconds: 300), + duration: const Duration(milliseconds: 300), child: Icon( _isAnyFocused ? Icons.keyboard_rounded @@ -208,8 +206,7 @@ class _AutoHideKeyboardExampleState extends State { width: 2, ), ), - prefixIcon: - const Icon(Icons.text_fields_rounded), + prefixIcon: const Icon(Icons.text_fields_rounded), filled: true, fillColor: colorScheme.surfaceContainerLowest, contentPadding: const EdgeInsets.symmetric( @@ -264,8 +261,7 @@ class _AutoHideKeyboardExampleState extends State { borderRadius: BorderRadius.circular(16), borderSide: BorderSide.none, ), - prefixIcon: - const Icon(Icons.lock_outline_rounded), + prefixIcon: const Icon(Icons.lock_outline_rounded), filled: true, fillColor: colorScheme.surfaceContainerHighest .withValues(alpha: 0.5), @@ -308,8 +304,11 @@ class _SectionLabel extends StatelessWidget { children: [ Row( children: [ - Icon(icon, size: 18, - color: colorScheme.onSurface.withValues(alpha: 0.7)), + Icon( + icon, + size: 18, + color: colorScheme.onSurface.withValues(alpha: 0.7), + ), const SizedBox(width: 8), Text( label.toUpperCase(), diff --git a/example/lib/screens/custom_theme_example.dart b/example/lib/screens/custom_theme_example.dart index 614722a..416f6a3 100644 --- a/example/lib/screens/custom_theme_example.dart +++ b/example/lib/screens/custom_theme_example.dart @@ -127,8 +127,7 @@ class _CustomThemeExampleState extends State { onTap: () => setState(() => _selectedTheme = index), child: AnimatedContainer( - duration: - const Duration(milliseconds: 250), + duration: const Duration(milliseconds: 250), padding: const EdgeInsets.symmetric( horizontal: 20, vertical: 10, @@ -164,8 +163,7 @@ class _CustomThemeExampleState extends State { children: [ Text( theme.emoji, - style: - const TextStyle(fontSize: 18), + style: const TextStyle(fontSize: 18), ), const SizedBox(width: 8), Text( @@ -239,13 +237,11 @@ class _CustomThemeExampleState extends State { decoration: InputDecoration( labelText: 'Type here', labelStyle: TextStyle( - color: - current.textColor.withValues(alpha: 0.5), + color: current.textColor.withValues(alpha: 0.5), ), hintText: 'Try the themed keyboard', hintStyle: TextStyle( - color: - current.textColor.withValues(alpha: 0.2), + color: current.textColor.withValues(alpha: 0.2), ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(16), @@ -254,8 +250,7 @@ class _CustomThemeExampleState extends State { enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(16), borderSide: BorderSide( - color: - current.accent.withValues(alpha: 0.15), + color: current.accent.withValues(alpha: 0.15), ), ), focusedBorder: OutlineInputBorder( @@ -269,8 +264,7 @@ class _CustomThemeExampleState extends State { fillColor: current.theme.keyColor, prefixIcon: Icon( Icons.palette_outlined, - color: - current.textColor.withValues(alpha: 0.35), + color: current.textColor.withValues(alpha: 0.35), ), contentPadding: const EdgeInsets.symmetric( horizontal: 18, diff --git a/example/lib/screens/email_url_example.dart b/example/lib/screens/email_url_example.dart index 4fcdd97..0f8dc86 100644 --- a/example/lib/screens/email_url_example.dart +++ b/example/lib/screens/email_url_example.dart @@ -187,8 +187,7 @@ class _EmailUrlExampleState extends State { width: 2, ), ), - prefixIcon: - const Icon(Icons.language_rounded), + prefixIcon: const Icon(Icons.language_rounded), suffixIcon: _isValidUrl(_urlController.text) ? const _AnimatedCheckmark() : null, @@ -319,8 +318,7 @@ class _InputCard extends StatelessWidget { description, style: TextStyle( fontSize: 12, - color: - colorScheme.onSurface.withValues(alpha: 0.45), + color: colorScheme.onSurface.withValues(alpha: 0.45), ), ), ], diff --git a/example/lib/screens/language_switching_example.dart b/example/lib/screens/language_switching_example.dart index 38d36e3..68b0ced 100644 --- a/example/lib/screens/language_switching_example.dart +++ b/example/lib/screens/language_switching_example.dart @@ -14,9 +14,27 @@ class _LanguageSwitchingExampleState extends State { String _currentLanguage = 'en'; final _languages = [ - ('en', 'English', '🇺🇸', 'QWERTY', [const Color(0xFF89f7fe), const Color(0xFF66a6ff)]), - ('bn', 'বাংলা', '🇧🇩', 'Bengali', [const Color(0xFF43e97b), const Color(0xFF38f9d7)]), - ('fr', 'Français', '🇫🇷', 'AZERTY', [const Color(0xFFf093fb), const Color(0xFFf5576c)]), + ( + 'en', + 'English', + '🇺🇸', + 'QWERTY', + [const Color(0xFF89f7fe), const Color(0xFF66a6ff)], + ), + ( + 'bn', + 'বাংলা', + '🇧🇩', + 'Bengali', + [const Color(0xFF43e97b), const Color(0xFF38f9d7)], + ), + ( + 'fr', + 'Français', + '🇫🇷', + 'AZERTY', + [const Color(0xFFf093fb), const Color(0xFFf5576c)], + ), ]; @override diff --git a/example/lib/screens/multi_field_example.dart b/example/lib/screens/multi_field_example.dart index acfcb1f..b994455 100644 --- a/example/lib/screens/multi_field_example.dart +++ b/example/lib/screens/multi_field_example.dart @@ -256,7 +256,9 @@ class _ProgressDots extends StatelessWidget { borderRadius: BorderRadius.circular(2), color: i < filled - 1 ? _kGreenComplete - : (i < filled ? _kGradientStart.withValues(alpha: 0.5) : muted), + : (i < filled + ? _kGradientStart.withValues(alpha: 0.5) + : muted), ), ), ], @@ -444,7 +446,11 @@ class _DottedLinePainter extends CustomPainter { var y = 0.0; while (y < size.height) { - canvas.drawLine(Offset(centerX, y), Offset(centerX, y + dashHeight), paint); + canvas.drawLine( + Offset(centerX, y), + Offset(centerX, y + dashHeight), + paint, + ); y += dashHeight + gap; } } diff --git a/example/lib/screens/numeric_input_example.dart b/example/lib/screens/numeric_input_example.dart index eed9c2a..9c7c9a2 100644 --- a/example/lib/screens/numeric_input_example.dart +++ b/example/lib/screens/numeric_input_example.dart @@ -93,8 +93,7 @@ class _NumericInputExampleState extends State { Text( 'How much would you like to send?', style: Theme.of(context).textTheme.bodyMedium?.copyWith( - color: - colorScheme.onSurface.withValues(alpha: 0.5), + color: colorScheme.onSurface.withValues(alpha: 0.5), ), ), const SizedBox(height: 24), diff --git a/example/lib/screens/password_entry_example.dart b/example/lib/screens/password_entry_example.dart index 53b65e3..213124c 100644 --- a/example/lib/screens/password_entry_example.dart +++ b/example/lib/screens/password_entry_example.dart @@ -178,8 +178,7 @@ class _PasswordEntryExampleState extends State { width: 2, ), ), - prefixIcon: - const Icon(Icons.lock_outline_rounded), + prefixIcon: const Icon(Icons.lock_outline_rounded), suffixIcon: IconButton( icon: Icon( _obscureText diff --git a/example/lib/screens/standalone_example.dart b/example/lib/screens/standalone_example.dart index 8ac3198..b2ec87a 100644 --- a/example/lib/screens/standalone_example.dart +++ b/example/lib/screens/standalone_example.dart @@ -161,8 +161,7 @@ class _StandaloneExampleState extends State { decoration: InputDecoration( labelText: 'Email', hintText: 'you@example.com', - prefixIcon: - const Icon(Icons.alternate_email_rounded), + prefixIcon: const Icon(Icons.alternate_email_rounded), border: OutlineInputBorder( borderRadius: BorderRadius.circular(16), borderSide: BorderSide.none, @@ -289,8 +288,11 @@ class _SectionLabel extends StatelessWidget { children: [ Row( children: [ - Icon(icon, size: 18, - color: colorScheme.onSurface.withValues(alpha: 0.7)), + Icon( + icon, + size: 18, + color: colorScheme.onSurface.withValues(alpha: 0.7), + ), const SizedBox(width: 8), Text( label.toUpperCase(), diff --git a/lib/src/layouts/languages/french.dart b/lib/src/layouts/languages/french.dart index d0304c7..a6d0131 100644 --- a/lib/src/layouts/languages/french.dart +++ b/lib/src/layouts/languages/french.dart @@ -246,25 +246,76 @@ final KeyboardLayout _urlLayoutTertiary = _textLayoutTertiary; /// Number, signed number, and phone layouts remain the same as in English. final KeyboardLayout _numberLayout = [ - [VirtualKey.character(text: '1'), VirtualKey.character(text: '2'), VirtualKey.character(text: '3')], - [VirtualKey.character(text: '4'), VirtualKey.character(text: '5'), VirtualKey.character(text: '6')], - [VirtualKey.character(text: '7'), VirtualKey.character(text: '8'), VirtualKey.character(text: '9')], - [VirtualKey.character(text: '.'), VirtualKey.character(text: '0'), VirtualKey.action(action: KeyAction.backSpace)], + [ + VirtualKey.character(text: '1'), + VirtualKey.character(text: '2'), + VirtualKey.character(text: '3'), + ], + [ + VirtualKey.character(text: '4'), + VirtualKey.character(text: '5'), + VirtualKey.character(text: '6'), + ], + [ + VirtualKey.character(text: '7'), + VirtualKey.character(text: '8'), + VirtualKey.character(text: '9'), + ], + [ + VirtualKey.character(text: '.'), + VirtualKey.character(text: '0'), + VirtualKey.action(action: KeyAction.backSpace), + ], ]; final KeyboardLayout _signedNumberLayout = [ - [VirtualKey.character(text: '1'), VirtualKey.character(text: '2'), VirtualKey.character(text: '3')], - [VirtualKey.character(text: '4'), VirtualKey.character(text: '5'), VirtualKey.character(text: '6')], - [VirtualKey.character(text: '7'), VirtualKey.character(text: '8'), VirtualKey.character(text: '9')], - [VirtualKey.character(text: '-'), VirtualKey.character(text: '0'), VirtualKey.character(text: '.')], - [VirtualKey.action(action: KeyAction.backSpace, flex: 2), VirtualKey.action(action: KeyAction.done)], + [ + VirtualKey.character(text: '1'), + VirtualKey.character(text: '2'), + VirtualKey.character(text: '3'), + ], + [ + VirtualKey.character(text: '4'), + VirtualKey.character(text: '5'), + VirtualKey.character(text: '6'), + ], + [ + VirtualKey.character(text: '7'), + VirtualKey.character(text: '8'), + VirtualKey.character(text: '9'), + ], + [ + VirtualKey.character(text: '-'), + VirtualKey.character(text: '0'), + VirtualKey.character(text: '.'), + ], + [ + VirtualKey.action(action: KeyAction.backSpace, flex: 2), + VirtualKey.action(action: KeyAction.done), + ], ]; final KeyboardLayout _phoneLayout = [ - [VirtualKey.character(text: '1'), VirtualKey.character(text: '2'), VirtualKey.character(text: '3')], - [VirtualKey.character(text: '4'), VirtualKey.character(text: '5'), VirtualKey.character(text: '6')], - [VirtualKey.character(text: '7'), VirtualKey.character(text: '8'), VirtualKey.character(text: '9')], - [VirtualKey.character(text: '*'), VirtualKey.character(text: '0'), VirtualKey.character(text: '#')], + [ + VirtualKey.character(text: '1'), + VirtualKey.character(text: '2'), + VirtualKey.character(text: '3'), + ], + [ + VirtualKey.character(text: '4'), + VirtualKey.character(text: '5'), + VirtualKey.character(text: '6'), + ], + [ + VirtualKey.character(text: '7'), + VirtualKey.character(text: '8'), + VirtualKey.character(text: '9'), + ], + [ + VirtualKey.character(text: '*'), + VirtualKey.character(text: '0'), + VirtualKey.character(text: '#'), + ], [ VirtualKey.character(text: '+'), VirtualKey.action(action: KeyAction.backSpace), diff --git a/lib/src/standalone_input_control.dart b/lib/src/standalone_input_control.dart index cb8abc0..84fcf48 100644 --- a/lib/src/standalone_input_control.dart +++ b/lib/src/standalone_input_control.dart @@ -30,22 +30,19 @@ class StandaloneInputControl with TextInputControl { bool get isAttached => _attached; /// Derives a [KeyboardType] from the attached field's [TextInputType]. - KeyboardType get keyboardType => - _toKeyboardType(_configuration?.inputType); + KeyboardType get keyboardType => _toKeyboardType(_configuration?.inputType); /// The input action from the attached field's configuration. TextInputAction get inputAction => _configuration?.inputAction ?? TextInputAction.done; /// Performs an input action (e.g. done, go, search) on the active client. - void performAction(TextInputAction action) => - _client?.performAction(action); + void performAction(TextInputAction action) => _client?.performAction(action); @override void attach(TextInputClient client, TextInputConfiguration configuration) { _client = client; - _currentValue = - client.currentTextEditingValue ?? TextEditingValue.empty; + _currentValue = client.currentTextEditingValue ?? TextEditingValue.empty; _configuration = configuration; _attached = true; } @@ -94,8 +91,7 @@ class StandaloneInputControl with TextInputControl { final newText = _currentValue.text.replaceRange(start, sel.end, ''); _updateEditingValue(newText, start); } else if (!sel.isCollapsed) { - final newText = - _currentValue.text.replaceRange(sel.start, sel.end, ''); + final newText = _currentValue.text.replaceRange(sel.start, sel.end, ''); _updateEditingValue(newText, sel.start); } } diff --git a/lib/src/standalone_scope.dart b/lib/src/standalone_scope.dart index 1a12fa9..b2fa253 100644 --- a/lib/src/standalone_scope.dart +++ b/lib/src/standalone_scope.dart @@ -34,8 +34,7 @@ class VirtualKeypadStandaloneScope extends StatefulWidget { /// Returns the nearest [VirtualKeypadStandaloneScopeState] ancestor, or /// null if there is none. static VirtualKeypadStandaloneScopeState? maybeOf(BuildContext context) { - return context - .findAncestorStateOfType(); + return context.findAncestorStateOfType(); } @override diff --git a/lib/src/widgets/keyboard.dart b/lib/src/widgets/keyboard.dart index a4fe93a..337d435 100644 --- a/lib/src/widgets/keyboard.dart +++ b/lib/src/widgets/keyboard.dart @@ -166,8 +166,7 @@ class _VirtualKeypadState extends State { // If wrapped in a scope, hide when focus moves outside that scope final myScope = VirtualKeypadStandaloneScope.maybeOf(context); if (myScope != null && _standaloneVisible) { - final focusedScope = - VirtualKeypadStandaloneScope.maybeOf(focus.context!); + final focusedScope = VirtualKeypadStandaloneScope.maybeOf(focus.context!); if (focusedScope != myScope) { setState(() => _standaloneVisible = false); } @@ -477,7 +476,8 @@ class _VirtualKeypadState extends State { Widget build(BuildContext context) { final bool shouldShowKeyboard; if (widget.standalone) { - shouldShowKeyboard = _standaloneVisible && (_inputControl?.isAttached ?? false); + shouldShowKeyboard = + _standaloneVisible && (_inputControl?.isAttached ?? false); } else { final hasController = _scope?.hasActiveController ?? false; final allowPhysical = _scope?.allowPhysicalKeyboard ?? false; From e49cadffab2f3b18e4ee12c38c0516b14e408023 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 11:11:28 +0000 Subject: [PATCH 4/8] fix: fix pin_pad color: split parameter formatting Co-authored-by: Masum-MSNR <70331283+Masum-MSNR@users.noreply.github.com> --- example/lib/screens/pin_pad_example.dart | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/example/lib/screens/pin_pad_example.dart b/example/lib/screens/pin_pad_example.dart index 83e78ef..bba761c 100644 --- a/example/lib/screens/pin_pad_example.dart +++ b/example/lib/screens/pin_pad_example.dart @@ -342,10 +342,9 @@ class _PinDot extends StatelessWidget { border: Border.all(color: const Color(0xFFf5576c), width: 2), boxShadow: [ BoxShadow( - color: - const Color(0xFFf093fb).withValues( - alpha: pulseAnimation.value, - ), + color: const Color(0xFFf093fb).withValues( + alpha: pulseAnimation.value, + ), blurRadius: 14, spreadRadius: 2, ), From da719b35e6497774eb179db51d8c870b470f344f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 11:29:21 +0000 Subject: [PATCH 5/8] fix: run dart format on all files using Dart SDK 3.7.0 Co-authored-by: Masum-MSNR <70331283+Masum-MSNR@users.noreply.github.com> --- example/lib/main.dart | 38 +--- .../screens/auto_hide_keyboard_example.dart | 61 ++--- example/lib/screens/custom_theme_example.dart | 73 +++--- example/lib/screens/email_url_example.dart | 54 ++--- .../screens/language_switching_example.dart | 146 ++++++------ example/lib/screens/multi_field_example.dart | 208 ++++++++++-------- .../lib/screens/multiline_text_example.dart | 40 ++-- .../lib/screens/numeric_input_example.dart | 96 ++++---- .../lib/screens/password_entry_example.dart | 31 ++- example/lib/screens/pin_pad_example.dart | 102 ++++----- example/lib/screens/standalone_example.dart | 34 +-- lib/src/layouts/keyboard_language.dart | 4 +- lib/src/layouts/languages/bengali.dart | 30 ++- lib/src/models.dart | 19 +- lib/src/scope.dart | 13 +- lib/src/standalone_scope.dart | 5 +- lib/src/theme.dart | 46 ++-- lib/src/widgets/keyboard.dart | 118 +++++----- lib/src/widgets/text_field.dart | 102 +++++---- test/virtual_keypad_test.dart | 80 ++++--- 20 files changed, 686 insertions(+), 614 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index f9ada75..0413554 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -59,11 +59,7 @@ class HomePage extends StatelessWidget { title: Row( mainAxisSize: MainAxisSize.min, children: [ - Image.asset( - 'assets/logo.png', - width: 24, - height: 24, - ), + Image.asset('assets/logo.png', width: 24, height: 24), const SizedBox(width: 10), Column( mainAxisSize: MainAxisSize.min, @@ -71,10 +67,7 @@ class HomePage extends StatelessWidget { children: [ const Text( 'Virtual Keypad', - style: TextStyle( - fontWeight: FontWeight.w800, - fontSize: 18, - ), + style: TextStyle(fontWeight: FontWeight.w800, fontSize: 18), ), Text( 'Flutter on-screen keyboard', @@ -92,10 +85,7 @@ class HomePage extends StatelessWidget { body: ListView( padding: const EdgeInsets.fromLTRB(16, 12, 16, 24), children: [ - const _SectionHeader( - title: 'Input Types', - icon: Icons.input_rounded, - ), + const _SectionHeader(title: 'Input Types', icon: Icons.input_rounded), _ExampleCard( icon: Icons.dialpad_rounded, title: 'Numeric Input', @@ -144,10 +134,7 @@ class HomePage extends StatelessWidget { onTap: () => _navigate(context, const MultilineTextExample()), ), const SizedBox(height: 4), - const _SectionHeader( - title: 'Features', - icon: Icons.stars_rounded, - ), + const _SectionHeader(title: 'Features', icon: Icons.stars_rounded), _ExampleCard( icon: Icons.bolt_rounded, title: 'Standalone Mode', @@ -188,18 +175,14 @@ class HomePage extends StatelessWidget { pageBuilder: (context, animation, secondaryAnimation) => page, transitionsBuilder: (context, animation, secondaryAnimation, child) { return FadeTransition( - opacity: CurvedAnimation( - parent: animation, - curve: Curves.easeOut, - ), + opacity: CurvedAnimation(parent: animation, curve: Curves.easeOut), child: SlideTransition( position: Tween( begin: const Offset(0.04, 0), end: Offset.zero, - ).animate(CurvedAnimation( - parent: animation, - curve: Curves.easeOut, - )), + ).animate( + CurvedAnimation(parent: animation, curve: Curves.easeOut), + ), child: child, ), ); @@ -349,8 +332,9 @@ class _ExampleCard extends StatelessWidget { subtitle, style: TextStyle( fontSize: 12, - color: - colorScheme.onSurface.withValues(alpha: 0.55), + color: colorScheme.onSurface.withValues( + alpha: 0.55, + ), ), ), ], diff --git a/example/lib/screens/auto_hide_keyboard_example.dart b/example/lib/screens/auto_hide_keyboard_example.dart index b7a9db4..a2fb43b 100644 --- a/example/lib/screens/auto_hide_keyboard_example.dart +++ b/example/lib/screens/auto_hide_keyboard_example.dart @@ -83,8 +83,9 @@ class _AutoHideKeyboardExampleState extends State { ), ], border: Border.all( - color: colorScheme.outlineVariant - .withValues(alpha: 0.1), + color: colorScheme.outlineVariant.withValues( + alpha: 0.1, + ), ), ), child: ClipRRect( @@ -97,10 +98,11 @@ class _AutoHideKeyboardExampleState extends State { decoration: BoxDecoration( border: Border( left: BorderSide( - color: _isAnyFocused - ? const Color(0xFF30cfd0) - : colorScheme.outlineVariant - .withValues(alpha: 0.4), + color: + _isAnyFocused + ? const Color(0xFF30cfd0) + : colorScheme.outlineVariant + .withValues(alpha: 0.4), width: 4, ), ), @@ -113,20 +115,24 @@ class _AutoHideKeyboardExampleState extends State { height: 10, decoration: BoxDecoration( shape: BoxShape.circle, - color: _isAnyFocused - ? const Color(0xFF30cfd0) - : colorScheme.outline - .withValues(alpha: 0.35), - boxShadow: _isAnyFocused - ? [ - BoxShadow( - color: const Color(0xFF30cfd0) - .withValues(alpha: 0.5), - blurRadius: 8, - spreadRadius: 1, + color: + _isAnyFocused + ? const Color(0xFF30cfd0) + : colorScheme.outline.withValues( + alpha: 0.35, ), - ] - : [], + boxShadow: + _isAnyFocused + ? [ + BoxShadow( + color: const Color( + 0xFF30cfd0, + ).withValues(alpha: 0.5), + blurRadius: 8, + spreadRadius: 1, + ), + ] + : [], ), ), const SizedBox(width: 12), @@ -142,9 +148,10 @@ class _AutoHideKeyboardExampleState extends State { style: TextStyle( fontSize: 14, fontWeight: FontWeight.w700, - color: _isAnyFocused - ? const Color(0xFF30cfd0) - : colorScheme.onSurface, + color: + _isAnyFocused + ? const Color(0xFF30cfd0) + : colorScheme.onSurface, ), ), const SizedBox(height: 2), @@ -168,10 +175,12 @@ class _AutoHideKeyboardExampleState extends State { ? Icons.keyboard_rounded : Icons.keyboard_hide_rounded, key: ValueKey(_isAnyFocused), - color: _isAnyFocused - ? const Color(0xFF30cfd0) - : colorScheme.outline - .withValues(alpha: 0.35), + color: + _isAnyFocused + ? const Color(0xFF30cfd0) + : colorScheme.outline.withValues( + alpha: 0.35, + ), size: 22, ), ), diff --git a/example/lib/screens/custom_theme_example.dart b/example/lib/screens/custom_theme_example.dart index 416f6a3..93b3858 100644 --- a/example/lib/screens/custom_theme_example.dart +++ b/example/lib/screens/custom_theme_example.dart @@ -118,14 +118,15 @@ class _CustomThemeExampleState extends State { child: ListView.separated( scrollDirection: Axis.horizontal, itemCount: _themes.length, - separatorBuilder: (_, _) => - const SizedBox(width: 10), + separatorBuilder: + (_, _) => const SizedBox(width: 10), itemBuilder: (context, index) { final theme = _themes[index]; final isSelected = index == _selectedTheme; return GestureDetector( - onTap: () => - setState(() => _selectedTheme = index), + onTap: + () => + setState(() => _selectedTheme = index), child: AnimatedContainer( duration: const Duration(milliseconds: 250), padding: const EdgeInsets.symmetric( @@ -133,30 +134,38 @@ class _CustomThemeExampleState extends State { vertical: 10, ), decoration: BoxDecoration( - color: isSelected - ? theme.accent - .withValues(alpha: 0.2) - : current.appBarBg - .withValues(alpha: 0.6), + color: + isSelected + ? theme.accent.withValues( + alpha: 0.2, + ) + : current.appBarBg.withValues( + alpha: 0.6, + ), borderRadius: BorderRadius.circular(26), border: Border.all( - color: isSelected - ? theme.accent - .withValues(alpha: 0.6) - : current.textColor - .withValues(alpha: 0.08), + color: + isSelected + ? theme.accent.withValues( + alpha: 0.6, + ) + : current.textColor.withValues( + alpha: 0.08, + ), width: isSelected ? 2 : 1, ), - boxShadow: isSelected - ? [ - BoxShadow( - color: theme.accent - .withValues(alpha: 0.25), - blurRadius: 12, - offset: const Offset(0, 3), - ), - ] - : [], + boxShadow: + isSelected + ? [ + BoxShadow( + color: theme.accent.withValues( + alpha: 0.25, + ), + blurRadius: 12, + offset: const Offset(0, 3), + ), + ] + : [], ), child: Row( mainAxisSize: MainAxisSize.min, @@ -170,13 +179,15 @@ class _CustomThemeExampleState extends State { theme.name, style: TextStyle( fontSize: 14, - fontWeight: isSelected - ? FontWeight.w700 - : FontWeight.w400, - color: isSelected - ? theme.accent - : current.textColor - .withValues(alpha: 0.55), + fontWeight: + isSelected + ? FontWeight.w700 + : FontWeight.w400, + color: + isSelected + ? theme.accent + : current.textColor + .withValues(alpha: 0.55), ), ), ], diff --git a/example/lib/screens/email_url_example.dart b/example/lib/screens/email_url_example.dart index 0f8dc86..596ce64 100644 --- a/example/lib/screens/email_url_example.dart +++ b/example/lib/screens/email_url_example.dart @@ -82,8 +82,9 @@ class _EmailUrlExampleState extends State { labelText: 'Email', hintText: 'user@example.com', hintStyle: TextStyle( - color: colorScheme.onSurface - .withValues(alpha: 0.25), + color: colorScheme.onSurface.withValues( + alpha: 0.25, + ), ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(14), @@ -119,21 +120,24 @@ class _EmailUrlExampleState extends State { gradient: LinearGradient( colors: [ Colors.transparent, - colorScheme.outlineVariant - .withValues(alpha: 0.4), + colorScheme.outlineVariant.withValues( + alpha: 0.4, + ), ], ), ), ), ), Padding( - padding: - const EdgeInsets.symmetric(horizontal: 14), + padding: const EdgeInsets.symmetric( + horizontal: 14, + ), child: Icon( Icons.more_horiz_rounded, size: 18, - color: colorScheme.outlineVariant - .withValues(alpha: 0.5), + color: colorScheme.outlineVariant.withValues( + alpha: 0.5, + ), ), ), Expanded( @@ -142,8 +146,9 @@ class _EmailUrlExampleState extends State { decoration: BoxDecoration( gradient: LinearGradient( colors: [ - colorScheme.outlineVariant - .withValues(alpha: 0.4), + colorScheme.outlineVariant.withValues( + alpha: 0.4, + ), Colors.transparent, ], ), @@ -173,8 +178,9 @@ class _EmailUrlExampleState extends State { labelText: 'Website', hintText: 'https://example.com', hintStyle: TextStyle( - color: colorScheme.onSurface - .withValues(alpha: 0.25), + color: colorScheme.onSurface.withValues( + alpha: 0.25, + ), ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(14), @@ -188,9 +194,10 @@ class _EmailUrlExampleState extends State { ), ), prefixIcon: const Icon(Icons.language_rounded), - suffixIcon: _isValidUrl(_urlController.text) - ? const _AnimatedCheckmark() - : null, + suffixIcon: + _isValidUrl(_urlController.text) + ? const _AnimatedCheckmark() + : null, filled: true, fillColor: colorScheme.surfaceContainerLowest, ), @@ -199,12 +206,13 @@ class _EmailUrlExampleState extends State { SnackBar( content: Row( children: [ - const Icon(Icons.open_in_browser, - color: Colors.white, size: 18), - const SizedBox(width: 10), - Text( - 'Opening ${_urlController.text}', + const Icon( + Icons.open_in_browser, + color: Colors.white, + size: 18, ), + const SizedBox(width: 10), + Text('Opening ${_urlController.text}'), ], ), behavior: SnackBarBehavior.floating, @@ -388,11 +396,7 @@ class _AnimatedCheckmarkState extends State<_AnimatedCheckmark> ), ], ), - child: const Icon( - Icons.check_rounded, - color: Colors.white, - size: 16, - ), + child: const Icon(Icons.check_rounded, color: Colors.white, size: 16), ), ); } diff --git a/example/lib/screens/language_switching_example.dart b/example/lib/screens/language_switching_example.dart index 68b0ced..ee79b49 100644 --- a/example/lib/screens/language_switching_example.dart +++ b/example/lib/screens/language_switching_example.dart @@ -90,23 +90,24 @@ class _LanguageSwitchingExampleState extends State { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Row( - children: _languages.map((lang) { - final (code, label, flag, subtitle, colors) = lang; - final isFirst = code == _languages.first.$1; - return Expanded( - child: Padding( - padding: EdgeInsets.only(left: isFirst ? 0 : 8), - child: _LanguageCard( - label: label, - flag: flag, - subtitle: subtitle, - isSelected: _currentLanguage == code, - gradientColors: colors, - onTap: () => _switchLanguage(code), - ), - ), - ); - }).toList(), + children: + _languages.map((lang) { + final (code, label, flag, subtitle, colors) = lang; + final isFirst = code == _languages.first.$1; + return Expanded( + child: Padding( + padding: EdgeInsets.only(left: isFirst ? 0 : 8), + child: _LanguageCard( + label: label, + flag: flag, + subtitle: subtitle, + isSelected: _currentLanguage == code, + gradientColors: colors, + onTap: () => _switchLanguage(code), + ), + ), + ); + }).toList(), ), const SizedBox(height: 18), @@ -117,8 +118,7 @@ class _LanguageSwitchingExampleState extends State { borderRadius: BorderRadius.circular(18), boxShadow: [ BoxShadow( - color: colorScheme.shadow - .withValues(alpha: 0.05), + color: colorScheme.shadow.withValues(alpha: 0.05), blurRadius: 16, offset: const Offset(0, 4), ), @@ -130,15 +130,13 @@ class _LanguageSwitchingExampleState extends State { minLines: 3, onChanged: (_) => setState(() {}), textAlignVertical: TextAlignVertical.top, - style: const TextStyle( - fontSize: 15, - height: 1.6, - ), + style: const TextStyle(fontSize: 15, height: 1.6), decoration: InputDecoration( hintText: hintText, hintStyle: TextStyle( - color: colorScheme.onSurface - .withValues(alpha: 0.2), + color: colorScheme.onSurface.withValues( + alpha: 0.2, + ), fontSize: 15, ), border: OutlineInputBorder( @@ -148,8 +146,9 @@ class _LanguageSwitchingExampleState extends State { enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(18), borderSide: BorderSide( - color: colorScheme.outlineVariant - .withValues(alpha: 0.15), + color: colorScheme.outlineVariant.withValues( + alpha: 0.15, + ), ), ), focusedBorder: OutlineInputBorder( @@ -175,8 +174,9 @@ class _LanguageSwitchingExampleState extends State { vertical: 8, ), decoration: BoxDecoration( - color: colorScheme.surfaceContainerHigh - .withValues(alpha: 0.3), + color: colorScheme.surfaceContainerHigh.withValues( + alpha: 0.3, + ), borderRadius: BorderRadius.circular(12), ), child: Row( @@ -184,8 +184,9 @@ class _LanguageSwitchingExampleState extends State { Icon( Icons.text_snippet_outlined, size: 14, - color: colorScheme.onSurface - .withValues(alpha: 0.35), + color: colorScheme.onSurface.withValues( + alpha: 0.35, + ), ), const SizedBox(width: 6), Text( @@ -193,8 +194,9 @@ class _LanguageSwitchingExampleState extends State { style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, - color: colorScheme.onSurface - .withValues(alpha: 0.45), + color: colorScheme.onSurface.withValues( + alpha: 0.45, + ), ), ), const Spacer(), @@ -218,8 +220,9 @@ class _LanguageSwitchingExampleState extends State { Icon( Icons.clear_rounded, size: 14, - color: colorScheme.error - .withValues(alpha: 0.6), + color: colorScheme.error.withValues( + alpha: 0.6, + ), ), const SizedBox(width: 4), Text( @@ -227,8 +230,9 @@ class _LanguageSwitchingExampleState extends State { style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, - color: colorScheme.error - .withValues(alpha: 0.6), + color: colorScheme.error.withValues( + alpha: 0.6, + ), ), ), ], @@ -280,34 +284,38 @@ class _LanguageCard extends StatelessWidget { padding: const EdgeInsets.symmetric(vertical: 14), decoration: BoxDecoration( borderRadius: BorderRadius.circular(16), - gradient: isSelected - ? LinearGradient( - colors: [ - gradientColors.first.withValues(alpha: 0.15), - gradientColors.last.withValues(alpha: 0.08), - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ) - : null, - color: isSelected - ? null - : colorScheme.surfaceContainerHigh.withValues(alpha: 0.4), + gradient: + isSelected + ? LinearGradient( + colors: [ + gradientColors.first.withValues(alpha: 0.15), + gradientColors.last.withValues(alpha: 0.08), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ) + : null, + color: + isSelected + ? null + : colorScheme.surfaceContainerHigh.withValues(alpha: 0.4), border: Border.all( - color: isSelected - ? gradientColors.first.withValues(alpha: 0.5) - : colorScheme.outlineVariant.withValues(alpha: 0.2), + color: + isSelected + ? gradientColors.first.withValues(alpha: 0.5) + : colorScheme.outlineVariant.withValues(alpha: 0.2), width: isSelected ? 2 : 1, ), - boxShadow: isSelected - ? [ - BoxShadow( - color: gradientColors.first.withValues(alpha: 0.15), - blurRadius: 12, - offset: const Offset(0, 4), - ), - ] - : [], + boxShadow: + isSelected + ? [ + BoxShadow( + color: gradientColors.first.withValues(alpha: 0.15), + blurRadius: 12, + offset: const Offset(0, 4), + ), + ] + : [], ), child: Column( mainAxisSize: MainAxisSize.min, @@ -319,9 +327,10 @@ class _LanguageCard extends StatelessWidget { style: TextStyle( fontWeight: isSelected ? FontWeight.w700 : FontWeight.w500, fontSize: 15, - color: isSelected - ? colorScheme.onSurface - : colorScheme.onSurface.withValues(alpha: 0.6), + color: + isSelected + ? colorScheme.onSurface + : colorScheme.onSurface.withValues(alpha: 0.6), ), ), const SizedBox(height: 2), @@ -330,9 +339,10 @@ class _LanguageCard extends StatelessWidget { style: TextStyle( fontSize: 11, fontWeight: FontWeight.w500, - color: isSelected - ? gradientColors.first.withValues(alpha: 0.8) - : colorScheme.onSurface.withValues(alpha: 0.35), + color: + isSelected + ? gradientColors.first.withValues(alpha: 0.8) + : colorScheme.onSurface.withValues(alpha: 0.35), ), ), ], diff --git a/example/lib/screens/multi_field_example.dart b/example/lib/screens/multi_field_example.dart index b994455..b4494b5 100644 --- a/example/lib/screens/multi_field_example.dart +++ b/example/lib/screens/multi_field_example.dart @@ -34,10 +34,10 @@ class _MultiFieldExampleState extends State { } List get _stepsDone => [ - _nameController.text.isNotEmpty, - _emailController.text.isNotEmpty, - _passwordController.text.isNotEmpty, - ]; + _nameController.text.isNotEmpty, + _emailController.text.isNotEmpty, + _passwordController.text.isNotEmpty, + ]; @override Widget build(BuildContext context) { @@ -86,23 +86,19 @@ class _MultiFieldExampleState extends State { // ── Header ── Text( 'Create Account', - style: Theme.of(context) - .textTheme - .headlineSmall + style: Theme.of(context).textTheme.headlineSmall ?.copyWith(fontWeight: FontWeight.w800), ), const SizedBox(height: 4), Text( 'Fill in your details to get started', - style: Theme.of(context) - .textTheme - .bodyMedium - ?.copyWith( - color: Theme.of(context) - .colorScheme - .onSurface - .withValues(alpha: 0.55), - ), + style: Theme.of( + context, + ).textTheme.bodyMedium?.copyWith( + color: Theme.of( + context, + ).colorScheme.onSurface.withValues(alpha: 0.55), + ), ), const SizedBox(height: 28), @@ -159,11 +155,13 @@ class _MultiFieldExampleState extends State { SnackBar( content: Row( children: [ - const Icon(Icons.check_circle, - color: Colors.white, size: 18), + const Icon( + Icons.check_circle, + color: Colors.white, + size: 18, + ), const SizedBox(width: 10), - Text( - 'Welcome, ${_nameController.text}!'), + Text('Welcome, ${_nameController.text}!'), ], ), behavior: SnackBarBehavior.floating, @@ -223,8 +221,10 @@ class _MultiFieldExampleState extends State { prefixIcon: Icon(icon), filled: true, fillColor: colorScheme.surfaceContainerLowest, - contentPadding: - const EdgeInsets.symmetric(horizontal: 16, vertical: 14), + contentPadding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 14, + ), ), ); } @@ -238,8 +238,9 @@ class _ProgressDots extends StatelessWidget { @override Widget build(BuildContext context) { - final muted = - Theme.of(context).colorScheme.outlineVariant.withValues(alpha: 0.4); + final muted = Theme.of( + context, + ).colorScheme.outlineVariant.withValues(alpha: 0.4); return Row( mainAxisAlignment: MainAxisAlignment.center, @@ -254,11 +255,12 @@ class _ProgressDots extends StatelessWidget { height: 3, decoration: BoxDecoration( borderRadius: BorderRadius.circular(2), - color: i < filled - 1 - ? _kGreenComplete - : (i < filled - ? _kGradientStart.withValues(alpha: 0.5) - : muted), + color: + i < filled - 1 + ? _kGreenComplete + : (i < filled + ? _kGradientStart.withValues(alpha: 0.5) + : muted), ), ), ], @@ -273,8 +275,9 @@ class _Dot extends StatelessWidget { @override Widget build(BuildContext context) { - final muted = - Theme.of(context).colorScheme.outlineVariant.withValues(alpha: 0.4); + final muted = Theme.of( + context, + ).colorScheme.outlineVariant.withValues(alpha: 0.4); return AnimatedContainer( duration: const Duration(milliseconds: 300), @@ -285,21 +288,23 @@ class _Dot extends StatelessWidget { shape: BoxShape.circle, color: active ? _kGreenComplete : Colors.transparent, border: active ? null : Border.all(color: muted, width: 2), - boxShadow: active - ? [ - BoxShadow( - color: _kGreenComplete.withValues(alpha: 0.35), - blurRadius: 8, - spreadRadius: 1, - ), - ] - : null, + boxShadow: + active + ? [ + BoxShadow( + color: _kGreenComplete.withValues(alpha: 0.35), + blurRadius: 8, + spreadRadius: 1, + ), + ] + : null, ), - child: active - ? const Center( - child: Icon(Icons.check, size: 11, color: Colors.white), - ) - : null, + child: + active + ? const Center( + child: Icon(Icons.check, size: 11, color: Colors.white), + ) + : null, ); } } @@ -312,10 +317,7 @@ class _StepperColumn extends StatelessWidget { @override Widget build(BuildContext context) { - return Column( - mainAxisSize: MainAxisSize.min, - children: steps, - ); + return Column(mainAxisSize: MainAxisSize.min, children: steps); } } @@ -354,43 +356,51 @@ class _StepItem extends StatelessWidget { height: 28, decoration: BoxDecoration( shape: BoxShape.circle, - color: done - ? _kGreenComplete - : colorScheme.surfaceContainerHigh, - border: done - ? null - : Border.all( - color: colorScheme.outlineVariant - .withValues(alpha: 0.6), - ), - boxShadow: done - ? [ - BoxShadow( - color: _kGreenComplete.withValues(alpha: 0.3), - blurRadius: 8, - spreadRadius: 1, + color: + done + ? _kGreenComplete + : colorScheme.surfaceContainerHigh, + border: + done + ? null + : Border.all( + color: colorScheme.outlineVariant.withValues( + alpha: 0.6, + ), ), - ] - : null, + boxShadow: + done + ? [ + BoxShadow( + color: _kGreenComplete.withValues(alpha: 0.3), + blurRadius: 8, + spreadRadius: 1, + ), + ] + : null, ), child: Center( child: AnimatedSwitcher( duration: const Duration(milliseconds: 250), - child: done - ? const Icon(Icons.check, - key: ValueKey('check'), - size: 14, - color: Colors.white) - : Text( - stepNumber, - key: ValueKey('num$stepNumber'), - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: colorScheme.onSurface - .withValues(alpha: 0.5), + child: + done + ? const Icon( + Icons.check, + key: ValueKey('check'), + size: 14, + color: Colors.white, + ) + : Text( + stepNumber, + key: ValueKey('num$stepNumber'), + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: colorScheme.onSurface.withValues( + alpha: 0.5, + ), + ), ), - ), ), ), ), @@ -401,10 +411,12 @@ class _StepItem extends StatelessWidget { padding: const EdgeInsets.symmetric(vertical: 4), child: CustomPaint( painter: _DottedLinePainter( - color: done - ? _kGreenComplete.withValues(alpha: 0.5) - : colorScheme.outlineVariant - .withValues(alpha: 0.35), + color: + done + ? _kGreenComplete.withValues(alpha: 0.5) + : colorScheme.outlineVariant.withValues( + alpha: 0.35, + ), ), child: const SizedBox(width: 2), ), @@ -435,10 +447,11 @@ class _DottedLinePainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { - final paint = Paint() - ..color = color - ..strokeWidth = 2 - ..strokeCap = StrokeCap.round; + final paint = + Paint() + ..color = color + ..strokeWidth = 2 + ..strokeCap = StrokeCap.round; const dashHeight = 4.0; const gap = 4.0; @@ -482,15 +495,16 @@ class _GradientButton extends StatelessWidget { begin: Alignment.topLeft, end: Alignment.bottomRight, ), - boxShadow: enabled - ? [ - BoxShadow( - color: _kGradientStart.withValues(alpha: 0.35), - blurRadius: 12, - offset: const Offset(0, 4), - ), - ] - : null, + boxShadow: + enabled + ? [ + BoxShadow( + color: _kGradientStart.withValues(alpha: 0.35), + blurRadius: 12, + offset: const Offset(0, 4), + ), + ] + : null, ), child: MaterialButton( onPressed: enabled ? onPressed : null, diff --git a/example/lib/screens/multiline_text_example.dart b/example/lib/screens/multiline_text_example.dart index 64ad0fc..2298378 100644 --- a/example/lib/screens/multiline_text_example.dart +++ b/example/lib/screens/multiline_text_example.dart @@ -92,13 +92,15 @@ class _MultilineTextExampleState extends State { color: const Color(0xFFFDFCFF), borderRadius: BorderRadius.circular(20), border: Border.all( - color: colorScheme.outlineVariant - .withValues(alpha: 0.25), + color: colorScheme.outlineVariant.withValues( + alpha: 0.25, + ), ), boxShadow: [ BoxShadow( - color: const Color(0xFFa18cd1) - .withValues(alpha: 0.06), + color: const Color( + 0xFFa18cd1, + ).withValues(alpha: 0.06), blurRadius: 24, offset: const Offset(0, 6), ), @@ -120,8 +122,9 @@ class _MultilineTextExampleState extends State { Icon( Icons.edit_note_rounded, size: 48, - color: const Color(0xFFa18cd1) - .withValues(alpha: 0.25), + color: const Color( + 0xFFa18cd1, + ).withValues(alpha: 0.25), ), const SizedBox(height: 8), Text( @@ -129,8 +132,9 @@ class _MultilineTextExampleState extends State { style: TextStyle( fontSize: 15, fontWeight: FontWeight.w500, - color: colorScheme.onSurface - .withValues(alpha: 0.2), + color: colorScheme.onSurface.withValues( + alpha: 0.2, + ), letterSpacing: 0.2, ), ), @@ -147,8 +151,9 @@ class _MultilineTextExampleState extends State { style: TextStyle( fontSize: 15, height: 1.6, - color: colorScheme.onSurface - .withValues(alpha: 0.85), + color: colorScheme.onSurface.withValues( + alpha: 0.85, + ), ), decoration: InputDecoration( hintText: '', @@ -185,8 +190,9 @@ class _MultilineTextExampleState extends State { icon: Icons.text_fields_rounded, value: '${_controller.text.length}', label: 'chars', - backgroundColor: - const Color(0xFFa18cd1).withValues(alpha: 0.10), + backgroundColor: const Color( + 0xFFa18cd1, + ).withValues(alpha: 0.10), iconColor: const Color(0xFFa18cd1), ), const SizedBox(width: 10), @@ -194,8 +200,9 @@ class _MultilineTextExampleState extends State { icon: Icons.short_text_rounded, value: '${_wordCount(_controller.text)}', label: 'words', - backgroundColor: - const Color(0xFFfbc2eb).withValues(alpha: 0.18), + backgroundColor: const Color( + 0xFFfbc2eb, + ).withValues(alpha: 0.18), iconColor: const Color(0xFFc97db8), ), const SizedBox(width: 10), @@ -203,8 +210,9 @@ class _MultilineTextExampleState extends State { icon: Icons.format_line_spacing_rounded, value: '${_lineCount(_controller.text)}', label: 'lines', - backgroundColor: - const Color(0xFF90CAF9).withValues(alpha: 0.18), + backgroundColor: const Color( + 0xFF90CAF9, + ).withValues(alpha: 0.18), iconColor: const Color(0xFF5C9CE6), ), ], diff --git a/example/lib/screens/numeric_input_example.dart b/example/lib/screens/numeric_input_example.dart index 9c7c9a2..4f56fcc 100644 --- a/example/lib/screens/numeric_input_example.dart +++ b/example/lib/screens/numeric_input_example.dart @@ -84,17 +84,16 @@ class _NumericInputExampleState extends State { const SizedBox(height: 16), Text( 'Enter Amount', - style: Theme.of(context) - .textTheme - .titleLarge - ?.copyWith(fontWeight: FontWeight.w700), + style: Theme.of(context).textTheme.titleLarge?.copyWith( + fontWeight: FontWeight.w700, + ), ), const SizedBox(height: 4), Text( 'How much would you like to send?', style: Theme.of(context).textTheme.bodyMedium?.copyWith( - color: colorScheme.onSurface.withValues(alpha: 0.5), - ), + color: colorScheme.onSurface.withValues(alpha: 0.5), + ), ), const SizedBox(height: 24), @@ -111,8 +110,9 @@ class _NumericInputExampleState extends State { color: colorScheme.surfaceContainerLowest, boxShadow: [ BoxShadow( - color: const Color(0xFF667eea) - .withValues(alpha: 0.08), + color: const Color( + 0xFF667eea, + ).withValues(alpha: 0.08), blurRadius: 24, offset: const Offset(0, 8), ), @@ -128,16 +128,18 @@ class _NumericInputExampleState extends State { keyboardType: KeyboardType.number, decoration: InputDecoration( prefixIcon: Padding( - padding: - const EdgeInsets.only(left: 20, right: 4), + padding: const EdgeInsets.only( + left: 20, + right: 4, + ), child: ShaderMask( - shaderCallback: (bounds) => - const LinearGradient( - colors: [ - Color(0xFF667eea), - Color(0xFF764ba2), - ], - ).createShader(bounds), + shaderCallback: + (bounds) => const LinearGradient( + colors: [ + Color(0xFF667eea), + Color(0xFF764ba2), + ], + ).createShader(bounds), child: const Text( '\$', style: TextStyle( @@ -154,8 +156,9 @@ class _NumericInputExampleState extends State { ), hintText: '0.00', hintStyle: TextStyle( - color: - colorScheme.onSurface.withValues(alpha: 0.15), + color: colorScheme.onSurface.withValues( + alpha: 0.15, + ), fontSize: 36, fontWeight: FontWeight.w800, ), @@ -184,28 +187,29 @@ class _NumericInputExampleState extends State { spacing: 10, runSpacing: 10, alignment: WrapAlignment.center, - children: _quickAmounts.map((amount) { - return ActionChip( - label: Text( - '\$$amount', - style: const TextStyle( - fontWeight: FontWeight.w600, - color: Colors.white, - fontSize: 13, - ), - ), - backgroundColor: const Color(0xFF667eea), - side: BorderSide.none, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(24), - ), - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 2, - ), - onPressed: () => _setAmount(amount), - ); - }).toList(), + children: + _quickAmounts.map((amount) { + return ActionChip( + label: Text( + '\$$amount', + style: const TextStyle( + fontWeight: FontWeight.w600, + color: Colors.white, + fontSize: 13, + ), + ), + backgroundColor: const Color(0xFF667eea), + side: BorderSide.none, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(24), + ), + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 2, + ), + onPressed: () => _setAmount(amount), + ); + }).toList(), ), const SizedBox(height: 20), @@ -223,8 +227,9 @@ class _NumericInputExampleState extends State { ), boxShadow: [ BoxShadow( - color: const Color(0xFF764ba2) - .withValues(alpha: 0.35), + color: const Color( + 0xFF764ba2, + ).withValues(alpha: 0.35), blurRadius: 16, offset: const Offset(0, 6), ), @@ -255,10 +260,7 @@ class _NumericInputExampleState extends State { ), ), ), - VirtualKeypad( - type: KeyboardType.number, - height: 260, - ), + VirtualKeypad(type: KeyboardType.number, height: 260), ], ), ), diff --git a/example/lib/screens/password_entry_example.dart b/example/lib/screens/password_entry_example.dart index 213124c..c0ed88c 100644 --- a/example/lib/screens/password_entry_example.dart +++ b/example/lib/screens/password_entry_example.dart @@ -116,20 +116,14 @@ class _PasswordEntryExampleState extends State { Text( 'Welcome Back', - style: Theme.of(context) - .textTheme - .headlineSmall + style: Theme.of(context).textTheme.headlineSmall ?.copyWith(fontWeight: FontWeight.w700), ), const SizedBox(height: 6), Text( 'Sign in to continue', - style: Theme.of(context) - .textTheme - .bodyMedium - ?.copyWith( - color: colorScheme.onSurfaceVariant, - ), + style: Theme.of(context).textTheme.bodyMedium + ?.copyWith(color: colorScheme.onSurfaceVariant), ), const SizedBox(height: 28), @@ -151,8 +145,9 @@ class _PasswordEntryExampleState extends State { width: 2, ), ), - prefixIcon: - const Icon(Icons.person_outline_rounded), + prefixIcon: const Icon( + Icons.person_outline_rounded, + ), filled: true, fillColor: colorScheme.surfaceContainerLowest, ), @@ -209,10 +204,11 @@ class _PasswordEntryExampleState extends State { ), decoration: BoxDecoration( borderRadius: BorderRadius.circular(3), - color: active - ? _strengthColor(strength) - : colorScheme.outlineVariant - .withValues(alpha: 0.3), + color: + active + ? _strengthColor(strength) + : colorScheme.outlineVariant + .withValues(alpha: 0.3), ), ), ); @@ -238,8 +234,9 @@ class _PasswordEntryExampleState extends State { onPressed: () {}, style: TextButton.styleFrom( foregroundColor: const Color(0xFF4facfe), - padding: - const EdgeInsets.symmetric(horizontal: 4), + padding: const EdgeInsets.symmetric( + horizontal: 4, + ), ), child: const Text( 'Forgot Password?', diff --git a/example/lib/screens/pin_pad_example.dart b/example/lib/screens/pin_pad_example.dart index bba761c..425a810 100644 --- a/example/lib/screens/pin_pad_example.dart +++ b/example/lib/screens/pin_pad_example.dart @@ -170,16 +170,17 @@ class _PinPadExampleState extends State height: 80, decoration: BoxDecoration( shape: BoxShape.circle, - gradient: _showSuccess - ? const LinearGradient( - colors: [ - Color(0xFF43A047), - Color(0xFF66BB6A), - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ) - : _gradient, + gradient: + _showSuccess + ? const LinearGradient( + colors: [ + Color(0xFF43A047), + Color(0xFF66BB6A), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ) + : _gradient, boxShadow: [ BoxShadow( color: (_showSuccess @@ -219,15 +220,13 @@ class _PinPadExampleState extends State child: Text( _showSuccess ? 'Unlocked!' : 'Enter PIN', key: ValueKey(_showSuccess), - style: Theme.of(context) - .textTheme - .titleLarge - ?.copyWith( - fontWeight: FontWeight.w700, - color: _showSuccess - ? const Color(0xFF43A047) - : null, - ), + style: Theme.of( + context, + ).textTheme.titleLarge?.copyWith( + fontWeight: FontWeight.w700, + color: + _showSuccess ? const Color(0xFF43A047) : null, + ), ), ), const SizedBox(height: 4), @@ -241,8 +240,9 @@ class _PinPadExampleState extends State _showSuccess ? 'granted' : 'enter', ), style: TextStyle( - color: - colorScheme.onSurface.withValues(alpha: 0.45), + color: colorScheme.onSurface.withValues( + alpha: 0.45, + ), fontSize: 13, ), ), @@ -269,8 +269,9 @@ class _PinPadExampleState extends State isActive: isActive, isSuccess: _showSuccess, pulseAnimation: _pulseAnimation, - outlineColor: - colorScheme.outline.withValues(alpha: 0.35), + outlineColor: colorScheme.outline.withValues( + alpha: 0.35, + ), ); }), ), @@ -342,9 +343,9 @@ class _PinDot extends StatelessWidget { border: Border.all(color: const Color(0xFFf5576c), width: 2), boxShadow: [ BoxShadow( - color: const Color(0xFFf093fb).withValues( - alpha: pulseAnimation.value, - ), + color: const Color( + 0xFFf093fb, + ).withValues(alpha: pulseAnimation.value), blurRadius: 14, spreadRadius: 2, ), @@ -363,32 +364,35 @@ class _PinDot extends StatelessWidget { height: isFilled ? 22 : 18, decoration: BoxDecoration( shape: BoxShape.circle, - gradient: isSuccess - ? const LinearGradient( - colors: [Color(0xFF43A047), Color(0xFF66BB6A)], - ) - : isFilled + gradient: + isSuccess + ? const LinearGradient( + colors: [Color(0xFF43A047), Color(0xFF66BB6A)], + ) + : isFilled ? _dotGradient : null, - border: isFilled || isSuccess - ? null - : Border.all(color: outlineColor, width: 2), - boxShadow: isFilled && !isSuccess - ? [ - BoxShadow( - color: const Color(0xFFf5576c).withValues(alpha: 0.4), - blurRadius: 10, - spreadRadius: 1, - ), - ] - : isSuccess + border: + isFilled || isSuccess + ? null + : Border.all(color: outlineColor, width: 2), + boxShadow: + isFilled && !isSuccess ? [ - BoxShadow( - color: const Color(0xFF43A047).withValues(alpha: 0.4), - blurRadius: 10, - spreadRadius: 1, - ), - ] + BoxShadow( + color: const Color(0xFFf5576c).withValues(alpha: 0.4), + blurRadius: 10, + spreadRadius: 1, + ), + ] + : isSuccess + ? [ + BoxShadow( + color: const Color(0xFF43A047).withValues(alpha: 0.4), + blurRadius: 10, + spreadRadius: 1, + ), + ] : null, ), ); diff --git a/example/lib/screens/standalone_example.dart b/example/lib/screens/standalone_example.dart index b2ec87a..b06c160 100644 --- a/example/lib/screens/standalone_example.dart +++ b/example/lib/screens/standalone_example.dart @@ -67,9 +67,7 @@ class _StandaloneExampleState extends State { accentEnd.withValues(alpha: 0.04), ], ), - border: Border.all( - color: accent.withValues(alpha: 0.15), - ), + border: Border.all(color: accent.withValues(alpha: 0.15)), ), child: Row( children: [ @@ -105,8 +103,9 @@ class _StandaloneExampleState extends State { 'Using standard Flutter TextFields with VirtualKeypad(standalone: true)', style: TextStyle( fontSize: 11, - color: colorScheme.onSurface - .withValues(alpha: 0.55), + color: colorScheme.onSurface.withValues( + alpha: 0.55, + ), ), ), ], @@ -139,10 +138,7 @@ class _StandaloneExampleState extends State { ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(16), - borderSide: const BorderSide( - color: accent, - width: 2, - ), + borderSide: const BorderSide(color: accent, width: 2), ), filled: true, fillColor: colorScheme.surfaceContainerLowest, @@ -168,10 +164,7 @@ class _StandaloneExampleState extends State { ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(16), - borderSide: const BorderSide( - color: accent, - width: 2, - ), + borderSide: const BorderSide(color: accent, width: 2), ), filled: true, fillColor: colorScheme.surfaceContainerLowest, @@ -197,10 +190,7 @@ class _StandaloneExampleState extends State { ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(16), - borderSide: const BorderSide( - color: accent, - width: 2, - ), + borderSide: const BorderSide(color: accent, width: 2), ), filled: true, fillColor: colorScheme.surfaceContainerLowest, @@ -239,10 +229,7 @@ class _StandaloneExampleState extends State { ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(16), - borderSide: const BorderSide( - color: accent, - width: 2, - ), + borderSide: const BorderSide(color: accent, width: 2), ), filled: true, fillColor: colorScheme.surfaceContainerLowest, @@ -257,10 +244,7 @@ class _StandaloneExampleState extends State { ), ), ), - VirtualKeypad( - standalone: true, - hideWhenUnfocused: true, - ), + VirtualKeypad(standalone: true, hideWhenUnfocused: true), ], ), ); diff --git a/lib/src/layouts/keyboard_language.dart b/lib/src/layouts/keyboard_language.dart index 0035623..12b226c 100644 --- a/lib/src/layouts/keyboard_language.dart +++ b/lib/src/layouts/keyboard_language.dart @@ -14,8 +14,8 @@ class KeyboardLayoutSet { /// Creates a simple layout set with only a primary layout (e.g., number pad). const KeyboardLayoutSet.single(this.primary) - : secondary = null, - tertiary = null; + : secondary = null, + tertiary = null; /// The primary layout (usually letters or main input). final KeyboardLayout primary; diff --git a/lib/src/layouts/languages/bengali.dart b/lib/src/layouts/languages/bengali.dart index 5093e08..bfc2329 100644 --- a/lib/src/layouts/languages/bengali.dart +++ b/lib/src/layouts/languages/bengali.dart @@ -53,7 +53,11 @@ final KeyboardLayout _textLayoutPrimary = [ ], [ VirtualKey.action( - action: KeyAction.symbols, label: '১২৩', altLabel: 'কখগ', flex: 1), + action: KeyAction.symbols, + label: '১২৩', + altLabel: 'কখগ', + flex: 1, + ), VirtualKey.character(text: 'স'), VirtualKey.character(text: 'হ'), VirtualKey.character(text: '্'), @@ -92,7 +96,11 @@ final KeyboardLayout _textLayoutSecondary = [ ], [ VirtualKey.action( - action: KeyAction.symbolsAlt, label: '#+=', altLabel: '১২৩', flex: 1), + action: KeyAction.symbolsAlt, + label: '#+=', + altLabel: '১২৩', + flex: 1, + ), VirtualKey.character(text: '-'), VirtualKey.character(text: '/'), VirtualKey.character(text: ':'), @@ -104,7 +112,11 @@ final KeyboardLayout _textLayoutSecondary = [ ], [ VirtualKey.action( - action: KeyAction.symbols, label: '১২৩', altLabel: 'কখগ', flex: 1), + action: KeyAction.symbols, + label: '১২৩', + altLabel: 'কখগ', + flex: 1, + ), VirtualKey.character(text: ','), VirtualKey.character(text: '্'), VirtualKey.action(action: KeyAction.space, flex: 3), @@ -142,7 +154,11 @@ final KeyboardLayout _textLayoutTertiary = [ ], [ VirtualKey.action( - action: KeyAction.symbolsAlt, label: '#+=', altLabel: '১২৩', flex: 1), + action: KeyAction.symbolsAlt, + label: '#+=', + altLabel: '১২৩', + flex: 1, + ), VirtualKey.character(text: '.'), VirtualKey.character(text: ','), VirtualKey.character(text: '?'), @@ -154,7 +170,11 @@ final KeyboardLayout _textLayoutTertiary = [ ], [ VirtualKey.action( - action: KeyAction.symbols, label: '১২৩', altLabel: 'কখগ', flex: 2), + action: KeyAction.symbols, + label: '১২৩', + altLabel: 'কখগ', + flex: 2, + ), VirtualKey.character(text: ','), VirtualKey.action(action: KeyAction.space, flex: 4), VirtualKey.character(text: '।'), diff --git a/lib/src/models.dart b/lib/src/models.dart index 3bf525d..12c8555 100644 --- a/lib/src/models.dart +++ b/lib/src/models.dart @@ -10,15 +10,12 @@ class VirtualKey { /// - [text]: The character to insert (and display in lowercase mode). /// - [capsText]: Optional uppercase variant. Defaults to [text.toUpperCase()]. /// - [flex]: Relative width of the key. Default is 1. - VirtualKey.character({ - required this.text, - String? capsText, - this.flex = 1, - }) : capsText = capsText ?? text?.toUpperCase(), - keyType = KeyType.character, - action = null, - label = null, - altLabel = null; + VirtualKey.character({required this.text, String? capsText, this.flex = 1}) + : capsText = capsText ?? text?.toUpperCase(), + keyType = KeyType.character, + action = null, + label = null, + altLabel = null; /// Creates an action key that performs a keyboard function. /// @@ -33,8 +30,8 @@ class VirtualKey { this.label, this.altLabel, this.flex = 1, - }) : capsText = null, - keyType = KeyType.action; + }) : capsText = null, + keyType = KeyType.action; /// The primary text character for this key. final String? text; diff --git a/lib/src/scope.dart b/lib/src/scope.dart index b7a67a3..309000a 100644 --- a/lib/src/scope.dart +++ b/lib/src/scope.dart @@ -21,10 +21,7 @@ import 'enums.dart'; /// ``` class VirtualKeypadScope extends StatefulWidget { /// Creates a scope for managing keyboard-textfield connections. - const VirtualKeypadScope({ - super.key, - required this.child, - }); + const VirtualKeypadScope({super.key, required this.child}); /// The child widget tree containing text fields and keyboard. final Widget child; @@ -120,7 +117,8 @@ class VirtualKeypadScopeState extends State { TextInputAction inputAction = TextInputAction.done, bool allowPhysicalKeyboard = false, }) { - final changed = _activeController != controller || + final changed = + _activeController != controller || _activeKeyboardType != keyboardType || _activeInputAction != inputAction || _allowPhysicalKeyboard != allowPhysicalKeyboard; @@ -193,10 +191,7 @@ class VirtualKeypadScopeState extends State { @override Widget build(BuildContext context) { - return _VirtualKeypadScopeInherited( - state: this, - child: widget.child, - ); + return _VirtualKeypadScopeInherited(state: this, child: widget.child); } } diff --git a/lib/src/standalone_scope.dart b/lib/src/standalone_scope.dart index b2fa253..7ced132 100644 --- a/lib/src/standalone_scope.dart +++ b/lib/src/standalone_scope.dart @@ -23,10 +23,7 @@ import 'package:flutter/widgets.dart'; /// focused text field in the application. class VirtualKeypadStandaloneScope extends StatefulWidget { /// Creates a standalone scope for [VirtualKeypad]. - const VirtualKeypadStandaloneScope({ - super.key, - required this.child, - }); + const VirtualKeypadStandaloneScope({super.key, required this.child}); /// The child widget tree containing text fields and the keyboard. final Widget child; diff --git a/lib/src/theme.dart b/lib/src/theme.dart index 6344d73..eee19d8 100644 --- a/lib/src/theme.dart +++ b/lib/src/theme.dart @@ -62,35 +62,37 @@ class VirtualKeypadTheme { /// Decoration for character keys. BoxDecoration get keyDecoration => BoxDecoration( - color: keyColor, - borderRadius: BorderRadius.circular(keyBorderRadius), - boxShadow: keyShadow + color: keyColor, + borderRadius: BorderRadius.circular(keyBorderRadius), + boxShadow: + keyShadow ? [ - BoxShadow( - color: Colors.black.withValues(alpha: 0.15), - blurRadius: 1, - spreadRadius: 0.5, - offset: const Offset(0, 1), - ), - ] + BoxShadow( + color: Colors.black.withValues(alpha: 0.15), + blurRadius: 1, + spreadRadius: 0.5, + offset: const Offset(0, 1), + ), + ] : null, - ); + ); /// Decoration for action keys. BoxDecoration get actionKeyDecoration => BoxDecoration( - color: actionKeyColor, - borderRadius: BorderRadius.circular(keyBorderRadius), - boxShadow: keyShadow + color: actionKeyColor, + borderRadius: BorderRadius.circular(keyBorderRadius), + boxShadow: + keyShadow ? [ - BoxShadow( - color: Colors.black.withValues(alpha: 0.15), - blurRadius: 1, - spreadRadius: 0.5, - offset: const Offset(0, 1), - ), - ] + BoxShadow( + color: Colors.black.withValues(alpha: 0.15), + blurRadius: 1, + spreadRadius: 0.5, + offset: const Offset(0, 1), + ), + ] : null, - ); + ); /// Creates a copy of this theme with the given fields replaced. VirtualKeypadTheme copyWith({ diff --git a/lib/src/widgets/keyboard.dart b/lib/src/widgets/keyboard.dart index 337d435..86fe231 100644 --- a/lib/src/widgets/keyboard.dart +++ b/lib/src/widgets/keyboard.dart @@ -187,9 +187,10 @@ class _VirtualKeypadState extends State { final myScope = VirtualKeypadStandaloneScope.maybeOf(context); if (myScope != null) { final focusedContext = FocusManager.instance.primaryFocus?.context; - final focusedScope = focusedContext != null - ? VirtualKeypadStandaloneScope.maybeOf(focusedContext) - : null; + final focusedScope = + focusedContext != null + ? VirtualKeypadStandaloneScope.maybeOf(focusedContext) + : null; if (focusedScope != myScope) { // The focused field is outside our scope – hide the keyboard. if (_standaloneVisible) setState(() => _standaloneVisible = false); @@ -497,11 +498,12 @@ class _VirtualKeypadState extends State { } // Use cached layout during close animation, or current layout when visible - final layout = shouldShowKeyboard - ? _currentLayout - : (_wasVisible && _cachedLayout != null - ? _cachedLayout! - : _currentLayout); + final layout = + shouldShowKeyboard + ? _currentLayout + : (_wasVisible && _cachedLayout != null + ? _cachedLayout! + : _currentLayout); // Reset cache after animation would complete if (!shouldShowKeyboard && _wasVisible && !widget.hideWhenUnfocused) { @@ -534,28 +536,32 @@ class _VirtualKeypadState extends State { ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: layout.map((row) { - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: row.map((key) { - return _KeyWidget( - key: ValueKey('${key.text ?? key.action}'), - virtualKey: key, - type: _effectiveKeyboardType, - height: keyHeight, - baseWidth: baseKeyWidth, - theme: widget.theme, - shift: _shift, - capsLock: _capsLock, - layoutStage: _layoutStage, - inputAction: _effectiveInputAction, - languageCode: - KeyboardLayoutProvider.instance.currentLanguageCode, - onPressed: _onKeyPressed, + children: + layout.map((row) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: + row.map((key) { + return _KeyWidget( + key: ValueKey('${key.text ?? key.action}'), + virtualKey: key, + type: _effectiveKeyboardType, + height: keyHeight, + baseWidth: baseKeyWidth, + theme: widget.theme, + shift: _shift, + capsLock: _capsLock, + layoutStage: _layoutStage, + inputAction: _effectiveInputAction, + languageCode: + KeyboardLayoutProvider + .instance + .currentLanguageCode, + onPressed: _onKeyPressed, + ); + }).toList(), ); }).toList(), - ); - }).toList(), ), ), ), @@ -646,32 +652,31 @@ class _KeyWidgetState extends State<_KeyWidget> { _removePopup(); - final keyWidth = widget.baseWidth * widget.virtualKey.flex + + final keyWidth = + widget.baseWidth * widget.virtualKey.flex + (widget.virtualKey.flex - 1) * widget.theme.horizontalGap; final popupWidth = keyWidth + 14; final popupHeight = widget.height + 12; const gap = 6.0; _popupEntry = OverlayEntry( - builder: (context) => UnconstrainedBox( - child: CompositedTransformFollower( - link: _layerLink, - showWhenUnlinked: false, - offset: Offset( - -(popupWidth - keyWidth) / 2, - -popupHeight - gap, - ), - child: _KeyPreviewBubble( - text: widget.virtualKey.getDisplayText( - shift: widget.shift, - capsLock: widget.capsLock, + builder: + (context) => UnconstrainedBox( + child: CompositedTransformFollower( + link: _layerLink, + showWhenUnlinked: false, + offset: Offset(-(popupWidth - keyWidth) / 2, -popupHeight - gap), + child: _KeyPreviewBubble( + text: widget.virtualKey.getDisplayText( + shift: widget.shift, + capsLock: widget.capsLock, + ), + width: popupWidth, + height: popupHeight, + theme: widget.theme, + ), ), - width: popupWidth, - height: popupHeight, - theme: widget.theme, ), - ), - ), ); Overlay.of(context).insert(_popupEntry!); @@ -690,11 +695,13 @@ class _KeyWidgetState extends State<_KeyWidget> { Widget build(BuildContext context) { final key = widget.virtualKey; final isAction = key.isAction; - final decoration = isAction - ? widget.theme.actionKeyDecoration - : widget.theme.keyDecoration; + final decoration = + isAction + ? widget.theme.actionKeyDecoration + : widget.theme.keyDecoration; - final width = widget.baseWidth * key.flex + + final width = + widget.baseWidth * key.flex + (key.flex - 1) * widget.theme.horizontalGap; return CompositedTransformTarget( @@ -720,9 +727,7 @@ class _KeyWidgetState extends State<_KeyWidget> { _showKeyPreview(); widget.onPressed(key); }, - child: Center( - child: _buildKeyContent(), - ), + child: Center(child: _buildKeyContent()), ), ), ), @@ -735,9 +740,10 @@ class _KeyWidgetState extends State<_KeyWidget> { if (key.action == KeyAction.shift && (widget.shift || widget.capsLock)) { return base.copyWith( - color: widget.capsLock - ? widget.theme.keyTextColor.withValues(alpha: 0.3) - : widget.theme.keyColor, + color: + widget.capsLock + ? widget.theme.keyTextColor.withValues(alpha: 0.3) + : widget.theme.keyColor, ); } diff --git a/lib/src/widgets/text_field.dart b/lib/src/widgets/text_field.dart index 2ca3c98..183009c 100644 --- a/lib/src/widgets/text_field.dart +++ b/lib/src/widgets/text_field.dart @@ -257,8 +257,9 @@ class _VirtualKeypadTextFieldState extends State { if (element.widget is EditableText) { final editableTextState = (element as StatefulElement).state as EditableTextState; - editableTextState - .bringIntoView(TextPosition(offset: selection.baseOffset)); + editableTextState.bringIntoView( + TextPosition(offset: selection.baseOffset), + ); return; } element.visitChildren(visitChildren); @@ -270,7 +271,8 @@ class _VirtualKeypadTextFieldState extends State { void _registerWithScope() { if (_scope != null && widget.enabled && !widget.readOnly) { - final inputAction = widget.textInputAction ?? + final inputAction = + widget.textInputAction ?? (widget.maxLines != 1 ? TextInputAction.newline : TextInputAction.done); @@ -324,50 +326,60 @@ class _VirtualKeypadTextFieldState extends State { } Widget _buildContextMenu( - BuildContext context, EditableTextState editableTextState) { + BuildContext context, + EditableTextState editableTextState, + ) { final List buttonItems = []; if (!editableTextState.textEditingValue.selection.isCollapsed) { - buttonItems.add(ContextMenuButtonItem( - label: 'Cut', - onPressed: () { - final selection = widget.controller.selection; - if (selection.isValid && !selection.isCollapsed) { - final selectedText = widget.controller.text.substring( - selection.start, - selection.end, - ); - Clipboard.setData(ClipboardData(text: selectedText)); - widget.controller.deleteRange(selection.start, selection.end); - } - editableTextState.hideToolbar(); - }, - )); + buttonItems.add( + ContextMenuButtonItem( + label: 'Cut', + onPressed: () { + final selection = widget.controller.selection; + if (selection.isValid && !selection.isCollapsed) { + final selectedText = widget.controller.text.substring( + selection.start, + selection.end, + ); + Clipboard.setData(ClipboardData(text: selectedText)); + widget.controller.deleteRange(selection.start, selection.end); + } + editableTextState.hideToolbar(); + }, + ), + ); } if (!editableTextState.textEditingValue.selection.isCollapsed) { - buttonItems.add(ContextMenuButtonItem( - label: 'Copy', + buttonItems.add( + ContextMenuButtonItem( + label: 'Copy', + onPressed: () { + editableTextState.copySelection(SelectionChangedCause.toolbar); + }, + ), + ); + } + + buttonItems.add( + ContextMenuButtonItem( + label: 'Paste', onPressed: () { - editableTextState.copySelection(SelectionChangedCause.toolbar); + _handlePaste(); + editableTextState.hideToolbar(); }, - )); - } + ), + ); - buttonItems.add(ContextMenuButtonItem( - label: 'Paste', - onPressed: () { - _handlePaste(); - editableTextState.hideToolbar(); - }, - )); - - buttonItems.add(ContextMenuButtonItem( - label: 'Select All', - onPressed: () { - editableTextState.selectAll(SelectionChangedCause.toolbar); - }, - )); + buttonItems.add( + ContextMenuButtonItem( + label: 'Select All', + onPressed: () { + editableTextState.selectAll(SelectionChangedCause.toolbar); + }, + ), + ); return AdaptiveTextSelectionToolbar.buttonItems( anchors: editableTextState.contextMenuAnchors, @@ -423,12 +435,14 @@ class _VirtualKeypadTextFieldState extends State { maxLines: widget.maxLines, minLines: widget.minLines, maxLength: widget.maxLength, - maxLengthEnforcement: widget.maxLength != null - ? MaxLengthEnforcement.enforced - : MaxLengthEnforcement.none, - keyboardType: widget.allowPhysicalKeyboard - ? _toTextInputType(widget.keyboardType) - : TextInputType.none, + maxLengthEnforcement: + widget.maxLength != null + ? MaxLengthEnforcement.enforced + : MaxLengthEnforcement.none, + keyboardType: + widget.allowPhysicalKeyboard + ? _toTextInputType(widget.keyboardType) + : TextInputType.none, enableInteractiveSelection: true, onTap: _handleTap, onSubmitted: widget.onSubmitted, diff --git a/test/virtual_keypad_test.dart b/test/virtual_keypad_test.dart index a5cc7f1..3e15dc7 100644 --- a/test/virtual_keypad_test.dart +++ b/test/virtual_keypad_test.dart @@ -47,8 +47,10 @@ void main() { test('insertText replaces selection', () { final controller = VirtualKeypadController(text: 'Hello World'); // Select "World" - controller.selection = - const TextSelection(baseOffset: 6, extentOffset: 11); + controller.selection = const TextSelection( + baseOffset: 6, + extentOffset: 11, + ); controller.insertText('Flutter'); expect(controller.text, 'Hello Flutter'); expect(controller.cursorPosition, 13); @@ -57,8 +59,10 @@ void main() { test('deleteBackward removes selection', () { final controller = VirtualKeypadController(text: 'Hello World'); // Select "World" - controller.selection = - const TextSelection(baseOffset: 6, extentOffset: 11); + controller.selection = const TextSelection( + baseOffset: 6, + extentOffset: 11, + ); controller.deleteBackward(); expect(controller.text, 'Hello '); expect(controller.cursorPosition, 6); @@ -69,9 +73,11 @@ void main() { test('insertText modifies current value', () { final control = StandaloneInputControl(); // Simulate attach with initial empty value - control.setEditingState(TextEditingValue.empty.copyWith( - selection: const TextSelection.collapsed(offset: 0), - )); + control.setEditingState( + TextEditingValue.empty.copyWith( + selection: const TextSelection.collapsed(offset: 0), + ), + ); control.insertText('Hi'); expect(control.currentValue.text, 'Hi'); expect(control.currentValue.selection.baseOffset, 2); @@ -79,10 +85,12 @@ void main() { test('deleteBackward removes character', () { final control = StandaloneInputControl(); - control.setEditingState(const TextEditingValue( - text: 'Hello', - selection: TextSelection.collapsed(offset: 5), - )); + control.setEditingState( + const TextEditingValue( + text: 'Hello', + selection: TextSelection.collapsed(offset: 5), + ), + ); control.deleteBackward(); expect(control.currentValue.text, 'Hell'); expect(control.currentValue.selection.baseOffset, 4); @@ -90,10 +98,12 @@ void main() { test('deleteBackward removes selection', () { final control = StandaloneInputControl(); - control.setEditingState(const TextEditingValue( - text: 'Hello World', - selection: TextSelection(baseOffset: 5, extentOffset: 11), - )); + control.setEditingState( + const TextEditingValue( + text: 'Hello World', + selection: TextSelection(baseOffset: 5, extentOffset: 11), + ), + ); control.deleteBackward(); expect(control.currentValue.text, 'Hello'); expect(control.currentValue.selection.baseOffset, 5); @@ -101,10 +111,12 @@ void main() { test('insertText replaces selection', () { final control = StandaloneInputControl(); - control.setEditingState(const TextEditingValue( - text: 'Hello World', - selection: TextSelection(baseOffset: 6, extentOffset: 11), - )); + control.setEditingState( + const TextEditingValue( + text: 'Hello World', + selection: TextSelection(baseOffset: 6, extentOffset: 11), + ), + ); control.insertText('Flutter'); expect(control.currentValue.text, 'Hello Flutter'); expect(control.currentValue.selection.baseOffset, 13); @@ -149,10 +161,7 @@ void main() { ), ), ); - expect( - VirtualKeypadStandaloneScope.maybeOf(capturedContext), - isNull, - ); + expect(VirtualKeypadStandaloneScope.maybeOf(capturedContext), isNull); }); testWidgets('maybeOf returns state when scope is ancestor', (tester) async { @@ -175,8 +184,9 @@ void main() { ); }); - testWidgets('two sibling scopes return different state instances', - (tester) async { + testWidgets('two sibling scopes return different state instances', ( + tester, + ) async { late BuildContext contextA; late BuildContext contextB; await tester.pumpWidget( @@ -184,16 +194,20 @@ void main() { home: Column( children: [ VirtualKeypadStandaloneScope( - child: Builder(builder: (ctx) { - contextA = ctx; - return const SizedBox.shrink(); - }), + child: Builder( + builder: (ctx) { + contextA = ctx; + return const SizedBox.shrink(); + }, + ), ), VirtualKeypadStandaloneScope( - child: Builder(builder: (ctx) { - contextB = ctx; - return const SizedBox.shrink(); - }), + child: Builder( + builder: (ctx) { + contextB = ctx; + return const SizedBox.shrink(); + }, + ), ), ], ), From cb8afa6f1407967081a1802e99fbce0882e8255b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 11:36:19 +0000 Subject: [PATCH 6/8] fix: reformat all files with Dart SDK 3.11.1 (latest stable) Co-authored-by: Masum-MSNR <70331283+Masum-MSNR@users.noreply.github.com> --- example/lib/main.dart | 13 +- .../screens/auto_hide_keyboard_example.dart | 69 ++++---- example/lib/screens/custom_theme_example.dart | 73 ++++---- example/lib/screens/email_url_example.dart | 14 +- .../screens/language_switching_example.dart | 103 +++++------ example/lib/screens/multi_field_example.dart | 164 ++++++++---------- .../lib/screens/numeric_input_example.dart | 49 +++--- .../lib/screens/password_entry_example.dart | 9 +- example/lib/screens/pin_pad_example.dart | 101 ++++++----- lib/src/theme.dart | 42 +++-- lib/src/widgets/keyboard.dart | 109 ++++++------ lib/src/widgets/text_field.dart | 14 +- 12 files changed, 355 insertions(+), 405 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 0413554..ffec06d 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -177,12 +177,13 @@ class HomePage extends StatelessWidget { return FadeTransition( opacity: CurvedAnimation(parent: animation, curve: Curves.easeOut), child: SlideTransition( - position: Tween( - begin: const Offset(0.04, 0), - end: Offset.zero, - ).animate( - CurvedAnimation(parent: animation, curve: Curves.easeOut), - ), + position: + Tween( + begin: const Offset(0.04, 0), + end: Offset.zero, + ).animate( + CurvedAnimation(parent: animation, curve: Curves.easeOut), + ), child: child, ), ); diff --git a/example/lib/screens/auto_hide_keyboard_example.dart b/example/lib/screens/auto_hide_keyboard_example.dart index a2fb43b..9b62c2d 100644 --- a/example/lib/screens/auto_hide_keyboard_example.dart +++ b/example/lib/screens/auto_hide_keyboard_example.dart @@ -74,10 +74,11 @@ class _AutoHideKeyboardExampleState extends State { borderRadius: BorderRadius.circular(14), boxShadow: [ BoxShadow( - color: (_isAnyFocused - ? const Color(0xFF30cfd0) - : colorScheme.shadow) - .withValues(alpha: 0.1), + color: + (_isAnyFocused + ? const Color(0xFF30cfd0) + : colorScheme.shadow) + .withValues(alpha: 0.1), blurRadius: 12, offset: const Offset(0, 3), ), @@ -98,11 +99,11 @@ class _AutoHideKeyboardExampleState extends State { decoration: BoxDecoration( border: Border( left: BorderSide( - color: - _isAnyFocused - ? const Color(0xFF30cfd0) - : colorScheme.outlineVariant - .withValues(alpha: 0.4), + color: _isAnyFocused + ? const Color(0xFF30cfd0) + : colorScheme.outlineVariant.withValues( + alpha: 0.4, + ), width: 4, ), ), @@ -115,24 +116,22 @@ class _AutoHideKeyboardExampleState extends State { height: 10, decoration: BoxDecoration( shape: BoxShape.circle, - color: - _isAnyFocused - ? const Color(0xFF30cfd0) - : colorScheme.outline.withValues( - alpha: 0.35, + color: _isAnyFocused + ? const Color(0xFF30cfd0) + : colorScheme.outline.withValues( + alpha: 0.35, + ), + boxShadow: _isAnyFocused + ? [ + BoxShadow( + color: const Color( + 0xFF30cfd0, + ).withValues(alpha: 0.5), + blurRadius: 8, + spreadRadius: 1, ), - boxShadow: - _isAnyFocused - ? [ - BoxShadow( - color: const Color( - 0xFF30cfd0, - ).withValues(alpha: 0.5), - blurRadius: 8, - spreadRadius: 1, - ), - ] - : [], + ] + : [], ), ), const SizedBox(width: 12), @@ -148,10 +147,9 @@ class _AutoHideKeyboardExampleState extends State { style: TextStyle( fontSize: 14, fontWeight: FontWeight.w700, - color: - _isAnyFocused - ? const Color(0xFF30cfd0) - : colorScheme.onSurface, + color: _isAnyFocused + ? const Color(0xFF30cfd0) + : colorScheme.onSurface, ), ), const SizedBox(height: 2), @@ -175,12 +173,11 @@ class _AutoHideKeyboardExampleState extends State { ? Icons.keyboard_rounded : Icons.keyboard_hide_rounded, key: ValueKey(_isAnyFocused), - color: - _isAnyFocused - ? const Color(0xFF30cfd0) - : colorScheme.outline.withValues( - alpha: 0.35, - ), + color: _isAnyFocused + ? const Color(0xFF30cfd0) + : colorScheme.outline.withValues( + alpha: 0.35, + ), size: 22, ), ), diff --git a/example/lib/screens/custom_theme_example.dart b/example/lib/screens/custom_theme_example.dart index 93b3858..2531bd1 100644 --- a/example/lib/screens/custom_theme_example.dart +++ b/example/lib/screens/custom_theme_example.dart @@ -118,15 +118,14 @@ class _CustomThemeExampleState extends State { child: ListView.separated( scrollDirection: Axis.horizontal, itemCount: _themes.length, - separatorBuilder: - (_, _) => const SizedBox(width: 10), + separatorBuilder: (_, _) => + const SizedBox(width: 10), itemBuilder: (context, index) { final theme = _themes[index]; final isSelected = index == _selectedTheme; return GestureDetector( - onTap: - () => - setState(() => _selectedTheme = index), + onTap: () => + setState(() => _selectedTheme = index), child: AnimatedContainer( duration: const Duration(milliseconds: 250), padding: const EdgeInsets.symmetric( @@ -134,38 +133,31 @@ class _CustomThemeExampleState extends State { vertical: 10, ), decoration: BoxDecoration( - color: - isSelected - ? theme.accent.withValues( - alpha: 0.2, - ) - : current.appBarBg.withValues( - alpha: 0.6, - ), + color: isSelected + ? theme.accent.withValues(alpha: 0.2) + : current.appBarBg.withValues( + alpha: 0.6, + ), borderRadius: BorderRadius.circular(26), border: Border.all( - color: - isSelected - ? theme.accent.withValues( - alpha: 0.6, - ) - : current.textColor.withValues( - alpha: 0.08, - ), + color: isSelected + ? theme.accent.withValues(alpha: 0.6) + : current.textColor.withValues( + alpha: 0.08, + ), width: isSelected ? 2 : 1, ), - boxShadow: - isSelected - ? [ - BoxShadow( - color: theme.accent.withValues( - alpha: 0.25, - ), - blurRadius: 12, - offset: const Offset(0, 3), + boxShadow: isSelected + ? [ + BoxShadow( + color: theme.accent.withValues( + alpha: 0.25, ), - ] - : [], + blurRadius: 12, + offset: const Offset(0, 3), + ), + ] + : [], ), child: Row( mainAxisSize: MainAxisSize.min, @@ -179,15 +171,14 @@ class _CustomThemeExampleState extends State { theme.name, style: TextStyle( fontSize: 14, - fontWeight: - isSelected - ? FontWeight.w700 - : FontWeight.w400, - color: - isSelected - ? theme.accent - : current.textColor - .withValues(alpha: 0.55), + fontWeight: isSelected + ? FontWeight.w700 + : FontWeight.w400, + color: isSelected + ? theme.accent + : current.textColor.withValues( + alpha: 0.55, + ), ), ), ], diff --git a/example/lib/screens/email_url_example.dart b/example/lib/screens/email_url_example.dart index 596ce64..ec80aae 100644 --- a/example/lib/screens/email_url_example.dart +++ b/example/lib/screens/email_url_example.dart @@ -98,10 +98,9 @@ class _EmailUrlExampleState extends State { ), ), prefixIcon: const Icon(Icons.email_outlined), - suffixIcon: - _isValidEmail(_emailController.text) - ? const _AnimatedCheckmark() - : null, + suffixIcon: _isValidEmail(_emailController.text) + ? const _AnimatedCheckmark() + : null, filled: true, fillColor: colorScheme.surfaceContainerLowest, ), @@ -194,10 +193,9 @@ class _EmailUrlExampleState extends State { ), ), prefixIcon: const Icon(Icons.language_rounded), - suffixIcon: - _isValidUrl(_urlController.text) - ? const _AnimatedCheckmark() - : null, + suffixIcon: _isValidUrl(_urlController.text) + ? const _AnimatedCheckmark() + : null, filled: true, fillColor: colorScheme.surfaceContainerLowest, ), diff --git a/example/lib/screens/language_switching_example.dart b/example/lib/screens/language_switching_example.dart index ee79b49..fdd2064 100644 --- a/example/lib/screens/language_switching_example.dart +++ b/example/lib/screens/language_switching_example.dart @@ -90,24 +90,23 @@ class _LanguageSwitchingExampleState extends State { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Row( - children: - _languages.map((lang) { - final (code, label, flag, subtitle, colors) = lang; - final isFirst = code == _languages.first.$1; - return Expanded( - child: Padding( - padding: EdgeInsets.only(left: isFirst ? 0 : 8), - child: _LanguageCard( - label: label, - flag: flag, - subtitle: subtitle, - isSelected: _currentLanguage == code, - gradientColors: colors, - onTap: () => _switchLanguage(code), - ), - ), - ); - }).toList(), + children: _languages.map((lang) { + final (code, label, flag, subtitle, colors) = lang; + final isFirst = code == _languages.first.$1; + return Expanded( + child: Padding( + padding: EdgeInsets.only(left: isFirst ? 0 : 8), + child: _LanguageCard( + label: label, + flag: flag, + subtitle: subtitle, + isSelected: _currentLanguage == code, + gradientColors: colors, + onTap: () => _switchLanguage(code), + ), + ), + ); + }).toList(), ), const SizedBox(height: 18), @@ -284,38 +283,34 @@ class _LanguageCard extends StatelessWidget { padding: const EdgeInsets.symmetric(vertical: 14), decoration: BoxDecoration( borderRadius: BorderRadius.circular(16), - gradient: - isSelected - ? LinearGradient( - colors: [ - gradientColors.first.withValues(alpha: 0.15), - gradientColors.last.withValues(alpha: 0.08), - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ) - : null, - color: - isSelected - ? null - : colorScheme.surfaceContainerHigh.withValues(alpha: 0.4), + gradient: isSelected + ? LinearGradient( + colors: [ + gradientColors.first.withValues(alpha: 0.15), + gradientColors.last.withValues(alpha: 0.08), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ) + : null, + color: isSelected + ? null + : colorScheme.surfaceContainerHigh.withValues(alpha: 0.4), border: Border.all( - color: - isSelected - ? gradientColors.first.withValues(alpha: 0.5) - : colorScheme.outlineVariant.withValues(alpha: 0.2), + color: isSelected + ? gradientColors.first.withValues(alpha: 0.5) + : colorScheme.outlineVariant.withValues(alpha: 0.2), width: isSelected ? 2 : 1, ), - boxShadow: - isSelected - ? [ - BoxShadow( - color: gradientColors.first.withValues(alpha: 0.15), - blurRadius: 12, - offset: const Offset(0, 4), - ), - ] - : [], + boxShadow: isSelected + ? [ + BoxShadow( + color: gradientColors.first.withValues(alpha: 0.15), + blurRadius: 12, + offset: const Offset(0, 4), + ), + ] + : [], ), child: Column( mainAxisSize: MainAxisSize.min, @@ -327,10 +322,9 @@ class _LanguageCard extends StatelessWidget { style: TextStyle( fontWeight: isSelected ? FontWeight.w700 : FontWeight.w500, fontSize: 15, - color: - isSelected - ? colorScheme.onSurface - : colorScheme.onSurface.withValues(alpha: 0.6), + color: isSelected + ? colorScheme.onSurface + : colorScheme.onSurface.withValues(alpha: 0.6), ), ), const SizedBox(height: 2), @@ -339,10 +333,9 @@ class _LanguageCard extends StatelessWidget { style: TextStyle( fontSize: 11, fontWeight: FontWeight.w500, - color: - isSelected - ? gradientColors.first.withValues(alpha: 0.8) - : colorScheme.onSurface.withValues(alpha: 0.35), + color: isSelected + ? gradientColors.first.withValues(alpha: 0.8) + : colorScheme.onSurface.withValues(alpha: 0.35), ), ), ], diff --git a/example/lib/screens/multi_field_example.dart b/example/lib/screens/multi_field_example.dart index b4494b5..4d81e4a 100644 --- a/example/lib/screens/multi_field_example.dart +++ b/example/lib/screens/multi_field_example.dart @@ -92,13 +92,11 @@ class _MultiFieldExampleState extends State { const SizedBox(height: 4), Text( 'Fill in your details to get started', - style: Theme.of( - context, - ).textTheme.bodyMedium?.copyWith( - color: Theme.of( - context, - ).colorScheme.onSurface.withValues(alpha: 0.55), - ), + style: Theme.of(context).textTheme.bodyMedium + ?.copyWith( + color: Theme.of(context).colorScheme.onSurface + .withValues(alpha: 0.55), + ), ), const SizedBox(height: 28), @@ -255,12 +253,11 @@ class _ProgressDots extends StatelessWidget { height: 3, decoration: BoxDecoration( borderRadius: BorderRadius.circular(2), - color: - i < filled - 1 - ? _kGreenComplete - : (i < filled - ? _kGradientStart.withValues(alpha: 0.5) - : muted), + color: i < filled - 1 + ? _kGreenComplete + : (i < filled + ? _kGradientStart.withValues(alpha: 0.5) + : muted), ), ), ], @@ -288,23 +285,21 @@ class _Dot extends StatelessWidget { shape: BoxShape.circle, color: active ? _kGreenComplete : Colors.transparent, border: active ? null : Border.all(color: muted, width: 2), - boxShadow: - active - ? [ - BoxShadow( - color: _kGreenComplete.withValues(alpha: 0.35), - blurRadius: 8, - spreadRadius: 1, - ), - ] - : null, + boxShadow: active + ? [ + BoxShadow( + color: _kGreenComplete.withValues(alpha: 0.35), + blurRadius: 8, + spreadRadius: 1, + ), + ] + : null, ), - child: - active - ? const Center( - child: Icon(Icons.check, size: 11, color: Colors.white), - ) - : null, + child: active + ? const Center( + child: Icon(Icons.check, size: 11, color: Colors.white), + ) + : null, ); } } @@ -356,51 +351,47 @@ class _StepItem extends StatelessWidget { height: 28, decoration: BoxDecoration( shape: BoxShape.circle, - color: - done - ? _kGreenComplete - : colorScheme.surfaceContainerHigh, - border: - done - ? null - : Border.all( - color: colorScheme.outlineVariant.withValues( - alpha: 0.6, - ), + color: done + ? _kGreenComplete + : colorScheme.surfaceContainerHigh, + border: done + ? null + : Border.all( + color: colorScheme.outlineVariant.withValues( + alpha: 0.6, ), - boxShadow: - done - ? [ - BoxShadow( - color: _kGreenComplete.withValues(alpha: 0.3), - blurRadius: 8, - spreadRadius: 1, - ), - ] - : null, + ), + boxShadow: done + ? [ + BoxShadow( + color: _kGreenComplete.withValues(alpha: 0.3), + blurRadius: 8, + spreadRadius: 1, + ), + ] + : null, ), child: Center( child: AnimatedSwitcher( duration: const Duration(milliseconds: 250), - child: - done - ? const Icon( - Icons.check, - key: ValueKey('check'), - size: 14, - color: Colors.white, - ) - : Text( - stepNumber, - key: ValueKey('num$stepNumber'), - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: colorScheme.onSurface.withValues( - alpha: 0.5, - ), + child: done + ? const Icon( + Icons.check, + key: ValueKey('check'), + size: 14, + color: Colors.white, + ) + : Text( + stepNumber, + key: ValueKey('num$stepNumber'), + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: colorScheme.onSurface.withValues( + alpha: 0.5, ), ), + ), ), ), ), @@ -411,12 +402,11 @@ class _StepItem extends StatelessWidget { padding: const EdgeInsets.symmetric(vertical: 4), child: CustomPaint( painter: _DottedLinePainter( - color: - done - ? _kGreenComplete.withValues(alpha: 0.5) - : colorScheme.outlineVariant.withValues( - alpha: 0.35, - ), + color: done + ? _kGreenComplete.withValues(alpha: 0.5) + : colorScheme.outlineVariant.withValues( + alpha: 0.35, + ), ), child: const SizedBox(width: 2), ), @@ -447,11 +437,10 @@ class _DottedLinePainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { - final paint = - Paint() - ..color = color - ..strokeWidth = 2 - ..strokeCap = StrokeCap.round; + final paint = Paint() + ..color = color + ..strokeWidth = 2 + ..strokeCap = StrokeCap.round; const dashHeight = 4.0; const gap = 4.0; @@ -495,16 +484,15 @@ class _GradientButton extends StatelessWidget { begin: Alignment.topLeft, end: Alignment.bottomRight, ), - boxShadow: - enabled - ? [ - BoxShadow( - color: _kGradientStart.withValues(alpha: 0.35), - blurRadius: 12, - offset: const Offset(0, 4), - ), - ] - : null, + boxShadow: enabled + ? [ + BoxShadow( + color: _kGradientStart.withValues(alpha: 0.35), + blurRadius: 12, + offset: const Offset(0, 4), + ), + ] + : null, ), child: MaterialButton( onPressed: enabled ? onPressed : null, diff --git a/example/lib/screens/numeric_input_example.dart b/example/lib/screens/numeric_input_example.dart index 4f56fcc..61bfc5a 100644 --- a/example/lib/screens/numeric_input_example.dart +++ b/example/lib/screens/numeric_input_example.dart @@ -133,8 +133,8 @@ class _NumericInputExampleState extends State { right: 4, ), child: ShaderMask( - shaderCallback: - (bounds) => const LinearGradient( + shaderCallback: (bounds) => + const LinearGradient( colors: [ Color(0xFF667eea), Color(0xFF764ba2), @@ -187,29 +187,28 @@ class _NumericInputExampleState extends State { spacing: 10, runSpacing: 10, alignment: WrapAlignment.center, - children: - _quickAmounts.map((amount) { - return ActionChip( - label: Text( - '\$$amount', - style: const TextStyle( - fontWeight: FontWeight.w600, - color: Colors.white, - fontSize: 13, - ), - ), - backgroundColor: const Color(0xFF667eea), - side: BorderSide.none, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(24), - ), - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 2, - ), - onPressed: () => _setAmount(amount), - ); - }).toList(), + children: _quickAmounts.map((amount) { + return ActionChip( + label: Text( + '\$$amount', + style: const TextStyle( + fontWeight: FontWeight.w600, + color: Colors.white, + fontSize: 13, + ), + ), + backgroundColor: const Color(0xFF667eea), + side: BorderSide.none, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(24), + ), + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 2, + ), + onPressed: () => _setAmount(amount), + ); + }).toList(), ), const SizedBox(height: 20), diff --git a/example/lib/screens/password_entry_example.dart b/example/lib/screens/password_entry_example.dart index c0ed88c..ade2dd9 100644 --- a/example/lib/screens/password_entry_example.dart +++ b/example/lib/screens/password_entry_example.dart @@ -204,11 +204,10 @@ class _PasswordEntryExampleState extends State { ), decoration: BoxDecoration( borderRadius: BorderRadius.circular(3), - color: - active - ? _strengthColor(strength) - : colorScheme.outlineVariant - .withValues(alpha: 0.3), + color: active + ? _strengthColor(strength) + : colorScheme.outlineVariant + .withValues(alpha: 0.3), ), ), ); diff --git a/example/lib/screens/pin_pad_example.dart b/example/lib/screens/pin_pad_example.dart index 425a810..335401a 100644 --- a/example/lib/screens/pin_pad_example.dart +++ b/example/lib/screens/pin_pad_example.dart @@ -170,23 +170,23 @@ class _PinPadExampleState extends State height: 80, decoration: BoxDecoration( shape: BoxShape.circle, - gradient: - _showSuccess - ? const LinearGradient( - colors: [ - Color(0xFF43A047), - Color(0xFF66BB6A), - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ) - : _gradient, + gradient: _showSuccess + ? const LinearGradient( + colors: [ + Color(0xFF43A047), + Color(0xFF66BB6A), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ) + : _gradient, boxShadow: [ BoxShadow( - color: (_showSuccess - ? const Color(0xFF43A047) - : const Color(0xFFf5576c)) - .withValues(alpha: 0.45), + color: + (_showSuccess + ? const Color(0xFF43A047) + : const Color(0xFFf5576c)) + .withValues(alpha: 0.45), blurRadius: 24, spreadRadius: 2, ), @@ -220,13 +220,13 @@ class _PinPadExampleState extends State child: Text( _showSuccess ? 'Unlocked!' : 'Enter PIN', key: ValueKey(_showSuccess), - style: Theme.of( - context, - ).textTheme.titleLarge?.copyWith( - fontWeight: FontWeight.w700, - color: - _showSuccess ? const Color(0xFF43A047) : null, - ), + style: Theme.of(context).textTheme.titleLarge + ?.copyWith( + fontWeight: FontWeight.w700, + color: _showSuccess + ? const Color(0xFF43A047) + : null, + ), ), ), const SizedBox(height: 4), @@ -364,36 +364,33 @@ class _PinDot extends StatelessWidget { height: isFilled ? 22 : 18, decoration: BoxDecoration( shape: BoxShape.circle, - gradient: - isSuccess - ? const LinearGradient( - colors: [Color(0xFF43A047), Color(0xFF66BB6A)], - ) - : isFilled - ? _dotGradient - : null, - border: - isFilled || isSuccess - ? null - : Border.all(color: outlineColor, width: 2), - boxShadow: - isFilled && !isSuccess - ? [ - BoxShadow( - color: const Color(0xFFf5576c).withValues(alpha: 0.4), - blurRadius: 10, - spreadRadius: 1, - ), - ] - : isSuccess - ? [ - BoxShadow( - color: const Color(0xFF43A047).withValues(alpha: 0.4), - blurRadius: 10, - spreadRadius: 1, - ), - ] - : null, + gradient: isSuccess + ? const LinearGradient( + colors: [Color(0xFF43A047), Color(0xFF66BB6A)], + ) + : isFilled + ? _dotGradient + : null, + border: isFilled || isSuccess + ? null + : Border.all(color: outlineColor, width: 2), + boxShadow: isFilled && !isSuccess + ? [ + BoxShadow( + color: const Color(0xFFf5576c).withValues(alpha: 0.4), + blurRadius: 10, + spreadRadius: 1, + ), + ] + : isSuccess + ? [ + BoxShadow( + color: const Color(0xFF43A047).withValues(alpha: 0.4), + blurRadius: 10, + spreadRadius: 1, + ), + ] + : null, ), ); } diff --git a/lib/src/theme.dart b/lib/src/theme.dart index eee19d8..06a9a41 100644 --- a/lib/src/theme.dart +++ b/lib/src/theme.dart @@ -64,34 +64,32 @@ class VirtualKeypadTheme { BoxDecoration get keyDecoration => BoxDecoration( color: keyColor, borderRadius: BorderRadius.circular(keyBorderRadius), - boxShadow: - keyShadow - ? [ - BoxShadow( - color: Colors.black.withValues(alpha: 0.15), - blurRadius: 1, - spreadRadius: 0.5, - offset: const Offset(0, 1), - ), - ] - : null, + boxShadow: keyShadow + ? [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.15), + blurRadius: 1, + spreadRadius: 0.5, + offset: const Offset(0, 1), + ), + ] + : null, ); /// Decoration for action keys. BoxDecoration get actionKeyDecoration => BoxDecoration( color: actionKeyColor, borderRadius: BorderRadius.circular(keyBorderRadius), - boxShadow: - keyShadow - ? [ - BoxShadow( - color: Colors.black.withValues(alpha: 0.15), - blurRadius: 1, - spreadRadius: 0.5, - offset: const Offset(0, 1), - ), - ] - : null, + boxShadow: keyShadow + ? [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.15), + blurRadius: 1, + spreadRadius: 0.5, + offset: const Offset(0, 1), + ), + ] + : null, ); /// Creates a copy of this theme with the given fields replaced. diff --git a/lib/src/widgets/keyboard.dart b/lib/src/widgets/keyboard.dart index 86fe231..9fe4a1f 100644 --- a/lib/src/widgets/keyboard.dart +++ b/lib/src/widgets/keyboard.dart @@ -187,10 +187,9 @@ class _VirtualKeypadState extends State { final myScope = VirtualKeypadStandaloneScope.maybeOf(context); if (myScope != null) { final focusedContext = FocusManager.instance.primaryFocus?.context; - final focusedScope = - focusedContext != null - ? VirtualKeypadStandaloneScope.maybeOf(focusedContext) - : null; + final focusedScope = focusedContext != null + ? VirtualKeypadStandaloneScope.maybeOf(focusedContext) + : null; if (focusedScope != myScope) { // The focused field is outside our scope – hide the keyboard. if (_standaloneVisible) setState(() => _standaloneVisible = false); @@ -498,12 +497,11 @@ class _VirtualKeypadState extends State { } // Use cached layout during close animation, or current layout when visible - final layout = - shouldShowKeyboard - ? _currentLayout - : (_wasVisible && _cachedLayout != null - ? _cachedLayout! - : _currentLayout); + final layout = shouldShowKeyboard + ? _currentLayout + : (_wasVisible && _cachedLayout != null + ? _cachedLayout! + : _currentLayout); // Reset cache after animation would complete if (!shouldShowKeyboard && _wasVisible && !widget.hideWhenUnfocused) { @@ -536,32 +534,28 @@ class _VirtualKeypadState extends State { ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: - layout.map((row) { - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: - row.map((key) { - return _KeyWidget( - key: ValueKey('${key.text ?? key.action}'), - virtualKey: key, - type: _effectiveKeyboardType, - height: keyHeight, - baseWidth: baseKeyWidth, - theme: widget.theme, - shift: _shift, - capsLock: _capsLock, - layoutStage: _layoutStage, - inputAction: _effectiveInputAction, - languageCode: - KeyboardLayoutProvider - .instance - .currentLanguageCode, - onPressed: _onKeyPressed, - ); - }).toList(), + children: layout.map((row) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: row.map((key) { + return _KeyWidget( + key: ValueKey('${key.text ?? key.action}'), + virtualKey: key, + type: _effectiveKeyboardType, + height: keyHeight, + baseWidth: baseKeyWidth, + theme: widget.theme, + shift: _shift, + capsLock: _capsLock, + layoutStage: _layoutStage, + inputAction: _effectiveInputAction, + languageCode: + KeyboardLayoutProvider.instance.currentLanguageCode, + onPressed: _onKeyPressed, ); }).toList(), + ); + }).toList(), ), ), ), @@ -660,23 +654,22 @@ class _KeyWidgetState extends State<_KeyWidget> { const gap = 6.0; _popupEntry = OverlayEntry( - builder: - (context) => UnconstrainedBox( - child: CompositedTransformFollower( - link: _layerLink, - showWhenUnlinked: false, - offset: Offset(-(popupWidth - keyWidth) / 2, -popupHeight - gap), - child: _KeyPreviewBubble( - text: widget.virtualKey.getDisplayText( - shift: widget.shift, - capsLock: widget.capsLock, - ), - width: popupWidth, - height: popupHeight, - theme: widget.theme, - ), + builder: (context) => UnconstrainedBox( + child: CompositedTransformFollower( + link: _layerLink, + showWhenUnlinked: false, + offset: Offset(-(popupWidth - keyWidth) / 2, -popupHeight - gap), + child: _KeyPreviewBubble( + text: widget.virtualKey.getDisplayText( + shift: widget.shift, + capsLock: widget.capsLock, ), + width: popupWidth, + height: popupHeight, + theme: widget.theme, ), + ), + ), ); Overlay.of(context).insert(_popupEntry!); @@ -695,10 +688,9 @@ class _KeyWidgetState extends State<_KeyWidget> { Widget build(BuildContext context) { final key = widget.virtualKey; final isAction = key.isAction; - final decoration = - isAction - ? widget.theme.actionKeyDecoration - : widget.theme.keyDecoration; + final decoration = isAction + ? widget.theme.actionKeyDecoration + : widget.theme.keyDecoration; final width = widget.baseWidth * key.flex + @@ -740,10 +732,9 @@ class _KeyWidgetState extends State<_KeyWidget> { if (key.action == KeyAction.shift && (widget.shift || widget.capsLock)) { return base.copyWith( - color: - widget.capsLock - ? widget.theme.keyTextColor.withValues(alpha: 0.3) - : widget.theme.keyColor, + color: widget.capsLock + ? widget.theme.keyTextColor.withValues(alpha: 0.3) + : widget.theme.keyColor, ); } @@ -792,8 +783,8 @@ class _KeyWidgetState extends State<_KeyWidget> { widget.capsLock ? Icons.keyboard_capslock : (widget.shift - ? Icons.arrow_upward - : Icons.arrow_upward_outlined), + ? Icons.arrow_upward + : Icons.arrow_upward_outlined), size: widget.theme.keyTextSize, color: widget.theme.keyTextColor, ); diff --git a/lib/src/widgets/text_field.dart b/lib/src/widgets/text_field.dart index 183009c..a9a9332 100644 --- a/lib/src/widgets/text_field.dart +++ b/lib/src/widgets/text_field.dart @@ -435,14 +435,12 @@ class _VirtualKeypadTextFieldState extends State { maxLines: widget.maxLines, minLines: widget.minLines, maxLength: widget.maxLength, - maxLengthEnforcement: - widget.maxLength != null - ? MaxLengthEnforcement.enforced - : MaxLengthEnforcement.none, - keyboardType: - widget.allowPhysicalKeyboard - ? _toTextInputType(widget.keyboardType) - : TextInputType.none, + maxLengthEnforcement: widget.maxLength != null + ? MaxLengthEnforcement.enforced + : MaxLengthEnforcement.none, + keyboardType: widget.allowPhysicalKeyboard + ? _toTextInputType(widget.keyboardType) + : TextInputType.none, enableInteractiveSelection: true, onTap: _handleTap, onSubmitted: widget.onSubmitted, From da8590ea9e29f8d93b35ec1e5700a791ee5769ab Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 11:48:07 +0000 Subject: [PATCH 7/8] chore: align formatting with CI (Dart 3.11, pkg config) Co-authored-by: Masum-MSNR <70331283+Masum-MSNR@users.noreply.github.com> --- example/lib/main.dart | 13 +++-- .../screens/auto_hide_keyboard_example.dart | 9 ++-- example/lib/screens/multi_field_example.dart | 24 +++++---- .../lib/screens/numeric_input_example.dart | 18 +++---- .../lib/screens/password_entry_example.dart | 10 ++-- example/lib/screens/pin_pad_example.dart | 43 ++++++++------- example/lib/screens/standalone_example.dart | 6 --- lib/src/layouts/keyboard_language.dart | 4 +- lib/src/models.dart | 14 ++--- lib/src/scope.dart | 3 +- lib/src/theme.dart | 52 +++++++++---------- lib/src/widgets/keyboard.dart | 14 +++-- lib/src/widgets/text_field.dart | 3 +- 13 files changed, 105 insertions(+), 108 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index ffec06d..0413554 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -177,13 +177,12 @@ class HomePage extends StatelessWidget { return FadeTransition( opacity: CurvedAnimation(parent: animation, curve: Curves.easeOut), child: SlideTransition( - position: - Tween( - begin: const Offset(0.04, 0), - end: Offset.zero, - ).animate( - CurvedAnimation(parent: animation, curve: Curves.easeOut), - ), + position: Tween( + begin: const Offset(0.04, 0), + end: Offset.zero, + ).animate( + CurvedAnimation(parent: animation, curve: Curves.easeOut), + ), child: child, ), ); diff --git a/example/lib/screens/auto_hide_keyboard_example.dart b/example/lib/screens/auto_hide_keyboard_example.dart index 9b62c2d..b15d6fd 100644 --- a/example/lib/screens/auto_hide_keyboard_example.dart +++ b/example/lib/screens/auto_hide_keyboard_example.dart @@ -74,11 +74,10 @@ class _AutoHideKeyboardExampleState extends State { borderRadius: BorderRadius.circular(14), boxShadow: [ BoxShadow( - color: - (_isAnyFocused - ? const Color(0xFF30cfd0) - : colorScheme.shadow) - .withValues(alpha: 0.1), + color: (_isAnyFocused + ? const Color(0xFF30cfd0) + : colorScheme.shadow) + .withValues(alpha: 0.1), blurRadius: 12, offset: const Offset(0, 3), ), diff --git a/example/lib/screens/multi_field_example.dart b/example/lib/screens/multi_field_example.dart index 4d81e4a..94fadd2 100644 --- a/example/lib/screens/multi_field_example.dart +++ b/example/lib/screens/multi_field_example.dart @@ -34,10 +34,10 @@ class _MultiFieldExampleState extends State { } List get _stepsDone => [ - _nameController.text.isNotEmpty, - _emailController.text.isNotEmpty, - _passwordController.text.isNotEmpty, - ]; + _nameController.text.isNotEmpty, + _emailController.text.isNotEmpty, + _passwordController.text.isNotEmpty, + ]; @override Widget build(BuildContext context) { @@ -86,15 +86,21 @@ class _MultiFieldExampleState extends State { // ── Header ── Text( 'Create Account', - style: Theme.of(context).textTheme.headlineSmall + style: Theme.of(context) + .textTheme + .headlineSmall ?.copyWith(fontWeight: FontWeight.w800), ), const SizedBox(height: 4), Text( 'Fill in your details to get started', - style: Theme.of(context).textTheme.bodyMedium + style: Theme.of(context) + .textTheme + .bodyMedium ?.copyWith( - color: Theme.of(context).colorScheme.onSurface + color: Theme.of(context) + .colorScheme + .onSurface .withValues(alpha: 0.55), ), ), @@ -256,8 +262,8 @@ class _ProgressDots extends StatelessWidget { color: i < filled - 1 ? _kGreenComplete : (i < filled - ? _kGradientStart.withValues(alpha: 0.5) - : muted), + ? _kGradientStart.withValues(alpha: 0.5) + : muted), ), ), ], diff --git a/example/lib/screens/numeric_input_example.dart b/example/lib/screens/numeric_input_example.dart index 61bfc5a..eacf54c 100644 --- a/example/lib/screens/numeric_input_example.dart +++ b/example/lib/screens/numeric_input_example.dart @@ -85,15 +85,15 @@ class _NumericInputExampleState extends State { Text( 'Enter Amount', style: Theme.of(context).textTheme.titleLarge?.copyWith( - fontWeight: FontWeight.w700, - ), + fontWeight: FontWeight.w700, + ), ), const SizedBox(height: 4), Text( 'How much would you like to send?', style: Theme.of(context).textTheme.bodyMedium?.copyWith( - color: colorScheme.onSurface.withValues(alpha: 0.5), - ), + color: colorScheme.onSurface.withValues(alpha: 0.5), + ), ), const SizedBox(height: 24), @@ -135,11 +135,11 @@ class _NumericInputExampleState extends State { child: ShaderMask( shaderCallback: (bounds) => const LinearGradient( - colors: [ - Color(0xFF667eea), - Color(0xFF764ba2), - ], - ).createShader(bounds), + colors: [ + Color(0xFF667eea), + Color(0xFF764ba2), + ], + ).createShader(bounds), child: const Text( '\$', style: TextStyle( diff --git a/example/lib/screens/password_entry_example.dart b/example/lib/screens/password_entry_example.dart index ade2dd9..708f1dc 100644 --- a/example/lib/screens/password_entry_example.dart +++ b/example/lib/screens/password_entry_example.dart @@ -116,13 +116,17 @@ class _PasswordEntryExampleState extends State { Text( 'Welcome Back', - style: Theme.of(context).textTheme.headlineSmall + style: Theme.of(context) + .textTheme + .headlineSmall ?.copyWith(fontWeight: FontWeight.w700), ), const SizedBox(height: 6), Text( 'Sign in to continue', - style: Theme.of(context).textTheme.bodyMedium + style: Theme.of(context) + .textTheme + .bodyMedium ?.copyWith(color: colorScheme.onSurfaceVariant), ), const SizedBox(height: 28), @@ -207,7 +211,7 @@ class _PasswordEntryExampleState extends State { color: active ? _strengthColor(strength) : colorScheme.outlineVariant - .withValues(alpha: 0.3), + .withValues(alpha: 0.3), ), ), ); diff --git a/example/lib/screens/pin_pad_example.dart b/example/lib/screens/pin_pad_example.dart index 335401a..e933e3b 100644 --- a/example/lib/screens/pin_pad_example.dart +++ b/example/lib/screens/pin_pad_example.dart @@ -182,11 +182,10 @@ class _PinPadExampleState extends State : _gradient, boxShadow: [ BoxShadow( - color: - (_showSuccess - ? const Color(0xFF43A047) - : const Color(0xFFf5576c)) - .withValues(alpha: 0.45), + color: (_showSuccess + ? const Color(0xFF43A047) + : const Color(0xFFf5576c)) + .withValues(alpha: 0.45), blurRadius: 24, spreadRadius: 2, ), @@ -220,13 +219,13 @@ class _PinPadExampleState extends State child: Text( _showSuccess ? 'Unlocked!' : 'Enter PIN', key: ValueKey(_showSuccess), - style: Theme.of(context).textTheme.titleLarge - ?.copyWith( - fontWeight: FontWeight.w700, - color: _showSuccess - ? const Color(0xFF43A047) - : null, - ), + style: + Theme.of(context).textTheme.titleLarge?.copyWith( + fontWeight: FontWeight.w700, + color: _showSuccess + ? const Color(0xFF43A047) + : null, + ), ), ), const SizedBox(height: 4), @@ -369,8 +368,8 @@ class _PinDot extends StatelessWidget { colors: [Color(0xFF43A047), Color(0xFF66BB6A)], ) : isFilled - ? _dotGradient - : null, + ? _dotGradient + : null, border: isFilled || isSuccess ? null : Border.all(color: outlineColor, width: 2), @@ -383,14 +382,14 @@ class _PinDot extends StatelessWidget { ), ] : isSuccess - ? [ - BoxShadow( - color: const Color(0xFF43A047).withValues(alpha: 0.4), - blurRadius: 10, - spreadRadius: 1, - ), - ] - : null, + ? [ + BoxShadow( + color: const Color(0xFF43A047).withValues(alpha: 0.4), + blurRadius: 10, + spreadRadius: 1, + ), + ] + : null, ), ); } diff --git a/example/lib/screens/standalone_example.dart b/example/lib/screens/standalone_example.dart index b06c160..74f3e53 100644 --- a/example/lib/screens/standalone_example.dart +++ b/example/lib/screens/standalone_example.dart @@ -115,7 +115,6 @@ class _StandaloneExampleState extends State { ), ), const SizedBox(height: 24), - _SectionLabel( icon: Icons.person_outline_rounded, label: 'Contact Info', @@ -123,7 +122,6 @@ class _StandaloneExampleState extends State { accent: accent, ), const SizedBox(height: 14), - TextField( controller: _nameController, keyboardType: TextInputType.name, @@ -149,7 +147,6 @@ class _StandaloneExampleState extends State { ), ), const SizedBox(height: 14), - TextField( controller: _emailController, keyboardType: TextInputType.emailAddress, @@ -175,7 +172,6 @@ class _StandaloneExampleState extends State { ), ), const SizedBox(height: 14), - TextField( controller: _phoneController, keyboardType: TextInputType.phone, @@ -201,7 +197,6 @@ class _StandaloneExampleState extends State { ), ), const SizedBox(height: 24), - _SectionLabel( icon: Icons.note_alt_outlined, label: 'Notes', @@ -209,7 +204,6 @@ class _StandaloneExampleState extends State { accent: accent, ), const SizedBox(height: 14), - TextField( controller: _notesController, keyboardType: TextInputType.multiline, diff --git a/lib/src/layouts/keyboard_language.dart b/lib/src/layouts/keyboard_language.dart index 12b226c..0035623 100644 --- a/lib/src/layouts/keyboard_language.dart +++ b/lib/src/layouts/keyboard_language.dart @@ -14,8 +14,8 @@ class KeyboardLayoutSet { /// Creates a simple layout set with only a primary layout (e.g., number pad). const KeyboardLayoutSet.single(this.primary) - : secondary = null, - tertiary = null; + : secondary = null, + tertiary = null; /// The primary layout (usually letters or main input). final KeyboardLayout primary; diff --git a/lib/src/models.dart b/lib/src/models.dart index 12c8555..2a28ea1 100644 --- a/lib/src/models.dart +++ b/lib/src/models.dart @@ -11,11 +11,11 @@ class VirtualKey { /// - [capsText]: Optional uppercase variant. Defaults to [text.toUpperCase()]. /// - [flex]: Relative width of the key. Default is 1. VirtualKey.character({required this.text, String? capsText, this.flex = 1}) - : capsText = capsText ?? text?.toUpperCase(), - keyType = KeyType.character, - action = null, - label = null, - altLabel = null; + : capsText = capsText ?? text?.toUpperCase(), + keyType = KeyType.character, + action = null, + label = null, + altLabel = null; /// Creates an action key that performs a keyboard function. /// @@ -30,8 +30,8 @@ class VirtualKey { this.label, this.altLabel, this.flex = 1, - }) : capsText = null, - keyType = KeyType.action; + }) : capsText = null, + keyType = KeyType.action; /// The primary text character for this key. final String? text; diff --git a/lib/src/scope.dart b/lib/src/scope.dart index 309000a..4961c52 100644 --- a/lib/src/scope.dart +++ b/lib/src/scope.dart @@ -117,8 +117,7 @@ class VirtualKeypadScopeState extends State { TextInputAction inputAction = TextInputAction.done, bool allowPhysicalKeyboard = false, }) { - final changed = - _activeController != controller || + final changed = _activeController != controller || _activeKeyboardType != keyboardType || _activeInputAction != inputAction || _allowPhysicalKeyboard != allowPhysicalKeyboard; diff --git a/lib/src/theme.dart b/lib/src/theme.dart index 06a9a41..6344d73 100644 --- a/lib/src/theme.dart +++ b/lib/src/theme.dart @@ -62,35 +62,35 @@ class VirtualKeypadTheme { /// Decoration for character keys. BoxDecoration get keyDecoration => BoxDecoration( - color: keyColor, - borderRadius: BorderRadius.circular(keyBorderRadius), - boxShadow: keyShadow - ? [ - BoxShadow( - color: Colors.black.withValues(alpha: 0.15), - blurRadius: 1, - spreadRadius: 0.5, - offset: const Offset(0, 1), - ), - ] - : null, - ); + color: keyColor, + borderRadius: BorderRadius.circular(keyBorderRadius), + boxShadow: keyShadow + ? [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.15), + blurRadius: 1, + spreadRadius: 0.5, + offset: const Offset(0, 1), + ), + ] + : null, + ); /// Decoration for action keys. BoxDecoration get actionKeyDecoration => BoxDecoration( - color: actionKeyColor, - borderRadius: BorderRadius.circular(keyBorderRadius), - boxShadow: keyShadow - ? [ - BoxShadow( - color: Colors.black.withValues(alpha: 0.15), - blurRadius: 1, - spreadRadius: 0.5, - offset: const Offset(0, 1), - ), - ] - : null, - ); + color: actionKeyColor, + borderRadius: BorderRadius.circular(keyBorderRadius), + boxShadow: keyShadow + ? [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.15), + blurRadius: 1, + spreadRadius: 0.5, + offset: const Offset(0, 1), + ), + ] + : null, + ); /// Creates a copy of this theme with the given fields replaced. VirtualKeypadTheme copyWith({ diff --git a/lib/src/widgets/keyboard.dart b/lib/src/widgets/keyboard.dart index 9fe4a1f..ac32ca5 100644 --- a/lib/src/widgets/keyboard.dart +++ b/lib/src/widgets/keyboard.dart @@ -500,8 +500,8 @@ class _VirtualKeypadState extends State { final layout = shouldShowKeyboard ? _currentLayout : (_wasVisible && _cachedLayout != null - ? _cachedLayout! - : _currentLayout); + ? _cachedLayout! + : _currentLayout); // Reset cache after animation would complete if (!shouldShowKeyboard && _wasVisible && !widget.hideWhenUnfocused) { @@ -646,8 +646,7 @@ class _KeyWidgetState extends State<_KeyWidget> { _removePopup(); - final keyWidth = - widget.baseWidth * widget.virtualKey.flex + + final keyWidth = widget.baseWidth * widget.virtualKey.flex + (widget.virtualKey.flex - 1) * widget.theme.horizontalGap; final popupWidth = keyWidth + 14; final popupHeight = widget.height + 12; @@ -692,8 +691,7 @@ class _KeyWidgetState extends State<_KeyWidget> { ? widget.theme.actionKeyDecoration : widget.theme.keyDecoration; - final width = - widget.baseWidth * key.flex + + final width = widget.baseWidth * key.flex + (key.flex - 1) * widget.theme.horizontalGap; return CompositedTransformTarget( @@ -783,8 +781,8 @@ class _KeyWidgetState extends State<_KeyWidget> { widget.capsLock ? Icons.keyboard_capslock : (widget.shift - ? Icons.arrow_upward - : Icons.arrow_upward_outlined), + ? Icons.arrow_upward + : Icons.arrow_upward_outlined), size: widget.theme.keyTextSize, color: widget.theme.keyTextColor, ); diff --git a/lib/src/widgets/text_field.dart b/lib/src/widgets/text_field.dart index a9a9332..a0c8735 100644 --- a/lib/src/widgets/text_field.dart +++ b/lib/src/widgets/text_field.dart @@ -271,8 +271,7 @@ class _VirtualKeypadTextFieldState extends State { void _registerWithScope() { if (_scope != null && widget.enabled && !widget.readOnly) { - final inputAction = - widget.textInputAction ?? + final inputAction = widget.textInputAction ?? (widget.maxLines != 1 ? TextInputAction.newline : TextInputAction.done); From ef186ccdbb9a68478aa16129192763ca4cc3b92d Mon Sep 17 00:00:00 2001 From: Masum Date: Wed, 4 Mar 2026 18:04:46 +0600 Subject: [PATCH 8/8] fix: format example files to pass CI dart format check --- example/lib/main.dart | 13 +++--- .../screens/auto_hide_keyboard_example.dart | 9 ++-- example/lib/screens/multi_field_example.dart | 24 ++++------- .../lib/screens/numeric_input_example.dart | 18 ++++---- .../lib/screens/password_entry_example.dart | 10 ++--- example/lib/screens/pin_pad_example.dart | 43 ++++++++++--------- example/pubspec.lock | 2 +- 7 files changed, 56 insertions(+), 63 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 0413554..ffec06d 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -177,12 +177,13 @@ class HomePage extends StatelessWidget { return FadeTransition( opacity: CurvedAnimation(parent: animation, curve: Curves.easeOut), child: SlideTransition( - position: Tween( - begin: const Offset(0.04, 0), - end: Offset.zero, - ).animate( - CurvedAnimation(parent: animation, curve: Curves.easeOut), - ), + position: + Tween( + begin: const Offset(0.04, 0), + end: Offset.zero, + ).animate( + CurvedAnimation(parent: animation, curve: Curves.easeOut), + ), child: child, ), ); diff --git a/example/lib/screens/auto_hide_keyboard_example.dart b/example/lib/screens/auto_hide_keyboard_example.dart index b15d6fd..9b62c2d 100644 --- a/example/lib/screens/auto_hide_keyboard_example.dart +++ b/example/lib/screens/auto_hide_keyboard_example.dart @@ -74,10 +74,11 @@ class _AutoHideKeyboardExampleState extends State { borderRadius: BorderRadius.circular(14), boxShadow: [ BoxShadow( - color: (_isAnyFocused - ? const Color(0xFF30cfd0) - : colorScheme.shadow) - .withValues(alpha: 0.1), + color: + (_isAnyFocused + ? const Color(0xFF30cfd0) + : colorScheme.shadow) + .withValues(alpha: 0.1), blurRadius: 12, offset: const Offset(0, 3), ), diff --git a/example/lib/screens/multi_field_example.dart b/example/lib/screens/multi_field_example.dart index 94fadd2..4d81e4a 100644 --- a/example/lib/screens/multi_field_example.dart +++ b/example/lib/screens/multi_field_example.dart @@ -34,10 +34,10 @@ class _MultiFieldExampleState extends State { } List get _stepsDone => [ - _nameController.text.isNotEmpty, - _emailController.text.isNotEmpty, - _passwordController.text.isNotEmpty, - ]; + _nameController.text.isNotEmpty, + _emailController.text.isNotEmpty, + _passwordController.text.isNotEmpty, + ]; @override Widget build(BuildContext context) { @@ -86,21 +86,15 @@ class _MultiFieldExampleState extends State { // ── Header ── Text( 'Create Account', - style: Theme.of(context) - .textTheme - .headlineSmall + style: Theme.of(context).textTheme.headlineSmall ?.copyWith(fontWeight: FontWeight.w800), ), const SizedBox(height: 4), Text( 'Fill in your details to get started', - style: Theme.of(context) - .textTheme - .bodyMedium + style: Theme.of(context).textTheme.bodyMedium ?.copyWith( - color: Theme.of(context) - .colorScheme - .onSurface + color: Theme.of(context).colorScheme.onSurface .withValues(alpha: 0.55), ), ), @@ -262,8 +256,8 @@ class _ProgressDots extends StatelessWidget { color: i < filled - 1 ? _kGreenComplete : (i < filled - ? _kGradientStart.withValues(alpha: 0.5) - : muted), + ? _kGradientStart.withValues(alpha: 0.5) + : muted), ), ), ], diff --git a/example/lib/screens/numeric_input_example.dart b/example/lib/screens/numeric_input_example.dart index eacf54c..61bfc5a 100644 --- a/example/lib/screens/numeric_input_example.dart +++ b/example/lib/screens/numeric_input_example.dart @@ -85,15 +85,15 @@ class _NumericInputExampleState extends State { Text( 'Enter Amount', style: Theme.of(context).textTheme.titleLarge?.copyWith( - fontWeight: FontWeight.w700, - ), + fontWeight: FontWeight.w700, + ), ), const SizedBox(height: 4), Text( 'How much would you like to send?', style: Theme.of(context).textTheme.bodyMedium?.copyWith( - color: colorScheme.onSurface.withValues(alpha: 0.5), - ), + color: colorScheme.onSurface.withValues(alpha: 0.5), + ), ), const SizedBox(height: 24), @@ -135,11 +135,11 @@ class _NumericInputExampleState extends State { child: ShaderMask( shaderCallback: (bounds) => const LinearGradient( - colors: [ - Color(0xFF667eea), - Color(0xFF764ba2), - ], - ).createShader(bounds), + colors: [ + Color(0xFF667eea), + Color(0xFF764ba2), + ], + ).createShader(bounds), child: const Text( '\$', style: TextStyle( diff --git a/example/lib/screens/password_entry_example.dart b/example/lib/screens/password_entry_example.dart index 708f1dc..ade2dd9 100644 --- a/example/lib/screens/password_entry_example.dart +++ b/example/lib/screens/password_entry_example.dart @@ -116,17 +116,13 @@ class _PasswordEntryExampleState extends State { Text( 'Welcome Back', - style: Theme.of(context) - .textTheme - .headlineSmall + style: Theme.of(context).textTheme.headlineSmall ?.copyWith(fontWeight: FontWeight.w700), ), const SizedBox(height: 6), Text( 'Sign in to continue', - style: Theme.of(context) - .textTheme - .bodyMedium + style: Theme.of(context).textTheme.bodyMedium ?.copyWith(color: colorScheme.onSurfaceVariant), ), const SizedBox(height: 28), @@ -211,7 +207,7 @@ class _PasswordEntryExampleState extends State { color: active ? _strengthColor(strength) : colorScheme.outlineVariant - .withValues(alpha: 0.3), + .withValues(alpha: 0.3), ), ), ); diff --git a/example/lib/screens/pin_pad_example.dart b/example/lib/screens/pin_pad_example.dart index e933e3b..335401a 100644 --- a/example/lib/screens/pin_pad_example.dart +++ b/example/lib/screens/pin_pad_example.dart @@ -182,10 +182,11 @@ class _PinPadExampleState extends State : _gradient, boxShadow: [ BoxShadow( - color: (_showSuccess - ? const Color(0xFF43A047) - : const Color(0xFFf5576c)) - .withValues(alpha: 0.45), + color: + (_showSuccess + ? const Color(0xFF43A047) + : const Color(0xFFf5576c)) + .withValues(alpha: 0.45), blurRadius: 24, spreadRadius: 2, ), @@ -219,13 +220,13 @@ class _PinPadExampleState extends State child: Text( _showSuccess ? 'Unlocked!' : 'Enter PIN', key: ValueKey(_showSuccess), - style: - Theme.of(context).textTheme.titleLarge?.copyWith( - fontWeight: FontWeight.w700, - color: _showSuccess - ? const Color(0xFF43A047) - : null, - ), + style: Theme.of(context).textTheme.titleLarge + ?.copyWith( + fontWeight: FontWeight.w700, + color: _showSuccess + ? const Color(0xFF43A047) + : null, + ), ), ), const SizedBox(height: 4), @@ -368,8 +369,8 @@ class _PinDot extends StatelessWidget { colors: [Color(0xFF43A047), Color(0xFF66BB6A)], ) : isFilled - ? _dotGradient - : null, + ? _dotGradient + : null, border: isFilled || isSuccess ? null : Border.all(color: outlineColor, width: 2), @@ -382,14 +383,14 @@ class _PinDot extends StatelessWidget { ), ] : isSuccess - ? [ - BoxShadow( - color: const Color(0xFF43A047).withValues(alpha: 0.4), - blurRadius: 10, - spreadRadius: 1, - ), - ] - : null, + ? [ + BoxShadow( + color: const Color(0xFF43A047).withValues(alpha: 0.4), + blurRadius: 10, + spreadRadius: 1, + ), + ] + : null, ), ); } diff --git a/example/pubspec.lock b/example/pubspec.lock index 9ade9f3..bccb95e 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -206,7 +206,7 @@ packages: path: ".." relative: true source: path - version: "0.3.0" + version: "0.3.1" vm_service: dependency: transitive description: