formwise 1.1.0 copy "formwise: ^1.1.0" to clipboard
formwise: ^1.1.0 copied to clipboard

Smart form fields for Flutter with auto-validation, auto-formatting, typo detection, and animated error feedback. Supports email, phone, credit card, URL, and custom fields.

formwise #

Smart form fields for Flutter with built-in validation, auto-formatting, typo detection, and animated error feedback.

CI pub package License: MIT

Features #

  • Smart Validators — Email (Levenshtein-based typo detection across 55+ domains), phone, URL, credit card (Luhn), postal code (20 countries), numeric range, pattern, and composable validators.
  • Auto-Formatters — Credit card, phone (8 country presets), smart date (digit clamping), currency, postal code, custom mask, title case, uppercase/lowercase, trimmed.
  • SmartTextFormField — Drop-in TextFormField replacement with 7 named constructors (.email(), .phone(), .creditCard(), .url(), .password(), .numeric(), .postalCode()), debounced validation, async validation, shake-on-error, and animated success/error indicators.
  • Animated Validation UXAnimatedValidationIcon (crossfade between states), StrengthIndicator (animated bar), AnimatedValidationBorder, PasswordStrength calculator.
  • SmartFormController — Manage multiple fields: validate all, reset, get/set values, track dirty state.
  • Postal Code Validation — Format validation and auto-formatting for 20 countries (US, UK, Canada, Japan, Germany, France, Australia, India, Brazil, Nigeria, and more).
  • ML Module (optional) — On-device TFLite email typo detection with automatic edit-distance fallback. Import formwise_ml.dart separately.

Installation #

dependencies:
  formwise: ^1.1.0
flutter pub add formwise

Quick Start #

Named Constructors #

The fastest way to get a fully configured field:

import 'package:formwise/formwise.dart';

// Email with typo detection, lowercase formatting, email keyboard
SmartTextFormField.email(
  name: 'email',
  onTypoDetected: (suggestion) => print('Did you mean $suggestion?'),
)

// Phone with mask formatting and digit keyboard
SmartTextFormField.phone(
  name: 'phone',
  mask: '(###) ###-####',
)

// Credit card with Luhn validation and auto-formatting
SmartTextFormField.creditCard(name: 'card')

// Password with strength requirements
SmartTextFormField.password(
  name: 'password',
  minLength: 8,
  requireUppercase: true,
  requireDigit: true,
  requireSpecialChar: true,
)

// URL with optional HTTPS enforcement
SmartTextFormField.url(name: 'website', requireHttps: true)

// Numeric with range validation
SmartTextFormField.numeric(name: 'age', min: 0, max: 150)

// Postal code with country-specific format
SmartTextFormField.postalCode(
  name: 'zip',
  country: PostalCountry.us,
)

Each named constructor pre-configures the validator, formatter, keyboard type, icon, label, and hint text.

Validators #

Email with Typo Detection #

Uses Levenshtein edit distance against 55+ known email providers. Catches typos like gmial.comgmail.com, yhaoo.comyahoo.com.

final validate = SmartValidators.email(
  suggestCorrection: (suggestion) {
    // suggestion = "user@gmail.com" when user types "user@gmial.com"
  },
);

// Add your organization's domains to the known-good list:
final validate = SmartValidators.email(
  customDomains: ['mycompany.com', 'mycompany.org'],
);

// Adjust sensitivity (default maxTypoDistance: 2):
final strict = SmartValidators.email(maxTypoDistance: 1);

Using EmailTypoDetector Directly

const detector = EmailTypoDetector();

// Check a domain
final match = detector.detectTypo('gmial.com');
// match?.suggested == 'gmail.com', match?.distance == 2

// Check a full email
final corrected = detector.suggestCorrection('user@gmial.com');
// corrected == 'user@gmail.com'

// Custom domain list
final custom = EmailTypoDetector(
  domains: [...EmailTypoDetector.defaultDomains, 'mycompany.com'],
);

Phone #

SmartValidators.phone(
  minDigits: 10,
  maxDigits: 10,
  allowCountryCode: false, // reject numbers starting with +
)

URL #

SmartValidators.url(
  requireHttps: true,
  allowedSchemes: ['https', 'ftp'],
)

Credit Card (Luhn) #

SmartValidators.creditCard()

// Detect brand:
final brand = SmartValidators.detectCardBrand('4111111111111111');
// CardBrand.visa, .mastercard, .amex, .discover, .unknown

