@prepared911/ui does not ship react-hook-form, Zod schemas, or Form* controller wrappers. Form is the form element. Field is a labeled control. Layout blocks compose Save and Cancel.
Import
Form
Import Form from @prepared911/ui/form. It renders a form element. It does not provide a form context.
Prop
Behavior
onSubmit
Runs after native validation. The caller validates and sets invalid or errorSummary. If it returns a promise and pending is not controlled, the form stays pending until the promise settles.
pending
Sets aria-busy and ignores further submits. useFormPending() is how a Save button reads that state.
errorSummary
Localized copy in an alert before the fields.
errorFocus
After a failed attempt, focus moves to the first invalid control (FirstInvalid, the default), the summary, or nowhere (None).
noValidate
Defaults to true so the browser does not race the caller's validation.
onAfterReset
Runs after a native reset. The form does not clear caller state.
Save stays enabled when values are unchanged. The form does not track dirty state.
Field
Import Field from @prepared911/ui/field. It composes a label, the control, description, and error. Input is the bare control and has no label or icons.
Prop
Behavior
label
Visible name of the control.
type
FieldType, including Password and Tel.
leadingIcon, trailingIcon
Decorative icons.
action
One button at the end. Search and Password own their own trailing control, so they do not take action.
mask
Input mask. It is not a separate enum to pass to Input.
onValueChange
The next value and a details object. This replaces onChange(event) on the old input.
An international country select is not part of Field. North American phone numbers use FieldType.Tel.
Select
Import Select from @prepared911/ui/select. Options replace an items list. An empty value is null. Put Select inside the app's controller when the form library owns the value.
Layout blocks
Block
Import
Role
FormLayoutStandard
@prepared911/ui/blocks/form-layout-standard
Fields plus a Save/Cancel footer. submitLabel is required. submitIntent defaults to accent.
FormLayoutSectioned
@prepared911/ui/blocks/form-layout-sectioned
The same submit contract across sections.
FormLayoutDrawer
@prepared911/ui/blocks/form-layout-drawer
A drawer with a scrolling body and a sticky footer. Closing a dirty form asks for confirmation.
FormDialog
@prepared911/ui/blocks/form-dialog
A dialog with the same submit and dirty-guard behavior.
These blocks pass onSubmit, errorSummary, invalid, errorFocus, pending, and noValidate through to Form. Copy props are localized messages with no default English strings.
FormLayoutStandard does not disable Save because the form is pristine. submitDisabled is an explicit prop, default false.
App-owned validation
Keep Zod and react-hook-form in the feature. Render Form or a layout block and pass onSubmit={form.handleSubmit(fn)} from the app. @prepared911/ui does not export useZodForm, emailSchema, or FormInput.