import type { EventEmitter } from '../../stencil-public-runtime'; import type { LocaleProp } from '../../utils/locale'; import type { TimeInputChangeDetail, TimeInputSize, TimeInputTypingDetail, TimeInputVariant } from './mud-time-input.types'; /** * Time Input — segment-masked `HH:MM` entry with an hour / minute picker. * * Pattern B (atom-interactive, form-associated): renders its own `` * inside shadow DOM, like `mud-date-input`, and overlays a ghost format hint * that keeps the unfilled segments visible while the user types. The clock * button opens `mud-time-picker` (Figma Time frame 13807:8471). * * @element mud-time-input * * Without a visible label, name the field with `aria-label` on the element; it * is moved onto the internal control. * * @slot label - Rich label content, replaces the `label` prop when present. * @slot helper - Rich helper / hint content, replaces the `helper-text` prop. Hidden when an error message is shown. */ export declare class MudTimeInput { /** * Color treatment. `destructive` is forced when `invalid` is set. * @default 'default' */ variant: TimeInputVariant; /** * Visual size rung. * @default 'md' */ size: TimeInputSize; /** * Disables interactivity. The internal control receives `aria-disabled` and * the native `disabled` attribute. * @default false */ disabled: boolean; /** * Marks the field as mandatory. Adds a red asterisk to the label and sets * `aria-required` on the internal control. * @default false */ required: boolean; /** * Renders the field read-only. The control remains focusable and copyable. * @default false */ readonly: boolean; /** * Forces destructive visuals regardless of `variant`. Sets `aria-invalid`. * Use together with `errorText` to surface the message. * @default false */ invalid: boolean; /** * Current display value, `HH:MM` (24-hour). Reflects to the host attribute; * typing rewrites it, so consumers can read it back at any time. * @default '' */ value: string; /** Form-control `name`. Used during form submission. */ name?: string; /** Earliest accepted time, `HH:MM` inclusive. Earlier entries get a `range` error. */ min?: string; /** Latest accepted time, `HH:MM` inclusive. Later entries get a `range` error. */ max?: string; /** Plain-text label. Use the `label` slot for richer content. */ label?: string; /** Plain-text helper / hint shown below the control. */ helperText?: string; /** * Plain-text error message shown below the control when `invalid` is set. * When present it replaces `helperText` and pairs with the error icon. */ errorText?: string; /** Placeholder shown when the control is empty. Defaults to `HH:MM`. */ placeholder?: string; /** * Shows a trailing clear (×) button while the field holds a value (Figma * `👁️ Clear Button` axis). Never shown while empty, disabled or read-only. * @default false */ clearable: boolean; /** * Language of the built-in labels and error messages. Unset, the component follows the * closest ancestor `lang` (`` included), else `ro-MD`. */ locale?: LocaleProp; /** * Accessible label for the clear (×) button. Overrides the `locale`'s copy when set to a * non-empty string. * @default 'Șterge' (ro-MD) */ clearLabel?: string; /** * Accessible label for the clock button that opens the picker. Overrides the `locale`'s * copy when set to a non-empty string. * @default 'Deschide selectorul de oră' (ro-MD) */ triggerLabel?: string; /** * Accessible name of the picker dialog. Overrides the `locale`'s copy when set to a * non-empty string. * @default 'Selectează ora' (ro-MD) */ pickerLabel?: string; /** * Message shown when a complete hour segment is outside 00–23. Overrides the `locale`'s * copy when set to a non-empty string. * @default 'Ora trebuie să fie între 00 și 23' (ro-MD) */ hourErrorText?: string; /** * Message shown when a complete minute segment is outside 00–59. Overrides the `locale`'s * copy when set to a non-empty string. * @default 'Minutele trebuie să fie între 00 și 59' (ro-MD) */ minuteErrorText?: string; /** * Message shown when a complete time is outside `min` / `max`. Overrides the `locale`'s * copy when set to a non-empty string. * @default 'Ora este în afara intervalului permis' (ro-MD) */ rangeErrorText?: string; /** * Message shown when a `required` field is empty and a form submit found it so. The same * text is the form's validation message. Overrides the `locale`'s copy when set to a * non-empty string. * @default 'Introduceți ora' (ro-MD) */ requiredErrorText?: string; private hasLabelSlot; private hasHelperSlot; private isFocused; private fieldsetDisabled; private pickerOpen; private validationError; /** Set when a form submit found the required field empty; cleared once it holds a value. */ private requiredShown; /** * The host's `aria-label`, moved onto the internal control. Read from the * attribute rather than declared as a prop, which would shadow * `HTMLElement.ariaLabel` (#88). */ private hostAriaLabel?; host: HTMLMudTimeInputElement; internals: ElementInternals; /** * Fires on every keystroke. `detail.value` is the current display value; * `detail.isoValue` is the `HH:MM` time when complete and valid, otherwise * `null`. `detail.segment` is the segment under the caret. */ mudInput: EventEmitter; /** * Fires when the value is committed — on `change` (blur), a picker selection * or the clear button. */ mudChange: EventEmitter; /** Fires when the internal control gains focus. The native `FocusEvent` is forwarded as-is. */ mudFocus: EventEmitter; /** Fires when the internal control loses focus. The native `FocusEvent` is forwarded as-is. */ mudBlur: EventEmitter; /** Fires when the user empties the field via the clear (×) button. */ mudClear: EventEmitter; private readonly instanceId; private readonly inputId; private readonly labelId; private readonly helperId; private readonly errorId; private readonly pickerId; private initialValue; private ariaLabelObserver?; private stopLang?; /** Set when the picker opens; cleared once focus has moved into it. */ private focusPickerOnRender; /** Whether the next open should move focus into the picker. */ private focusPickerOnOpen; validateVariant(next: TimeInputVariant): void; validateSize(next: TimeInputSize): void; handleValueChange(next: string): void; revalidate(): void; /** * Opening the picker from the clock button moves focus into it (dialog * pattern); opening it from the field leaves focus in the input. */ handlePickerOpenChange(open: boolean): void; /** Close the picker when a click lands outside the field (light or shadow DOM). */ handleOutsideClick(ev: MouseEvent): void; /** * A form submit (or `checkValidity()`) found the field invalid. When it is a * required field left empty, show the required message under it. */ handleInvalid(): void; /** * Close the popover when focus leaves the field and its popover — Tab past * the last control, or focus moved elsewhere on the page. A view switch * inside the popover briefly drops focus before moving it on, so a focus * loss with no destination is checked again two frames later. */ handleFocusOut(ev: FocusEvent): void; /** Escape closes the picker and returns focus to the clock button. */ handlePopoverKeyDown(ev: KeyboardEvent): void; connectedCallback(): void; disconnectedCallback(): void; componentWillLoad(): void; componentDidRender(): void; formDisabledCallback(disabled: boolean): void; formResetCallback(): void; formStateRestoreCallback(state: string | File | FormData | null): void; /** Whether focus is on the field, its buttons or anything in its popover. */ private hasFocusWithin; /** Built-in strings in the resolved locale, with the override props on top. */ private messages; /** * Move the host's `aria-label` onto the internal control: the host has no * role, so a name left on it would not be exposed. */ private captureAriaLabel; private readonly togglePicker; /** * A click anywhere on the field opens the picker, not only the clock button, * as the date input opens its calendar. Focus stays where the click put it — * the caret in the input — so the user can keep typing; only the clock * button moves focus into the picker. */ private readonly handleFieldClick; private readonly handlePickerChange; /** * Re-format raw input into `HH:MM`. With `trailingSeparator`, a just-completed * valid hour also gets its `:` so the caret moves on to the minutes; an * invalid one keeps the caret in place so it can be corrected. */ private formatMasked; private segmentAtPosition; private segmentInRange; /** Minutes since midnight of a complete `HH:MM`, else `null`. */ private minuteOfDay; private withinBounds; /** Validate a (possibly partial) value segment by segment; incomplete segments are not errors yet. */ private validate; private updateValidation; /** A required, editable field with no value. */ private isValueMissing; private validationMessage; private changeDetail; private detail; private onLabelSlotChange; private onHelperSlotChange; private slotHasContent; private handleInput; private handleChange; private handleFocus; private handleBlur; /** `:` while the hour is part-typed pads it with a leading zero (`9` + `:` → `09:`). */ private handleKeyDown; private handleClearClick; private shouldShowClear; private isInert; /** Invalid when the consumer says so or the built-in validation fails. */ private isInvalid; private hasVisibleLabel; /** The consumer's `errorText` while `invalid` is set, otherwise the built-in validation message. */ private errorMessage; private hasHelperMessage; private describedBy; render(): any; }