Inputs
Every editor a form is built from, at rest and in the states a field actually reaches: required and empty, and carrying an error.
Spec of record: design-system/components/forms/TextField.d.ts
Live
Real widgets, built from the real kit. Turn a knob and it rebuilds; the theme bar above applies the design system's own tokens — including anything you changed under Customize — and the device selector uses the same sizes the golden baselines gate on, so what you see here is what CI holds the widget to.
Press Focus on any preview to take it to the full window — at a desktop width that renders most devices at 1:1, which is when the widget's own controls become clickable. The bar always states the device and the scale, so a shrunk preview says it is shrunk. Esc leaves.
Every specimen at once, in one state. Per-specimen controls would rebuild the wall a board exists to remove.
Dart for these values
family_inputs() What it is made of
The widgets this screen assembles, with their full API below. They used to live on a second entry of their own; one thing you choose gets one page.
AppTextField widget
The design-system TextField — a themed, token-driven text input claiming the M3 outlined-text-field archetype. Anatomy (the FIELD pattern every later kit field reuses): a DesignTokens.label micro-label rendered above the box (never a floating label — `app_theme.dart` sets…
Full dartdoc
The design-system TextField — a themed, token-driven text input claiming the M3 outlined-text-field archetype. Anatomy (the FIELD pattern every later kit field reuses): a DesignTokens.label micro-label rendered above the box (never a floating label — `app_theme.dart` sets `FloatingLabelBehavior.never` on the shared `inputDecorationTheme`), a box-style field painted entirely by that theme (fill, the 3:1 field border, the focus halo, the DesignTokens.fld height), and an inline danger error line below the box. **Validation runs on blur, not per keystroke.** validator is called once when the field loses focus; a non-null return sets the box to its 2px danger border drawn inside the box (the theme's `errorBorder`; focused, `focusedErrorBorder` with the danger halo) and renders the family's error line 6 below the box — the Warning glyph, then the message in the label size and DesignTokens.danger (TextField.d.ts THE FIELD STATES), the message also being the field node's hint. Typing after an error clears it immediately (re-validated on the next blur) rather than leaving a stale error visible while the user is mid-edit. Uncontrolled by default (`value` / `onChanged`, mirroring the `TextEditingController` idiom in the repo's variation-point canon); pass controller for programmatic control. Exactly one of `value` / `controller` should be supplied. ```dart AppTextField(label: 'Name', onChanged: setName) AppTextField( label: 'Min %', variant: AppTextFieldVariant.data, keyboardType: TextInputType.number, value: min, onChanged: setMin, validator: (v) => rangeError(v), ) ```
AppTextFielddefault constructor
| Knob | Type | Default | What it does |
|---|---|---|---|
| autofocus | bool | false | Requests focus as soon as the field mounts. |
| controller | TextEditingController? | null | Programmatic controller — the `TextEditingController` idiom. When null, the widget owns an internal controller seeded from value. |
| enabled | bool | true | Disables the field (DesignTokens.ink40 foreground, not focusable) when false. |
| error | String? | null | Controlled inline error. When non-null the field renders exactly this copy as the inline danger error — same anatomy as a validator-produced error (danger border on the box, danger message line below). The blur validator still runs and wins after interaction: from the first blur onward its result… |
| focusNode | FocusNode? | null | External focus node — for composition into focus-coordinating hosts (e.g. an autocomplete overlay). When null the widget owns one. Blur validation runs against whichever node is in effect. |
| helper | String? | null | Helper text rendered below the box when there is no active error. An error from validator (or a controlled error) replaces this line rather than stacking beneath it. |
| hint | String? | null | Placeholder shown while the field is empty (theme's `hintStyle`). |
| inputFormatters | List<TextInputFormatter>? | null | Input filters applied before the text changes (TextField.inputFormatters pass-through) — e.g. a digit filter on a numeric field so a rejected character never desyncs the display from the stored value. |
| isRequired | bool | false | Renders the required marker — the trailing accent `*` on the micro-label (design-system pin `5908e48`). Visual only; the programmatic requiredness channel is the form's validation. |
| keyboardType | TextInputType? | null | Software keyboard type. Defaults to TextInputType.text; pass e.g. TextInputType.number alongside `variant: AppTextFieldVariant.data` for numeric fields. |
| label | String? | null | Micro-label rendered above the box, in the label role — sentence case, exactly as passed (`--type-label-transform: none`). Optional per the spec (`label?`): null renders the bare box — used by hosts that own the label row themselves (the stepped-number editor renders its label full-width above the… |
| obscureText | bool | false | Masks the value (password entry). |
| onChanged | ValueChanged<String>? | null | Fires on every keystroke with the field's current text. |
| onSubmitted | ValueChanged<String>? | null | Fired when the user submits from the software keyboard (the TextField.onSubmitted pass-through). Null ignores keyboard submit. |
| prefix | String? | null | A quiet leading text inside the box — the currency symbol (`$`). `TextField.d.ts` THE ADORNMENTS (#783): data font, ink40, NOT the value (never typed, never in onChanged), shown on an empty box and on the disabled face. It joins the field's accessible label after the micro-label. Null or blank:… |
| readOnly | bool | false | Renders the value but blocks editing (distinct from enabled: a read-only field still looks and focuses like an active field). |
| suffix | String? | null | A quiet trailing text inside the box — the unit (`lb`, `%`), drawn before any trailing widget. Same contract as prefix. |
| textAlign | TextAlign | TextAlign.start | How the value aligns in the box (TextField.textAlign pass-through). Default start; a number in a data-table cell is END-aligned (`DataTable.d.ts` THE EDITOR PER TYPE — the digits line up with the column they edit). |
| textInputAction | TextInputAction? | null | The keyboard's action key (TextField.textInputAction pass-through). `next` advances focus to the next field, `done` dismisses — the form assigns these by position so the keyboard walks the form. |
| trailing | Widget? | null | Optional single trailing widget (e.g. a clear or reveal-password affordance). Sized and centered by the field; the caller supplies only the icon/content. |
| validator | String? Function(String value)? | null | Runs on blur (focus loss), not per keystroke. A non-null return is shown as the inline danger error and switches the box to the danger border; null clears any existing error. |
| value | String? | null | Initial value for the uncontrolled form (ignored when controller is supplied). |
| variant | AppTextFieldVariant text · data | AppTextFieldVariant.text | Selects the value's font — AppTextFieldVariant.data for number / date / time values (per the spec, these render in the data font automatically), AppTextFieldVariant.text (default) for free text. |
AppTextArea widget
The design-system TextArea — a themed, token-driven multi-line text input claiming the M3 outlined-text-field archetype. Anatomy mirrors AppTextField's FIELD pattern exactly: a DesignTokens.label micro-label above the box, a box-style field painted entirely by the shared `inputDecorationTheme`, and…
Full dartdoc
The design-system TextArea — a themed, token-driven multi-line text input claiming the M3 outlined-text-field archetype. Anatomy mirrors AppTextField's FIELD pattern exactly: a DesignTokens.label micro-label above the box, a box-style field painted entirely by the shared `inputDecorationTheme`, and an inline danger error line below the box. The differences are multi-line specific: the value text top-aligns, the field grows from minLines to maxLines (then scrolls — no drag-to-resize handle, touch-first), and there is no single-line submit action. **Validation runs on blur, not per keystroke** — identical contract to AppTextField: validator is called once when the field loses focus; a non-null return sets the box to its danger border and renders the message in DesignTokens.dataS / DesignTokens.danger below the box. Typing after an error clears it immediately. When maxLength is set, a quiet `count/max` counter renders in the data font at the trailing end of the meta row (error line leads, counter trails) — never the stock `TextField` counter widget. Uncontrolled by default (`value` / `onChanged`); pass controller for programmatic control. Exactly one of `value` / `controller` should be supplied. ```dart AppTextArea(label: 'Work note', onChanged: setNote) AppTextArea( label: 'Work note', value: note, onChanged: setNote, minLines: 3, maxLines: 6, maxLength: 280, hint: 'What the next crew needs to know', ) ```
AppTextAreadefault constructor
| Knob | Type | Default | What it does |
|---|---|---|---|
| autoGrow | bool | true | `TextArea.d.ts` `autoGrow` — true (the default) grows from minLines to maxLines then scrolls; false pins the box height to minLines and scrolls inside it. |
| autofocus | bool | false | Requests focus as soon as the field mounts. |
| controller | TextEditingController? | null | Programmatic controller — the `TextEditingController` idiom. When null, the widget owns an internal controller seeded from value. |
| enabled | bool | true | Disables the field (DesignTokens.ink40 foreground, not focusable) when false. |
| error | String? | null | Controlled inline error. When non-null the field renders exactly this copy as the inline danger error — same anatomy as a validator-produced error (danger border on the box, danger message line below). The blur validator still runs and wins after interaction: from the first blur onward its result… |
| focusNode | FocusNode? | null | Optional external focus node (the TextField.focusNode idiom) — lets a host land focus programmatically (the form kit's auto-advance). When null, the widget owns an internal node. |
| helper | String? | null | Helper text rendered below the box when there is no active error. An error from validator (or a controlled error) replaces this line rather than stacking beneath it. |
| hint | String? | null | Placeholder shown while the field is empty (theme's `hintStyle`). |
| isRequired | bool | false | Renders the required marker — the trailing accent `*` on the micro-label (design-system pin `5908e48`). Visual only. |
| label | String? | null | Micro-label rendered above the box, in the label role — sentence case, exactly as passed (`--type-label-transform: none`). Optional, matching `TextArea.d.ts` (`label?`) — the Dart port was stricter than its own spec until the thread composer needed the label-less pinned posture. Null renders no… |
| maxLength | int? | null | Hard character cap — input refuses the `maxLength + 1`th character (enforced by a LengthLimitingTextInputFormatter). When set, renders a quiet `count/max` counter in the data font under the box instead of the stock `TextField` counter. |
| maxLines | int? | 8 | Auto-grow cap before the box scrolls. Defaults to 8 (spec: auto-grow from rows to maxRows then scroll); pass null to grow unbounded. |
| minLines | int | 3 | Starting height in text rows. Defaults to 3 (spec default). |
| onChanged | ValueChanged<String>? | null | Fires on every keystroke with the field's current text. |
| readOnly | bool | false | Renders the value but blocks editing (distinct from enabled: a read-only field still looks and focuses like an active field). |
| validator | String? Function(String value)? | null | Runs on blur (focus loss), not per keystroke. A non-null return is shown as the inline danger error and switches the box to the danger border; null clears any existing error. |
| value | String? | null | Initial value for the uncontrolled form (ignored when controller is supplied). |
AppSelect widget
The design-system Select — a themed, token-driven single-select dropdown claiming the M3 exposed-dropdown-menu archetype. Anatomy (the FIELD pattern shared with `AppTextField`): a DesignTokens.label micro-label rendered above the box, and a box-style trigger showing the selected option's label (or…
Full dartdoc
The design-system Select — a themed, token-driven single-select dropdown claiming the M3 exposed-dropdown-menu archetype. Anatomy (the FIELD pattern shared with `AppTextField`): a DesignTokens.label micro-label rendered above the box, and a box-style trigger showing the selected option's label (or hint when value is null) plus a trailing ▾ chevron that flips when open. Tapping (or activating via keyboard) the trigger opens a hairline popover menu of options; the current selection carries a trailing ✓. Selected state is the ✓ only — no filled row, no accent background (constitution: encode once). Uncontrolled selection is not supported — value / onChanged is the only shape (mirrors `AppRadio`'s `value`/`groupValue`/`onChanged`, not `AppTextField`'s controller idiom, since a select's "value" is a single atomic choice rather than editable text). ```dart AppSelect<String>( label: 'Crew', value: crew, onChanged: setCrew, options: const [ ('B-7', 'B-7 — bridge crew'), ('C-2', 'C-2'), ], hint: 'Select crew', ) ```
AppSelectdefault constructor
| Knob | Type | Default | What it does |
|---|---|---|---|
| dataValue | bool | false | Renders the selected value — and the popover option labels — in the data type role (DesignTokens.data): enum codes, IDs, and other machine values. The hint placeholder stays in the body role. Default false (body role, current behavior). |
| disabledValues | Set<T> | const {} | Option values rendered as per-option disabled (Select.jsx `o.disabled`): DesignTokens.ink40 label, not tappable, skipped by keyboard traversal (a disabled `MenuItemButton` never takes focus). Additive to the `(value, label)` tuple so existing option lists keep compiling. Default empty — every option… |
| enabled | bool | true | Disables the trigger (DesignTokens.ink40 foreground, not focusable, popover suppressed) when false. |
| error | String? | null | Controlled inline error. When non-null the select renders exactly this copy as the field family's error line below the box (the Warning glyph, then the message in the UI font at the label size in DesignTokens.danger — `KitFieldMessage`) and the trigger border switches to danger. Default null — no… |
| hint | String | 'Select' | Placeholder shown in DesignTokens.ink40 while value is null. |
| isRequired | bool | false | Renders the required marker — the trailing accent `*` on the micro-label (design-system pin `5908e48`). Visual only. |
| label | String? | null | Micro-label rendered above the box, in the label role — sentence case, exactly as passed (`--type-label-transform: none`). |
| onChanged | ValueChanged<T>? | null | Fires with the tapped option's value when an option is chosen. Null disables the control (not tappable, muted paint). |
| onCleared | VoidCallback? | null | THE NO-VALUE ROW (Select.d.ts, the web kit's `clearable`): non-null makes this a NULLABLE select — its list leads with a row labeled kSelectNoneLabel that fires this and closes, carrying the ✓ while value is null. Null (the default) offers no such row: a required field has no honest "none" to offer.… |
| options * | List<AppSelectOption<T>> | — | The options offered by the popover, in display order. |
| registerOpen | ValueChanged<VoidCallback?>? | null | Hands the host an OPEN for the options — called with it at mount and with null at dispose (the `FieldController.registerActivator` shape the form editors already speak). The form's enum editor registers it as its activator, so auto-advance and a data-table cell's open land on the options, as a… |
| value | T? | null | The current selection, or `null` when nothing is selected yet. |
AppDateField widget
The design-system DateField — a themed, token-driven box-style date input claiming the M3 `showDatePicker` archetype. Anatomy (the FIELD pattern shared with `AppTextField`): a DesignTokens.label micro-label above the box, a box-style field painted entirely by the theme's `inputDecorationTheme`, and…
Full dartdoc
The design-system DateField — a themed, token-driven box-style date input claiming the M3 `showDatePicker` archetype. Anatomy (the FIELD pattern shared with `AppTextField`): a DesignTokens.label micro-label above the box, a box-style field painted entirely by the theme's `inputDecorationTheme`, and an inline danger error line below the box. **The native picker is the touch surface.** Tapping anywhere in the box (not only the trailing calendar glyph) opens `showDatePicker` — manual ISO typing on mobile is poor, so this field is read-only text with a picker-driven value, matching the spec's "native picker IS the picking surface" rule. The trailing calendar glyph is an *accelerator* for the same picker, not a separate or required affordance. **value is a `DateTime?`**, rendered in ISO `yyyy-MM-dd` form using DesignTokens.data (dates are machine text). onChanged fires with the picked `DateTime`, or `null` when the clearable affordance blanks an optional field. **min / max constrain the picker** (`firstDate` / `lastDate`) — they never silently clamp a value that falls outside the range. If value falls before min or after max, the field renders that value with an inline danger error below the box instead of correcting it. ```dart AppDateField(label: 'Due', value: due, onChanged: setDue) AppDateField( label: 'Due', value: due, onChanged: setDue, min: opened, hint: 'Select a date', ) ```
AppDateFielddefault constructor
| Knob | Type | Default | What it does |
|---|---|---|---|
| clearable | bool | false | Renders a clear (✕) affordance beside the calendar glyph while a value is set; activating it fires `onChanged(null)`. Off by default — a required field stays one-way. Without it, an OPTIONAL date field can never be blanked once set. |
| enabled | bool | true | Disables the field (DesignTokens.ink40 foreground, not focusable, picker not launchable) when false. |
| error | String? | null | Controlled inline error. When non-null the field renders exactly this copy as the inline danger error (same anatomy as the self-computed range error), overriding the built-in min/max copy. Default null — range violations render the built-in copy (current behavior). |
| helper | String? | null | Helper text rendered below the box when there is no active error. An error (controlled error or self-computed range copy) replaces this line rather than stacking beneath it. |
| hint | String? | null | Placeholder shown while value is null (theme's `hintStyle`). |
| includeTime | bool | false | Renders the value as `yyyy-MM-dd HH:mm` instead of the date-only ISO form — the dateTime editor's display, so the picked time-of-day is visible and reviewable in the box. |
| isRequired | bool | false | Renders the required marker — the trailing accent `*` on the micro-label (design-system pin `5908e48`). Visual only. |
| label * | String | — | Micro-label rendered above the box, in the label role — sentence case, exactly as passed (`--type-label-transform: none`). |
| max | DateTime? | null | Latest selectable date, passed to `showDatePicker` as `lastDate`. Never silently clamps value — a value after max instead renders an inline danger error. |
| min | DateTime? | null | Earliest selectable date, passed to `showDatePicker` as `firstDate`. Never silently clamps value — a value before min instead renders an inline danger error. |
| onChanged | ValueChanged<DateTime?>? | null | Fires with the newly picked date whenever `showDatePicker` resolves to a non-null selection, and with `null` when the clear affordance (clearable) is activated — the spec's "onChange receives '' when cleared" contract. |
| value | DateTime? | null | The field's current value. Rendered as ISO `yyyy-MM-dd` in the data font; `null` renders hint instead. |
AppSearchField widget
The design-system SearchField — a themed, token-driven box-style search input claiming the M3 `TextField` archetype (never the pill-shaped `SearchBar`). Anatomy: a leading search glyph, the value rendered in DesignTokens.data (operator grammar like `status:blocked` works but is never advertised —…
Full dartdoc
The design-system SearchField — a themed, token-driven box-style search input claiming the M3 `TextField` archetype (never the pill-shaped `SearchBar`). Anatomy: a leading search glyph, the value rendered in DesignTokens.data (operator grammar like `status:blocked` works but is never advertised — hint stays plain), and an intrinsic clear (✕) affordance that appears once the field is non-empty. No micro-label — a search box uses hint in place of the FIELD pattern's above-box label. **Esc clears the field; Enter submits** (onSubmitted). At most ONE trailing action may be supplied in addition to the intrinsic clear — the constitution's "search fields may host one trailing action" ceiling. **On a chrome band** (`chrome: accent | deep` — the compact bar's search mode, the hero band; `AppBar.d.ts` ON A BAND, #1186) the box is the band's FIELD BOX: at rest the DesignTokens.chromeField tonal fill with no border, the value and the placeholder in the on-chrome ink and the glyphs in the on-chrome 60 ink (text needs 4.5:1 on the tonal fill, a glyph 3:1); hovered the 18% state layer; focused it LIFTS to the ordinary field face — paper, ink, the ink60 placeholder and glyphs, and the normal focus ring. Under `chrome: ground` nothing changes. Uncontrolled by default (`value` / `onChanged`, mirroring the `TextEditingController` idiom used by the sibling `AppTextField`); pass controller for programmatic control. Exactly one of `value` / `controller` should be supplied — controller wins when both are given. ```dart AppSearchField(onChanged: setQuery, onSubmitted: runQuery) AppSearchField( hint: 'Search records', value: query, onChanged: setQuery, onSubmitted: runQuery, trailing: AppIconButton(glyph: KitGlyph.filter, title: 'Filter', onPressed: openFilters), ) ```
AppSearchFielddefault constructor
| Knob | Type | Default | What it does |
|---|---|---|---|
| autofocus | bool | false | Requests focus as soon as the field mounts. |
| controller | TextEditingController? | null | Programmatic controller — the `TextEditingController` idiom. When null, the widget owns an internal controller seeded from value. |
| enabled | bool | true | Disables the field (DesignTokens.ink40 foreground, not focusable, clear affordance hidden) when false. |
| hint | String | 'Search' | Placeholder shown while the field is empty (theme's `hintStyle`). Stays plain prose — operator grammar is a hidden power layer, never advertised here. |
| onChanged | ValueChanged<String>? | null | Fires on every keystroke (and when Esc or the clear ✕ empties the field) with the field's current text. |
| onSubmitted | ValueChanged<String>? | null | Fires when Enter is pressed (or the software keyboard's search action is invoked), with the field's current text. |
| trailing | Widget? | null | At most ONE trailing action widget (e.g. a ghost `AppIconButton` for "Filter"), rendered after the intrinsic clear ✕. Null renders none. |
| value | String? | null | Initial value for the uncontrolled form (ignored when controller is supplied). |
ImageEditorWidget widget
Tap-to-capture editor for an image field.
ImageEditorWidgetdefault constructor
| Knob | Type | Default | What it does |
|---|---|---|---|
| controller * | FieldController | — | The field controller (read/write the `staged://{id}` string). |
| spec * | FieldSpec | — | The field spec. |
FileEditorWidget widget
Tap-to-attach editor for a file field.
FileEditorWidgetdefault constructor
| Knob | Type | Default | What it does |
|---|---|---|---|
| controller * | FieldController | — | The field controller (read/write the `staged://{id}` string). |
| spec * | FieldSpec | — | The field spec. |
CanvasEditorWidget widget
Tap-to-capture editor for a signature / drawing field.
CanvasEditorWidgetdefault constructor
| Knob | Type | Default | What it does |
|---|---|---|---|
| controller * | FieldController | — | The field controller (read/write the `staged://{id}` string). |
| mode * | CanvasEditorMode signature · drawing | — | Signature vs drawing vocabulary. |
| spec * | FieldSpec | — | The field spec. |
LatLongEditorWidget widget
Map-window + tile editor for a `"lat,long"` field.
LatLongEditorWidgetdefault constructor
| Knob | Type | Default | What it does |
|---|---|---|---|
| controller * | FieldController | — | The field controller (read/write the `"lat,long"` string). |
| spec * | FieldSpec | — | The field spec. |
| tileProvider | TileProvider? | null | Explicit tile provider for the nudge window AND the pushed LatLongPicker (ledger F-51) — the picker's own sanctioned seam, so the editor→picker→commit chain is testable headlessly. A host wanting it registers a closure over LatLongEditorWidget instead of the bare latLongEditor entry. Null keeps the… |
ImagePointEditorWidget widget
Tile + preview + picker editor for an `"x, y"` image-point field.
ImagePointEditorWidgetdefault constructor
| Knob | Type | Default | What it does |
|---|---|---|---|
| controller * | FieldController | — | The field controller (reads/writes the `"x, y"` string). |
| spec * | FieldSpec | — | The field spec. |
CanvasPadScreen widget
The full-screen capture pad — a paper canvas collecting freehand strokes, a Clear ghost action, and a Done slab that pops the rasterized image. Public for widget tests; hosts never construct it directly.
CanvasPadScreendefault constructor
| Knob | Type | Default | What it does |
|---|---|---|---|
| clearLabel * | String | — | Clear-strokes action label. |
| doneLabel * | String | — | Commit action label. |
| title * | String | — | Header title (signature vs drawing vocabulary). |
Types its knobs take
These are not things you choose — they are the shapes the knobs above expect. They live under this entry rather than in the navigation for exactly that reason.
FieldController support
Per-field handle threaded into each `FieldEditor` widget. Bundles read/write access to the field's value with its derived editable / required / error state.
| Field | Type | Default | What it does |
|---|---|---|---|
| _parent * | FormController | — | |
| _spec * | FieldSpec | — | |
| onAdvance | void Function(FieldSpec spec)? | null | |
| setActivator | void Function(Object owner, String snakeName, VoidCallback? activate)? | null | |
| textInputAction | TextInputAction? | null | The software keyboard's action key for this field, assigned by the form from the field's position: `next` on every single-line editor except the last, `done` on the last — so the keyboard walks the form instead of dismissing between every field. Null (a standalone editor host) keeps the platform… |
FieldSpec support
Per-field static metadata describing how a single column renders in a `FormView`. Pure data — no widget references, no controllers.
| Field | Type | Default | What it does |
|---|---|---|---|
| allowOtherValues | bool | false | Whether an `enumValue` or `enumList` column accepts values outside enumValues (origin `AllowOtherValues:true` — 238/263 enums). When true an `enumValue` editor is an open combobox: a text input + filtered suggestions + a pinned `Add "{typed}"` row committing the typed value verbatim; an `enumList`… |
| columnType * | ColumnType | — | Column type — drives editor dispatch in `FieldEditorRegistry`. |
| decimalPlaces | int? | null | An `exactDecimal` field (and a quantity's number): at most this many digits after the point, counted as typed (`FormView.d.ts` AN EXACT DECIMAL IS ITS STRING). An intrinsic check. Null: any number of places, within `numeric`'s limit. |
| defaultUnit | String? | null | A quantity field's starting unit code; null starts at the first of units. |
| derive | FieldDeriver? | null | Recomputes this field's value from the live values map whenever any field changes — the in-form face of a write-time computed column. A derived field is **read-only by construction**: `FormController.isEditable` returns false for it, so a user edit can never be clobbered by the next unrelated… |
| editableIf | FieldPredicate? | null | Reactive `Editable_If` — when non-null, overrides isReadOnly: the editor accepts input only while this returns true. Null falls back to `!isReadOnly`. §D1. |
| enumDisplay | EnumDisplay | EnumDisplay.buttons | Display mode for `enumValue` columns (see EnumDisplay). Ignored for every other column type. Defaults to EnumDisplay.buttons. |
| enumValues | List<String>? | null | Pre-defined value set for `enumValue` / `enumList` / `color` editors. Null for other column types. |
| exactMax | ExactDecimal? | null | The inclusive upper bound, as exactMin. |
| exactMin | ExactDecimal? | null | An `exactDecimal` field (and a quantity's number): the inclusive lower bound, compared EXACTLY (ExactDecimal.compareTo, never through a float). An intrinsic check. A quantity's bound is in the value's own unit; a bound in another unit is the host's validator. |
| formatRules | List<FormatRule<Map<String, Object?>>>? | null | FORMAT RULES on the LOCKED face only (`FormView.d.ts` THE LOCKED FACE WEARS ITS RULE, #1006; `FormatRules.d.ts`): while the field is locked (read-only, editableIf false, a derived field) its value wears the first holding rule, as a detail field does. The SUBJECT is the field's value, and the ROW an… |
| helper | String? | null | Optional helper text rendered below the field label. Slice 18 surfaces this in `FieldCard`; emit threads it from the source per-field description when present. |
| initialValue | Object? Function()? | null | Optional seed for the field's value at form construction. A plain thunk — `() => DateTime.now()`, `() => 0.45` — invoked once when the controller builds (and again on reset). Returning `null` (or leaving it unset) starts the field empty. |
| inlineAction | FieldAction? | null | Field-scoped auxiliary action rendered beneath this field's editor — see FieldAction. Null renders no affordance. |
| isHidden | bool | false | Hidden fields are seeded into form state and round-trip through save, but render no editor — useful for a system key column carrying a generated id via initialValue. |
| isOwed | bool | false | Required LATER, never at save (`FormView.d.ts` A FIELD MAY BE OWED, #1496): the micro-label carries the required marker and the control is announced required, but the field never gates the save, never counts toward `FormController.requiredBlankCount` and never raises the required message, and its… |
| isReadOnly | bool | false | Static read-only flag — the editor is disabled whenever this is true. |
| isRequired | bool | false | Static "required regardless of state" flag — drives the required-blank validation in `FormController`. |
| label * | String | — | Human-readable label rendered as the editor's `labelText`. |
| listSeparator | String? | null | The write separator of an `enumList` / `refList` field — the column's own spelling (`ColumnDef.listSeparator`, threaded by the field plan, `bindFieldPlan`). Null writes `kEnumListSeparator`. The source platform's item separator is a per-column property; reads are separator-tolerant. |
| listValue | bool | false | An `enumList` (or a list of refs) whose value is a `List<String>`, not the joined string (`FormView.d.ts` AN ENUM LIST'S VALUE MAY BE ITS LIST, #1496): members verbatim, in held order, any text, never split, so a member may hold the separator. A held joined string is read through the list grammar… |
| maxDate | DateTime? | null | The latest offered day, inclusive, as minDate. |
| minDate | DateTime? | null | A `date` / `dateTime` field's earliest offered day, inclusive (`FormView.d.ts` A DATE CAN BE BOUNDED): reaches `AppDateField.min` and an intrinsic check. Null: unbounded. |
| noLabel | String? | null | The no-word of a `yesNo` field (origin `NoLabel`) — where the value is READ BACK rather than edited (a detail, a cell, a review line); the form's row never shows it. Null reads "No". §D4. |
| numberFormat | AppNumberFormat? | null | How a `number` / `decimal` / `percent` value reads on the field's LOCKED face (`FormView.d.ts` `FormField.numberFormat`; the rules are `DataTable.d.ts` NumberFormat's). THE LOCKED FACE READS AS THE CELL READS: while the field is not editable (read-only, editableIf false, a derived field) the box… |
| options | List<FieldOption>? | null | Labeled options for an `enumValue` / `enumList` field (`FormView.d.ts` AN OPTION HAS A LABEL, AND A RETIRED OPTION IS ONLY EVER HELD; steady-core #1491). When set it wins over enumValues: the stored value is FieldOption.value, every face shows FieldOption.label, and a FieldOption.retired option is… |
| override | FieldOverride? | null | The field's value comes from a WIDER SCOPE and may be overridden here (`FormView.d.ts` A FIELD MAY INHERIT ITS VALUE) — see FieldOverride. Null: an ordinary field whose value is its own, and nothing renders. |
| placeholderOf | String? Function(Map<String, Object?> values)? | null | What an EMPTY value MEANS, read against the live values (`FormView.d.ts` `FormField.placeholderOf`, 2026-10-09, #1217) — a nullable override whose blank is "auto", or a typical rate the blank falls back to. The answer paints in `--ink40` inside the editor's box while the value is blank: on the form,… |
| ref | RefFieldConfig? | null | Ref-column config — target table, choice-list stream, add-new builder. Null for every column that holds no ref: a `ref` column, and a LIST of refs (an `enumList` whose members are target keys — its editor is `kitRefListEditor`), carry one. |
| requiredIf | FieldPredicate? | null | Reactive `Required_If` — when non-null, overrides isRequired: the field is a save-gate only while this returns true. Null falls back to the static isRequired. §D1. |
| resetRule | ResetRule? | null | Reactive reset rule (origin `Reset_If` / `ResetOnEdit`). Null means the field is never auto-cleared. See ResetRule, §D1. |
| ruleLock | FieldRuleReading? | null | A DECLARED RULE's lock (`FormView.d.ts` `FormField.ruleLock`, FieldRules.d.ts THE BINDING): why the rule locks the field over the live and stored values, or null while it does not. The binding sets it (withFieldRules) and ANDs the same answer into editableIf; the form reads it only for THE WORDS… |
| ruleRefusal | FieldRuleReading? | null | A DECLARED RULE's save-time check (`FormField.ruleRefusal`): why the server would refuse THIS save's write of the field, or null when it permits. A refusal is the field's error line, in THE WORDS (`FormController.ruleRefusal`). The binding sets it. |
| section | String? | null | Optional section grouping. Null means "no section header" — the field still renders, but in the default un-headered section. Sourced from the source form's section settings. |
| showIf | FieldPredicate? | null | Reactive `Show_If` — when non-null, the field renders an editor only while this returns true over the form's current values. Null means "always visible" (the static default). A hidden-by-rule field leaves the layout, semantics, and focus tree; it does **not** null its value (only an explicit reset… |
| snakeName * | String | — | snake_case column name. Matches the key produced by `RowCodec<T>.encode(row)` and serves as the form-state map key. |
| span | FieldSpan | FieldSpan.auto | Layout span on tablet form factors (see FieldSpan). Phone always collapses to single column regardless of span. Defaults to FieldSpan.auto — the editor's natural width decides pairing. |
| stepValue | num? | null | Step increment for a `number` / `decimal` / `percent` editor (origin `StepValue`, e.g. `number_of_people` StepValue 1; a percent steps in the whole points it shows). When non-null the editor flanks the field with −/+ 48dp targets; the field still accepts typed input. Null renders a plain numeric… |
| suggestedValues | SuggestedValuesResolver? | null | Live suggestion source for an OPEN enum's combobox, and an OPEN enum list's entry surface (allowOtherValues) — typically the column's own already-used values, so free entry converges on the estate's vocabulary instead of minting near-duplicates. The editor subscribes once for its lifetime and merges… |
| temporal | TemporalSemantic | TemporalSemantic.instant | What a NAIVE `dateTime` value means (`FormView.d.ts` `temporal`, the column's `ColumnDef.temporal`, threaded by `bindFieldPlan`): TemporalSemantic.instant (the default) reads it in device-local time; TemporalSemantic.wallClock keeps the time as written. Read by a data table cell's typed entry and a… |
| units | List<QuantityUnit>? | null | An `exactDecimal` field that edits a QUANTITY (`FormView.d.ts` A QUANTITY IS A NUMBER AND ITS UNIT): the units it offers, in order. When set the value is a QuantityValue (`value`, `unit`), never a string; one unit is the box's suffix, several an `AppSelect` beside it. Null: a plain exact decimal. |
| validator | FieldValidator? | null | Value-level validation rule. Null means "any non-blank value is acceptable" (the static default) — this field is the ONLY way a form rejects a value on grounds other than blankness. The rule runs **after** the blank / required decision and only on a non-blank value, so it never re-implements… |
| yesLabel | String? | null | The yes-word of a `yesNo` field — the label of its one checkbox row, what ticking asserts (origin `YesLabel`, e.g. `report_request.is_report_package` → "Report Package"). Static: it is never re-worded per toggle. Null renders "Yes". |
Where it lives
| Class | File |
|---|---|
| AppTextField | packages/app_widgets/lib/src/kit/forms/text_field.dart |
| AppTextArea | packages/app_widgets/lib/src/kit/forms/text_area.dart |
| AppSelect | packages/app_widgets/lib/src/kit/forms/select.dart |
| AppDateField | packages/app_widgets/lib/src/kit/forms/date_field.dart |
| AppSearchField | packages/app_widgets/lib/src/kit/forms/search_field.dart |
| ImageEditorWidget | packages/app_widgets/lib/src/form/_image_editor.dart |
| FileEditorWidget | packages/app_widgets/lib/src/form/_file_editor.dart |
| CanvasEditorWidget | packages/app_widgets/lib/src/form/_canvas_editor.dart |
| LatLongEditorWidget | packages/app_widgets/lib/src/form/_lat_long_editor.dart |
| ImagePointEditorWidget | packages/app_widgets/lib/src/form/_image_point_editor.dart |
| CanvasPadScreen | packages/app_widgets/lib/src/form/_canvas_editor.dart |