Postal Code (20 Countries) #

// Validate for a specific country
final validate = PostalCodeValidator.forCountry(PostalCountry.uk);
validate('SW1A 1AA'); // null (valid)
validate('12345');     // 'Invalid postal code for UK (e.g. SW1A 1AA)'

// Auto-detect country format
final validate = PostalCodeValidator.autoDetect();

// Detect which countries match a code
final countries = PostalCodeValidator.detectCountry('12345');
// [PostalCountry.us, PostalCountry.germany, PostalCountry.france, ...]

Supported countries: US, UK, Canada, Japan, Germany, France, Australia, India, Brazil, Nigeria, Netherlands, Italy, Spain, South Korea, China, Russia, Mexico, Switzerland, Poland, Sweden.

Composing Validators #

SmartValidators.compose([
  SmartValidators.required(errorMessage: 'Required'),
  SmartValidators.minLength(length: 8),
  SmartValidators.pattern(
    regex: RegExp(r'[A-Z]'),
    errorMessage: 'Must contain an uppercase letter',
  ),
])

Other Validators #

SmartValidators.required()
SmartValidators.minLength(length: 3)
SmartValidators.maxLength(length: 100)
SmartValidators.numericRange(min: 0, max: 999, allowDecimals: false)
SmartValidators.pattern(regex: RegExp(r'^\d+$'), errorMessage: 'Digits only')

Formatters #

Phone #

// Custom mask
SmartFormatters.phone(mask: '(###) ###-####')

// Country presets
SmartFormatters.phoneInternational(PhoneFormat.japan)   // ###-####-####
SmartFormatters.phoneInternational(PhoneFormat.nigeria)  // #### ### ####
SmartFormatters.phoneInternational(PhoneFormat.uk)       // +44 #### ######

Presets: PhoneFormat.us, .uk, .japan, .nigeria, .germany, .india, .brazil, .international

Smart Date (with Digit Clamping) #

Auto-clamps month to 01–12 and day to 01–31 (adjusted per month) as the user types:

SmartFormatters.smartDate(DateFormat.mmddyyyy)    // MM/DD/YYYY
SmartFormatters.smartDate(DateFormat.ddmmyyyy)    // DD/MM/YYYY
SmartFormatters.smartDate(DateFormat.iso)          // YYYY-MM-DD
SmartFormatters.smartDate(DateFormat.ddmmyyyyDot)  // DD.MM.YYYY
SmartFormatters.smartDate(DateFormat.yyyymmdd)     // YYYY/MM/DD

Credit Card #

SmartFormatters.creditCard()                      // 4-4-4-4 standard
SmartFormatters.creditCard(amexFormat: true)       // 4-6-5 Amex
SmartFormatters.creditCard(autoDetectBrand: true)  // switches by prefix

Currency #

SmartFormatters.currency()                         // $1,234.56
SmartFormatters.currency(symbol: '€', showSymbol: true)
SmartFormatters.currency(symbol: '', separator: '.', decimal: ',') // 1.234,56

Postal Code #

PostalCodeFormatter(PostalCountry.us)     // 12345 or 12345-6789
PostalCodeFormatter(PostalCountry.japan)  // 123-4567
PostalCodeFormatter(PostalCountry.uk)     // SW1A 1AA
PostalCodeFormatter(PostalCountry.canada) // K1A 0B1

Other Formatters #

SmartFormatters.mask('###-##-####')    // SSN: 123-45-6789
SmartFormatters.titleCase()            // "john doe" → "John Doe"
SmartFormatters.uppercase()
SmartFormatters.lowercase()
SmartFormatters.trimmed()              // collapses multiple spaces
SmartFormatters.digitsOnly()

Animated Validation UX #

AnimatedValidationIcon #

Crossfades between idle/spinner/checkmark/error with scale+fade transitions. Used internally by SmartTextFormField, or use standalone:

AnimatedValidationIcon(
  state: ValidationState.valid,  // .idle, .validating, .valid, .invalid
  validColor: Colors.green,
  invalidColor: Colors.red,
  size: 20,
)

StrengthIndicator #

Animated bar from 0.0 to 1.0 with red→amber→green color interpolation:

StrengthIndicator(
  strength: PasswordStrength.calculate(password),
  label: PasswordStrength.label(strength), // "Very weak" → "Very strong"
  height: 4,
)

PasswordStrength #

