cmx_fields 0.0.1 copy "cmx_fields: ^0.0.1" to clipboard
cmx_fields: ^0.0.1 copied to clipboard

PlatformAndroid

A comprehensive Flutter input fields kit with smart, animated field types, a phone country picker with contact suggestions, password strength, OTP autofill, and a consistent themeable API across all fields.

cmx_fields #

A comprehensive, modern, animated smart-input-fields kit for Flutter. One package, ten field types โ€” all sharing a single field engine so they look, animate, theme and validate identically.

Fields: ๐Ÿ“ฑ Phone ยท ๐Ÿ”’ Password ยท ๐Ÿ”ข OTP ยท ๐Ÿ’ณ Card ยท ๐Ÿ“ง Email ยท ๐Ÿ”ฃ Number ยท ๐Ÿ“… Date ยท ๐Ÿ” Search ยท ๐Ÿ“ Text area ยท ๐Ÿท๏ธ Tags.

Showcase #

Landscape previews from the example app (example/).

cmx_fields โ€” phone, country picker, password, OTP, card, email

Phone with country-aware validation & fill-progress ยท searchable country picker ยท password strength ยท OTP ยท card ยท email

cmx_fields โ€” email, OTP, card, date, tags, autocomplete

Email & OTP ยท card & date picker ยท tag chips ยท email domain suggestions

Why cmx_fields? #

intl_phone_field cmx_fields
Actively maintained โŒ โœ…
Multiple field types โŒ phone only โœ… 10 field types
Consistent API across fields โŒ โœ…
Global theming โŒ โœ… CmxFieldThemeProvider
Built-in animations (shake / pulse / checkmark) โŒ โœ…
Respects reduced-motion โŒ โœ…
Contact suggestions โŒ โœ… (graceful)
Device number hint (Android) โŒ โœ… Google Phone Number Hint
Fill-progress ring + valid tick โŒ โœ…
Password strength n/a โœ…
OTP autofill (oneTimeCode) n/a โœ… no native code
RTL-aware partial โœ…

Install #

dependencies:
  cmx_fields: ^0.0.1
import 'package:cmx_fields/cmx_fields.dart';

Phone contact suggestions (Android / iOS) #

If you use showContactSuggestions: true (default), add permissions to your app:

Android โ€” android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_CONTACTS" />

iOS โ€” ios/Runner/Info.plist:

<key>NSContactsUsageDescription</key>
<string>Used to suggest phone numbers from your contacts while typing.</string>

The package requests runtime permission before reading contacts. If the user denies, suggestions are hidden and the app keeps running.

Global theming #

Wrap your app (or any subtree) once โ€” every field below inherits the look. Per-field props always override the inherited theme.

CmxFieldThemeProvider(
  theme: CmxFieldTheme(
    focusedColor: Colors.indigo,
    borderRadius: 16,
    borderStyle: CmxBorderStyle.outlined, // outlined | underline | filled | rounded | none
  ),
  child: MyForm(),
)

Fields #

๐Ÿ“ฑ CmxPhoneField #

CmxPhoneField(
  label: 'Mobile number',
  showContactSuggestions: true,
  onChanged: (phone) => print('${phone.fullNumber} ${phone.isValid}'),
  // Turnkey, country-aware validation โ€” India needs 10 digits, others their own.
  validator: CmxPhoneField.validNumber(),
)
  • Country-aware validation: isValid (and the ready-made CmxPhoneField.validNumber() validator) enforce each country's own rules via phone_numbers_parser โ€” India requires 10 digits, the US 10, and so on. PhoneResult.expectedLength exposes the target count.
  • Tappable flag + dial-code prefix opens a searchable country picker (118 countries, popular ones pinned on top โ€” order and list are customizable).
  • As-you-type formatting per country.
  • Auto-detects the country from the device locale.
  • In-app contact suggestions once โ‰ฅ3 digits are typed โ€” silently disabled on web/desktop or when permission is denied (never crashes).
  • Device number hint (Android): Google's Phone Number Hint picker auto-opens shortly after the field appears (and via the suffix button), letting the user fill a SIM/Google number in one tap. No phone-read permission needed; silently inert on iOS/web/desktop.
  • Green fill-progress ring: the suffix ring fills 0 โ†’ 100% as the national number is typed, then settles to a full green ring with a drawn checkmark once the number validates.
  • Emits a PhoneResult { nationalNumber, dialCode, fullNumber, country, isValid, expectedLength }.

