import { Nullable } from '@viasat/beam-shared/utils/types'; import { DateFieldPart, SegmentAdjustment, SegmentText, SegmentType, SegmentValues } from './DateField.types'; export declare const DEFAULT_LOCALE = "en-US"; /** Returns the locale month name for a 1-based month (1 = January). */ export declare const getMonthName: (month: number) => string; /** * Absolute spin ceiling for day — independent of the current month. * * Intentional divergence (MUI-X model, not React Aria clamp): the day segment * spins to this absolute max (31) even though `aria-valuemax` is month-aware * (28–30, computed in `DateField.Segments`). So a user can spin ONE step past the * announced ceiling into an out-of-range day (e.g. April 30 → 31); the validity * layer surfaces that via `aria-invalid` rather than clamping to `daysInMonth`. * The announced-vs-reachable gap is deliberate — see docs/adr/calendar.md (spin * model). Out-of-range days (e.g. Feb 31) are caught by the validity layer, not here. */ export declare const DAY_SPIN_MAX = 31; /** Absolute maximum for month (1-based). */ export declare const MONTH_MAX = 12; /** * Absolute floor/ceiling for the free-spinning year segment. `minDate`/`maxDate` * don't bound the year directly — the whole date clamps to them on blur instead. */ export declare const YEAR_MIN = 1; export declare const YEAR_MAX = 9999; /** Clamps `n` to `[lo, hi]` (inclusive). */ export declare const clamp: (n: number, lo: number, hi: number) => number; /** * Modular wrap within a 1-based inclusive range `[1, max]`. * Handles negative deltas correctly (e.g. 1 − 1 in a max-12 range → 12). */ export declare const wrapInRange: (n: number, max: number) => number; /** * Returns the number of days in the given month/year combination. * * - `month` is 1-based (1 = January, 12 = December). * - When `month` is null (unknown), returns 31 (conservative maximum). * - When `month` is provided but `year` is null, uses {@link LEAP_YEAR_FALLBACK} * so February correctly reports 29 days (leap-safe fallback). */ export declare const getDaysInMonth: (year: Nullable, month: Nullable) => number; /** Returns today's date parts as a plain object. */ export declare const todayParts: () => { day: number; month: number; year: number; }; /** True for a `Date` instance that isn't `Invalid Date`. */ export declare const isValidDate: (value: unknown) => value is Date; /** Context passed into {@link adjustSegmentValue} — kept pure by the caller. */ export interface AdjustSegmentContext { /** Days in the current month (use {@link getDaysInMonth} to compute). */ daysInMonth: number; /** * Today's local-date values. Only `year` is read now — it seeds an empty * year segment on the first press. Day/month seed to a fixed first/last * valid value instead, so `day`/`month` here go unused. */ today: { day: number; month: number; year: number; }; } /** * Computes the next numeric value for a date segment after an increment, * decrement, or boundary jump. * * Day and month wrap modularly within their absolute ranges; an impossible * combination such as Feb 31 is left for the validity layer rather than clamped * here. The year clamps without wrapping and spins free of `minDate`/`maxDate`, * which bound the whole date on blur instead, so year `'min'`/`'max'` returns * `null`. An empty segment seeds on the first press: day and month follow the * direction of travel, the year starts at today. */ export declare const adjustSegmentValue: (type: SegmentType, current: Nullable, amount: SegmentAdjustment, ctx: AdjustSegmentContext) => Nullable; export declare const deriveValue: (segments: SegmentValues) => Nullable; export declare const isSameDateValue: (a: Nullable, b: Nullable) => boolean; /** * `dateKey` for a possibly-absent/invalid `Date`, collapsing both to `null` * (never `NaN` — a `NaN` dependency would itself churn every render). Used to * key memo/callback deps on a bound's primitive calendar day instead of the * `Date` object's identity. */ export declare const dateKeyOrNull: (d?: Nullable) => Nullable; /** * True when `value`'s calendar day falls within `[minDate, maxDate]` * (inclusive). Compared by calendar day only, so a `maxDate` with a non-zero * time-of-day still accepts the same day. A missing bound is unbounded on * that side. */ export declare const isDateInRange: (value: Date, minDate?: Nullable, maxDate?: Nullable) => boolean; /** * True when both bounds are valid Dates but `minDate`'s calendar day is after * `maxDate`'s — a misconfiguration where no date can satisfy both. `DateField` * dev-warns on this, and `clampDateToRange` skips clamping so a touched value * isn't flip-flopped between the two bounds on repeated blurs. */ export declare const isMinMaxMisconfigured: (minDate?: Nullable, maxDate?: Nullable) => boolean; /** * Clamps `value` to the nearest in-range bound by calendar day: `minDate` when * the value is before it, `maxDate` when after, else the value unchanged. An * invalid/absent bound is ignored (unbounded on that side). Returns a * local-midnight `Date` on the bound's calendar day. Used by `commitOnBlur` to * normalize a well-formed out-of-range date; structural invalids (Feb 30) never * reach here since they derive to `null`. */ export declare const clampDateToRange: (value: Date, minDate?: Nullable, maxDate?: Nullable) => Date; export declare const toISODateString: (value: Nullable) => string; /** Type guard: a literal separator (`/`, `.`, `年`, …) rather than a segment. */ export declare const isLiteralPart: (part: DateFieldPart) => part is DateFieldPart & { type: "literal"; }; /** Ordered segment types from a parts array (literals stripped). */ export declare const getSegmentOrder: (parts: ReadonlyArray) => ReadonlyArray; /** * Locale-derived segment order and separators, memoized per locale. Falls * back to {@link DEFAULT_LOCALE} for any locale Intl can't resolve to the three * date segments. Resolved lazily on first use, so a broken Intl (which can't * render the field anyway — `getMonthName` needs it too) surfaces at render, * catchable by an error boundary, instead of crashing the bundle at import. */ export declare const getDateParts: (locale: string) => ReadonlyArray; /** @internal — test-only. Clears the per-locale parts cache for Intl isolation. */ export declare const __clearDatePartsCache: () => void; /** Per-segment zero-padded strings from a Date. All-empty for null/invalid. */ export declare const segmentTextFromValue: (value: Nullable) => SegmentText; /** The number a segment string contributes to the date / `aria-valuenow`, or * null when it shouldn't yet: empty, a parsed 0, or a year under 4 digits. */ export declare const segmentNumber: (type: SegmentType, text: string) => Nullable; /** Derives a Date from the per-segment strings (single source of truth). */ export declare const deriveValueFromText: (text: SegmentText) => Nullable; /** Zero-pads a segment to its full width on blur (day/month → 2, year → 4), * e.g. "1" → "01" / "0001". No year minimum, so a lone "1" settles as year 1. */ export declare const normalizeSegmentText: (type: SegmentType, text: string) => string; export interface SegmentDisplay { displayValue: string; isPlaceholder: boolean; } /** Placeholder when empty, else the digits zero-padded to the segment width * ("1" → "01" / "0001"). Display-only — the raw query drives append + value. */ export declare const getSegmentDisplay: (type: SegmentType, text: string, placeholder: string) => SegmentDisplay; /** Selects an element's entire textContent (whole-segment highlight). */ export declare const selectElementContents: (element: HTMLElement) => void; /** Clears the DOM selection when it currently lives inside `container`. Chrome * leaves the whole-segment Range highlighted after the field blurs; Safari * clears it automatically. Scoped to `container` so a selection elsewhere on * the page is untouched. */ export declare const clearSelectionWithin: (container: HTMLElement | null) => void;