import type * as React from 'react'; import type { FormValidityHandle, FormValidityStateView } from '../utils/formControl.js'; import type { PrimitivePropsWithRef } from '../utils/primitive.js'; /** @internal Shared state distributed from {@link TextField} to its parts via context. */ export interface TextFieldContextValue { inputId: string; disabled: boolean; readOnly: boolean; invalid: boolean; required: boolean; value: string; setValue: (value: string) => void; /** Submitted under this key by the wrapped input; `undefined` submits nothing. */ name?: string | undefined; /** Id of the `
` the wrapped input submits with; `undefined` uses the enclosing one. */ form?: string | undefined; /** The wrapped ``, so the root can answer `checkValidity()` off it and find the owning form. */ inputRef: React.RefObject; /** Root `id` and aria attributes that belong on the wrapped input, so `FormControl` and `Field` wiring lands there. */ forwarded: Pick, 'id' | 'aria-describedby' | 'aria-invalid' | 'aria-labelledby'>; } /** * The forwarded ref's handle: the root `
` with constraint-validation methods and live `validity`/`validationMessage` getters over the wrapped ``. */ export type TextFieldHandle = HTMLDivElement & FormValidityHandle & FormValidityStateView; /** Props for the {@link TextField} root. */ export interface TextFieldProps extends PrimitivePropsWithRef<'div'> { /** * Disables the field and the input it wraps. * @default false */ disabled?: boolean | undefined; /** * Marks the field as invalid, exposed as `data-invalid` on the root and * `aria-invalid`/`data-invalid` on the input. * @default false */ invalid?: boolean | undefined; /** * Marks the wrapped input as required. * @default false */ required?: boolean | undefined; /** * Current value, for controlled usage; pair with `onValueChange`. * @default undefined — uncontrolled, tracks its own value internally. */ value?: string | undefined; /** * Initial value, for uncontrolled usage — seeds the internally-tracked value. * @default undefined — starts empty. */ defaultValue?: string | undefined; /** * Fires with the new value whenever the input changes, controlled or not. * @default undefined — no-op. */ onValueChange?: ((value: string) => void) | undefined; /** * Form field name, set on the wrapped native `` so the field submits, validates, and resets with the surrounding ``. * @default undefined — submits nothing. */ name?: string | undefined; /** * Id of the `` this field submits with, put on the wrapped native `` as its `form` attribute. * @default undefined — the enclosing ``. */ form?: string | undefined; /** * Renders a derived `TextFieldClearButton` once the field has a value; ignored when `children` is given. * @default false */ clearable?: boolean | undefined; /** * The derived clear button's accessible name, meaningful only with `clearable`. * @default 'Clear' */ clearLabel?: string | undefined; /** * Renders a leading `TextFieldSlot` holding this content, before the input; ignored when `children` is given. * @default undefined — no leading slot rendered. */ leading?: React.ReactNode | undefined; /** * Renders a trailing `TextFieldSlot` holding this content, after the input; ignored when `children` is given. * @default undefined — no trailing slot rendered. */ trailing?: React.ReactNode | undefined; /** * Placeholder for the derived input; ignored when `children` is given, since the root forwards no arbitrary input attributes. * @default undefined */ placeholder?: string | undefined; /** * Native `type` for the derived input, such as `'email'` or `'search'`; ignored when `children` is given. * @default 'text' */ type?: string | undefined; /** * Native `readonly` for the derived input; ignored when `children` is given. * @default false */ readOnly?: boolean | undefined; /** * Size rung the skin scales the field by, mirrored to `data-size`. * @default undefined — the skin's own default size. */ size?: 'md' | 'sm' | 'lg' | (string & {}) | undefined; /** * Visual weight rung the skin gives the field, mirrored to `data-variant`. * @default undefined — the skin's own default weight. */ variant?: 'filled' | 'ghost' | (string & {}) | undefined; } /** Props for {@link TextFieldInput}, the native `` driven by `TextField`'s context. */ export interface TextFieldInputProps extends Omit, 'value' | 'defaultValue' | 'size'> { /** * Native `readonly`: value stays selectable, copyable, focusable and submitted, * but editing is blocked — unlike `disabled` on the root. * @default false */ readOnly?: boolean | undefined; /** * Size rung the skin scales the input by, mirrored to `data-size`. * @default undefined — the skin's own default size. */ size?: 'md' | 'sm' | 'lg' | (string & {}) | undefined; /** * Visual weight rung the skin gives the input, mirrored to `data-variant`. * @default undefined — the skin's own default weight. */ variant?: 'filled' | 'ghost' | (string & {}) | undefined; } /** Props for {@link TextFieldSlot}, a decorative container for icons/adornments beside the input. */ export interface TextFieldSlotProps extends PrimitivePropsWithRef<'span'> { /** * Which end of the field this slot sits at, exposed as `data-side`. * @default 'start' */ side?: 'start' | 'end' | undefined; } /** Props for {@link TextFieldClearButton}, a button that resets the field's value to empty. */ export interface TextFieldClearButtonProps extends PrimitivePropsWithRef<'button'> { /** * Keep mounted even when the field is empty or uncontrolled (for exit animations). * @default false */ forceMount?: boolean | undefined; /** * Accessible name for the button (icon-only, no text); a directly-written `aria-label` still wins. * @default 'Clear' */ label?: string | undefined; }