final strength = PasswordStrength.calculate('MyP@ss123');  // 0.0–1.0
final label = PasswordStrength.label(strength);            // "Strong"

Scores based on: length, character variety (lowercase, uppercase, digits, special), uniqueness ratio.

AnimatedValidationBorder #

Wraps any widget with animated border color per validation state:

AnimatedValidationBorder(
  state: ValidationState.valid,
  child: TextField(...),
)

SmartFormController #

Manage multiple fields programmatically:

final controller = SmartFormController();

// Register fields via formController parameter:
SmartTextFormField.email(name: 'email', formController: controller)
SmartTextFormField.password(name: 'password', formController: controller)

// Validate all fields:
if (controller.validate()) {
  final data = controller.values; // {'email': '...', 'password': '...'}
}

// Other operations:
controller.reset();                    // restore initial values, clear errors
controller.isDirty;                    // any field modified?
controller.isValid;                    // all fields valid?
controller.errors;                     // {'email': 'error msg'} — only failing
controller.getValue('email');          // get one field
controller.setValue('email', 'new');   // set one field

Async Validation #

For server-side checks (username availability, etc.):

SmartTextFormField(
  name: 'username',
  asyncValidator: (value) async {
    final available = await api.checkUsername(value!);
    return available ? null : 'Username is already taken';
  },
  validationDebounce: Duration(milliseconds: 500),
)

Shows an animated spinner during validation, automatically cancels stale requests when the user keeps typing.

ML Module (Optional) #

For on-device ML email validation using TFLite. It's split into a separate formwise_ml.dart entry point so the ML API surface doesn't clutter the core import — but note that tflite_flutter is a package dependency either way, so its native binaries are bundled into your app regardless of whether you import formwise_ml.dart.

import 'package:formwise/formwise_ml.dart';

final validator = EmailMlValidator(
  modelAsset: 'assets/models/email_typo.tflite',
  labels: ['valid', 'gmail.com', 'yahoo.com', 'outlook.com'],
);
await validator.initialize();

final result = await validator.validateEmail('user@gmial.com');
// result.isValid == false
// result.suggestion == 'user@gmail.com'
// result.confidence == 0.92

Falls back to edit-distance detection when the model isn't available.

API Reference #

SmartValidators #

Validator Description
email() Email with Levenshtein typo detection (55+ domains)
phone() Phone number with configurable digit range
url() URL with optional HTTPS enforcement
creditCard() Credit card via Luhn algorithm
numericRange() Number within min/max bounds
pattern() Custom regex pattern
required() Non-empty check
minLength() Minimum character count
maxLength() Maximum character count
compose() Combine multiple validators (first error wins)
detectCardBrand() Visa, Mastercard, Amex, Discover detection

SmartFormatters #

Formatter Example Output
creditCard() 4111 1111 1111 1111
phone() (234) 567-8901
smartDate() 12/31/2025 (with digit clamping)
currency() $1,234.56
mask() ###-##-####123-45-6789
titleCase() John Doe
uppercase() / lowercase() Case conversion
trimmed() Collapse multiple spaces
digitsOnly() Strip non-digits

PostalCodeValidator #

Method Description
forCountry() Validate against a specific country format
autoDetect() Try all country formats
detectCountry() List countries matching a code

Animated Widgets #

Widget Description
AnimatedValidationIcon Crossfade spinner/check/error icons
StrengthIndicator Animated strength bar with color gradient
AnimatedValidationBorder Animated border per validation state
PasswordStrength Calculate and label password strength

SmartTextFormField Named Constructors #

Constructor Pre-configured
.email() Email validator + typo detection, lowercase, email keyboard
.phone() Phone validator, mask formatter, phone keyboard
.creditCard() Luhn validator, card formatter, number keyboard
.url() URL validator, lowercase, URL keyboard
.password() Composed strength validator, obscured text
.numeric() Range validator, number keyboard
.postalCode() Country validator + formatter, characters capitalization

Example #

See the example app for a complete demo with 5 interactive screens.

License #

MIT License — see LICENSE for details.

0
likes
160
points
30
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Smart form fields for Flutter with auto-validation, auto-formatting, typo detection, and animated error feedback. Supports email, phone, credit card, URL, and custom fields.

Repository (GitHub)
View/report issues

Topics

#form #validation #input #formatting #widget

License

MIT (license)

Dependencies

flutter, tflite_flutter

More

Packages that depend on formwise