import { type FormHTMLAttributes, type ReactNode } from 'react'; /** * A form: Enter in a field, or a submit button, sends it, and the page never * reloads. On Base UI's `Form` (UIG-7, 16 September), which the apps' five * forms had each written around a plain `
`: `preventDefault`, a busy * flag, and `disabled={busy}` on every field one by one. * * Base UI's part, as it renders it: a `` — the browser's own * validation bubbles are off, which no field in either app used — that, on * submit, checks every `Field` inside and moves focus to the first one that is * invalid instead of sending. `Field`'s `error` is still how an error shows. * * `busy` is ours. While it is on, the children sit in a disabled * `
` (Base UI's `Fieldset`, with no box of its own), so every field * and button inside is switched off at once — the package's Button, * IconButton and Checkbox wearing their own switched-off look, which a * fieldset alone does not give them (`formBusy.ts`) — and focus waits on the form * rather than falling to the page. Chrome drops focus to `` the moment * the focused field is disabled, before any effect runs, and jsdom does not — * so the form remembers the last element inside it that had focus, and takes * focus back from the page on its behalf (measured in Chrome, 16 September). * When `busy` ends, focus goes to the first invalid field, else to what sent * the form, else to the first control. That is `CommandPalette`'s order * too, so the two read the same (UIG-29). * * The keys are ours, the same in every form (Katerina, 16 September): Enter in * a one-line field sends; Enter in a text area is a new line; Enter in a list * or a people picker picks; Ctrl+Enter (Cmd+Enter) sends from anywhere inside. * The form sends on Enter itself rather than leaving it to the browser, whose * implicit submission depends on whether the form has a submit button and how * many fields it holds. `enterSends={false}` keeps Enter in a one-line field * from sending, for a form where only Ctrl+Enter may send (`CommandPalette`). * Every way of sending goes through the form's submit, so Base UI's field * check runs for each. * * **The form places its fields** (Katerina, 28 September). It drew no box and * left the space between fields to every caller, and they chose three: Peek's * dialogs 8px — the label's own distance from its box, so a label sat as close * to the field above it as to its own — Ship's 24px, and the package's own * launcher 16px. Everything inside now stacks 24px apart, and the gate lint * refuses a layout passed in (`no-restyled-part`). A form that is not a list * of fields — a field and its button, a composer — says `layout="free"` and * lays itself out. */ export interface FormProps extends Omit, 'onSubmit' | 'children' | 'noValidate'> { /** Enter in a field, or a submit button. The page's own submit is already prevented. */ onSubmit: () => void | Promise; /** While sending: every field and button inside is switched off, and focus waits on the form. */ busy?: boolean; /** * Whether Enter in a one-line field sends. On by default. Off where only * Ctrl+Enter may send — a form inside `CommandPalette`. Ctrl+Enter sends either way. */ enterSends?: boolean; /** * `fields`, the default: everything inside stacks 24px apart. `free`: the * form places nothing, for a form that is not a list of fields — a field and * its button, a composer — which lays itself out through `className`. */ layout?: 'fields' | 'free'; children: ReactNode; } /** A list of fields: one column, 24px apart. `CommandPalette` stacks its fields with it too. */ export declare const FIELDS_CLASSES = "flex flex-col gap-6"; export declare function Form({ onSubmit, busy: ownBusy, enterSends, layout, className, children, ...props }: FormProps): import("react").JSX.Element; //# sourceMappingURL=Form.d.ts.map