Skip to content

Repository files navigation

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 ⏳ Stub
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>.

Installation

dependencies:
  smart_multi_form_fields: ^1.1.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.


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

🤝 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.

About

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

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages