@rcarls/rc-select 0.0.0-next-20260921045401
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +184 -0
- package/README.md +93 -0
- package/dist/custom-elements.json +1445 -0
- package/dist/rc-select-MQcvA385.js +1079 -0
- package/dist/rc-select-MQcvA385.js.map +1 -0
- package/dist/rc-select-define.js +8 -0
- package/dist/rc-select-define.js.map +1 -0
- package/dist/rc-select.js +5 -0
- package/dist/rc-select.js.map +1 -0
- package/dist/types/packages/rc-select/src/define.d.ts +1 -0
- package/dist/types/packages/rc-select/src/index.d.ts +1 -0
- package/dist/types/packages/rc-select/src/rc-select.d.ts +430 -0
- package/dist/types/packages/rc-select/src/rc-select.styles.d.ts +2 -0
- package/package.json +68 -0
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
import { LitElement, PropertyValues } from 'lit';
|
|
2
|
+
import { ActiveDescendantController, AnchorController, NativeChildController } from '@rcarls/rc-common';
|
|
3
|
+
import { RCListbox, ListboxOption, ListboxSelectableOption } from '@rcarls/rc-listbox';
|
|
4
|
+
import { RCDialog, RCDialogCloseEvent } from '@rcarls/rc-dialog';
|
|
5
|
+
export type RCSelectValue = string | string[];
|
|
6
|
+
export type RCSelectPopupMode = 'popover' | 'dialog';
|
|
7
|
+
export interface RCSelectChangeEvent {
|
|
8
|
+
/** Updated value after the change. */
|
|
9
|
+
value: RCSelectValue;
|
|
10
|
+
/** All selected option values after the change. */
|
|
11
|
+
selectedValues: string[];
|
|
12
|
+
/** All selected option objects after the change. */
|
|
13
|
+
selectedOptions: ListboxSelectableOption[];
|
|
14
|
+
}
|
|
15
|
+
declare global {
|
|
16
|
+
interface HTMLElementTagNameMap {
|
|
17
|
+
'rc-select': RCSelect;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Select-only combobox backed by a native <select>, following the WAI-ARIA Combobox
|
|
22
|
+
* pattern.
|
|
23
|
+
*
|
|
24
|
+
* Wraps a native `<select>` (default slot) as the form value reflector while
|
|
25
|
+
* rendering a custom button trigger and popup listbox. Popup placement
|
|
26
|
+
* and `aria-activedescendant` virtual keyboard navigation are supported.
|
|
27
|
+
*
|
|
28
|
+
* @see {@link https://richardcarls.github.io/rc-webcomponents/components/rc-select rc-select docs}
|
|
29
|
+
* @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/combobox/ WAI-ARIA Combobox pattern}
|
|
30
|
+
*
|
|
31
|
+
* @slot - Required. A native `<select>` element used for form submission
|
|
32
|
+
* and as the source of truth for options, multiple, and disabled state.
|
|
33
|
+
* @slot display - Optional. Replaces the default value label in the trigger.
|
|
34
|
+
* @slot toggle-indicator - Optional. Replaces the default chevron indicator. Accepts any
|
|
35
|
+
* element(s); the container shifts to inline-start in RTL via flex direction.
|
|
36
|
+
*
|
|
37
|
+
* @fires rc-select-change - When user interaction changes selection.
|
|
38
|
+
* `detail: { value, selectedValues, selectedOptions }`
|
|
39
|
+
* @fires rc-select-open - When the popup opens.
|
|
40
|
+
* @fires rc-select-close - When the popup closes.
|
|
41
|
+
*
|
|
42
|
+
* @csspart anchor - The flex container wrapping chips and trigger.
|
|
43
|
+
* @csspart trigger - The combobox trigger element (div).
|
|
44
|
+
* @csspart chips - The chips group container (when multiple).
|
|
45
|
+
* @csspart chip - Individual chip (when multiple).
|
|
46
|
+
* @csspart chip-label - Text label inside a chip.
|
|
47
|
+
* @csspart chip-remove - Remove button inside a chip.
|
|
48
|
+
* @csspart value-display - The text label showing selected value(s).
|
|
49
|
+
* @csspart toggle-indicator - The open/close indicator container.
|
|
50
|
+
* @csspart listbox - The `<rc-listbox>` popup element.
|
|
51
|
+
* @csspart dialog - Dialog popup surface.
|
|
52
|
+
* @csspart dialog-header - Managed leading/title/trailing header.
|
|
53
|
+
* @csspart dialog-cancel - Leading button that discards pending changes.
|
|
54
|
+
* @csspart dialog-cancel-icon - Decorative close icon inside the cancel button.
|
|
55
|
+
* @csspart dialog-title - Visible dialog title.
|
|
56
|
+
* @csspart dialog-selected - Scrollable pending-selection chip region.
|
|
57
|
+
* @csspart dialog-actions - Dialog confirmation action group.
|
|
58
|
+
* @csspart dialog-confirm - Commits pending changes and closes the dialog.
|
|
59
|
+
* @csspart dialog-listbox - Dialog option list.
|
|
60
|
+
*
|
|
61
|
+
* @attr open - Reflects whether the popup listbox is open.
|
|
62
|
+
* @attr multiple - Enables selection of multiple options simultaneously.
|
|
63
|
+
* @attr disabled - Disables the trigger and prevents the popup from opening.
|
|
64
|
+
* @attr required - Reflects the slotted native `<select>`'s own `required`, for `aria-required`
|
|
65
|
+
* on the trigger. Set `required` on the slotted `<select>` itself, not here.
|
|
66
|
+
* @attr placeholder - Text shown in the trigger when no value is selected.
|
|
67
|
+
* @attr display - Controls how selected values appear in the trigger: `'auto'`,
|
|
68
|
+
* `'chips'`, or `'compact'`.
|
|
69
|
+
* @attr popup-mode - Presents options in an anchored `popover` (default) or transactional
|
|
70
|
+
* modal `dialog`.
|
|
71
|
+
* @attr dialog-confirm-label - Text for the dialog confirmation action.
|
|
72
|
+
* @attr dialog-cancel-label - Accessible label for the leading cancel action.
|
|
73
|
+
* @attr dialog-cancel-button - Shows or hides the leading cancel action.
|
|
74
|
+
* @attr [has-value] - Present when one or more options are selected. Use with CSS
|
|
75
|
+
* selectors (e.g. `rc-select[has-value]`) for floating-label wrappers.
|
|
76
|
+
*
|
|
77
|
+
* @cssprop [--rc-select-max-height=20em] - Maximum popup height.
|
|
78
|
+
* @cssprop [--rc-select-control-block-size=var(--rc-control-block-size)] - Trigger block size.
|
|
79
|
+
* @cssprop [--rc-select-padding-block=var(--rc-control-padding-block)] - Trigger block-axis padding.
|
|
80
|
+
* @cssprop [--rc-select-padding-inline=var(--rc-control-padding-inline)] - Trigger inline-axis padding.
|
|
81
|
+
* @cssprop [--rc-select-gap=var(--rc-control-gap)] - Gap between trigger content, chips, and icon.
|
|
82
|
+
* @cssprop [--rc-select-radius=var(--rc-control-radius)] - Trigger border radius.
|
|
83
|
+
* @cssprop [--rc-select-border=var(--rc-border)] - Trigger border.
|
|
84
|
+
* @cssprop [--rc-select-listbox-radius=var(--rc-control-radius)] - Popup listbox border radius.
|
|
85
|
+
* @cssprop [--rc-select-listbox-duration=150ms] - Popup listbox open/close fade transition duration.
|
|
86
|
+
* @cssprop [--rc-select-listbox-border=var(--rc-border)] - Popup listbox border.
|
|
87
|
+
* @cssprop [--rc-select-shadow=var(--rc-shadow)] - Popup listbox box shadow.
|
|
88
|
+
* @cssprop [--rc-select-listbox-padding-block=var(--rc-control-padding-block)] - Popup listbox block padding.
|
|
89
|
+
* @cssprop [--rc-select-chip-radius=var(--rc-radius-md)] - Multi-select chip border radius.
|
|
90
|
+
* @cssprop [--rc-select-chip-padding-block=0.1em] - Multi-select chip block-axis padding.
|
|
91
|
+
* @cssprop [--rc-select-chip-padding-inline-start=0.3em] - Multi-select chip leading padding.
|
|
92
|
+
* @cssprop [--rc-select-chip-padding-inline-end=calc(var(--rc-chip-remove-target-size, 1.5rem) + var(--rc-chip-remove-offset-inline, 0.125rem))] - Multi-select chip trailing padding, including the remove affordance.
|
|
93
|
+
* @cssprop [--rc-select-chip-gap=calc(var(--rc-control-gap, 0.25em) * 0.8)] - Gap between chip
|
|
94
|
+
* content items.
|
|
95
|
+
* @cssprop [--rc-select-chip-border=var(--rc-border)] - Multi-select chip border.
|
|
96
|
+
* @cssprop [--rc-chip-remove-target-size=1.5rem] - Inherited remove-target width reserved by
|
|
97
|
+
* generated multi-select chips.
|
|
98
|
+
* @cssprop [--rc-chip-remove-offset-inline=0.125rem] - Inherited edge offset reserved by
|
|
99
|
+
* generated multi-select chips.
|
|
100
|
+
* @cssprop [--rc-select-toggle-indicator-size=1.1em] - Inline size of the toggle indicator container.
|
|
101
|
+
* @cssprop [--rc-select-dialog-gap=1rem] - Gap between fullscreen dialog regions.
|
|
102
|
+
* @cssprop [--rc-select-dialog-header-gap=0.5rem] - Gap between fullscreen dialog header slots.
|
|
103
|
+
*/
|
|
104
|
+
export declare class RCSelect extends LitElement {
|
|
105
|
+
static styles: import('lit').CSSResult;
|
|
106
|
+
/** Reflects whether the popup listbox is open. */
|
|
107
|
+
open: boolean;
|
|
108
|
+
/** Enables selection of multiple options simultaneously. */
|
|
109
|
+
multiple: boolean;
|
|
110
|
+
/** Disables the trigger and prevents the popup from opening. */
|
|
111
|
+
disabled: boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Mirrors the slotted native `<select>`'s own `required`, for `aria-required` on the trigger.
|
|
114
|
+
* Read-only in practice: set `required` on the slotted `<select>` itself, the source of truth
|
|
115
|
+
* for form participation and constraint validation.
|
|
116
|
+
*/
|
|
117
|
+
required: boolean;
|
|
118
|
+
/** Text shown in the trigger when no value is selected. */
|
|
119
|
+
placeholder: string;
|
|
120
|
+
/**
|
|
121
|
+
* Controls how selected values appear in the trigger.
|
|
122
|
+
*
|
|
123
|
+
* - `'chips'` — each selected value renders as a removable chip.
|
|
124
|
+
* - `'compact'` — selected values are summarized as "First, +N more".
|
|
125
|
+
* - `'auto'` — uses `'chips'` on pointer devices and `'compact'` on touch.
|
|
126
|
+
*/
|
|
127
|
+
display: 'auto' | 'chips' | 'compact';
|
|
128
|
+
/** Presents options in an anchored popover or transactional modal dialog. */
|
|
129
|
+
popupMode: RCSelectPopupMode;
|
|
130
|
+
/** Text for the dialog confirmation action. */
|
|
131
|
+
dialogConfirmLabel: string;
|
|
132
|
+
/** Accessible label for the leading dialog cancel action. */
|
|
133
|
+
dialogCancelLabel: string;
|
|
134
|
+
/** Whether the leading dialog cancel action is visible. */
|
|
135
|
+
dialogCancelButton: 'visible' | 'hidden';
|
|
136
|
+
/** Flex container used by `_anchorCtrl` as the positioning reference for the popup. */
|
|
137
|
+
protected _$anchor: HTMLElement;
|
|
138
|
+
/**
|
|
139
|
+
* The combobox trigger div.
|
|
140
|
+
*
|
|
141
|
+
* Owns `role="combobox"`, `aria-activedescendant`,
|
|
142
|
+
* `aria-expanded`, and receives focus during keyboard navigation.
|
|
143
|
+
*/
|
|
144
|
+
protected _$trigger: HTMLElement;
|
|
145
|
+
/** The `<rc-listbox>` popup. Receives option lists and selected-value updates from the host. */
|
|
146
|
+
protected _$listbox: RCListbox;
|
|
147
|
+
protected _$dialogHost?: RCDialog;
|
|
148
|
+
/**
|
|
149
|
+
* Reactive set of currently selected option values.
|
|
150
|
+
*
|
|
151
|
+
* Drive changes through `_applySelection` rather than mutating this directly
|
|
152
|
+
* so the listbox and native `<select>` stay in sync.
|
|
153
|
+
*/
|
|
154
|
+
protected _selectedValues: Set<string>;
|
|
155
|
+
/** Transaction-local selection while a dialog popup is open. */
|
|
156
|
+
protected _pendingSelectedValues: Set<string> | null;
|
|
157
|
+
protected _accessibleName: string;
|
|
158
|
+
protected _activePopupMode: RCSelectPopupMode;
|
|
159
|
+
/**
|
|
160
|
+
* Index into the chip button array for roving-tabindex chip navigation.
|
|
161
|
+
*
|
|
162
|
+
* `-1` means focus is on the trigger.
|
|
163
|
+
*/
|
|
164
|
+
protected _chipNavIndex: number;
|
|
165
|
+
/**
|
|
166
|
+
* The resolved option list, as rendered in the listbox.
|
|
167
|
+
*
|
|
168
|
+
* `_options` is sourced from the `options` property or the slotted `<select>`.
|
|
169
|
+
*/
|
|
170
|
+
protected _options: ListboxOption[];
|
|
171
|
+
/** WeakRef to the slotted `<select>`. Refreshed on every `slotchange`; `null` when absent. */
|
|
172
|
+
protected _$selectRef: WeakRef<HTMLSelectElement> | null;
|
|
173
|
+
protected readonly _selectController: NativeChildController<HTMLSelectElement>;
|
|
174
|
+
/**
|
|
175
|
+
* Watches the slotted `<select>` for `childList`, `subtree`, and `attributes` changes
|
|
176
|
+
* so the option list and disabled/multiple state stay in sync with author mutations.
|
|
177
|
+
*/
|
|
178
|
+
protected _mutationObserver: MutationObserver | null;
|
|
179
|
+
private _defaultValue;
|
|
180
|
+
private _propertyOptions;
|
|
181
|
+
private _value;
|
|
182
|
+
private _selectionInitialized;
|
|
183
|
+
/** True while `_applyPickerGuard` has force-disabled the slotted multiple `<select>`. */
|
|
184
|
+
protected _pickerGuardActive: boolean;
|
|
185
|
+
/** Consumer's `disabled` state on the select before the picker guard forced it; restored on teardown. */
|
|
186
|
+
protected _pickerGuardConsumerDisabled: boolean;
|
|
187
|
+
/** Form currently carrying the picker guard's `formdata` listener. */
|
|
188
|
+
protected _pickerGuardForm: HTMLFormElement | null;
|
|
189
|
+
/** Accumulated printable characters for type-ahead matching; cleared after 500 ms idle. */
|
|
190
|
+
protected _typeAheadBuffer: string;
|
|
191
|
+
/** `window.setTimeout` handle for resetting `_typeAheadBuffer`; cancel before modifying. */
|
|
192
|
+
protected _typeAheadTimer: number;
|
|
193
|
+
/**
|
|
194
|
+
* Manages `aria-activedescendant` on `_$trigger` and keyboard cursor position
|
|
195
|
+
* within `_$listbox.navigableItems`.
|
|
196
|
+
*/
|
|
197
|
+
protected _activeDescendantCtrl: ActiveDescendantController;
|
|
198
|
+
/** Manages CSS-anchored (or JS-fallback) placement of `_$listbox` relative to `_$anchor`. */
|
|
199
|
+
protected _anchorCtrl: AnchorController;
|
|
200
|
+
/** Element that owns `aria-activedescendant` for the currently rendered popup. */
|
|
201
|
+
protected get _$activeDescendantHost(): HTMLElement | null;
|
|
202
|
+
connectedCallback(): void;
|
|
203
|
+
disconnectedCallback(): void;
|
|
204
|
+
updated(changed: PropertyValues): void;
|
|
205
|
+
/**
|
|
206
|
+
* Forwards focus to the trigger. The host itself is never in the tab order, so without this
|
|
207
|
+
* override, calling `.focus()` on `<rc-select>` (as `rc-field` does when treating it as a
|
|
208
|
+
* control provider) would be a no-op.
|
|
209
|
+
*/
|
|
210
|
+
focus(options?: FocusOptions): void;
|
|
211
|
+
/** Forwards blur to the trigger; see `focus()`. */
|
|
212
|
+
blur(): void;
|
|
213
|
+
/** Opens the popup listbox if not already open or disabled. */
|
|
214
|
+
openPopup(): void;
|
|
215
|
+
/**
|
|
216
|
+
* Closes the popup listbox.
|
|
217
|
+
*
|
|
218
|
+
* @param returnFocus - When `true` (default), returns focus to the trigger.
|
|
219
|
+
*/
|
|
220
|
+
closePopup(returnFocus?: boolean): void;
|
|
221
|
+
/**
|
|
222
|
+
* Current selection. Host writes update selection silently; user interaction
|
|
223
|
+
* emits `rc-select-change`.
|
|
224
|
+
*/
|
|
225
|
+
get value(): RCSelectValue;
|
|
226
|
+
set value(value: RCSelectValue | undefined);
|
|
227
|
+
/** Initial uncontrolled selection, applied before user or native state owns the value. */
|
|
228
|
+
get defaultValue(): RCSelectValue | undefined;
|
|
229
|
+
set defaultValue(value: RCSelectValue | undefined);
|
|
230
|
+
/** Programmatic option source. Omit to derive options from the slotted `<select>`. */
|
|
231
|
+
get options(): ListboxOption[] | undefined;
|
|
232
|
+
set options(options: ListboxOption[] | undefined);
|
|
233
|
+
/** Selected values as a consistently-array-shaped convenience getter. */
|
|
234
|
+
get selectedValues(): string[];
|
|
235
|
+
/** `ListboxOption` objects for the current selection; falls back to label-only stubs for unknown values. */
|
|
236
|
+
protected get selectedOptions(): ListboxSelectableOption[];
|
|
237
|
+
/**
|
|
238
|
+
* Applies an already-normalized array of values as the current selection.
|
|
239
|
+
*
|
|
240
|
+
* In single-select mode only the first value is kept. Syncs `_$listbox` and the
|
|
241
|
+
* native `<select>` but does NOT dispatch `rc-select-change`.
|
|
242
|
+
*
|
|
243
|
+
* @param fromUser - Pass `true` only for a selection driven by real user interaction, so
|
|
244
|
+
* `_syncNativeSelect` dispatches native `input`/`change` on the underlying `<select>` (a
|
|
245
|
+
* programmatic `value`/`defaultValue` write is not a native interaction and relies on an
|
|
246
|
+
* external `sync()` call instead, the same as `rc-textarea`'s controlled-value contract).
|
|
247
|
+
*/
|
|
248
|
+
protected _applySelection(values: string[], fromUser?: boolean): void;
|
|
249
|
+
/** Document-capture click handler that closes the popup when a click lands outside `this`. */
|
|
250
|
+
protected _onDocClick: (e: MouseEvent) => void;
|
|
251
|
+
/** Document-capture keydown handler; closes the popup on `Escape`. */
|
|
252
|
+
protected _onDocKeyDown: (e: KeyboardEvent) => void;
|
|
253
|
+
/**
|
|
254
|
+
* Suppress the native `<select>`'s default click action
|
|
255
|
+
*/
|
|
256
|
+
protected _onNativeSelectClick: (e: Event) => void;
|
|
257
|
+
/**
|
|
258
|
+
* Countermeasure for select["multiple"] bug in Firefox for Android / GeckoView.
|
|
259
|
+
*
|
|
260
|
+
* Works around a GeckoView bug where tapping anywhere inside an
|
|
261
|
+
* ancestor `<label>`'s bounds opens the native picker dialog of a wrapped
|
|
262
|
+
* `<select multiple>`, even though the select is hidden and the tap landed on this
|
|
263
|
+
* component's own UI.
|
|
264
|
+
*
|
|
265
|
+
* Label activation on a disabled control is a spec-defined no-op, so the slotted select
|
|
266
|
+
* is force-disabled after upgrade while it is `multiple`. A disabled select submits
|
|
267
|
+
* nothing, so form submission is restored by appending the current selection in a
|
|
268
|
+
* `formdata` listener on the owning form (`_handleFormData`). A disabled select is also
|
|
269
|
+
* barred from native constraint validation, so `_handleFormSubmit` enforces its
|
|
270
|
+
* `ValidityState` at submit time instead.
|
|
271
|
+
*
|
|
272
|
+
* Scoped to multiple selects: the single-select picker path is already suppressed by
|
|
273
|
+
* `_onNativeSelectClick`. Pre-upgrade behavior is unaffected — the guard
|
|
274
|
+
* only applies once the component initializes.
|
|
275
|
+
*
|
|
276
|
+
* @see https://bugzilla.mozilla.org/show_bug.cgi?id=1475723
|
|
277
|
+
*/
|
|
278
|
+
protected _applyPickerGuard($select: HTMLSelectElement): void;
|
|
279
|
+
/** Moves the picker guard's `formdata` and `submit` listeners to `$form`; pass `null` to detach. */
|
|
280
|
+
protected _syncFormListeners($form: HTMLFormElement | null): void;
|
|
281
|
+
/**
|
|
282
|
+
* Appends the current selection to the owning form's entry list.
|
|
283
|
+
*
|
|
284
|
+
* Replaces the submission the select would have produced were it
|
|
285
|
+
* not force-disabled by `_applyPickerGuard`.
|
|
286
|
+
*
|
|
287
|
+
* Append-only: entries from other same-named controls in the form
|
|
288
|
+
* are left alone.
|
|
289
|
+
*/
|
|
290
|
+
protected _handleFormData: (e: FormDataEvent) => void;
|
|
291
|
+
/**
|
|
292
|
+
* Enforces the slotted select's constraints at submit time.
|
|
293
|
+
*
|
|
294
|
+
* Mirrors native scoping: skipped for `novalidate`
|
|
295
|
+
* forms and `formnovalidate` submitters, and never runs for `form.submit()`
|
|
296
|
+
*
|
|
297
|
+
* The native validation bubble cannot render on a hidden control, so a
|
|
298
|
+
* cancelable `invalid` event is fired on the select (matching native
|
|
299
|
+
* reporting) and focus moves to the trigger unless the consumer cancels it.
|
|
300
|
+
*/
|
|
301
|
+
protected _handleFormSubmit: (e: SubmitEvent) => void;
|
|
302
|
+
/**
|
|
303
|
+
* Resolves the slotted `<select>` on every `slotchange`, wires `_mutationObserver`,
|
|
304
|
+
* and seeds initial state via `queueMicrotask` to stay safe inside framework reactive passes.
|
|
305
|
+
*/
|
|
306
|
+
protected _handleSelectSlotChange(): void;
|
|
307
|
+
protected _setupSelect($select: HTMLSelectElement | null): void;
|
|
308
|
+
/**
|
|
309
|
+
* Derives options from `$select` (or defers to `_propertyOptions` when set)
|
|
310
|
+
* and re-applies selection from the current authoritative source.
|
|
311
|
+
*/
|
|
312
|
+
protected _syncOptionsFromSelect($select: HTMLSelectElement): void;
|
|
313
|
+
/**
|
|
314
|
+
* Picks the correct selection source in priority order:
|
|
315
|
+
* controlled `_value` → `_defaultValue` → native `<select>` default/current state.
|
|
316
|
+
*/
|
|
317
|
+
protected _applySelectionFromCurrentSource(): void;
|
|
318
|
+
/** Writes `_options` and pushes the list to `_$listbox` when it is mounted. */
|
|
319
|
+
protected _syncOptions(options: ListboxOption[]): void;
|
|
320
|
+
/** Returns `_propertyOptions` when set; otherwise reads live from the slotted `<select>`. */
|
|
321
|
+
protected _currentOptions(): ListboxOption[];
|
|
322
|
+
/**
|
|
323
|
+
* Maps non-empty native `<option>` nodes to `ListboxOption` objects.
|
|
324
|
+
*
|
|
325
|
+
* Options with empty `value` are skipped (placeholder guard).
|
|
326
|
+
*/
|
|
327
|
+
protected _optionsFromSelect($select: HTMLSelectElement): ListboxOption[];
|
|
328
|
+
/** Returns values of currently selected `<option>` nodes; falls back to `selectedValues` when no native select is present. */
|
|
329
|
+
protected _selectedValuesFromNativeSelect(): string[];
|
|
330
|
+
/** Returns values of `defaultSelected` `<option>` nodes (author `selected` attribute); falls back to `selectedValues`. */
|
|
331
|
+
protected _defaultSelectedValuesFromNativeSelect(): string[];
|
|
332
|
+
/**
|
|
333
|
+
* Rebuilds native `<select>` options from `_propertyOptions`.
|
|
334
|
+
*
|
|
335
|
+
* Only runs when `_propertyOptions` is set; pauses then resumes `_mutationObserver`
|
|
336
|
+
* while writing to avoid re-entrant sync.
|
|
337
|
+
*/
|
|
338
|
+
protected _mirrorOptionsToNativeSelect(): void;
|
|
339
|
+
/**
|
|
340
|
+
* Upserts a single option into `_options` (and `_propertyOptions` when set)
|
|
341
|
+
* and adds the corresponding `<option>` to the native `<select>` if absent.
|
|
342
|
+
*/
|
|
343
|
+
protected _addOption(option: ListboxOption): void;
|
|
344
|
+
/** Coerces `RCSelectValue` (string or string[]) to `string[]`; returns `[]` for empty-string singles. */
|
|
345
|
+
protected _normalizeValue(value: RCSelectValue): string[];
|
|
346
|
+
/**
|
|
347
|
+
* Copies `aria-label` or first-label text from the native `<select>` to `_$trigger`.
|
|
348
|
+
*
|
|
349
|
+
* No-op when the trigger already has an explicit `aria-label`.
|
|
350
|
+
*/
|
|
351
|
+
protected _syncAccessibleName($sel: HTMLSelectElement): void;
|
|
352
|
+
/**
|
|
353
|
+
* Handles `rc-listbox-change` from the popup.
|
|
354
|
+
*
|
|
355
|
+
* Stops propagation, mutates `_selectedValues`, syncs state, and fires
|
|
356
|
+
* `rc-select-change`.
|
|
357
|
+
*/
|
|
358
|
+
protected _handleListboxChange(e: CustomEvent): void;
|
|
359
|
+
/** Removes a single value from `_selectedValues`, syncs the listbox and native select, and dispatches `rc-select-change`. */
|
|
360
|
+
protected _removeValue(value: string): void;
|
|
361
|
+
/**
|
|
362
|
+
* Flips `selected` on each `<option>` in the native `<select>` to match `_selectedValues`;
|
|
363
|
+
* no-op when no native select is present.
|
|
364
|
+
*
|
|
365
|
+
* @param fromUser - When `true`, also dispatches native `input` and `change` on `$select`
|
|
366
|
+
* (in that order, matching a real `<select>`) so outside listeners, including an
|
|
367
|
+
* `rc-field` ancestor treating this component as its control provider, observe the change.
|
|
368
|
+
*/
|
|
369
|
+
protected _syncNativeSelect(fromUser?: boolean): void;
|
|
370
|
+
/** Constructs and dispatches `rc-select-change` with current `value`, `selectedValues`, and `selectedOptions`. */
|
|
371
|
+
protected _dispatchChange(): void;
|
|
372
|
+
/** Maps value strings to `ListboxOption` objects from `_options`; creates label-only fallback stubs for unknown values. */
|
|
373
|
+
protected _selectedOptionsFor(values: string[]): ListboxSelectableOption[];
|
|
374
|
+
/** Resolved display mode after `auto` pointer-detection: `'chips'` on fine-pointer devices, `'compact'` on coarse. */
|
|
375
|
+
protected get _effectiveDisplay(): 'chips' | 'compact';
|
|
376
|
+
/** Looks up the display label for `value` from native `<select>` option text; returns `value` itself as a fallback. */
|
|
377
|
+
protected _labelFor(value: string): string;
|
|
378
|
+
/** Text shown in the trigger's value-display area; returns placeholder when chips are active or nothing is selected. */
|
|
379
|
+
protected get _displayLabel(): string;
|
|
380
|
+
/**
|
|
381
|
+
* APG Combobox keyboard handler on the trigger.
|
|
382
|
+
*
|
|
383
|
+
* Arrow keys navigate/open, Space/Enter activate, Tab closes without focus return,
|
|
384
|
+
* ArrowLeft enters chip navigation, and printable chars forward to type-ahead.
|
|
385
|
+
*/
|
|
386
|
+
protected _handleTriggerKeyDown(e: KeyboardEvent): void;
|
|
387
|
+
/**
|
|
388
|
+
* Dispatches a synthetic `pointerdown` on the active listbox item to activate it.
|
|
389
|
+
*
|
|
390
|
+
* Prefers `pointerdown` over a direct call so listbox item click logic
|
|
391
|
+
* (which is bound to `pointerdown`) fires through its normal path.
|
|
392
|
+
*/
|
|
393
|
+
protected _activateActive(): void;
|
|
394
|
+
/**
|
|
395
|
+
* Accumulates characters in `_typeAheadBuffer` and either immediately selects
|
|
396
|
+
* the first match (closed single-select) or moves the virtual cursor (open popup).
|
|
397
|
+
*/
|
|
398
|
+
protected _handleTypeAhead(char: string): void;
|
|
399
|
+
/** Focuses the last chip button and sets `_chipNavIndex` to begin roving-tabindex navigation within the chip group. */
|
|
400
|
+
protected _enterChipNav(): void;
|
|
401
|
+
/** Queries all native remove buttons inside input chips; order matches DOM order. */
|
|
402
|
+
protected _$chipButtons(): HTMLButtonElement[];
|
|
403
|
+
/**
|
|
404
|
+
* Keyboard handler for chip buttons.
|
|
405
|
+
*
|
|
406
|
+
* ArrowLeft/Right rove chip focus, Escape returns to trigger,
|
|
407
|
+
* Delete/Backspace/Enter/Space remove the chip's value
|
|
408
|
+
* and return focus to the trigger.
|
|
409
|
+
*/
|
|
410
|
+
protected _handleChipKeyDown(e: KeyboardEvent, value: string): void;
|
|
411
|
+
/** Toggles the popup open or closed on trigger click. */
|
|
412
|
+
protected _handleTriggerClick(): void;
|
|
413
|
+
protected get _dialogSelectedValues(): string[];
|
|
414
|
+
protected _focusDialogContent(): void;
|
|
415
|
+
/** Hook for subclasses to finalize provisional options before dialog selection commits. */
|
|
416
|
+
protected _prepareDialogCommit(): void;
|
|
417
|
+
protected _commitDialogSelection(): void;
|
|
418
|
+
protected _discardDialogSelection(): void;
|
|
419
|
+
protected _finishDialogClose(returnFocus: boolean): void;
|
|
420
|
+
protected _handleDialogClose(e: CustomEvent<RCDialogCloseEvent>): void;
|
|
421
|
+
protected _stopDialogEvent(e: Event): void;
|
|
422
|
+
protected _removePendingValue(value: string): void;
|
|
423
|
+
protected _renderDialogBody(): import('lit').TemplateResult<1>;
|
|
424
|
+
protected _renderDialogPopup(): import('lit').TemplateResult<1>;
|
|
425
|
+
protected render(): import('lit').TemplateResult<1>;
|
|
426
|
+
protected _renderAnchor(): import('lit').TemplateResult<1>;
|
|
427
|
+
/** Renders selected values as removable input chips inside the shared chip-group layout. */
|
|
428
|
+
protected _renderChips(values?: Iterable<string>, pending?: boolean): import('lit').TemplateResult<1>;
|
|
429
|
+
}
|
|
430
|
+
export default RCSelect;
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rcarls/rc-select",
|
|
3
|
+
"publishConfig": {
|
|
4
|
+
"access": "public"
|
|
5
|
+
},
|
|
6
|
+
"version": "0.0.0-next-20260921045401",
|
|
7
|
+
"description": "Select-only combobox backed by a native <select>.",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/richardcarls/rc-webcomponents.git",
|
|
11
|
+
"directory": "packages/rc-select"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://richardcarls.github.io/rc-webcomponents/components/rc-select",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"type": "module",
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"module": "./dist/rc-select.js",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"import": {
|
|
23
|
+
"types": "./dist/types/packages/rc-select/src/index.d.ts",
|
|
24
|
+
"default": "./dist/rc-select.js"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"./define": {
|
|
28
|
+
"import": {
|
|
29
|
+
"types": "./dist/types/packages/rc-select/src/define.d.ts",
|
|
30
|
+
"default": "./dist/rc-select-define.js"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"types": "./dist/types/packages/rc-select/src/index.d.ts",
|
|
35
|
+
"sideEffects": [
|
|
36
|
+
"./dist/rc-select-define.js"
|
|
37
|
+
],
|
|
38
|
+
"customElements": "dist/custom-elements.json",
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsc && vite build && cem analyze",
|
|
41
|
+
"cem:analyze": "cem analyze",
|
|
42
|
+
"preview": "vite preview",
|
|
43
|
+
"test:browser": "vitest --run",
|
|
44
|
+
"test:browser:chrome": "vitest --run --project=chromium",
|
|
45
|
+
"test:browser:firefox": "vitest --run --project=firefox"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@rcarls/rc-chip-group": "0.0.0-next-20260921045401",
|
|
49
|
+
"@rcarls/rc-common": "0.0.0-next-20260921045401",
|
|
50
|
+
"@rcarls/rc-dialog": "0.0.0-next-20260921045401",
|
|
51
|
+
"@rcarls/rc-listbox": "0.0.0-next-20260921045401"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@custom-elements-manifest/analyzer": "0.11.0",
|
|
55
|
+
"@vitest/browser-playwright": "4.1.5",
|
|
56
|
+
"lit": "^3.0.0",
|
|
57
|
+
"playwright": "^1.56.0",
|
|
58
|
+
"rollup": "^4.60.2",
|
|
59
|
+
"typescript": "~5.9.3",
|
|
60
|
+
"vite": "^7.1.7",
|
|
61
|
+
"vite-plugin-dts": "^4.5.4",
|
|
62
|
+
"vitest": "^4.0.6",
|
|
63
|
+
"vitest-browser-lit": "^1.0.1"
|
|
64
|
+
},
|
|
65
|
+
"peerDependencies": {
|
|
66
|
+
"lit": "^3.0.0"
|
|
67
|
+
}
|
|
68
|
+
}
|