smart_multi_form_fields 1.3.0 copy "smart_multi_form_fields: ^1.3.0" to clipboard
smart_multi_form_fields: ^1.3.0 copied to clipboard

A single, production-grade Flutter form field widget rendering text, password, phone, OTP, date, dropdown, and file inputs via sealed configurations.

Smart Form Field (smart_multi_form_fields) #

A production-grade, type-safe Flutter form field package that provides a single public widget (SmartFormField) capable of rendering multiple input types through a sealed configuration hierarchy.


Implementation Status #

Type Config Status
Text SmartTextConfig ✅ Complete
Password SmartPasswordConfig ✅ Complete
Phone SmartPhoneConfig ✅ Complete
OTP SmartOtpConfig ✅ Complete
Date SmartDateConfig ⏳ Stub
Dropdown SmartDropdownConfig ⏳ Stub
File SmartFileConfig ⏳ Stub

Features #

  • 📱 Supported Platforms: Tested and officially supported on Android & iOS.
  • 🎯 Single Public Widget: SmartFormField(config: ...) for every input type.
  • 🔒 Type-Safe Sealed Configs: SmartFieldConfig is sealed — compile-time safety, zero dead properties.
  • 🛡️ Built-in Validation: Required check, minLength, maxLength, custom validator chain (SmartValidators.email).
  • 🔑 Password Strength & Custom Scoring: Animated 4-segment strength meter, custom scoring algorithms, custom meter UI, obscuring character selection (, *), custom eye icons.
  • 🔄 Confirm Password Matching: Real-time exact string match validation via confirmPasswordController.
  • ✍️ Formatting & Capitalization: autoCapitalizeWords, custom inputFormatters, auto-trimming.
  • 🔌 External Controller: Optional controller property — you own disposal if provided, package handles it if omitted.
  • 🎨 Automatic Theming: Seamlessly inherits app InputDecorationTheme and light/dark ColorScheme.
  • ☎️ Phone Field with Real Validation: Country-code picker with flags, libphonenumber-derived per-country format validation, and E.164-formatted output — no manual dial-code string manipulation needed.
  • Debounced & Async Search: SmartTextConfig.search() with race-condition-safe async execution.
  • 🔑 Programmatic Control: Validate, reset, read values via GlobalKey<SmartBaseShellState>.
  • 🔢 OTP / PIN Field: Segmented box UI, native SMS autofill, zero-touch controller-based interception support, optional PIN-style masking, auto-submit on completion — zero external dependencies.

Installation #

dependencies:
  smart_multi_form_fields: ^1.3.0

Usage Examples & Previews #

import 'package:smart_multi_form_fields/smart_multi_form_fields.dart';

Section 1: Text Input (SmartTextConfig) #

SmartTextField Previews

Basic Text & Email Validation Bio Multiline & Character Counter
Text Field Demo 1 Text Field Demo 2

1. Basic Text Input & Validation

SmartFormField(
  config: SmartTextConfig(
    label: 'Full Name',
    hint: 'John Doe',
    isRequired: true,
    autoCapitalizeWords: true,
    prefixIcon: const Icon(Icons.person),
    validators: [
      (value) => value!.length < 3 ? 'Name must be at least 3 characters' : null,
    ],
  ),
)

2. Email Field with Built-in Validator

SmartFormField(
  config: SmartTextConfig(
    label: 'Email Address',
    hint: 'user@example.com',
    isRequired: true,
    validators: [SmartValidators.email],
    prefixIcon: const Icon(Icons.email),
  ),
)

3. Multiline & Character Counter (Bio / Notes)

SmartFormField(
  config: SmartTextConfig(
    label: 'Bio',
    hint: 'Write a short bio...',
    minLength: 10,
    maxLength: 200,
    maxLines: 4,
    minLines: 2,
    prefixIcon: const Icon(Icons.info),
  ),
)

4. Auto-Clear Button & Icons

SmartFormField(
  config: SmartTextConfig(
    label: 'Address',
    hint: 'Enter your address',
    showClearButton: true, // Auto-shows (×) clear icon when non-empty
    prefixIcon: const Icon(Icons.location_on),
  ),
)

5. Async Search Field with Debounce

SmartFormField(
  config: SmartTextConfig.search(
    label: 'Search Products',
    hint: 'Type product name...',
    debounce: const Duration(milliseconds: 400),
    onSearchAsync: (query, isCurrent) async {
      final results = await myApi.searchProducts(query);
      if (isCurrent()) { // Ensures older, slower API responses don't overwrite newer results
        setState(() => _searchResults = results);
      }
    },
  ),
)

