import type { EventEmitter } from '../../stencil-public-runtime'; import type { SelectChangeDetail, SelectSize, SelectVariant } from './mud-select.types'; import type { LocaleProp } from '../../utils/locale'; /** * Select — single-select dropdown atom. * * Matches the Figma `select-input` component (page "Select (Dropdown)", * node 411:23995) — kept here under the shorter `mud-select` name. Size rungs * follow Figma's own names: `medium` (40px) and `large` (48px). * * Pattern B (atom-interactive, form-associated): renders a custom-styled * trigger button and a listbox popover inside shadow DOM. Form participation * works via `formAssociated` + `ElementInternals`. Shares the visual primitives * of `mud-text-input` (border, focus ring, label, helper / error text, sizes, * states) and adds a trailing chevron icon, listbox menu, and keyboard * navigation (ArrowUp/Down/Home/End/Enter/Escape) per the WAI-ARIA combobox * pattern. * * @element mud-select * * @slot - (default) The option list, written as the markup a native `` receives the `disabled` attribute. * @default false */ disabled: boolean; /** * Marks the field as mandatory. Adds a red asterisk to the label and sets * `aria-required` on the trigger. * @default false */ required: boolean; /** * Renders the field read-only. The trigger remains focusable but the * listbox cannot be opened. * @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; /** * Reflects the open state of the listbox popover. Read-only externally — * use `mudOpen` / `mudClose` to react to changes. * @default false */ open: boolean; /** * Selected value. Reflects to the host attribute. Set to empty string when * no option is selected. * @default '' */ value: string; /** Form-control `name`. Used during form submission. */ name?: string; /** Placeholder shown when no option is selected. */ placeholder?: 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; /** * Language of the built-in copy. Unset, the component follows the closest ancestor `lang` * (`` included), else `ro-MD`. */ locale?: LocaleProp; /** * Shown in place of the list when nothing matches the query. Overrides the `locale`'s copy * when set to a string; an empty string renders nothing. * @default 'Nicio opțiune' (ro-MD) */ emptyLabel?: string; /** * Names the listbox for assistive technology when the field has no visible * label and no `aria-label` to borrow. Overrides the `locale`'s copy when set to a * non-empty string. * @default 'Opțiuni' (ro-MD) */ listboxLabel?: string; /** * Validation message reported when the field is `required` and nothing is * selected. Overrides the `locale`'s copy when set to a non-empty string. * @default 'Selectați o opțiune.' (ro-MD) */ requiredMessage?: string; /** * Lets the user narrow the list by typing into the control. * * Off by default: turning it on makes the control a text field, which changes * how every existing select behaves — including raising an on-screen keyboard * on touch — so it is the consumer's call, not a default. * @default false */ searchable: boolean; private hasLabelSlot; private hasHelperSlot; private hasIconStart; private isFocused; private fieldsetDisabled; private highlightedIndex; private entries; /** What the user has typed. Empty unless `searchable` and the user is typing. */ private query; /** The host's `aria-label` (attribute or native `ariaLabel` property), mirrored to the trigger when no visible label is present. */ private resolvedAriaLabel?; /** True when the listbox is flipped above the control (not enough room below). */ private dropUp; /** Runtime cap (px) on the listbox height so it never spills past the viewport. */ private listboxMaxBlockSize?; host: HTMLMudSelectElement; internals: ElementInternals; /** Fires when the selected value changes. `detail.value` is the new value. */ mudChange: EventEmitter; /** Fires when the listbox opens. */ mudOpen: EventEmitter; /** Fires when the listbox closes. */ mudClose: EventEmitter; /** Fires when the trigger gains focus. The native `FocusEvent` is forwarded as-is. */ mudFocus: EventEmitter; /** Fires when the trigger loses focus. The native `FocusEvent` is forwarded as-is. */ mudBlur: EventEmitter; private readonly instanceId; private readonly labelId; private readonly helperId; private readonly errorId; private readonly triggerId; private readonly listboxId; private initialValue; private triggerEl?; private listboxEl?; private stopAriaLabel?; private optionsObserver?; private typeaheadBuffer; private typeaheadTimer?; private stopLang?; connectedCallback(): void; /** Built-in strings in the resolved locale, with the override props on top. */ private messages; /** * `slotchange` is not enough on its own. Appending an `` leaves the slot's assigned nodes untouched — the `optgroup` * itself did not change — so the event never fires and the listbox keeps * showing a stale list. The same goes for flipping `disabled` or rewriting an * option's text, neither of which is a slot change at all. */ private observeOptions; componentWillLoad(): void; componentDidLoad(): void; private primeHighlight; /** * Reflects required + value into `ElementInternals` so the host participates * in native form validation. Anchored on the trigger button so a11y focus * lands on the visible control. */ private syncValidity; validateVariant(next: SelectVariant): void; validateSize(next: SelectSize): void; handleValueChange(next: string): void; handleRequiredChange(): void; handleLocaleChange(): void; handleOpenChange(next: boolean): void; /** * The listbox stays `position: absolute` under the control (predictable, no * containing-block surprises). This only measures the room above / below the * trigger to (a) flip the popover above it when it doesn't fit below and * (b) cap its height so it never spills past the viewport edge. Pure DOM read * + two primitive `@State` writes — safe to call on scroll / resize. */ private positionListbox; private measureListbox; componentDidRender(): void; disconnectedCallback(): void; /** Mirrors `disabled` from an ancestor `
` without clobbering the consumer-set prop. */ formDisabledCallback(disabled: boolean): void; formResetCallback(): void; formStateRestoreCallback(state: string | File | FormData | null): void; handleDocumentClick(ev: MouseEvent): void; private onLabelSlotChange; private onHelperSlotChange; private onIconStartSlotChange; private onDefaultSlotChange; private slotHasContent; /** * Seeds `value` from `