Android setup: the number hint uses Google Play Services โ€” test on a real device (emulators without Play Services may not show it). No manifest permission is required. If Gradle fails with phone_number_hint is currently compiled against android-31, add this to your appโ€™s android/build.gradle.kts (see example/android/build.gradle.kts):

import com.android.build.gradle.LibraryExtension
subprojects {
    afterEvaluate {
        extensions.findByType<LibraryExtension>()?.compileSdk = 36
    }
}
Prop Type Default
label, hint String? โ€”
initialCountry Country? locale / US
initialValue String? โ€”
showContactSuggestions bool true
autoDetectCountry bool true
enablePhoneNumberHint bool true
autoRequestHint bool true
hintRequestDelay Duration 500ms
showHintButton bool true
showFillProgress bool true
countryPicker CountryPickerConfig popular = [kPopularCountryCodes]
onChanged, onSubmitted ValueChanged<PhoneResult>? โ€”
validator String? Function(PhoneResult?) โ€”
controller, focusNode, enabled โ€” โ€”
theme overrides focusedColor, borderStyle, borderRadius, โ€ฆ inherited

Country picker customization:

CmxPhoneField(
  countryPicker: CountryPickerConfig(
    // Shown first, in this exact order:
    popularCountryCodes: ['IN', 'US', 'AE', 'GB', 'SG'],
    popularSectionTitle: 'Frequent',
    // Optional: only these countries in the sheet:
    // allowedCountryCodes: ['IN', 'US', 'GB', 'AE'],
    // Optional: hide countries:
    // excludedCountryCodes: ['CU', 'KP'],
  ),
)

๐Ÿ”’ CmxPasswordField #

final pwd = TextEditingController();

CmxPasswordField(
  label: 'Password',
  controller: pwd,
  showStrengthIndicator: true,
  showRules: true,
  minStrength: PasswordStrength.strong,
)

CmxPasswordField(
  label: 'Confirm password',
  validator: CmxValidators.match(() => pwd.text, 'Passwords do not match'),
)
  • Animated show/hide eye toggle and a focus-bounce lock icon.
  • Live 4-segment strength bar (none โ†’ weak โ†’ medium โ†’ strong โ†’ veryStrong).
  • Optional rules checklist that ticks off as each rule is met.
  • minStrength enforced during Form validation.
Prop Type Default
showStrengthIndicator bool true
showRules bool false
rules List<PasswordRule>? kDefaultPasswordRules
minStrength PasswordStrength? โ€”
obscureInitially bool true
onChanged, onSubmitted ValueChanged<String>? โ€”
validator CmxValidator<String>? โ€”

๐Ÿ”ข CmxOtpField #

final otp = CmxOtpController();

CmxOtpField(
  length: 6,
  controller: otp,
  autoReadSms: true, // OS oneTimeCode autofill โ€” no native code
  onCompleted: (code) => verify(code),
  validator: (v) => (v == null || v.length < 6) ? 'Enter all 6 digits' : null,
)

// later:
otp.shake();  // wrong code feedback
otp.clear();  // reset boxes
  • Auto-advance, backspace-to-previous, paste/OS-autofill distribution across boxes.
  • Shake on error, success flash, four box styles (outlined / underline / filled / rounded).
Prop Type Default
length int 6
controller CmxOtpController? โ€”
autoReadSms bool true
fieldStyle OtpFieldStyle outlined
boxSize, spacing double 52, 8
obscureText bool false
onChanged, onCompleted ValueChanged<String>? โ€”
validator FormFieldValidator<String>? โ€”

๐Ÿ’ณ CmxCardField #

CmxCardField(
  onChanged: (c) => print('${c.cardType} ${c.isValid}'),
  validator: (c) => (c == null || !c.isValid) ? 'Invalid card' : null,
)

Auto-detects brand (Visa, Mastercard, Amex, Discover, RuPay, Maestro) from the digits, groups the number (4242 4242 4242 4242, Amex 3782 822463 10005), Luhn-validates, and pairs it with MM/YY expiry + brand-aware CVV fields. Emits a CardResult.

๐Ÿ“ง CmxEmailField #