6. External Controller & Focus Traversal

final _nameController = TextEditingController();
final _nextFocus = FocusNode();

SmartFormField(
  config: SmartTextConfig(
    label: 'First Name',
    controller: _nameController,
    nextFocusNode: _nextFocus,
    textInputAction: TextInputAction.next,
  ),
)

// Read or pre-fill value anytime:
_nameController.text = 'Pre-filled';

7. Programmatic Validation via GlobalKey

final _formKey = GlobalKey<SmartBaseShellState>();

SmartFormField(
  key: _formKey,
  config: SmartTextConfig(label: 'Username', isRequired: true),
)

// On submit button click:
void onSubmit() {
  final error = _formKey.currentState?.validate();
  if (error == null) {
    final value = _formKey.currentState?.value;
    print('Valid value: $value');
  }
}

Section 2: Password Input (SmartPasswordConfig) #

SmartPasswordField Previews

Strength Meter & Custom Policy Custom Validators & Live Values Card
Password Field Demo 1 Password Field Demo 2

1. Password with Strength Meter

SmartFormField(
  config: SmartPasswordConfig(
    label: 'Password',
    hint: 'Enter your password',
    isRequired: true,
    minPasswordLength: 8,
    showStrengthMeter: true, // Animated 4-segment strength bar
  ),
)

2. Strict Password with Complexity Rules

SmartFormField(
  config: SmartPasswordConfig(
    label: 'Strong Password',
    isRequired: true,
    minPasswordLength: 8,
    requireUppercase: true,   // Must include A-Z
    requireLowercase: true,   // Must include a-z
    requireDigit: true,       // Must include 0-9
    requireSpecialChar: true, // Must include !@#$%^&*
  ),
)

3. Confirm Password Match Validation

final _passwordController = TextEditingController();

// Original password field
SmartFormField(
  config: SmartPasswordConfig(
    label: 'Password',
    controller: _passwordController,
    isRequired: true,
  ),
)

// Confirm password field — compares value against original field
SmartFormField(
  config: SmartPasswordConfig(
    label: 'Confirm Password',
    confirmPasswordController: _passwordController,
    confirmMismatchMessage: 'Passwords do not match',
    showStrengthMeter: false,
    isRequired: true,
  ),
)

4. Custom Obscuring Character & Custom Toggle Icon

SmartFormField(
  config: SmartPasswordConfig(
    label: 'Custom Password',
    obscuringCharacter: '*', // Mask symbol (* instead of default •)
    toggleIconBuilder: (isObscured) => Icon(
      isObscured ? Icons.lock_outline : Icons.lock_open_outlined,
      color: Colors.blue,
      size: 20,
    ),
  ),
)

5. Custom Strength Scorer & Custom Strength UI Builder

SmartFormField(
  config: SmartPasswordConfig(
    label: 'Custom Policy Password',
    // Custom scoring algorithm
    customStrengthScorer: (password, minLength) {
      if (password.length < minLength) return PasswordStrength.weak;
      if (password.contains('123456')) return PasswordStrength.weak;
      return PasswordStrengthScorer.score(password, minLength: minLength);
    },
    // Custom strength meter UI replacement
    strengthMeterBuilder: (context, strength) {
      return Text('Strength: ${strength.label}', style: TextStyle(color: strength.color));
    },
  ),
)

Section 3: Phone Input (SmartPhoneConfig) #

SmartPhoneField Previews

Phone Field Implementation Validation & Selection
Phone Field Demo 1 Phone Field Demo 2

1. Basic Phone Field

SmartFormField(
  config: SmartPhoneConfig(
    label: 'Phone Number',
    defaultCountryCode: 'IN', // required — pick your app's primary market
    isRequired: true,
    helperText: 'We\'ll text you a verification code',
  ),
)

2. Custom Error Message & Country Change Callback

SmartFormField(
  config: SmartPhoneConfig(
    label: 'Phone Number',
    defaultCountryCode: 'GB',
    invalidNumberMessage: 'That doesn\'t look like a valid number',
    onCountryChanged: (isoCode, dialCode) {
      print('User switched to $isoCode ($dialCode)');
    },
  ),
)

3. Getting the Full E.164 Value

