FlexTextInput
Bjanczak\FilamentFlexFields\Filament\Forms\Components\FlexTextInput extends
Filament TextInput. Filament owns persisted state, casts, validation, actions,
relationships and binding modifiers. FLEX owns its presentation and optional
browser tools. The browser tools use the native input binding, with no separate persisted-state engine.
Native compatibility
Use nativeemail(), numeric(), integer(), password(), tel(), url(),
type(), inputMode(), minValue(), maxValue(), step(), minLength(),
maxLength(), length(), masks (including RawJs), stripCharacters(),
datalist(), autocomplete, autofocus, capitalization and spellcheck as usual.
Native validation, hydration/dehydration callbacks, disabled/read-only behavior,
live()/lazy()/blur bindings, affixes, icons, colors, prefix/suffix actions,
extraInputAttributes() and extraAlpineAttributes() remain available through
inheritance. Native CopyAction, ShowPasswordAction and HidePasswordAction
retain their visibility, disabled state, attributes and accessible labels.
A mask uses native text-input rendering. Explicit type() is respected;
password reveal only changes the DOM type when the native type is password
and no mask is configured. Read-only fields may still offer copying. Clearing,
suggestions, drafts, emoji and dictation cannot edit a disabled/read-only field.
Native maxLength() has the browser’s UTF-16 maxlength semantics while native
server string validation uses Laravel’s semantics. FLEX counterLimit() with
enforceCounterLimit() provides a separate, explicitly selected unit on both
client and server. Neither counter mode nor visual strength silently replaces
native validation. Domain-specific validation still belongs to application rules.
Options
Options accept closures where their fluent signature allows them. Defaults and budgets are centralized inSupport/TextInput/TextInputOptions.php; unsupported
choices fail explicitly. Builder configuration uses the same contract with
snake_case names (for example counter_mode, draft_lifetime). Callback-backed
suggestions and verification belong to application PHP, not serialized config.
Counters
Word counting splits trimmed text on Unicode whitespace. Grapheme counting uses
PHP Unicode clusters and browser
Intl.Segmenter; an unsupported browser reports
unavailable counting and rejects an enforced grapheme edit instead of changing
the unit silently. Older ICU/Unicode versions can differ on newly introduced
clusters. Server validation is authoritative. Large text is not segmented unless
a counter, hard unit limit or reading-time feature needs it.
Editing and reading
Typing uses native DOM selection and IME composition. Tool edits dispatch one
input event and preserve the relevant caret. Ctrl/Cmd+Z can undo the most recent
FLEX tool edit while the input still matches its result; unrelated native edits
invalidate that tool history. This is not a replacement for browser undo history.
Normalization runs on blur and is opt-in; apply equivalent server normalization
when the stored representation must satisfy an application rule.
Copying and toolbar
Native
copyable(true, 'Copied!', 1200) configures the message and duration.
Clipboard success is shown only after copying succeeds. The legacy fallback
preserves source type, focus and selection. Loading stays in the input control,
independent of toolbar visibility. A toolbar with no available actions leaves
no separator or empty position.
Passwords
Emoji and dictation
Enable with
emojiPicker() and/or speechDictation(). Additional methods are
emojiPickerLocale(), emojiPickerLabel(), speechDictationLanguage() and
speechDictationLabel(). Browser support and permission still govern dictation.
A browser network recognition error means communication with its speech service
failed, even when the device remains online. The field displays that distinction.
Only native SpeechRecognition / webkitSpeechRecognition is used; FLEX does
not download or install speech models. Service access is provided by the browser.
Click the microphone again to retry after an error.
Stopping keeps the session busy until final results arrive. Final results are
committed once through the native input event, updating Livewire state and the
counter together. Finalized text survives a subsequent service error; interim
text is never saved as a final transcript. Only one field in a document uses the
recognition microphone at a time. Switching fields, revoking editability,
hiding the document or disposing the owner retires its session and callbacks.
Closing/removing/disabling its owner aborts a session and discards pending text.
Emoji content loads only when opened. Input and textarea reuse one picker,
Select’s positioning, portals, exclusivity and enter/exit transitions. Shared CSS
has one owner; it is not copied into each consuming field.
Default action icons use Hugeicons: Mic01 (the shape without a horizontal foot),
LookTop and MultiplicationSign. Override with microphoneIcon(), emojiIcon(),
clearIcon(), copyIcon(), copySuccessIcon(), showPasswordIcon() and
hidePasswordIcon(). Password reveal uses ViewIcon / ViewOffIcon. All default FLEX icons are from the package’s Hugeicons set.
Suggestions, verification and drafts
City and User are example application models. Authorize tenant/user access
inside callbacks. These independent examples use native
skipRenderAfterStateUpdated() so a deferred text update bundled with a lookup
does not replace the focused input. Keep normal rendering when your server-side
state hooks must update other fields or the input configuration.
Static suggestions accept at most 200 normalized records;
value ≤512, label ≤120 and description ≤240 characters. Disabled records remain visible but cannot
be selected; this is an option state, not a loading error. Free text remains permitted. Keyboard arrows, Enter and Escape,
ARIA listbox/combobox semantics and retry feedback are built in. Suggestions use
the same menu surface as Select, not a second overlay engine.
Remote methods are exposed through Filament with renderless callbacks, bounded
input and shared actor/field rate limiting. Single-flight work retains only the
latest pending query; a small bounded cache avoids repeated suggestion requests.
Late results cannot restore a disposed/disabled field. Callback verification
returns success/error/warning and a message ≤512 characters; the field stays idle
when verification is not eligible. This is
advisory and does not replace submit-time server validation. Avoid putting
sensitive values into remote verification callbacks.
Drafts use pathname + explicit key, TTL and a maximum 8192 UTF-16 code units.
Restoration only occurs into an empty field; it never overwrites filled server
state. An empty edit removes the stored draft. Storage failures produce feedback.
Use unique keys when several instances exist. Keep sensitive data out of browser
drafts. No draft module is initialized without opting in.
Additional presentation API
variant(primary|secondary|flat|soft), size(sm|md|lg),
rounding(native|none|sm|md|lg|xl|full) and focusOutline() preserve FLEX’s visual
language. characterCounter(), clearable(), loading(), passwordStrength(),
passwordStrengthLabels() and validating() enable their respective features.
The password indicator has four neutral segments before editing. Weak and very
weak values fill one red segment; fair values fill two amber segments; good and
strong values fill three and four green segments. Fill transitions run in both
directions, mirror in RTL, and respect reduced-motion preferences. Existing
five-level passwordStrengthLabels() remain configurable. The indicator is an
estimate; passwordRequirements() and native validation enforce your actual
submission policy. When passwordRequirementsVisible() is enabled, each rule
has its own row and circular check indicator. Green check indicators animate when rules are met,
and their spoken met/not-met state is localized. The list follows RTL and stays
in one column on small screens.
Static badges use verificationStatus(), verificationStatusIcon() and
verificationStatusColor() independently of async verification.
Demo and examples
The live demo groups examples by task: native input features, Unicode limits, editing, actions, passwords, emoji and dictation, suggestions and drafts, and appearance including RTL. Open Code Example for copyable PHP configurations. Only the active demo group loads its optional tools.Loading and behavior
Plain inputs do not load icon or emoji catalogs. Enable only the tools your field needs: suggestions, verification, drafts and dictation load on demand, and the emoji picker loads its content when opened. Shared resources are reused across instances. Emoji and icon menus align to the whole input, rather than their toolbar button: right edge in LTR and left edge in RTL. Suggestions match the input’s width and align with its start edge. Menus follow resize and scroll, open above when space below is limited, and stay inside the viewport. Small screens use the shared mobile sheet. Removing a field, changing its capabilities or making it disabled/read-only releases its active tools and prevents late responses from changing its state. Normal Livewire value updates preserve the active controller.Associated icon picker
Add an icon action inside the text input without a separate form row. The text remains a normal string, while the icon is a separate, server-validated value. The dropdown shares the existing Icon Picker: search, library filters, pagination, SVG caching, keyboard support and virtualized results.statePath('data') saves data.title and data.title_icon. In a repeater, each row keeps its own text and icon. Do not add a second Hidden or Icon Picker field for the same icon path: the embedded native field already owns hydration, validation and dehydration. Add a nullable string column for the icon when using ordinary Eloquent columns, or keep both keys in your JSON form data.
The configuration callback accepts the ordinary Icon Picker API. Installed Blade icon sets are available through sets(); a library must be registered in your application before you select it. icons() restricts choices to explicit identities, and excludeIcons() removes identities. Both search results and save validation enforce the same policy.
null. The text value is preserved, and a cleared icon stays empty after reload; the trigger displays the default picker symbol. Use clearable(false) in the callback to hide the clear action. Use required() if an empty icon must fail server validation.
Available callback settings include sets(), icons(), excludeIcons(), searchResultsLayout('icons'|'grid'|'list'), gridColumns(), perPage(), limitPerSet(), preload(), closeOnSelect(), clearable(), label(), required() and native field validation hooks. The owner fixes the embedded state path, inline trigger and parent disabled/read-only boundary.
preload() is explicitly enabled. Choosing an icon does not transmit or replace the text input’s value.
For standalone compact triggers, IconPickerField::make('icon')->inlineTrigger() uses the same control without its usual select label/name presentation. Use the associated-input API above when it belongs to a text input.
Server-side value protection
FLEX rejects structured array/object values submitted to a scalar text input, including empty arrays. Optional empty and null values retain native Filament behavior. Required, email, URL, numeric, unique, length and application-specific rules still belong to the native form. Enforced Unicode limits and password requirements are checked on the server as well as shown in the browser. The animated strength meter andverifyUsing() feedback are advisory; use
passwordRequirements(), native validation rules and your form’s save action to
enforce the policy. Selecting an icon stores its name separately and validates
it against the configured libraries and allowed list.
Emoji and icon menus fit the viewport: at widths up to 768 px they use the shared
mobile sheet; above that boundary they use a clamped desktop panel with automatic
above/below placement. Their results scroll internally when height is limited.
An empty search placeholder follows RTL, while entered Latin/Arabic text keeps
native automatic text direction.