import{type TemplateResult,type PropertyValues}from'lit';import{LyraElement}from'../../../internal/lyra-element.js';import type{LyraSize}from'../../../internal/variants.js';import{type FormOwnerValue}from'../../../internal/form-associated.js';export type TimeRangeHandle='start'|'end'; /** Formats a finite, clamped handle value for `aria-valuetext`; return a nullish value to omit * the attribute for that handle. */ export type TimeRangeValueFormatter=(value:number,handle:TimeRangeHandle)=>string|null|undefined; /** A single discrete-preset option for the `presets` property. Deliberately the same shape as * ``'s `LyraDateRangePreset` (`label`/`start`/`end`/`id`) so the library has one * preset vocabulary rather than two; the only difference is the unit (numbers, not ISO dates). */ export interface TimeRangePreset{readonly label:string;readonly start:number;readonly end:number; /** * Caller-owned stable identity, echoed verbatim on `appliedPreset` -- never read, compared, or * otherwise interpreted by this component. Exists so a consumer can persist WHICH preset is * active (`appliedPreset.id`) without a downcast or a side `WeakMap`. Optional: an untagged * preset is unaffected. Unlike `label`/`start`/`end`, which are copied into a frozen defensive * snapshot on assignment, `id` is copied through that same snapshot rather than the original * object, so it round-trips by value, not by the caller's own object identity. */ readonly id?:string;}export interface LyraTimeRangeEventMap{input:Event;change:Event;'lr-input':CustomEvent<{start:number;end:number;}>;'lr-change':CustomEvent<{start:number;end:number;}>;focus:FocusEvent;blur:FocusEvent;'lr-invalid':CustomEvent;} /** * `` — a two-handle brush/scrubber over a numeric domain. * Callers map their own time axis to `[min, max]`; no date logic lives here * (matches the no-date-library constraint used elsewhere in this library). * * Optionally paired with a row of discrete presets (`presets`) — e.g. "Last * 7 days" / "Last 30 days" — rendered above the track; picking one is just a * shortcut that sets both handles at once, the continuous brush underneath * is unaffected and both interaction modes coexist. `appliedPreset` preserves which shortcut * produced the current range without guessing from numeric equality. * * Form-associated for the `
` cascade and for validation, not for a submitted * value: it attaches `ElementInternals` (like ``'s minimal pattern, rather than the * single-string-value `FormAssociated` mixin, which doesn't fit a two-handle range) so that an * ancestor `
` disables both handles and every preset button through * `effectiveDisabled` the same way it would a native ``, without touching the * consumer-facing `disabled` property/attribute itself. Unlike ``, it never calls * `internals.setFormValue()` and has no `name` — the selected range is not included in the owning * form's `FormData` on submit; read `start`/`end` directly (e.g. from `lr-change`) instead of * relying on native form submission. It still takes part in `form.reset()`, though — see * `formResetCallback()`, which restores the declared `start`/`end` and puts the control back to * pristine so it cannot keep blocking a form the user just reset. * Direct disablement, fieldset disablement, and form reset synchronously retire every active * keyboard/pointer gesture without a stale `change` commit on a later key or pointer release. * * It has no constraints of its own — every reachable range is a legal one, so `checkValidity()` * passes unless a consumer has set an error through `setCustomValidity()`. That method is the * whole point of the validity surface here: a range this component cannot know is wrong (an * overlapping booking, a window the server rejects) still blocks submission of the form the * element sits in. * * Clicking anywhere on the track — the vast majority of the control's clickable area — jumps * whichever handle is nearer the clicked position to that point and continues as the same drag * gesture, then leaves that handle focused so arrow keys carry on from there. Mirrors * ``'s `range` mode exactly, including the RTL ratio mirroring and the tie-break toward * the handle that can actually travel toward the click. A pointerdown that starts on a handle stays * a plain handle drag. * * Deliberately no label/hint/error chrome -- `startLabel`/`endLabel` here are per-handle * accessible-name overrides, not visible label text, the same carve-out `` states for * its own single-handle `label`; a labeled-field consumer wraps this element in their own layout. * The `base` around both handles is still an accessible `role="group"`, named by a non-empty host * `aria-label`; native external `