final _phoneKey = GlobalKey<SmartBaseShellState>();

SmartFormField(
  key: _phoneKey,
  config: SmartPhoneConfig(label: 'Phone', defaultCountryCode: 'US'),
)

// Always returns the full international format, e.g. "+14155551234":
final phone = _phoneKey.currentState?.value;

Important: defaultCountryCode is required by design — this package does not attempt to auto-detect a user's country from device locale, since a phone's display-language setting is not a reliable proxy for actual location. Set it to whichever country your app primarily targets; users elsewhere can switch via the flag picker at any time.

Section 4: OTP / PIN Input (SmartOtpConfig) #

SmartOtpField Previews

Basic 6-Digit OTP Auto-Submit & Autofill
OTP Demo 1 OTP Demo 2

1. Basic 6-Digit OTP

SmartFormField(
  config: SmartOtpConfig(
    label: 'Verification Code',
    helperText: 'Sent to your phone via SMS',
    isRequired: true,
  ),
)

2. Auto-Submit on Completion

SmartFormField(
  config: SmartOtpConfig(
    label: 'Verification Code',
    autoSubmit: true,
    onSubmitted: (code) => verifyOtp(code),
  ),
)

3. 4-Digit PIN, Masked

SmartFormField(
  config: SmartOtpConfig(
    label: 'Enter PIN',
    length: 4,
    obscureText: true,
    obscuringCharacter: '*',
    enableSmsAutofill: false, // PINs aren't SMS codes
  ),
)

4. Zero-Touch Background SMS Interception

If your app already reads incoming SMS itself (e.g. via the Android SMS Retriever API), just feed the code into a controller you provide — no special wiring needed on this package's side:

final _otpController = TextEditingController();

SmartFormField(
  config: SmartOtpConfig(
    label: 'Verification Code',
    controller: _otpController,
    autoSubmit: true,
  ),
)

// Elsewhere, once your app's SMS listener receives the code:
_otpController.text = '482913'; // boxes update, autoSubmit fires automatically

5. Custom Box Colors

SmartFormField(
  config: SmartOtpConfig(
    label: 'Verification Code',
    enabledBorderColor: Colors.grey,
    focusedBorderColor: Colors.deepPurple,
    errorBorderColor: Colors.redAccent,
  ),
)

SmartTextConfig Property Reference #

Property Type Description
label String? Field label header shown above input
hint String? Placeholder text inside input
helperText String? Supporting text shown below field
isRequired bool Adds * asterisk and runs empty validation
validators List<SmartValidator> Custom validation functions chain
minLength int? Minimum character length constraint
maxLength int? Maximum character length constraint (renders counter)
maxLines int? Maximum lines for multiline input
minLines int? Minimum lines for multiline input
autoCapitalizeWords bool Automatically capitalizes first letter of every word
showClearButton bool Renders (×) clear button when text is non-empty
prefixIcon Widget? Icon displayed at the start of input
suffixIcon Widget? Icon displayed at the end of input
onSuffixIconTap VoidCallback? Tap handler for suffixIcon
readOnly bool Focusable and selectable but prevents editing
enabled bool Disables field interactions and dims colors
controller TextEditingController? External controller override
focusNode FocusNode? External focus node override
nextFocusNode FocusNode? Focus node to request on keyboard submit
debounce Duration Delay for debounced callbacks (default: 300ms)
onDebouncedChanged ValueChanged<String>? Sync callback invoked after debounce delay
onSearchAsync Future<void> Function(query, isCurrent)? Async search callback with stale response checker
showSearchLoadingIndicator bool Auto-swaps suffix icon to spinner during async search

SmartPasswordConfig Property Reference #

