/** One editable piece of a segmented date/time value. */ export type SegmentType = 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second' | 'dayPeriod'; /** How far down a segmented field is editable (no 'hour': would duplicate 'minute'). */ export type Granularity = 'day' | 'minute' | 'second'; /** Whether hours read `1`–`12` (with an AM/PM segment) or `0`–`23`. */ export type HourCycle = 12 | 24; /** Current numeric value of each editable segment; `null` means "not typed yet". */ export type SegmentValues = Partial>; /** One rendered piece of a segmented field — an editable segment or a locale literal. */ export interface Segment { /** The segment this piece edits, or `'literal'` for the text between segments. */ type: SegmentType | 'literal'; /** What to render: the padded value, the placeholder, or the literal itself. */ text: string; /** Current numeric value; `null` for literals and for untyped segments. */ value: number | null; /** Lowest accepted value (`0` for literals). */ min: number; /** Highest accepted value (`0` for literals). Dynamic for `day`. */ max: number; /** Whether this segment is still showing its placeholder. */ isPlaceholder: boolean; /** `false` only for literals. */ isEditable: boolean; } /** Default placeholder text; unreachable by Intl and untranslatable by locale. */ export declare const SEGMENT_PLACEHOLDERS: Record; /** The `aria-valuetext` an untyped segment announces, so a spinbutton never reads a value the user did not enter. */ export declare const EMPTY_VALUE_TEXT = "Empty"; /** Accessible names for each segment type. */ export declare const SEGMENT_LABELS: Record; /** Localization strings for segmented date/time fields. */ export interface SegmentedLabelProps { /** * Words the accessible name of each segment type. * @default undefined — the built-in English names ('year', 'month', 'AM/PM', …). */ getSegmentLabel?: ((type: SegmentType) => string | undefined) | undefined; /** * Aria text for untyped segments. * @default 'Empty' */ emptySegmentText?: string | undefined; /** * Words the placeholder for each segment. * @default undefined — the built-in English letters ('yyyy', 'mm', 'dd', …). */ getSegmentPlaceholder?: SegmentPlaceholderResolver | undefined; } /** The runtime's own locale, used whenever `locale` is omitted — matches `calendar-locale`'s `resolveLocale`. */ export declare function resolveLocale(locale?: string): string; /** * The hour cycle to render with: the explicit `hourCycle` when given, otherwise * whatever the locale resolves to (`h11`/`h12` → `12`, `h23`/`h24` → `24`). * * @example * ```ts * resolveHourCycle('en-US'); // 12 * resolveHourCycle('de-DE'); // 24 * ``` */ export declare function resolveHourCycle(locale?: string, hourCycle?: HourCycle): HourCycle; /** * The editable segments a field of this kind and granularity owns, in canonical (not locale) order; `dayPeriod` is appended by {@link buildSegments} only when the resolved hour cycle is 12. * * @example * ```ts * segmentTypesFor('date', 'minute'); // ['year','month','day','hour','minute'] * segmentTypesFor('time', 'second'); // ['hour','minute','second'] * ``` */ export declare function segmentTypesFor(kind: 'date' | 'time', granularity: Granularity): SegmentType[]; /** Days in a Gregorian month; `31` while either input is unknown, so `day` stays fully typeable. */ export declare function daysInMonth(year: number | null | undefined, month: number | null | undefined): number; /** The accepted range of one segment, given the values around it. */ export declare function segmentRange(type: SegmentType, values: SegmentValues, hourCycle: HourCycle): { min: number; max: number; }; /** The locale's AM and PM names, e.g. `['AM', 'PM']` or `['vorm.', 'nachm.']`. */ export declare function getDayPeriodNames(locale?: string): [string, string]; /** Converts a keystroke to day period index (0 AM, 1 PM, null if neither). */ export declare function dayPeriodFromKey(key: string, locale?: string): number | null; /** Words the placeholder of one segment type; return the built-in {@link SEGMENT_PLACEHOLDERS} entry for the types you do not want to change. */ export type SegmentPlaceholderResolver = (type: SegmentType) => string; /** * How a segment renders: zero-padded digits, the locale's AM/PM name, or the * placeholder. * * @param shouldForceLeadingZeros `false` renders a one-digit month, day or hour * bare — see {@link SEGMENT_PAD_UNFORCED} for why those three and no others. */ export declare function formatSegmentText(type: SegmentType, value: number | null, locale?: string, getSegmentPlaceholder?: SegmentPlaceholderResolver, shouldForceLeadingZeros?: boolean): string; /** Options for {@link buildSegments}. */ export interface BuildSegmentsOptions { /** `'date'` adds year/month/day ahead of the time segments. */ kind: 'date' | 'time'; /** How far down the field is editable. */ granularity: Granularity; /** BCP-47 locale deciding segment order, literals and AM/PM names. */ locale?: string | undefined; /** Forced hour cycle; omitted means "whatever the locale uses". */ hourCycle?: HourCycle | undefined; /** Current per-segment values. */ values: SegmentValues; /** Words each segment's placeholder; omitted keeps the built-in English letters. */ getSegmentPlaceholder?: SegmentPlaceholderResolver | undefined; /** * Whether a one-digit month, day or hour renders zero-padded (`05`) or bare * (`5`). Never touches `year`, `minute` or `second`. * @default true */ shouldForceLeadingZeros?: boolean | undefined; } /** * The full ordered render list for a segmented field — editable segments * interleaved with the locale's literals. * * @example * ```ts * buildSegments({ kind: 'date', granularity: 'day', locale: 'en-US', values: {} }) * .filter((s) => s.isEditable) * .map((s) => s.type); // ['month', 'day', 'year'] * ``` */ export declare function buildSegments(options: BuildSegmentsOptions): Segment[]; /** * How many units one Arrow press moves a segment, given the field-level `step` in seconds; drives only the finest rendered segment, falling back to `1` when `step` doesn't fit the grid. * * @example * ```ts * segmentStepFor('minute', 'minute', 900); // 15 * segmentStepFor('hour', 'minute', 900); // 1 — only the finest segment steps * ``` */ export declare function segmentStepFor(type: SegmentType, granularity: Granularity, step?: number): number; /** * Stepper one segment by `delta`, wrapping around its range, snapping onto the `step` grid like a native stepper when `step` is past 1. * @param step the segment's own step, from {@link segmentStepFor} */ export declare function stepSegment(segment: Segment, delta: number, step?: number): number; /** The `aria-valuenow` a segment publishes: its current value pulled back inside its own `aria-valuemin`/`aria-valuemax`, since mid-entry it can legitimately sit below minimum. */ export declare function segmentValueNow(segment: Segment): number; /** The result of typing one digit into a segment. */ export interface DigitEntry { /** The segment's new value. May be below `min` mid-entry (typing `0` then `5` into a month). */ value: number; /** Buffer to carry into the next keystroke on this segment; `0` once entry is complete. */ buffer: number; /** Whether focus should move to the next editable segment. */ advance: boolean; } /** * Types one digit into a segment: an overflowing keystroke restarts entry at that digit instead of being rejected, and focus advances once no further digit could fit. * * @param segment the segment being typed into * @param buffer what has been typed into it so far (`0` when entry just started) * @param digit the digit `0`–`9` just pressed * * @example * ```ts * // month, "1" already typed, user presses 5 → 15 overflows, restart at 5 * typeDigit(monthSegment, 1, 5); // { value: 5, buffer: 0, advance: true } * ``` */ export declare function typeDigit(segment: Segment, buffer: number, digit: number): DigitEntry; /** Whether every editable segment has been typed and sits inside its range. */ export declare function isComplete(segments: Segment[]): boolean; /** Converts a possibly-12-hour `hour` plus `dayPeriod` into the 0-23 hour. */ export declare function to24Hour(hour: number, dayPeriod: number | null | undefined, hourCycle: HourCycle): number; /** Converts a 0-23 hour into the `[hour, dayPeriod]` pair the given cycle renders. */ export declare function from24Hour(hour: number, hourCycle: HourCycle): [number, number | null]; /** * The `Date` these segment values describe, in local time, or `null` while * any date segment is still untyped; unowned time segments default to `0`, * like ``. */ export declare function valuesToDate(values: SegmentValues, hourCycle: HourCycle): Date | null; /** Splits a `Date` back into segment values for the given hour cycle. */ export declare function dateToValues(date: Date, hourCycle: HourCycle): SegmentValues; /** * The `HH:mm` / `HH:mm:ss` string these segment values describe — always 24 * hour, like ``, regardless of the rendered `hourCycle` — * or `null` while hour or minute is untyped. */ export declare function valuesToTimeString(values: SegmentValues, granularity: Granularity, hourCycle: HourCycle): string | null; /** Parses `HH:mm[:ss]` (24 hour) into segment values for the given hour cycle. Invalid input yields empty values. */ export declare function timeStringToValues(time: string, hourCycle: HourCycle): SegmentValues; /** The `YYYY-MM-DD` / `YYYY-MM-DDTHH:mm[:ss]` string a segmented date field submits. */ export declare function dateToFormValue(date: Date, granularity: Granularity): string; /** * The inverse of {@link dateToFormValue}, built field by field rather than `new Date(string)`, which reads a bare `YYYY-MM-DD` as UTC midnight. * * @param value a string in the shape {@link dateToFormValue} produces * @returns the local date, or `null` when the string is not one of those shapes */ export declare function parseDateFormValue(value: string): Date | null; /** Which side of a `min`/`max` bound a value falls outside, or `null` when it is in range. */ export type RangeViolation = 'underflow' | 'overflow'; /** * Whether a `HH:mm[:ss]` time falls outside `min`/`max`, compared as strings * (24-hour times sort chronologically when zero-padded). * * @param value the field's current wire value, or `null` while incomplete * @param min the earliest accepted time, `HH:mm[:ss]` * @param max the latest accepted time, `HH:mm[:ss]` * @returns which bound was crossed, or `null` when in range */ export declare function timeRangeViolation(value: string | null | undefined, min?: string, max?: string): RangeViolation | null; /** * Whether an `HH:mm[:ss]` time misses the `step` grid — the `stepMismatch` `` raises. Step counts seconds, anchored on `min` or midnight. * * @param value the field's current wire value, or `null` while incomplete * @param step the field's step in seconds; non-positive or non-finite is no constraint * @param min the step base — the same `min` the range check uses */ export declare function timeStepMismatch(value: string | null | undefined, step?: number, min?: string): boolean; /** Pulls segment values inside `min`/`max` bounds (Home/End only); arrow-stepping and typing deliberately do not clamp so out-of-bounds values stay reachable for validation. */ export declare function clampValuesToTimeRange(values: SegmentValues, granularity: Granularity, hourCycle: HourCycle, min?: string, max?: string): SegmentValues; /** Whether a `Date` falls outside `minDate`/`maxDate`, compared at the field's `granularity` (a `day` field ignores time of day), string-compared via {@link dateToFormValue} to match the native input's behavior. */ export declare function dateRangeViolation(value: Date | null | undefined, granularity: Granularity, minDate?: Date, maxDate?: Date): RangeViolation | null; /** @internal Drops every memoized `Intl` result. */ export declare function clearDateSegmentCache(): void; export declare function editableSegments(root: HTMLElement | null): HTMLElement[];