CmxEmailField(
  label: 'Email',
  showSuggestions: true, // gmail.com, yahoo.com, โ€ฆ completions after @
  validator: CmxValidators.compose([CmxValidators.required(), CmxValidators.email()]),
)

Green fill-progress ring + tick suffix (same as phone), animated envelope prefix, and a domain-completion overlay after @.

๐Ÿ”ฃ CmxNumberField #

CmxNumberField(label: 'Quantity', min: 0, max: 99, showSteppers: true)

CmxNumberField(
  label: 'Amount',
  currencySymbol: 'โ‚น ',
  decimalPlaces: 2,
  grouping: NumberGrouping.indian, // 12,34,567   (or .western โ†’ 1,234,567)
)

Grouping (none/western/indian), decimal precision, currency prefix, optional +/- steppers, and min/max validation.

๐Ÿ“… CmxDateField #

CmxDateField(
  label: 'Date of birth',
  dateFormat: 'dd/MM/yyyy', // also MMM d, yyyy ยท d MMMM yyyy ยท โ€ฆ
  pickerStyle: DatePickerStyle.adaptive, // material | cupertino | adaptive
  onChanged: (d) => print(d),
)

Tap opens a Material or Cupertino picker; read-only formatted display with an animated calendar icon. No intl dependency.

๐Ÿ” CmxSearchField #

CmxSearchField(
  label: 'Search',
  debounceDuration: Duration(milliseconds: 300),
  onSearch: (q) async => api.suggest(q), // overlay + loading spinner
  recentSearches: ['Mango', 'Cherry'],
  onSuggestionTap: (s) => run(s),
)

Debounced input, async-suggestion overlay with a loading indicator, recent-search list, and an animated clear button. Stale async results are discarded.

๐Ÿ“ CmxTextAreaField #

CmxTextAreaField(label: 'Description', maxLength: 200, minLines: 3, maxLines: 8)

Auto-expands smoothly between minLines and maxLines, with a live 47 / 200 counter that turns red near the limit.

๐Ÿท๏ธ CmxTagField #

CmxTagField(
  label: 'Skills',
  initialTags: ['Flutter', 'Dart'],
  maxTags: 8,
  suggestions: ['Firebase', 'Riverpod', 'Bloc'],
  onTagsChanged: (tags) => print(tags),
)

Type + Enter/comma to add chips, โœ• or backspace to remove, with add/remove animations, duplicate/maxTags guards, and a suggestions overlay.

Validators #

Shared (CmxValidators): required, email, minLength, maxLength, pattern, match, compose.

Built-in per field (clear default messages):

Field Helper Example error
Phone CmxPhoneField.validNumber() Enter 10 digits for India (+91) (3 more)
Email CmxValidators.email() Enter a valid email
Password minStrength + CmxValidators.required() Password is too weak (minimum: Strong)
OTP CmxOtpField.complete(6) Enter all 6 digits
Card CmxCardField.validCard() Enter valid card details
Number CmxNumberField.inRange(min: 0, max: 99) Must be at most 99
Date CmxDateField.required() Select a date
Tags CmxTagField.minTags(2) Add at least 2 tags
CmxPhoneField(validator: CmxPhoneField.validNumber());
CmxEmailField(
  validator: CmxValidators.compose([
    CmxValidators.required('Enter your email'),
    CmxValidators.email(),
  ]),
);

Form integration #

Every field works standalone or inside a Form:

final formKey = GlobalKey<FormState>();

Form(
  key: formKey,
  child: Column(children: [
    CmxPhoneField(validator: CmxPhoneField.validNumber()),
    CmxPasswordField(
      minStrength: PasswordStrength.strong,
      validator: CmxValidators.required('Enter a password'),
    ),
  ]),
);

if (formKey.currentState!.validate()) submit();

Failed validation shows the error text, flips the border to the error color, and shakes the field (unless reduced-motion is enabled).

Platform support #

Android ยท iOS ยท Web ยท macOS ยท Windows ยท Linux. Mobile-only features (contacts, OS OTP autofill) degrade silently on platforms or permission states that don't support them.

License #

MIT

0
likes
140
points
32
downloads
screenshot

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A comprehensive Flutter input fields kit with smart, animated field types, a phone country picker with contact suggestions, password strength, OTP autofill, and a consistent themeable API across all fields.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

fast_contacts, flutter, permission_handler, phone_number_hint, phone_numbers_parser

More

Packages that depend on cmx_fields