/** * TimePicker — a time of day behind a trigger, in one of three faces. * * ```tsx * const [time, setTime] = useState(); * * * ``` * * The value is `{ hour, minute }` on a 24-hour clock, whatever the face shows. * A 12-hour display is a rendering choice; storing 7pm as `{ hour: 7 }` plus a * meridiem flag would put the flag into every comparison downstream. * * ## Three layouts, because "pick a time" is three different tasks * * - **`wheel`** — hour, minute and meridiem as snapping columns. The precise * one: any minute in the day is two or three flicks away. The default. * - **`clock`** — a face beside a list of times at a fixed step. For picking a * *slot* rather than a time — a booking, a reminder, an appointment — where * the face answers "is that morning or evening?" faster than reading digits. * - **`ruler`** — one large readout over a swipeable scale. The coarse one, and * the only one that reads at arm's length, so it is the one for a sheet with * a thumb on it. * * All three produce the same value and take the same props. Swapping between * them is a one-word change, which is the point of them being one component. * * ## Presentation is separate from layout * * `popover`, `dialog` and `bottom-sheet` wrap the same panel; `inline` renders * it bare, for composing into a Frame or a form. Popover and sheet hand off to * `Popover`, which already owns both — but `Popover` has no dialog form, so * the switch lives here rather than being pushed down into it. A picker is * also the wrong place to widen a general-purpose overlay: the three shapes * differ in how they are *dismissed*, not in what they contain. * * ## Scroll offset, not gesture maths * * The wheel, the clock's list and the ruler are snapping scroll views, and the * selection is `Math.round(offset / itemSize)`. That buys momentum, * deceleration, edge bounce and platform-correct fling physics for nothing, * and none of it would be worth rebuilding on a pan gesture. The ruler keeps * that full scroll range but mounts only an overscanned window of its ticks. */ import { type ReactElement, type ReactNode } from 'react'; import { type HourCycle, type TimeValue } from '../../utils/time.js'; export type { HourCycle, TimeValue }; /** Which face the panel draws. */ export type TimePickerLayout = 'wheel' | 'clock' | 'ruler'; /** How the panel gets onto the screen. */ export type TimePickerPresentation = 'popover' | 'dialog' | 'bottom-sheet' | 'inline'; /** * How loudly the ruler face states the time it is on. * * `default` is the big centred number, right when the scale is the only thing * on the panel. `compact` steps it down to sit under something that outranks * it, and `none` drops it for a caller that writes the time itself. */ export type TimePickerReadout = 'default' | 'compact' | 'none'; export interface TimePickerProps { /** Controlled selection, as `{ hour, minute }` on a 24-hour clock. */ value?: TimeValue; /** Starting selection when uncontrolled. Defaults to the top of the hour. */ defaultValue?: TimeValue; onValueChange?: (value: TimeValue) => void; /** Which face the panel draws. */ layout?: TimePickerLayout; /** How the panel gets onto the screen. `inline` renders it with no trigger. */ presentation?: TimePickerPresentation; /** Controlled open state of the panel. */ open?: boolean; onOpenChange?: (open: boolean) => void; /** `24` drops the meridiem column and writes hours 00–23. */ hourCycle?: HourCycle; /** * Minutes between selectable times. `wheel` defaults to 1; `clock` and * `ruler` default to 30 and 15, since both scroll the whole day at once. */ minuteStep?: number; /** Earliest selectable time, inclusive. */ minTime?: TimeValue; /** Latest selectable time, inclusive. */ maxTime?: TimeValue; /** What the trigger reads when nothing has been chosen. */ placeholder?: string; /** Override how the chosen time is written on the trigger. */ format?: (value: TimeValue) => string; /** BCP 47 tag for the time's text and the meridiem labels. */ locale?: string; /** * How loudly the `ruler` face states the time it is on. The other two faces * spell the time out in their own columns and hands, and ignore this. * * The big centred number is right when the scale is the only thing on the * panel. Under something that outranks it — a calendar, a form row — it is * the largest text on screen for the smaller half of the answer, so step it * down with `compact` or take it over yourself with `none`. */ readout?: TimePickerReadout; /** Stop the trigger opening it, and the faces from being scrolled. */ disabled?: boolean; className?: string; /** * A trigger of your own. Given one, it is cloned with an `onPress` that * opens the panel — so a field row or an icon button can stand in for the * default button without this component knowing what either looks like. * * Ignored by `presentation="inline"`, which has no trigger. */ children?: ReactElement<{ onPress?: () => void; }> | ReactNode; } declare function TimePickerRoot({ value: valueProp, defaultValue, onValueChange, layout, presentation, open: openProp, onOpenChange, hourCycle, minuteStep, minTime, maxTime, placeholder, format, locale, readout, disabled, className, children, }: TimePickerProps): import("react").JSX.Element; declare namespace TimePickerRoot { var displayName: string; } export declare const TimePicker: typeof TimePickerRoot & { Trigger: ({ children }: import("../popover/index.js").PopoverTriggerProps) => import("react").JSX.Element; }; //# sourceMappingURL=index.d.ts.map