@rcarls/rc-listbox 0.3.2 → 0.4.0
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/README.md +3 -0
- package/dist/custom-elements.json +21 -13
- package/dist/{rc-listbox-CTedy14U.js → rc-listbox-B2htLg2W.js} +17 -3
- package/dist/rc-listbox-B2htLg2W.js.map +1 -0
- package/dist/rc-listbox-define.js +1 -1
- package/dist/rc-listbox.js +1 -1
- package/dist/types/packages/rc-listbox/src/rc-listbox.d.ts +31 -12
- package/package.json +1 -1
- package/dist/rc-listbox-CTedy14U.js.map +0 -1
package/README.md
CHANGED
|
@@ -64,7 +64,10 @@ listbox.addEventListener('rc-listbox-change', (event) => {
|
|
|
64
64
|
| Property / method | Type | Description |
|
|
65
65
|
| --- | --- | --- |
|
|
66
66
|
| `multiple` | `boolean` | Enables multi-selection and reflects `aria-multiselectable`. |
|
|
67
|
+
| `checkmark` | `boolean` | Renders a checkmark indicator inside each option element. |
|
|
67
68
|
| `filterStrategy` | `'prefix' \| 'contains' \| function` | Controls how `filterOptions()` matches labels. |
|
|
69
|
+
| `value` | `string \| string[]` | Current selection. Host writes update silently. |
|
|
70
|
+
| `defaultValue` | `string \| string[] \| undefined` | Initial uncontrolled selection. |
|
|
68
71
|
| `options` | `ListboxOption[]` | Replaces the rendered option list. |
|
|
69
72
|
| `allOptions` | `readonly ListboxOption[]` | All configured options. |
|
|
70
73
|
| `filteredOptions` | `readonly ListboxOption[]` | Options currently passing the filter. |
|
|
@@ -75,35 +75,43 @@
|
|
|
75
75
|
},
|
|
76
76
|
{
|
|
77
77
|
"description": "Background of a hovered option.",
|
|
78
|
-
"name": "--rc-listbox-hover-bg"
|
|
78
|
+
"name": "--rc-listbox-hover-bg",
|
|
79
|
+
"default": "color-mix(in srgb, Highlight 8%, transparent)"
|
|
79
80
|
},
|
|
80
81
|
{
|
|
81
82
|
"description": "Text color of a hovered option.",
|
|
82
|
-
"name": "--rc-listbox-hover-color"
|
|
83
|
+
"name": "--rc-listbox-hover-color",
|
|
84
|
+
"default": "inherit"
|
|
83
85
|
},
|
|
84
86
|
{
|
|
85
87
|
"description": "Background of the keyboard-active option.",
|
|
86
|
-
"name": "--rc-listbox-active-bg"
|
|
88
|
+
"name": "--rc-listbox-active-bg",
|
|
89
|
+
"default": "color-mix(in srgb, Highlight 8%, transparent)"
|
|
87
90
|
},
|
|
88
91
|
{
|
|
89
92
|
"description": "Text color of the keyboard-active option.",
|
|
90
|
-
"name": "--rc-listbox-active-color"
|
|
93
|
+
"name": "--rc-listbox-active-color",
|
|
94
|
+
"default": "var(--rc-listbox-hover-color, inherit)"
|
|
91
95
|
},
|
|
92
96
|
{
|
|
93
97
|
"description": "Background of a selected option.",
|
|
94
|
-
"name": "--rc-listbox-selected-bg"
|
|
98
|
+
"name": "--rc-listbox-selected-bg",
|
|
99
|
+
"default": "Highlight"
|
|
95
100
|
},
|
|
96
101
|
{
|
|
97
102
|
"description": "Text color of a selected option.",
|
|
98
|
-
"name": "--rc-listbox-selected-color"
|
|
103
|
+
"name": "--rc-listbox-selected-color",
|
|
104
|
+
"default": "HighlightText"
|
|
99
105
|
},
|
|
100
106
|
{
|
|
101
107
|
"description": "Text color of a disabled option.",
|
|
102
|
-
"name": "--rc-listbox-disabled-color"
|
|
108
|
+
"name": "--rc-listbox-disabled-color",
|
|
109
|
+
"default": "GrayText"
|
|
103
110
|
},
|
|
104
111
|
{
|
|
105
112
|
"description": "Opacity of a disabled option.",
|
|
106
|
-
"name": "--rc-listbox-disabled-opacity"
|
|
113
|
+
"name": "--rc-listbox-disabled-opacity",
|
|
114
|
+
"default": "1"
|
|
107
115
|
}
|
|
108
116
|
],
|
|
109
117
|
"cssParts": [
|
|
@@ -217,7 +225,7 @@
|
|
|
217
225
|
"type": {
|
|
218
226
|
"text": "string"
|
|
219
227
|
},
|
|
220
|
-
"privacy": "
|
|
228
|
+
"privacy": "protected",
|
|
221
229
|
"default": "''"
|
|
222
230
|
},
|
|
223
231
|
{
|
|
@@ -429,7 +437,7 @@
|
|
|
429
437
|
{
|
|
430
438
|
"kind": "method",
|
|
431
439
|
"name": "_handleActivate",
|
|
432
|
-
"privacy": "
|
|
440
|
+
"privacy": "protected",
|
|
433
441
|
"return": {
|
|
434
442
|
"type": {
|
|
435
443
|
"text": "void"
|
|
@@ -609,30 +617,30 @@
|
|
|
609
617
|
],
|
|
610
618
|
"attributes": [
|
|
611
619
|
{
|
|
620
|
+
"description": "Allow multiple selection. Reflected as `aria-multiselectable` on the host.",
|
|
612
621
|
"name": "multiple",
|
|
613
622
|
"type": {
|
|
614
623
|
"text": "boolean"
|
|
615
624
|
},
|
|
616
625
|
"default": "false",
|
|
617
|
-
"description": "Allow multiple selection. Reflected as `aria-multiselectable` on the host.",
|
|
618
626
|
"fieldName": "multiple"
|
|
619
627
|
},
|
|
620
628
|
{
|
|
629
|
+
"description": "Render a checkmark indicator inside each option element.\n\nHidden by default; enable for combobox / select patterns where the\nconsumer's CSS shows it conditionally via `[aria-selected='true']`.",
|
|
621
630
|
"name": "checkmark",
|
|
622
631
|
"type": {
|
|
623
632
|
"text": "boolean"
|
|
624
633
|
},
|
|
625
634
|
"default": "false",
|
|
626
|
-
"description": "Render a checkmark indicator inside each option element.\n\nHidden by default; enable for combobox / select patterns where the\nconsumer's CSS shows it conditionally via `[aria-selected='true']`.",
|
|
627
635
|
"fieldName": "checkmark"
|
|
628
636
|
},
|
|
629
637
|
{
|
|
638
|
+
"description": "How option labels are matched against the active filter text.\n\nDefaults to `'contains'` (substring). Set to `'prefix'` for starts-with\nmatching, or pass a custom predicate for full control.\nFunction values are JS-only; string values may be set via the\n`filter-strategy` attribute.",
|
|
630
639
|
"name": "filter-strategy",
|
|
631
640
|
"type": {
|
|
632
641
|
"text": "FilterStrategy"
|
|
633
642
|
},
|
|
634
643
|
"default": "'contains'",
|
|
635
|
-
"description": "How option labels are matched against the active filter text.\n\nDefaults to `'contains'` (substring). Set to `'prefix'` for starts-with\nmatching, or pass a custom predicate for full control.\nFunction values are JS-only; string values may be set via the\n`filter-strategy` attribute.",
|
|
636
644
|
"fieldName": "filterStrategy"
|
|
637
645
|
}
|
|
638
646
|
],
|
|
@@ -139,11 +139,25 @@ const r = (s = class extends d {
|
|
|
139
139
|
get options() {
|
|
140
140
|
return [...this._itemsCollectionCtrl.allOptions];
|
|
141
141
|
}
|
|
142
|
-
/**
|
|
142
|
+
/**
|
|
143
|
+
* Replace the full options list.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* listbox.options = [
|
|
147
|
+
* { value: 'apple', label: 'Apple' },
|
|
148
|
+
* { value: 'banana', label: 'Banana', disabled: true },
|
|
149
|
+
* { kind: 'action', action: 'clear', value: 'clear', label: 'Clear selection' },
|
|
150
|
+
* ];
|
|
151
|
+
*/
|
|
143
152
|
set options(t) {
|
|
144
153
|
this._itemsCollectionCtrl.setOptions([...t]), this._applySelectionFromSource();
|
|
145
154
|
}
|
|
146
|
-
/**
|
|
155
|
+
/**
|
|
156
|
+
* Append a single option without replacing the list.
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* listbox.appendOption({ value: 'cherry', label: 'Cherry' });
|
|
160
|
+
*/
|
|
147
161
|
appendOption(t) {
|
|
148
162
|
this._itemsCollectionCtrl.appendOption(t);
|
|
149
163
|
}
|
|
@@ -334,4 +348,4 @@ let x = r;
|
|
|
334
348
|
export {
|
|
335
349
|
x as R
|
|
336
350
|
};
|
|
337
|
-
//# sourceMappingURL=rc-listbox-
|
|
351
|
+
//# sourceMappingURL=rc-listbox-B2htLg2W.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rc-listbox-B2htLg2W.js","sources":["../src/rc-listbox.ts"],"sourcesContent":["import { LitElement, html, css } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport {\n ActiveDescendantController,\n ItemsCollectionController,\n type ItemsCollectionActionOption,\n type ItemsCollectionOption,\n type ItemsCollectionSelectableOption,\n type ItemsCollectionFilterStrategy,\n} from '@rcarls/rc-common';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'rc-listbox': RCListbox;\n }\n}\n\n/** Option shape accepted by `rc-listbox`. */\nexport type ListboxOption = ItemsCollectionOption;\nexport type ListboxSelectableOption = ItemsCollectionSelectableOption;\nexport type ListboxActionOption<Action extends string = string> = ItemsCollectionActionOption & {\n action: Action;\n};\n\n/**\n * Listbox that keeps option DOM in light DOM for aria-activedescendant navigation,\n * following the WAI-ARIA Listbox pattern.\n *\n * - `'prefix'`: label must start with the query (default, matches native `<select>` type-ahead).\n * - `'contains'`: label must contain the query anywhere.\n * - `function`: custom predicate; receives lowercased label and query, return `true` to show the option.\n */\nexport type FilterStrategy = ItemsCollectionFilterStrategy;\n\nexport interface RCListboxSelectChangeEvent {\n reason: 'select';\n\n /** Canonical selected value for single mode, or selected values for multi mode. */\n value: string | string[];\n\n /** Whether the option was selected (false means it was deselected). */\n selected: boolean;\n\n /** The option value that was activated. */\n optionValue: string;\n\n /** The option that was activated. */\n option: ListboxSelectableOption;\n\n /** Selected values array (length=1 for single-selection mode). */\n selectedValues: string[];\n\n /** Selected options. */\n selectedOptions: ListboxSelectableOption[];\n}\n\nexport interface RCListboxActionChangeEvent<Action extends string = string> {\n reason: 'action';\n\n /** Current canonical selected value; action rows do not mutate selection. */\n value: string | string[];\n\n /** Action activations never select the action row. */\n selected: false;\n\n /** The action option value that was activated. */\n optionValue: string;\n\n /** The action option that was activated. */\n option: ListboxActionOption<Action>;\n\n /** The activated action command. */\n action: Action;\n\n /** Selected values array (length=1 for single-selection mode). */\n selectedValues: string[];\n\n /** Selected options. */\n selectedOptions: ListboxSelectableOption[];\n}\n\nexport type RCListboxChangeEvent = RCListboxSelectChangeEvent | RCListboxActionChangeEvent;\n\nlet _uid = 0;\n\n/** Structural CSS injected into the root that contains rc-listbox's light-DOM options. */\nconst LIGHT_DOM_CSS = `\n@layer rc-base {\n rc-listbox ul {\n list-style: none;\n margin: 0;\n padding: 0;\n }\n\n rc-listbox li[role='option'] {\n display: flex;\n align-items: center;\n gap: var(--rc-listbox-option-gap, 0.25rem);\n min-block-size: var(--rc-listbox-option-min-block-size, 0px);\n padding: var(--rc-listbox-option-padding-block, 2px) var(--rc-listbox-option-padding-inline, 4px);\n cursor: default;\n user-select: none;\n outline: none;\n background: transparent;\n color: inherit;\n transition: var(--rc-listbox-option-transition);\n }\n\n rc-listbox li[role='option']:hover {\n background: var(--rc-listbox-hover-bg, color-mix(in srgb, Highlight 8%, transparent));\n color: var(--rc-listbox-hover-color, inherit);\n }\n\n rc-listbox li[role='option'][data-active] {\n background: var(--rc-listbox-active-bg, color-mix(in srgb, Highlight 8%, transparent));\n color: var(--rc-listbox-active-color, var(--rc-listbox-hover-color, inherit));\n }\n\n rc-listbox li[role='option'][aria-selected='true'] {\n background: var(--rc-listbox-selected-bg, Highlight);\n color: var(--rc-listbox-selected-color, HighlightText);\n }\n\n rc-listbox li[role='option'][aria-disabled='true'] {\n color: var(--rc-listbox-disabled-color, GrayText);\n opacity: var(--rc-listbox-disabled-opacity, 1);\n pointer-events: none;\n }\n\n rc-listbox [part~='option-checkmark'] {\n display: none;\n min-inline-size: 1em;\n text-align: center;\n }\n\n rc-listbox[checkmark] [part~='option-checkmark'] {\n display: inline;\n visibility: hidden;\n }\n\n rc-listbox[checkmark] li[role='option'][aria-selected='true'] [part~='option-checkmark'] {\n visibility: visible;\n }\n}\n`;\n\n/**\n * A WAI-ARIA listbox component that renders a `<ul role=\"presentation\">`\n * + `<li role=\"option\">` subtree directly into its own light DOM to facilitate\n * `aria-activedescendant` virtual navigation with IDs inside the same document\n * or shadow root.\n *\n * Pre-rendered `<ul>/<li>` children are accepted as a progressive enhancement\n * baseline. The component reads them on first connect if no `options` setter\n * has been called.\n *\n * Consumers drive this component via its JS API:\n * - Set `options` to populate the list\n * - Set `value` / `defaultValue` to manage selection\n * - Call `toggleOption()` for internal keyboard/pointer activation\n * - Call `filterOptions()` to filter visible options\n * - Read `navigableItems` to feed `ActiveDescendantController`\n *\n * @see {@link https://richardcarls.github.io/rc-webcomponents/components/rc-listbox rc-listbox docs}\n * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/listbox/ WAI-ARIA Listbox pattern}\n *\n * @slot — Accepts pre-rendered `<ul>` with `<li>` children for progressive enhancement.\n *\n * @fires rc-listbox-change - Fired when an option is activated (clicked or Enter/Space)\n *\n * @csspart option - Individual `<li role=\"option\">` elements\n * @csspart option-checkmark - The checkmark `<span>` inside each option (when `checkmark` is true)\n * @csspart create-option - The \"Create\" option when allow-create is active\n *\n * @attr multiple - Allow multiple selection. Reflected as `aria-multiselectable` on the host.\n * @attr checkmark - Render a checkmark indicator inside each option element.\n * @attr filter-strategy - How option labels are matched against the active filter text:\n * `prefix`, `contains`, or omit to keep the `contains` default. Function values are JS-only.\n *\n * @cssprop [--rc-listbox-option-gap=0.25rem] - Gap between the checkmark and option label.\n * @cssprop [--rc-listbox-option-min-block-size=0px] - Minimum block size (height) of each option row.\n * @cssprop [--rc-listbox-option-padding-block=2px] - Block-axis padding of each option row.\n * @cssprop [--rc-listbox-option-padding-inline=4px] - Inline-axis padding of each option row.\n * @cssprop [--rc-listbox-option-transition] - CSS transition applied to each option row.\n * @cssprop [--rc-listbox-hover-bg=color-mix(in srgb, Highlight 8%, transparent)] - Background of a hovered option.\n * @cssprop [--rc-listbox-hover-color=inherit] - Text color of a hovered option.\n * @cssprop [--rc-listbox-active-bg=color-mix(in srgb, Highlight 8%, transparent)] - Background of the keyboard-active option.\n * @cssprop [--rc-listbox-active-color=var(--rc-listbox-hover-color, inherit)] - Text color of the keyboard-active option.\n * @cssprop [--rc-listbox-selected-bg=Highlight] - Background of a selected option.\n * @cssprop [--rc-listbox-selected-color=HighlightText] - Text color of a selected option.\n * @cssprop [--rc-listbox-disabled-color=GrayText] - Text color of a disabled option.\n * @cssprop [--rc-listbox-disabled-opacity=1] - Opacity of a disabled option.\n */\nexport class RCListbox extends LitElement {\n static override styles = css`\n :host {\n display: block;\n overflow-y: auto;\n }\n `;\n\n private static readonly _styledRoots = new Set<Document | ShadowRoot>();\n\n private static _ensureBaseStyles(root: Document | ShadowRoot): void {\n if (RCListbox._styledRoots.has(root)) return;\n RCListbox._styledRoots.add(root);\n\n const $style = document.createElement('style');\n $style.setAttribute('data-rc-light-dom-base', 'rc-listbox');\n $style.textContent = LIGHT_DOM_CSS;\n\n if (root instanceof Document) {\n root.head.appendChild($style);\n } else {\n root.appendChild($style);\n }\n }\n\n /** Allow multiple selection. Reflected as `aria-multiselectable` on the host. */\n @property({ type: Boolean, reflect: true })\n multiple = false;\n\n /**\n * Render a checkmark indicator inside each option element.\n *\n * Hidden by default; enable for combobox / select patterns where the\n * consumer's CSS shows it conditionally via `[aria-selected='true']`.\n */\n @property({ type: Boolean, reflect: true })\n checkmark = false;\n\n /**\n * How option labels are matched against the active filter text.\n *\n * Defaults to `'contains'` (substring). Set to `'prefix'` for starts-with\n * matching, or pass a custom predicate for full control.\n * Function values are JS-only; string values may be set via the\n * `filter-strategy` attribute.\n */\n @property({ attribute: 'filter-strategy', reflect: false })\n filterStrategy: FilterStrategy = 'contains';\n\n private _defaultValue: string | string[] | undefined;\n private _value: string | string[] | undefined;\n private _selectionInitialized = false;\n protected _filterText = '';\n\n /** Unique ID prefix for all rendered option elements in this instance. */\n protected readonly _uid = `rc-lb-${++_uid}`;\n\n /** Manages the `<ul>/<li>` option DOM subtree in the component's light DOM. */\n protected readonly _itemsCollectionCtrl = new ItemsCollectionController(this, {\n idPrefix: this._uid,\n onInitFromDom: () => this._applySelectionFromSource(),\n onActivate: (option) => this._handleActivate(option),\n });\n\n /** Active-descendant controller; tracks keyboard focus within the option list. */\n protected readonly _activeDescendantCtrl = new ActiveDescendantController(this, {\n host: () => this,\n items: () => this.navigableItems,\n });\n\n override connectedCallback(): void {\n super.connectedCallback();\n\n RCListbox._ensureBaseStyles(this.getRootNode() as Document | ShadowRoot);\n\n if (!this.hasAttribute('role')) {\n this.setAttribute('role', 'listbox');\n }\n\n this.addEventListener('keydown', this._onKeydown);\n this.addEventListener('blur', this._onBlur);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n\n this.removeEventListener('keydown', this._onKeydown);\n this.removeEventListener('blur', this._onBlur);\n }\n\n override updated(changed: Map<PropertyKey, unknown>): void {\n if (changed.has('multiple')) {\n this.multiple\n ? this.setAttribute('aria-multiselectable', 'true')\n : this.removeAttribute('aria-multiselectable');\n }\n\n if (changed.has('checkmark')) {\n this._itemsCollectionCtrl.checkmark = this.checkmark;\n }\n }\n\n protected override render() {\n return html`<slot></slot>`;\n }\n\n /** All options regardless of filter state. */\n get allOptions(): readonly ListboxOption[] {\n return this._itemsCollectionCtrl.allOptions;\n }\n\n /** Options currently passing the active filter. */\n get filteredOptions(): readonly ListboxOption[] {\n const filterText = this._filterText;\n\n if (!filterText) {\n return [...this._itemsCollectionCtrl.allOptions];\n }\n\n return this._itemsCollectionCtrl.allOptions.filter((option) => this._isVisible(option));\n }\n\n /** Replace the full options list. */\n get options(): ListboxOption[] {\n return [...this._itemsCollectionCtrl.allOptions];\n }\n\n /**\n * Replace the full options list.\n *\n * @example\n * listbox.options = [\n * { value: 'apple', label: 'Apple' },\n * { value: 'banana', label: 'Banana', disabled: true },\n * { kind: 'action', action: 'clear', value: 'clear', label: 'Clear selection' },\n * ];\n */\n set options(options: ListboxOption[]) {\n this._itemsCollectionCtrl.setOptions([...options]);\n this._applySelectionFromSource();\n }\n\n /**\n * Append a single option without replacing the list.\n *\n * @example\n * listbox.appendOption({ value: 'cherry', label: 'Cherry' });\n */\n appendOption(option: ListboxOption): void {\n this._itemsCollectionCtrl.appendOption(option);\n }\n\n /** Current selection as a consistently-array-shaped read-only view. */\n get selectedValues(): string[] {\n return this._itemsCollectionCtrl.selectedValues;\n }\n\n /** Current selection. Host writes update silently. */\n get value(): string | string[] {\n return this.multiple ? this.selectedValues : (this.selectedValues[0] ?? '');\n }\n\n /** Current selection. Host writes update silently. */\n set value(value: string | string[] | undefined) {\n this._value = value;\n\n if (value === undefined) return;\n\n this._selectionInitialized = true;\n this._applySelection(this._normalizeValue(value));\n }\n\n /** Initial uncontrolled selection. */\n get defaultValue(): string | string[] | undefined {\n return this._defaultValue;\n }\n\n /** Initial uncontrolled selection. */\n set defaultValue(value: string | string[] | undefined) {\n this._defaultValue = value;\n\n if (!this._selectionInitialized && this._value === undefined && value !== undefined) {\n this._applySelection(this._normalizeValue(value));\n }\n }\n\n /** Replace the selection set without firing `rc-listbox-change`. */\n setSelectedValues(values: string[]): void {\n this._applySelection(values);\n }\n\n /**\n * Toggle the selected state of the option with `value`.\n * In single-select mode, toggling a selected item deselects it (and selects\n * the new item). Fires `rc-listbox-change`.\n */\n toggleOption(value: string): void {\n const option = this._itemsCollectionCtrl.allOptions.find((opt) => opt.value === value);\n\n if (!option || option.kind === 'action' || option.disabled) return;\n\n const wasSelected = this._itemsCollectionCtrl.isSelected(value);\n\n if (this.multiple) {\n const next = new Set(this._itemsCollectionCtrl.selectedValues);\n\n if (wasSelected) {\n next.delete(value);\n } else {\n next.add(value);\n }\n\n this._itemsCollectionCtrl.setSelectedValues([...next]);\n } else {\n this._itemsCollectionCtrl.setSelectedValues(wasSelected ? [] : [value]);\n }\n\n this._selectionInitialized = true;\n this._dispatchChange(option, !wasSelected);\n }\n\n /** Clears all selected values without firing `rc-listbox-change`. */\n clearSelection(): void {\n this._applySelection([]);\n }\n\n /** Filter visible options to those whose label matches `text` (case-insensitive). */\n filterOptions(text: string): void {\n this._filterText = text;\n this._itemsCollectionCtrl.filterOptions(text, this.filterStrategy);\n }\n\n /** Removes any active filter, making all options visible. */\n clearFilter(): void {\n this._filterText = '';\n this._itemsCollectionCtrl.clearFilter();\n }\n\n /**\n * Ordered list of currently navigable option elements (visible and not disabled).\n *\n * Feed this to `ActiveDescendantController.items` in the parent component.\n * Includes the create option element when one is set.\n */\n get navigableItems(): Element[] {\n return this._itemsCollectionCtrl.navigableItems;\n }\n\n /**\n * Show or hide the \"Create\" option at the end of the list.\n *\n * Pass `null` to hide it, or a non-empty string to show `Create \"{label}\"`.\n * Fires `rc-listbox-change` with `reason: 'action'` and `action: 'create'`\n * when activated.\n */\n setCreateOption(label: string | null): void {\n this._itemsCollectionCtrl.setCreateOption(label);\n }\n\n /** Clears the active descendant when focus leaves the listbox. */\n protected _onBlur = (): void => {\n this._activeDescendantCtrl.clear();\n };\n\n /**\n * Handles arrow-key navigation and Enter/Space activation.\n *\n * Passes modifier-key combos through to parent handlers unchanged.\n */\n protected _onKeydown = (e: KeyboardEvent): void => {\n // Pass modifier-key combos to parent handlers (e.g. Alt+Arrow in rc-transfer-list).\n if (e.altKey || e.ctrlKey || e.metaKey) {\n return;\n }\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n\n if (this._activeDescendantCtrl.activeItem) {\n this._activeDescendantCtrl.navigate(1);\n } else {\n this._activeDescendantCtrl.navigateToFirst();\n }\n\n if (!this.multiple) {\n this._selectActiveItem();\n }\n\n break;\n }\n\n case 'ArrowUp': {\n e.preventDefault();\n\n if (this._activeDescendantCtrl.activeItem) {\n this._activeDescendantCtrl.navigate(-1);\n } else {\n this._activeDescendantCtrl.navigateToLast();\n }\n\n if (!this.multiple) {\n this._selectActiveItem();\n }\n\n break;\n }\n\n case 'Home': {\n e.preventDefault();\n\n this._activeDescendantCtrl.navigateToFirst();\n\n if (!this.multiple) {\n this._selectActiveItem();\n }\n\n break;\n }\n\n case 'End': {\n e.preventDefault();\n this._activeDescendantCtrl.navigateToLast();\n\n if (!this.multiple) {\n this._selectActiveItem();\n }\n\n break;\n }\n\n case ' ':\n case 'Enter': {\n e.preventDefault();\n\n const option = this._activeOption();\n\n if (!option) {\n break;\n }\n\n if (option.kind === 'action') {\n this._dispatchAction(option);\n } else if (this.multiple) {\n this.toggleOption(option.value);\n } else {\n this._selectActiveItem();\n }\n\n break;\n }\n }\n };\n\n /** Routes pointer activations from the controller. */\n protected _handleActivate(option: ListboxOption): void {\n if (option.kind === 'action') {\n this._dispatchAction(option);\n } else {\n this.toggleOption(option.value);\n }\n }\n\n /**\n * Selects the active-descendant item without toggling.\n *\n * Used by arrow-key navigation so the item under the cursor is always selected.\n */\n protected _selectActiveItem(): void {\n const activeOption = this._activeOption();\n\n if (!activeOption || activeOption.kind === 'action' || activeOption.disabled) return;\n\n const value = activeOption.value;\n const current = this._itemsCollectionCtrl.selectedValues;\n\n if (current.length === 1 && current[0] === value) {\n return;\n }\n\n this._itemsCollectionCtrl.setSelectedValues([value]);\n this._selectionInitialized = true;\n\n this._dispatchChange(activeOption, true);\n }\n\n /**\n * Returns `true` when `opt` passes the current `_filterText` and `filterStrategy`.\n */\n protected _isVisible(option: ListboxOption): boolean {\n if (!this._filterText) return true;\n\n const label = option.label.toLowerCase();\n const query = this._filterText.toLowerCase();\n\n if (typeof this.filterStrategy === 'function') {\n return this.filterStrategy(label, query);\n }\n\n if (this.filterStrategy === 'contains') {\n return label.includes(query);\n }\n\n return label.startsWith(query);\n }\n\n /**\n * Directly replaces the selection without firing an event.\n *\n * Enforces the single-select limit when `multiple` is false.\n */\n protected _applySelection(values: string[]): void {\n this._itemsCollectionCtrl.setSelectedValues(this.multiple ? values : values.slice(0, 1));\n }\n\n /**\n * Re-applies `_value` or `_defaultValue` after `options` or DOM bootstrap changes.\n */\n protected _applySelectionFromSource(): void {\n if (this._value !== undefined) {\n this._applySelection(this._normalizeValue(this._value));\n\n return;\n }\n\n if (!this._selectionInitialized && this._defaultValue !== undefined) {\n this._selectionInitialized = true;\n\n this._applySelection(this._normalizeValue(this._defaultValue));\n }\n }\n\n /** Coerces a `string | string[]` value to `string[]`. */\n protected _normalizeValue(value: string | string[]): string[] {\n return Array.isArray(value) ? value : value ? [value] : [];\n }\n\n protected _activeOption(): ListboxOption | null {\n const $active = this._activeDescendantCtrl.activeItem;\n\n return $active ? this._itemsCollectionCtrl.optionForElement($active) : null;\n }\n\n /** Fires `rc-listbox-change` for a command/action row without mutating selection. */\n protected _dispatchAction(option: ListboxActionOption): void {\n this.dispatchEvent(\n new CustomEvent<RCListboxActionChangeEvent>('rc-listbox-change', {\n bubbles: true,\n composed: true,\n detail: {\n reason: 'action',\n value: this.value,\n selected: false,\n optionValue: option.value,\n option,\n action: option.action,\n selectedValues: this.selectedValues,\n selectedOptions: this._selectedOptionsFor(this.selectedValues),\n },\n }),\n );\n }\n\n /** Fires `rc-listbox-change` with a fully-populated detail object. */\n protected _dispatchChange(option: ListboxSelectableOption, selected: boolean): void {\n this.dispatchEvent(\n new CustomEvent<RCListboxSelectChangeEvent>('rc-listbox-change', {\n bubbles: true,\n composed: true,\n detail: {\n reason: 'select',\n value: this.value,\n selected,\n optionValue: option.value,\n option,\n selectedValues: this.selectedValues,\n selectedOptions: this._selectedOptionsFor(this.selectedValues),\n },\n }),\n );\n }\n\n /**\n * Maps value strings to their `ListboxOption` objects.\n * Creates synthetic `{ value, label: value }` entries for values not in the list.\n */\n protected _selectedOptionsFor(values: string[]): ListboxSelectableOption[] {\n return values.map(\n (value) =>\n this._itemsCollectionCtrl.allOptions.find(\n (opt): opt is ListboxSelectableOption => opt.kind !== 'action' && opt.value === value,\n ) ?? { value, label: value },\n );\n }\n}\n\nexport default RCListbox;\n"],"names":["_uid","LIGHT_DOM_CSS","_RCListbox","_a","LitElement","ItemsCollectionController","option","ActiveDescendantController","e","root","$style","changed","html","options","value","values","opt","wasSelected","next","text","label","activeOption","current","query","$active","selected","css","__decorateClass","property","RCListbox"],"mappings":"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"}
|
package/dist/rc-listbox.js
CHANGED
|
@@ -81,19 +81,24 @@ export type RCListboxChangeEvent = RCListboxSelectChangeEvent | RCListboxActionC
|
|
|
81
81
|
* @csspart option-checkmark - The checkmark `<span>` inside each option (when `checkmark` is true)
|
|
82
82
|
* @csspart create-option - The "Create" option when allow-create is active
|
|
83
83
|
*
|
|
84
|
+
* @attr multiple - Allow multiple selection. Reflected as `aria-multiselectable` on the host.
|
|
85
|
+
* @attr checkmark - Render a checkmark indicator inside each option element.
|
|
86
|
+
* @attr filter-strategy - How option labels are matched against the active filter text:
|
|
87
|
+
* `prefix`, `contains`, or omit to keep the `contains` default. Function values are JS-only.
|
|
88
|
+
*
|
|
84
89
|
* @cssprop [--rc-listbox-option-gap=0.25rem] - Gap between the checkmark and option label.
|
|
85
90
|
* @cssprop [--rc-listbox-option-min-block-size=0px] - Minimum block size (height) of each option row.
|
|
86
91
|
* @cssprop [--rc-listbox-option-padding-block=2px] - Block-axis padding of each option row.
|
|
87
92
|
* @cssprop [--rc-listbox-option-padding-inline=4px] - Inline-axis padding of each option row.
|
|
88
93
|
* @cssprop [--rc-listbox-option-transition] - CSS transition applied to each option row.
|
|
89
|
-
* @cssprop [--rc-listbox-hover-bg] - Background of a hovered option.
|
|
90
|
-
* @cssprop [--rc-listbox-hover-color] - Text color of a hovered option.
|
|
91
|
-
* @cssprop [--rc-listbox-active-bg] - Background of the keyboard-active option.
|
|
92
|
-
* @cssprop [--rc-listbox-active-color] - Text color of the keyboard-active option.
|
|
93
|
-
* @cssprop [--rc-listbox-selected-bg] - Background of a selected option.
|
|
94
|
-
* @cssprop [--rc-listbox-selected-color] - Text color of a selected option.
|
|
95
|
-
* @cssprop [--rc-listbox-disabled-color] - Text color of a disabled option.
|
|
96
|
-
* @cssprop [--rc-listbox-disabled-opacity] - Opacity of a disabled option.
|
|
94
|
+
* @cssprop [--rc-listbox-hover-bg=color-mix(in srgb, Highlight 8%, transparent)] - Background of a hovered option.
|
|
95
|
+
* @cssprop [--rc-listbox-hover-color=inherit] - Text color of a hovered option.
|
|
96
|
+
* @cssprop [--rc-listbox-active-bg=color-mix(in srgb, Highlight 8%, transparent)] - Background of the keyboard-active option.
|
|
97
|
+
* @cssprop [--rc-listbox-active-color=var(--rc-listbox-hover-color, inherit)] - Text color of the keyboard-active option.
|
|
98
|
+
* @cssprop [--rc-listbox-selected-bg=Highlight] - Background of a selected option.
|
|
99
|
+
* @cssprop [--rc-listbox-selected-color=HighlightText] - Text color of a selected option.
|
|
100
|
+
* @cssprop [--rc-listbox-disabled-color=GrayText] - Text color of a disabled option.
|
|
101
|
+
* @cssprop [--rc-listbox-disabled-opacity=1] - Opacity of a disabled option.
|
|
97
102
|
*/
|
|
98
103
|
export declare class RCListbox extends LitElement {
|
|
99
104
|
static styles: import('lit').CSSResult;
|
|
@@ -120,7 +125,7 @@ export declare class RCListbox extends LitElement {
|
|
|
120
125
|
private _defaultValue;
|
|
121
126
|
private _value;
|
|
122
127
|
private _selectionInitialized;
|
|
123
|
-
|
|
128
|
+
protected _filterText: string;
|
|
124
129
|
/** Unique ID prefix for all rendered option elements in this instance. */
|
|
125
130
|
protected readonly _uid: string;
|
|
126
131
|
/** Manages the `<ul>/<li>` option DOM subtree in the component's light DOM. */
|
|
@@ -137,9 +142,23 @@ export declare class RCListbox extends LitElement {
|
|
|
137
142
|
get filteredOptions(): readonly ListboxOption[];
|
|
138
143
|
/** Replace the full options list. */
|
|
139
144
|
get options(): ListboxOption[];
|
|
140
|
-
/**
|
|
145
|
+
/**
|
|
146
|
+
* Replace the full options list.
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* listbox.options = [
|
|
150
|
+
* { value: 'apple', label: 'Apple' },
|
|
151
|
+
* { value: 'banana', label: 'Banana', disabled: true },
|
|
152
|
+
* { kind: 'action', action: 'clear', value: 'clear', label: 'Clear selection' },
|
|
153
|
+
* ];
|
|
154
|
+
*/
|
|
141
155
|
set options(options: ListboxOption[]);
|
|
142
|
-
/**
|
|
156
|
+
/**
|
|
157
|
+
* Append a single option without replacing the list.
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* listbox.appendOption({ value: 'cherry', label: 'Cherry' });
|
|
161
|
+
*/
|
|
143
162
|
appendOption(option: ListboxOption): void;
|
|
144
163
|
/** Current selection as a consistently-array-shaped read-only view. */
|
|
145
164
|
get selectedValues(): string[];
|
|
@@ -189,7 +208,7 @@ export declare class RCListbox extends LitElement {
|
|
|
189
208
|
*/
|
|
190
209
|
protected _onKeydown: (e: KeyboardEvent) => void;
|
|
191
210
|
/** Routes pointer activations from the controller. */
|
|
192
|
-
|
|
211
|
+
protected _handleActivate(option: ListboxOption): void;
|
|
193
212
|
/**
|
|
194
213
|
* Selects the active-descendant item without toggling.
|
|
195
214
|
*
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rc-listbox-CTedy14U.js","sources":["../src/rc-listbox.ts"],"sourcesContent":["import { LitElement, html, css } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport {\n ActiveDescendantController,\n ItemsCollectionController,\n type ItemsCollectionActionOption,\n type ItemsCollectionOption,\n type ItemsCollectionSelectableOption,\n type ItemsCollectionFilterStrategy,\n} from '@rcarls/rc-common';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'rc-listbox': RCListbox;\n }\n}\n\n/** Option shape accepted by `rc-listbox`. */\nexport type ListboxOption = ItemsCollectionOption;\nexport type ListboxSelectableOption = ItemsCollectionSelectableOption;\nexport type ListboxActionOption<Action extends string = string> = ItemsCollectionActionOption & {\n action: Action;\n};\n\n/**\n * Listbox that keeps option DOM in light DOM for aria-activedescendant navigation,\n * following the WAI-ARIA Listbox pattern.\n *\n * - `'prefix'`: label must start with the query (default, matches native `<select>` type-ahead).\n * - `'contains'`: label must contain the query anywhere.\n * - `function`: custom predicate; receives lowercased label and query, return `true` to show the option.\n */\nexport type FilterStrategy = ItemsCollectionFilterStrategy;\n\nexport interface RCListboxSelectChangeEvent {\n reason: 'select';\n\n /** Canonical selected value for single mode, or selected values for multi mode. */\n value: string | string[];\n\n /** Whether the option was selected (false means it was deselected). */\n selected: boolean;\n\n /** The option value that was activated. */\n optionValue: string;\n\n /** The option that was activated. */\n option: ListboxSelectableOption;\n\n /** Selected values array (length=1 for single-selection mode). */\n selectedValues: string[];\n\n /** Selected options. */\n selectedOptions: ListboxSelectableOption[];\n}\n\nexport interface RCListboxActionChangeEvent<Action extends string = string> {\n reason: 'action';\n\n /** Current canonical selected value; action rows do not mutate selection. */\n value: string | string[];\n\n /** Action activations never select the action row. */\n selected: false;\n\n /** The action option value that was activated. */\n optionValue: string;\n\n /** The action option that was activated. */\n option: ListboxActionOption<Action>;\n\n /** The activated action command. */\n action: Action;\n\n /** Selected values array (length=1 for single-selection mode). */\n selectedValues: string[];\n\n /** Selected options. */\n selectedOptions: ListboxSelectableOption[];\n}\n\nexport type RCListboxChangeEvent = RCListboxSelectChangeEvent | RCListboxActionChangeEvent;\n\nlet _uid = 0;\n\n/** Structural CSS injected into the root that contains rc-listbox's light-DOM options. */\nconst LIGHT_DOM_CSS = `\n@layer rc-base {\n rc-listbox ul {\n list-style: none;\n margin: 0;\n padding: 0;\n }\n\n rc-listbox li[role='option'] {\n display: flex;\n align-items: center;\n gap: var(--rc-listbox-option-gap, 0.25rem);\n min-block-size: var(--rc-listbox-option-min-block-size, 0px);\n padding: var(--rc-listbox-option-padding-block, 2px) var(--rc-listbox-option-padding-inline, 4px);\n cursor: default;\n user-select: none;\n outline: none;\n background: transparent;\n color: inherit;\n transition: var(--rc-listbox-option-transition);\n }\n\n rc-listbox li[role='option']:hover {\n background: var(--rc-listbox-hover-bg, color-mix(in srgb, Highlight 8%, transparent));\n color: var(--rc-listbox-hover-color, inherit);\n }\n\n rc-listbox li[role='option'][data-active] {\n background: var(--rc-listbox-active-bg, color-mix(in srgb, Highlight 8%, transparent));\n color: var(--rc-listbox-active-color, var(--rc-listbox-hover-color, inherit));\n }\n\n rc-listbox li[role='option'][aria-selected='true'] {\n background: var(--rc-listbox-selected-bg, Highlight);\n color: var(--rc-listbox-selected-color, HighlightText);\n }\n\n rc-listbox li[role='option'][aria-disabled='true'] {\n color: var(--rc-listbox-disabled-color, GrayText);\n opacity: var(--rc-listbox-disabled-opacity, 1);\n pointer-events: none;\n }\n\n rc-listbox [part~='option-checkmark'] {\n display: none;\n min-inline-size: 1em;\n text-align: center;\n }\n\n rc-listbox[checkmark] [part~='option-checkmark'] {\n display: inline;\n visibility: hidden;\n }\n\n rc-listbox[checkmark] li[role='option'][aria-selected='true'] [part~='option-checkmark'] {\n visibility: visible;\n }\n}\n`;\n\n/**\n * A WAI-ARIA listbox component that renders a `<ul role=\"presentation\">`\n * + `<li role=\"option\">` subtree directly into its own light DOM to facilitate\n * `aria-activedescendant` virtual navigation with IDs inside the same document\n * or shadow root.\n *\n * Pre-rendered `<ul>/<li>` children are accepted as a progressive enhancement\n * baseline. The component reads them on first connect if no `options` setter\n * has been called.\n *\n * Consumers drive this component via its JS API:\n * - Set `options` to populate the list\n * - Set `value` / `defaultValue` to manage selection\n * - Call `toggleOption()` for internal keyboard/pointer activation\n * - Call `filterOptions()` to filter visible options\n * - Read `navigableItems` to feed `ActiveDescendantController`\n *\n * @see {@link https://richardcarls.github.io/rc-webcomponents/components/rc-listbox rc-listbox docs}\n * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/listbox/ WAI-ARIA Listbox pattern}\n *\n * @slot — Accepts pre-rendered `<ul>` with `<li>` children for progressive enhancement.\n *\n * @fires rc-listbox-change - Fired when an option is activated (clicked or Enter/Space)\n *\n * @csspart option - Individual `<li role=\"option\">` elements\n * @csspart option-checkmark - The checkmark `<span>` inside each option (when `checkmark` is true)\n * @csspart create-option - The \"Create\" option when allow-create is active\n *\n * @cssprop [--rc-listbox-option-gap=0.25rem] - Gap between the checkmark and option label.\n * @cssprop [--rc-listbox-option-min-block-size=0px] - Minimum block size (height) of each option row.\n * @cssprop [--rc-listbox-option-padding-block=2px] - Block-axis padding of each option row.\n * @cssprop [--rc-listbox-option-padding-inline=4px] - Inline-axis padding of each option row.\n * @cssprop [--rc-listbox-option-transition] - CSS transition applied to each option row.\n * @cssprop [--rc-listbox-hover-bg] - Background of a hovered option.\n * @cssprop [--rc-listbox-hover-color] - Text color of a hovered option.\n * @cssprop [--rc-listbox-active-bg] - Background of the keyboard-active option.\n * @cssprop [--rc-listbox-active-color] - Text color of the keyboard-active option.\n * @cssprop [--rc-listbox-selected-bg] - Background of a selected option.\n * @cssprop [--rc-listbox-selected-color] - Text color of a selected option.\n * @cssprop [--rc-listbox-disabled-color] - Text color of a disabled option.\n * @cssprop [--rc-listbox-disabled-opacity] - Opacity of a disabled option.\n */\nexport class RCListbox extends LitElement {\n static override styles = css`\n :host {\n display: block;\n overflow-y: auto;\n }\n `;\n\n private static readonly _styledRoots = new Set<Document | ShadowRoot>();\n\n private static _ensureBaseStyles(root: Document | ShadowRoot): void {\n if (RCListbox._styledRoots.has(root)) return;\n RCListbox._styledRoots.add(root);\n\n const style = document.createElement('style');\n style.setAttribute('data-rc-light-dom-base', 'rc-listbox');\n style.textContent = LIGHT_DOM_CSS;\n\n if (root instanceof Document) {\n root.head.appendChild(style);\n } else {\n root.appendChild(style);\n }\n }\n\n /** Allow multiple selection. Reflected as `aria-multiselectable` on the host. */\n @property({ type: Boolean, reflect: true })\n multiple = false;\n\n /**\n * Render a checkmark indicator inside each option element.\n *\n * Hidden by default; enable for combobox / select patterns where the\n * consumer's CSS shows it conditionally via `[aria-selected='true']`.\n */\n @property({ type: Boolean, reflect: true })\n checkmark = false;\n\n /**\n * How option labels are matched against the active filter text.\n *\n * Defaults to `'contains'` (substring). Set to `'prefix'` for starts-with\n * matching, or pass a custom predicate for full control.\n * Function values are JS-only; string values may be set via the\n * `filter-strategy` attribute.\n */\n @property({ attribute: 'filter-strategy', reflect: false })\n filterStrategy: FilterStrategy = 'contains';\n\n private _defaultValue: string | string[] | undefined;\n private _value: string | string[] | undefined;\n private _selectionInitialized = false;\n private _filterText = '';\n\n /** Unique ID prefix for all rendered option elements in this instance. */\n protected readonly _uid = `rc-lb-${++_uid}`;\n\n /** Manages the `<ul>/<li>` option DOM subtree in the component's light DOM. */\n protected readonly _itemsCollectionCtrl = new ItemsCollectionController(this, {\n idPrefix: this._uid,\n onInitFromDom: () => this._applySelectionFromSource(),\n onActivate: (option) => this._handleActivate(option),\n });\n\n /** Active-descendant controller; tracks keyboard focus within the option list. */\n protected readonly _activeDescendantCtrl = new ActiveDescendantController(this, {\n host: () => this,\n items: () => this.navigableItems,\n });\n\n override connectedCallback(): void {\n super.connectedCallback();\n\n RCListbox._ensureBaseStyles(this.getRootNode() as Document | ShadowRoot);\n\n if (!this.hasAttribute('role')) {\n this.setAttribute('role', 'listbox');\n }\n\n this.addEventListener('keydown', this._onKeydown);\n this.addEventListener('blur', this._onBlur);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n\n this.removeEventListener('keydown', this._onKeydown);\n this.removeEventListener('blur', this._onBlur);\n }\n\n override updated(changed: Map<PropertyKey, unknown>): void {\n if (changed.has('multiple')) {\n this.multiple\n ? this.setAttribute('aria-multiselectable', 'true')\n : this.removeAttribute('aria-multiselectable');\n }\n\n if (changed.has('checkmark')) {\n this._itemsCollectionCtrl.checkmark = this.checkmark;\n }\n }\n\n protected override render() {\n return html`<slot></slot>`;\n }\n\n /** All options regardless of filter state. */\n get allOptions(): readonly ListboxOption[] {\n return this._itemsCollectionCtrl.allOptions;\n }\n\n /** Options currently passing the active filter. */\n get filteredOptions(): readonly ListboxOption[] {\n const filterText = this._filterText;\n\n if (!filterText) {\n return [...this._itemsCollectionCtrl.allOptions];\n }\n\n return this._itemsCollectionCtrl.allOptions.filter((option) => this._isVisible(option));\n }\n\n /** Replace the full options list. */\n get options(): ListboxOption[] {\n return [...this._itemsCollectionCtrl.allOptions];\n }\n\n /** Replace the full options list. */\n set options(options: ListboxOption[]) {\n this._itemsCollectionCtrl.setOptions([...options]);\n this._applySelectionFromSource();\n }\n\n /** Append a single option without replacing the list. */\n appendOption(option: ListboxOption): void {\n this._itemsCollectionCtrl.appendOption(option);\n }\n\n /** Current selection as a consistently-array-shaped read-only view. */\n get selectedValues(): string[] {\n return this._itemsCollectionCtrl.selectedValues;\n }\n\n /** Current selection. Host writes update silently. */\n get value(): string | string[] {\n return this.multiple ? this.selectedValues : (this.selectedValues[0] ?? '');\n }\n\n /** Current selection. Host writes update silently. */\n set value(value: string | string[] | undefined) {\n this._value = value;\n\n if (value === undefined) return;\n\n this._selectionInitialized = true;\n this._applySelection(this._normalizeValue(value));\n }\n\n /** Initial uncontrolled selection. */\n get defaultValue(): string | string[] | undefined {\n return this._defaultValue;\n }\n\n /** Initial uncontrolled selection. */\n set defaultValue(value: string | string[] | undefined) {\n this._defaultValue = value;\n\n if (!this._selectionInitialized && this._value === undefined && value !== undefined) {\n this._applySelection(this._normalizeValue(value));\n }\n }\n\n /** Replace the selection set without firing `rc-listbox-change`. */\n setSelectedValues(values: string[]): void {\n this._applySelection(values);\n }\n\n /**\n * Toggle the selected state of the option with `value`.\n * In single-select mode, toggling a selected item deselects it (and selects\n * the new item). Fires `rc-listbox-change`.\n */\n toggleOption(value: string): void {\n const option = this._itemsCollectionCtrl.allOptions.find((opt) => opt.value === value);\n\n if (!option || option.kind === 'action' || option.disabled) return;\n\n const wasSelected = this._itemsCollectionCtrl.isSelected(value);\n\n if (this.multiple) {\n const next = new Set(this._itemsCollectionCtrl.selectedValues);\n\n if (wasSelected) {\n next.delete(value);\n } else {\n next.add(value);\n }\n\n this._itemsCollectionCtrl.setSelectedValues([...next]);\n } else {\n this._itemsCollectionCtrl.setSelectedValues(wasSelected ? [] : [value]);\n }\n\n this._selectionInitialized = true;\n this._dispatchChange(option, !wasSelected);\n }\n\n /** Clears all selected values without firing `rc-listbox-change`. */\n clearSelection(): void {\n this._applySelection([]);\n }\n\n /** Filter visible options to those whose label matches `text` (case-insensitive). */\n filterOptions(text: string): void {\n this._filterText = text;\n this._itemsCollectionCtrl.filterOptions(text, this.filterStrategy);\n }\n\n /** Removes any active filter, making all options visible. */\n clearFilter(): void {\n this._filterText = '';\n this._itemsCollectionCtrl.clearFilter();\n }\n\n /**\n * Ordered list of currently navigable option elements (visible and not disabled).\n *\n * Feed this to `ActiveDescendantController.items` in the parent component.\n * Includes the create option element when one is set.\n */\n get navigableItems(): Element[] {\n return this._itemsCollectionCtrl.navigableItems;\n }\n\n /**\n * Show or hide the \"Create\" option at the end of the list.\n *\n * Pass `null` to hide it, or a non-empty string to show `Create \"{label}\"`.\n * Fires `rc-listbox-change` with `reason: 'action'` and `action: 'create'`\n * when activated.\n */\n setCreateOption(label: string | null): void {\n this._itemsCollectionCtrl.setCreateOption(label);\n }\n\n /** Clears the active descendant when focus leaves the listbox. */\n protected _onBlur = (): void => {\n this._activeDescendantCtrl.clear();\n };\n\n /**\n * Handles arrow-key navigation and Enter/Space activation.\n *\n * Passes modifier-key combos through to parent handlers unchanged.\n */\n protected _onKeydown = (e: KeyboardEvent): void => {\n // Pass modifier-key combos to parent handlers (e.g. Alt+Arrow in rc-transfer-list).\n if (e.altKey || e.ctrlKey || e.metaKey) {\n return;\n }\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n\n if (this._activeDescendantCtrl.activeItem) {\n this._activeDescendantCtrl.navigate(1);\n } else {\n this._activeDescendantCtrl.navigateToFirst();\n }\n\n if (!this.multiple) {\n this._selectActiveItem();\n }\n\n break;\n }\n\n case 'ArrowUp': {\n e.preventDefault();\n\n if (this._activeDescendantCtrl.activeItem) {\n this._activeDescendantCtrl.navigate(-1);\n } else {\n this._activeDescendantCtrl.navigateToLast();\n }\n\n if (!this.multiple) {\n this._selectActiveItem();\n }\n\n break;\n }\n\n case 'Home': {\n e.preventDefault();\n\n this._activeDescendantCtrl.navigateToFirst();\n\n if (!this.multiple) {\n this._selectActiveItem();\n }\n\n break;\n }\n\n case 'End': {\n e.preventDefault();\n this._activeDescendantCtrl.navigateToLast();\n\n if (!this.multiple) {\n this._selectActiveItem();\n }\n\n break;\n }\n\n case ' ':\n case 'Enter': {\n e.preventDefault();\n\n const option = this._activeOption();\n\n if (!option) {\n break;\n }\n\n if (option.kind === 'action') {\n this._dispatchAction(option);\n } else if (this.multiple) {\n this.toggleOption(option.value);\n } else {\n this._selectActiveItem();\n }\n\n break;\n }\n }\n };\n\n /** Routes pointer activations from the controller. */\n private _handleActivate(option: ListboxOption): void {\n if (option.kind === 'action') {\n this._dispatchAction(option);\n } else {\n this.toggleOption(option.value);\n }\n }\n\n /**\n * Selects the active-descendant item without toggling.\n *\n * Used by arrow-key navigation so the item under the cursor is always selected.\n */\n protected _selectActiveItem(): void {\n const activeOption = this._activeOption();\n\n if (!activeOption || activeOption.kind === 'action' || activeOption.disabled) return;\n\n const value = activeOption.value;\n const current = this._itemsCollectionCtrl.selectedValues;\n\n if (current.length === 1 && current[0] === value) {\n return;\n }\n\n this._itemsCollectionCtrl.setSelectedValues([value]);\n this._selectionInitialized = true;\n\n this._dispatchChange(activeOption, true);\n }\n\n /**\n * Returns `true` when `opt` passes the current `_filterText` and `filterStrategy`.\n */\n protected _isVisible(option: ListboxOption): boolean {\n if (!this._filterText) return true;\n\n const label = option.label.toLowerCase();\n const query = this._filterText.toLowerCase();\n\n if (typeof this.filterStrategy === 'function') {\n return this.filterStrategy(label, query);\n }\n\n if (this.filterStrategy === 'contains') {\n return label.includes(query);\n }\n\n return label.startsWith(query);\n }\n\n /**\n * Directly replaces the selection without firing an event.\n *\n * Enforces the single-select limit when `multiple` is false.\n */\n protected _applySelection(values: string[]): void {\n this._itemsCollectionCtrl.setSelectedValues(this.multiple ? values : values.slice(0, 1));\n }\n\n /**\n * Re-applies `_value` or `_defaultValue` after `options` or DOM bootstrap changes.\n */\n protected _applySelectionFromSource(): void {\n if (this._value !== undefined) {\n this._applySelection(this._normalizeValue(this._value));\n\n return;\n }\n\n if (!this._selectionInitialized && this._defaultValue !== undefined) {\n this._selectionInitialized = true;\n\n this._applySelection(this._normalizeValue(this._defaultValue));\n }\n }\n\n /** Coerces a `string | string[]` value to `string[]`. */\n protected _normalizeValue(value: string | string[]): string[] {\n return Array.isArray(value) ? value : value ? [value] : [];\n }\n\n protected _activeOption(): ListboxOption | null {\n const active = this._activeDescendantCtrl.activeItem;\n\n return active ? this._itemsCollectionCtrl.optionForElement(active) : null;\n }\n\n /** Fires `rc-listbox-change` for a command/action row without mutating selection. */\n protected _dispatchAction(option: ListboxActionOption): void {\n this.dispatchEvent(\n new CustomEvent<RCListboxActionChangeEvent>('rc-listbox-change', {\n bubbles: true,\n composed: true,\n detail: {\n reason: 'action',\n value: this.value,\n selected: false,\n optionValue: option.value,\n option,\n action: option.action,\n selectedValues: this.selectedValues,\n selectedOptions: this._selectedOptionsFor(this.selectedValues),\n },\n }),\n );\n }\n\n /** Fires `rc-listbox-change` with a fully-populated detail object. */\n protected _dispatchChange(option: ListboxSelectableOption, selected: boolean): void {\n this.dispatchEvent(\n new CustomEvent<RCListboxSelectChangeEvent>('rc-listbox-change', {\n bubbles: true,\n composed: true,\n detail: {\n reason: 'select',\n value: this.value,\n selected,\n optionValue: option.value,\n option,\n selectedValues: this.selectedValues,\n selectedOptions: this._selectedOptionsFor(this.selectedValues),\n },\n }),\n );\n }\n\n /**\n * Maps value strings to their `ListboxOption` objects.\n * Creates synthetic `{ value, label: value }` entries for values not in the list.\n */\n protected _selectedOptionsFor(values: string[]): ListboxSelectableOption[] {\n return values.map(\n (value) =>\n this._itemsCollectionCtrl.allOptions.find(\n (opt): opt is ListboxSelectableOption => opt.kind !== 'action' && opt.value === value,\n ) ?? { value, label: value },\n );\n }\n}\n\nexport default RCListbox;\n"],"names":["_uid","LIGHT_DOM_CSS","_RCListbox","_a","LitElement","ItemsCollectionController","option","ActiveDescendantController","e","root","style","changed","html","options","value","values","opt","wasSelected","next","text","label","activeOption","current","query","active","selected","css","__decorateClass","property","RCListbox"],"mappings":"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"}
|