Property Type Description
label String? Field label header shown above input
hint String? Placeholder text inside input
helperText String? Supporting text shown below field
isRequired bool Adds * asterisk and runs empty validation
obscuringCharacter String Mask symbol used when obscured (default: '•')
showToggleIcon bool Renders visibility eye icon toggle (default: true)
toggleIconBuilder Widget Function(bool isObscured)? Builder for custom visibility toggle icon
showStrengthMeter bool Renders animated 4-segment password strength bar (default: true)
strengthMeterBuilder Widget Function(BuildContext, PasswordStrength)? Builder for replacing default strength meter UI
customStrengthScorer PasswordStrength Function(String, int)? Custom algorithm function for password strength scoring
minPasswordLength int Minimum password length requirement & strength threshold baseline (default: 8)
requireUppercase bool Requires at least one uppercase letter [A-Z]
requireLowercase bool Requires at least one lowercase letter [a-z]
requireDigit bool Requires at least one numeric digit [0-9]
requireSpecialChar bool Requires at least one special character [!@#$%^&*...]
confirmPasswordController TextEditingController? Controller of original password field for match validation
confirmMismatchMessage String? Custom error message when confirm password does not match

SmartPhoneConfig Property Reference #

Property Type Description
label String? Field label header shown above input
hint String? Placeholder text inside input
helperText String? Supporting text shown below field
isRequired bool Adds * asterisk and runs empty validation
defaultCountryCode String Required. ISO 3166-1 alpha-2 starting country (e.g. 'IN', 'US', 'GB')
onCountryChanged void Function(String isoCode, String dialCode)? Fires when the user picks a different country
invalidNumberMessage String? Custom error message for format validation failure
showDropdownIcon bool Show/hide the chevron next to the flag (flag stays tappable either way)
flagsButtonPadding EdgeInsetsGeometry? Padding around the flag/dial-code button
flagsButtonMargin EdgeInsets? Margin around the flag/dial-code button
validateMode AutovalidateMode Controls live re-validation behavior as the user types
controller TextEditingController? External controller override (holds the national number)
focusNode / nextFocusNode FocusNode? External focus control / focus traversal target
validators List<SmartValidator> Custom validators — receive the raw national number, no dial code

SmartOtpConfig Property Reference #

Property Type Description
label String? Field label header shown above the boxes
helperText String? Supporting text shown below the boxes
isRequired bool Adds * asterisk and runs empty validation
length int Number of boxes / required code length (default: 6)
obscureText bool Mask entered digits like a PIN
obscuringCharacter String Mask symbol used when obscureText is true (default: '●')
enableSmsAutofill bool Enable native SMS/platform autofill via AutofillHints.oneTimeCode
onCompleted ValueChanged<String>? Fires once each time the code reaches full length
autoSubmit bool Auto-dismiss keyboard and fire onSubmitted on completion
enabledBorderColor Color? Box border color in normal state (field-level override)
focusedBorderColor Color? Box border color for the currently active box
errorBorderColor Color? Box border color when validation fails
controller TextEditingController? External controller — supports zero-touch SMS interception by assignment
validators List<SmartValidator> Custom validators — receive the full entered code as one string

🤝 Community, Feedback & Contributing #

Why use smart_multi_form_fields? #

Form building in Flutter shouldn't require copy-pasting hundreds of lines of TextFormField boilerplate or mixing separate third-party packages for every input type.

smart_multi_form_fields unifies all your form fields into a single, production-grade widget with compile-time type safety, theme adaptability, built-in validation rules, animated strength feedback, and zero maintenance bloat.

If this package saves you development time or makes your Flutter codebase cleaner, please ⭐ star the repository on GitHub to support the project!


🐛 How to Report Issues & Request Features #

We welcome feature requests, bug reports, and pull requests! To ensure issues are resolved as quickly as possible, please follow these guidelines when opening a GitHub issue.

Steps to File an Issue:

  1. Check existing GitHub Issues to verify your bug or feature request hasn't already been reported.
  2. Click New Issue on the repository's Issues tab.
  3. Provide the required details listed below.

Required Issue Details Checklist:

  • 📌 Environment Info: Include output of flutter doctor -v (Flutter SDK and Dart versions).
  • 📦 Package Version: State the package version used (e.g. smart_multi_form_fields: ^1.1.0).
  • 🧩 Config Type: Specify which configuration was used (e.g. SmartTextConfig or SmartPasswordConfig).
  • 📝 Minimal Reproducible Code: Provide a complete, self-contained Flutter snippet reproducing the behavior.
  • 🎯 Expected vs Actual Behavior: Clearly describe what should happen vs what actually occurred.
  • 📷 Screenshots / Logs: Attach error stack traces or visual screenshots if applicable.

License #

MIT License.

1
likes
160
points
171
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A single, production-grade Flutter form field widget rendering text, password, phone, OTP, date, dropdown, and file inputs via sealed configurations.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

cupertino_icons, file_picker, flutter, flutter_gap, flutter_intl_phone_field, image_picker, intl, intl_phone_field_v2, phone_numbers_parser

More

Packages that depend on smart_multi_form_fields