@aurodesignsystem-dev/auro-formkit 0.0.0-pr1541.4 → 0.0.0-pr1542.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/components/checkbox/demo/customize.min.js +1 -1
- package/components/checkbox/demo/getting-started.min.js +1 -1
- package/components/checkbox/demo/index.min.js +1 -1
- package/components/checkbox/dist/index.js +1 -1
- package/components/checkbox/dist/registered.js +1 -1
- package/components/combobox/demo/api.md +2 -2
- package/components/combobox/demo/customize.md +1 -1
- package/components/combobox/demo/customize.min.js +40 -90
- package/components/combobox/demo/getting-started.min.js +40 -90
- package/components/combobox/demo/index.md +0 -1
- package/components/combobox/demo/index.min.js +40 -90
- package/components/combobox/demo/keyboard-behavior.md +1 -4
- package/components/combobox/dist/auro-combobox.d.ts +3 -1
- package/components/combobox/dist/index.js +23 -4
- package/components/combobox/dist/registered.js +23 -4
- package/components/counter/demo/customize.min.js +2 -2
- package/components/counter/demo/index.min.js +2 -2
- package/components/counter/dist/index.js +2 -2
- package/components/counter/dist/registered.js +2 -2
- package/components/datepicker/demo/customize.min.js +3 -3
- package/components/datepicker/demo/index.min.js +3 -3
- package/components/datepicker/dist/index.js +3 -3
- package/components/datepicker/dist/registered.js +3 -3
- package/components/dropdown/demo/customize.min.js +1 -1
- package/components/dropdown/demo/getting-started.min.js +1 -1
- package/components/dropdown/demo/index.min.js +1 -1
- package/components/dropdown/dist/index.js +1 -1
- package/components/dropdown/dist/registered.js +1 -1
- package/components/form/demo/customize.min.js +51 -105
- package/components/form/demo/getting-started.min.js +51 -105
- package/components/form/demo/index.min.js +51 -105
- package/components/form/demo/registerDemoDeps.min.js +51 -105
- package/components/input/demo/customize.min.js +1 -1
- package/components/input/demo/getting-started.min.js +1 -1
- package/components/input/demo/index.min.js +1 -1
- package/components/input/dist/index.js +1 -1
- package/components/input/dist/registered.js +1 -1
- package/components/menu/demo/accessibility.md +4 -4
- package/components/menu/demo/api.md +19 -26
- package/components/menu/demo/css-only.md +19 -26
- package/components/menu/demo/customize.md +47 -307
- package/components/menu/demo/design.md +1 -1
- package/components/menu/demo/getting-started.md +7 -144
- package/components/menu/demo/index.min.js +18 -213
- package/components/menu/demo/keyboard-behavior.md +4 -83
- package/components/menu/demo/voiceover.md +3 -3
- package/components/menu/demo/why-menu.md +9 -8
- package/components/menu/dist/auro-menu-utils.d.ts +0 -19
- package/components/menu/dist/auro-menu.d.ts +7 -3
- package/components/menu/dist/auro-menuoption.d.ts +0 -12
- package/components/menu/dist/index.js +17 -86
- package/components/menu/dist/registered.js +17 -86
- package/components/radio/demo/customize.min.js +1 -1
- package/components/radio/demo/getting-started.min.js +1 -1
- package/components/radio/demo/index.min.js +1 -1
- package/components/radio/dist/index.js +1 -1
- package/components/radio/dist/registered.js +1 -1
- package/components/select/demo/api.md +2 -2
- package/components/select/demo/customize.md +2 -5
- package/components/select/demo/customize.min.js +20 -93
- package/components/select/demo/design.md +10 -10
- package/components/select/demo/getting-started.md +1 -1
- package/components/select/demo/getting-started.min.js +20 -93
- package/components/select/demo/index.md +2 -2
- package/components/select/demo/index.min.js +20 -93
- package/components/select/demo/keyboard-behavior.md +18 -49
- package/components/select/dist/auro-select.d.ts +2 -6
- package/components/select/dist/index.js +3 -7
- package/components/select/dist/registered.js +3 -7
- package/custom-elements.json +1514 -1599
- package/package.json +1 -1
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
</ol>
|
|
21
21
|
<div class="note"><strong>Note:</strong> <code><auro-menuoption></code> is not directly focusable — <code>tabindex="-1"</code> keeps it out of the tab order. In a select or combobox context, focus stays on the parent trigger and the active option is pointed at via <code>aria-activedescendant</code> (using <code>ariaActiveDescendantElement</code> to cross the shadow-root boundary).</div>
|
|
22
22
|
<auro-header level="3" id="voiceOverSelection">Selection</auro-header>
|
|
23
|
-
<p>When an option is selected via Enter
|
|
23
|
+
<p>When an option is selected via Enter or Space:</p>
|
|
24
24
|
<ul>
|
|
25
25
|
<li>VoiceOver announces the option label followed by <em>"selected"</em></li>
|
|
26
26
|
<li>In multi-select mode, previously selected options remain selected and their state is preserved</li>
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
<ol>
|
|
30
30
|
<li><strong>Enter the menu:</strong> Focus moves into the listbox; VoiceOver announces role and item count</li>
|
|
31
31
|
<li><strong>Navigate options:</strong> Use Arrow Down/Up keys; VoiceOver announces each option's label, role, and position</li>
|
|
32
|
-
<li><strong>Select an option:</strong> Press Enter; VoiceOver confirms the selection</li>
|
|
33
|
-
<li><strong>Exit:</strong> Tab out of the menu
|
|
32
|
+
<li><strong>Select an option:</strong> Press Enter or Space; VoiceOver confirms the selection</li>
|
|
33
|
+
<li><strong>Exit:</strong> Tab out of the menu or press Escape (when used within a dropdown context)</li>
|
|
34
34
|
</ol>
|
|
35
35
|
<auro-header level="2" id="voiceOverNestedMenus">Nested Menus</auro-header>
|
|
36
36
|
<p>When a nested <code>auro-menu</code> is encountered, VoiceOver announces a new listbox context. Each nested menu maintains its own option count and position tracking.</p>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<p>Custom list implementations often fail to provide correct ARIA semantics, keyboard navigation, or screen reader announcements.</p>
|
|
5
5
|
<p><code>auro-menu</code> provides:</p>
|
|
6
6
|
<ul>
|
|
7
|
-
<li><strong>Keyboard navigation</strong> — Arrow
|
|
7
|
+
<li><strong>Keyboard navigation</strong> — Arrow keys move between options, Enter selects, Escape cancels, Home/End jump to the first and last options.</li>
|
|
8
8
|
<li><strong>Active option tracking</strong> — The currently highlighted option is tracked programmatically, enabling <code>aria-activedescendant</code> patterns in parent components like <code>auro-select</code> and <code>auro-combobox</code>.</li>
|
|
9
9
|
<li><strong>Multi-select semantics</strong> — When <code>multiSelect</code> is enabled, <code>aria-multiselectable</code> is set on the menu.</li>
|
|
10
10
|
<li><strong>Loading state</strong> — <code>aria-busy</code> is set during loading, with customizable loading icon and text slots.</li>
|
|
@@ -24,14 +24,15 @@
|
|
|
24
24
|
<ul>
|
|
25
25
|
<li>Checkmark indicators for each selected option</li>
|
|
26
26
|
<li>A <code>value</code> that returns a JSON-stringified array of selections</li>
|
|
27
|
-
<li>
|
|
28
|
-
<li><code>
|
|
27
|
+
<li><code>allowDeselect</code> to toggle selections off</li>
|
|
28
|
+
<li><code>selectAllMatchingOptions</code> for bulk selection operations</li>
|
|
29
|
+
<li><code>clearSelection()</code> and <code>reset()</code> methods for programmatic control</li>
|
|
29
30
|
</ul>
|
|
30
31
|
<auro-header level="2" id="searchAndFiltering">Search and filtering</auro-header>
|
|
31
32
|
<p>Native menus have no concept of filtering or highlighting matched text.</p>
|
|
32
33
|
<p><code>auro-menu</code> supports:</p>
|
|
33
34
|
<ul>
|
|
34
|
-
<li><
|
|
35
|
+
<li><code>matchWord</code> to highlight matching portions of option text as the user types (used by <code>auro-combobox</code> for real-time filtering)</li>
|
|
35
36
|
<li>Programmatic <code>navigateOptions(direction)</code> for keyboard-driven traversal</li>
|
|
36
37
|
</ul>
|
|
37
38
|
<auro-header level="2" id="loadingState">Loading state</auro-header>
|
|
@@ -87,7 +88,7 @@
|
|
|
87
88
|
<tr>
|
|
88
89
|
<td>Keyboard navigation</td>
|
|
89
90
|
<td>Browser-dependent</td>
|
|
90
|
-
<td>
|
|
91
|
+
<td>Full arrow/Enter/Escape/Home/End</td>
|
|
91
92
|
</tr>
|
|
92
93
|
<tr>
|
|
93
94
|
<td>Composable primitive</td>
|
|
@@ -95,9 +96,9 @@
|
|
|
95
96
|
<td>Foundation for select and combobox</td>
|
|
96
97
|
</tr>
|
|
97
98
|
<tr>
|
|
98
|
-
<td>
|
|
99
|
-
<td>
|
|
100
|
-
<td>
|
|
99
|
+
<td>Deselect support</td>
|
|
100
|
+
<td>No</td>
|
|
101
|
+
<td><code>allowDeselect</code> attribute</td>
|
|
101
102
|
</tr>
|
|
102
103
|
</tbody>
|
|
103
104
|
</table>
|
|
@@ -10,15 +10,6 @@
|
|
|
10
10
|
* or if the value cannot be parsed into an array from a JSON string.
|
|
11
11
|
*/
|
|
12
12
|
export function arrayConverter(value: any): any[] | undefined;
|
|
13
|
-
/**
|
|
14
|
-
* Serializes a multi-select value array back into the String `value` property.
|
|
15
|
-
* An empty (or missing) array collapses to `undefined` so an emptied selection
|
|
16
|
-
* clears `value` rather than reflecting a `"[]"` attribute.
|
|
17
|
-
* @private
|
|
18
|
-
* @param {Array<string>|undefined} values - The selected values.
|
|
19
|
-
* @returns {string|undefined} JSON string of the values, or undefined when empty.
|
|
20
|
-
*/
|
|
21
|
-
export function serializeMultiSelectValue(values: Array<string> | undefined): string | undefined;
|
|
22
13
|
/**
|
|
23
14
|
* Compare two arrays for equality.
|
|
24
15
|
* @private
|
|
@@ -34,16 +25,6 @@ export function arraysAreEqual(arr1: any[], arr2: any[]): boolean;
|
|
|
34
25
|
* @returns {boolean} True if option is interactive.
|
|
35
26
|
*/
|
|
36
27
|
export function isOptionInteractive(option: HTMLElement): boolean;
|
|
37
|
-
/**
|
|
38
|
-
* Validates if an option may be selected by matching a programmatic value.
|
|
39
|
-
* Unlike `isOptionInteractive`, `hidden` is allowed: the combobox toggles
|
|
40
|
-
* `hidden` as its type-ahead filter, so a filtered-out option is still a
|
|
41
|
-
* valid programmatic selection. Only disabled and static options — which are
|
|
42
|
-
* never selectable — are rejected.
|
|
43
|
-
* @param {HTMLElement} option - The option to check.
|
|
44
|
-
* @returns {boolean} True if option can be selected by value.
|
|
45
|
-
*/
|
|
46
|
-
export function isSelectableByValue(option: HTMLElement): boolean;
|
|
47
28
|
/**
|
|
48
29
|
* Helper method to dispatch custom events.
|
|
49
30
|
* @param {HTMLElement} element - Element to dispatch event from.
|
|
@@ -60,17 +60,21 @@ export class AuroMenu extends AuroElement {
|
|
|
60
60
|
reflect: boolean;
|
|
61
61
|
attribute: string;
|
|
62
62
|
};
|
|
63
|
+
/**
|
|
64
|
+
* Specifies the current active menuOption.
|
|
65
|
+
*/
|
|
63
66
|
optionActive: {
|
|
64
67
|
type: ObjectConstructor;
|
|
65
68
|
attribute: string;
|
|
66
69
|
};
|
|
70
|
+
/**
|
|
71
|
+
* An array of currently selected menu options, type `HTMLElement` by default. In multi-select mode, `optionSelected` is an array of HTML elements.
|
|
72
|
+
*/
|
|
67
73
|
optionSelected: {
|
|
68
74
|
type: ObjectConstructor;
|
|
69
|
-
attribute: boolean;
|
|
70
75
|
};
|
|
71
76
|
/**
|
|
72
77
|
* The value of the selected option. In multi-select mode, this is a JSON stringified array of selected option values.
|
|
73
|
-
* Options marked `disabled` or `static` are not selectable by value; `hidden` options remain selectable. In single-select mode, if the value matches a non-selectable option the selection is cleared (`optionSelected` becomes `undefined`) and `auroMenu-selectValueFailure` is dispatched. In multi-select mode, non-selectable entries are dropped from the value and the remaining selectable entries are selected; `auroMenu-selectValueFailure` is dispatched only when none of the entries match a selectable option.
|
|
74
78
|
*/
|
|
75
79
|
value: {
|
|
76
80
|
type: StringConstructor;
|
|
@@ -167,7 +171,7 @@ export class AuroMenu extends AuroElement {
|
|
|
167
171
|
*/
|
|
168
172
|
private get formattedValue();
|
|
169
173
|
/**
|
|
170
|
-
* Selects options by value.
|
|
174
|
+
* Selects options by value.
|
|
171
175
|
* @param {string|string[]|undefined|null} value - The value(s) to select.
|
|
172
176
|
* @public
|
|
173
177
|
*/
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
* The `auro-menuoption` element provides users a way to define a menu option.
|
|
3
3
|
* @customElement auro-menuoption
|
|
4
4
|
*
|
|
5
|
-
* @attr {Boolean} static - When present, marks the option as non-interactive — it renders but is skipped during keyboard navigation and cannot be selected. Useful for section headers, informational rows inside a menu, or attaching event listeners.
|
|
6
5
|
* @slot default - The default slot for the menu option text.
|
|
7
6
|
*
|
|
8
7
|
* @event auroMenuOption-mouseover - Notifies that this option has been hovered over.
|
|
@@ -14,11 +13,6 @@ export class AuroMenuOption extends AuroElement {
|
|
|
14
13
|
type: BooleanConstructor;
|
|
15
14
|
reflect: boolean;
|
|
16
15
|
};
|
|
17
|
-
/**
|
|
18
|
-
* **Deprecated.** Use the `value` attribute on `auro-menu` to set the selected option when the menu renders (or call `menu.selectByValue(value)` programmatically). Support for the child-level `selected` attribute will be removed in a future major release.
|
|
19
|
-
*
|
|
20
|
-
* @deprecated Use the `value` attribute on `auro-menu` instead.
|
|
21
|
-
*/
|
|
22
16
|
selected: {
|
|
23
17
|
type: BooleanConstructor;
|
|
24
18
|
reflect: boolean;
|
|
@@ -51,11 +45,6 @@ export class AuroMenuOption extends AuroElement {
|
|
|
51
45
|
reflect: boolean;
|
|
52
46
|
attribute: string;
|
|
53
47
|
};
|
|
54
|
-
/** When true, this option is excluded from `matchWord` DOM rewriting — useful for utility rows (e.g., "Add new…") that must render identically regardless of the current filter. */
|
|
55
|
-
persistent: {
|
|
56
|
-
type: BooleanConstructor;
|
|
57
|
-
reflect: boolean;
|
|
58
|
-
};
|
|
59
48
|
layout: {
|
|
60
49
|
type: StringConstructor;
|
|
61
50
|
attribute: string;
|
|
@@ -85,7 +74,6 @@ export class AuroMenuOption extends AuroElement {
|
|
|
85
74
|
noCheckmark: boolean;
|
|
86
75
|
disabled: boolean;
|
|
87
76
|
noMatch: boolean;
|
|
88
|
-
persistent: boolean;
|
|
89
77
|
/**
|
|
90
78
|
* @private
|
|
91
79
|
*/
|
|
@@ -241,18 +241,6 @@ function arrayConverter(value) {
|
|
|
241
241
|
throw new Error('Invalid value: Input must be an array or undefined');
|
|
242
242
|
}
|
|
243
243
|
|
|
244
|
-
/**
|
|
245
|
-
* Serializes a multi-select value array back into the String `value` property.
|
|
246
|
-
* An empty (or missing) array collapses to `undefined` so an emptied selection
|
|
247
|
-
* clears `value` rather than reflecting a `"[]"` attribute.
|
|
248
|
-
* @private
|
|
249
|
-
* @param {Array<string>|undefined} values - The selected values.
|
|
250
|
-
* @returns {string|undefined} JSON string of the values, or undefined when empty.
|
|
251
|
-
*/
|
|
252
|
-
function serializeMultiSelectValue(values) {
|
|
253
|
-
return values && values.length > 0 ? JSON.stringify(values) : undefined;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
244
|
/**
|
|
257
245
|
* Validates if an option can be interacted with.
|
|
258
246
|
* @private
|
|
@@ -265,20 +253,6 @@ function isOptionInteractive(option) {
|
|
|
265
253
|
!option.hasAttribute('static');
|
|
266
254
|
}
|
|
267
255
|
|
|
268
|
-
/**
|
|
269
|
-
* Validates if an option may be selected by matching a programmatic value.
|
|
270
|
-
* Unlike `isOptionInteractive`, `hidden` is allowed: the combobox toggles
|
|
271
|
-
* `hidden` as its type-ahead filter, so a filtered-out option is still a
|
|
272
|
-
* valid programmatic selection. Only disabled and static options — which are
|
|
273
|
-
* never selectable — are rejected.
|
|
274
|
-
* @param {HTMLElement} option - The option to check.
|
|
275
|
-
* @returns {boolean} True if option can be selected by value.
|
|
276
|
-
*/
|
|
277
|
-
function isSelectableByValue(option) {
|
|
278
|
-
return !option.hasAttribute('disabled') &&
|
|
279
|
-
!option.hasAttribute('static');
|
|
280
|
-
}
|
|
281
|
-
|
|
282
256
|
/**
|
|
283
257
|
* Helper method to dispatch custom events.
|
|
284
258
|
* @param {HTMLElement} element - Element to dispatch event from.
|
|
@@ -448,7 +422,6 @@ class AuroMenu extends AuroElement {
|
|
|
448
422
|
|
|
449
423
|
/**
|
|
450
424
|
* Specifies the current active menuOption.
|
|
451
|
-
* @readonly
|
|
452
425
|
*/
|
|
453
426
|
optionActive: {
|
|
454
427
|
type: Object,
|
|
@@ -456,18 +429,15 @@ class AuroMenu extends AuroElement {
|
|
|
456
429
|
},
|
|
457
430
|
|
|
458
431
|
/**
|
|
459
|
-
*
|
|
460
|
-
* @readonly
|
|
432
|
+
* An array of currently selected menu options, type `HTMLElement` by default. In multi-select mode, `optionSelected` is an array of HTML elements.
|
|
461
433
|
*/
|
|
462
434
|
optionSelected: {
|
|
463
435
|
// Allow HTMLElement, HTMLElement[] arrays and undefined
|
|
464
|
-
type: Object
|
|
465
|
-
attribute: false
|
|
436
|
+
type: Object
|
|
466
437
|
},
|
|
467
438
|
|
|
468
439
|
/**
|
|
469
440
|
* The value of the selected option. In multi-select mode, this is a JSON stringified array of selected option values.
|
|
470
|
-
* Options marked `disabled` or `static` are not selectable by value; `hidden` options remain selectable. In single-select mode, if the value matches a non-selectable option the selection is cleared (`optionSelected` becomes `undefined`) and `auroMenu-selectValueFailure` is dispatched. In multi-select mode, non-selectable entries are dropped from the value and the remaining selectable entries are selected; `auroMenu-selectValueFailure` is dispatched only when none of the entries match a selectable option.
|
|
471
441
|
*/
|
|
472
442
|
value: {
|
|
473
443
|
type: String,
|
|
@@ -591,7 +561,7 @@ class AuroMenu extends AuroElement {
|
|
|
591
561
|
}
|
|
592
562
|
|
|
593
563
|
/**
|
|
594
|
-
* Selects options by value.
|
|
564
|
+
* Selects options by value.
|
|
595
565
|
* @param {string|string[]|undefined|null} value - The value(s) to select.
|
|
596
566
|
* @public
|
|
597
567
|
*/
|
|
@@ -676,11 +646,6 @@ class AuroMenu extends AuroElement {
|
|
|
676
646
|
this.initItems();
|
|
677
647
|
}
|
|
678
648
|
|
|
679
|
-
// Set when reconciliation reassigns `value` below. That reassignment schedules a
|
|
680
|
-
// second updated() cycle, so the `event`-attribute dispatch is deferred to that
|
|
681
|
-
// cycle to avoid firing option custom events twice on the same selection.
|
|
682
|
-
let valueReconciled = false;
|
|
683
|
-
|
|
684
649
|
// Handle null/undefined/empty case — empty/whitespace strings clear selection
|
|
685
650
|
// consistently with selectByValue(''), and avoid downstream `.includes('')` matches.
|
|
686
651
|
if (this.value === undefined || this.value === null || (typeof this.value === 'string' && this.value.trim() === '')) {
|
|
@@ -693,31 +658,11 @@ class AuroMenu extends AuroElement {
|
|
|
693
658
|
// Defensive default: `formattedValue` can be undefined for unexpected value types,
|
|
694
659
|
// and calling `.includes` on undefined would throw during reconciliation.
|
|
695
660
|
const valueArray = this.formattedValue || [];
|
|
696
|
-
const matchingOptions = this.items ? this.items.filter((item) =>
|
|
661
|
+
const matchingOptions = this.items ? this.items.filter((item) => valueArray.includes(item.value)) : [];
|
|
697
662
|
newSelected = matchingOptions.length > 0 ? matchingOptions : undefined;
|
|
698
|
-
|
|
699
|
-
// Reconcile `value` with the selectable set. Drop only entries whose option is
|
|
700
|
-
// loaded but non-selectable (disabled/static) — leaving them would desync `value`
|
|
701
|
-
// from `optionSelected`, and the toggle handlers rebuild `value` from `formattedValue`,
|
|
702
|
-
// so the rejected entry would resurface on the next select/deselect. Entries with no
|
|
703
|
-
// matching item yet are preserved so async preselection still works once options render.
|
|
704
|
-
const rejectedValues = this.items
|
|
705
|
-
? this.items.filter((item) => !isSelectableByValue(item) && valueArray.includes(item.value)).map((item) => item.value)
|
|
706
|
-
: [];
|
|
707
|
-
if (rejectedValues.length > 0) {
|
|
708
|
-
const reconciled = valueArray.filter((val) => !rejectedValues.includes(val));
|
|
709
|
-
this.value = serializeMultiSelectValue(reconciled);
|
|
710
|
-
valueReconciled = true;
|
|
711
|
-
}
|
|
712
663
|
} else {
|
|
713
|
-
// In single-select mode, this.value should be a string
|
|
714
|
-
|
|
715
|
-
// non-selectable option falls through to the no-match path below
|
|
716
|
-
// (dispatching auroMenu-selectValueFailure) instead of pinning it.
|
|
717
|
-
// `hidden` is intentionally NOT excluded: the combobox toggles
|
|
718
|
-
// `hidden` as its type-ahead filter, so a filtered-out option is
|
|
719
|
-
// still a valid programmatic selection.
|
|
720
|
-
const matchingOption = this.items ? this.items.find((item) => isSelectableByValue(item) && item.value === this.value) : undefined;
|
|
664
|
+
// In single-select mode, this.value should be a string
|
|
665
|
+
const matchingOption = this.items ? this.items.find((item) => item.value === this.value) : undefined;
|
|
721
666
|
|
|
722
667
|
if (matchingOption) {
|
|
723
668
|
newSelected = matchingOption;
|
|
@@ -759,9 +704,8 @@ class AuroMenu extends AuroElement {
|
|
|
759
704
|
]
|
|
760
705
|
]));
|
|
761
706
|
|
|
762
|
-
// Notify of changes
|
|
763
|
-
|
|
764
|
-
if (this.optionSelected !== undefined && !valueReconciled) {
|
|
707
|
+
// Notify of changes
|
|
708
|
+
if (this.optionSelected !== undefined) {
|
|
765
709
|
const selected = Array.isArray(this.optionSelected) ? this.optionSelected : [this.optionSelected];
|
|
766
710
|
selected.forEach((opt) => {
|
|
767
711
|
if (opt.hasAttribute('event')) {
|
|
@@ -974,7 +918,7 @@ class AuroMenu extends AuroElement {
|
|
|
974
918
|
const currentSelected = this.optionSelected || [];
|
|
975
919
|
|
|
976
920
|
if (!currentValue.includes(option.value)) {
|
|
977
|
-
this.value =
|
|
921
|
+
this.value = JSON.stringify([
|
|
978
922
|
...currentValue,
|
|
979
923
|
option.value
|
|
980
924
|
]);
|
|
@@ -1000,9 +944,15 @@ class AuroMenu extends AuroElement {
|
|
|
1000
944
|
*/
|
|
1001
945
|
handleDeselectState(option) {
|
|
1002
946
|
if (this.multiSelect) {
|
|
1003
|
-
// Remove this option from array
|
|
947
|
+
// Remove this option from array
|
|
1004
948
|
const newFormattedValue = (this.formattedValue || []).filter((val) => val !== option.value);
|
|
1005
|
-
|
|
949
|
+
|
|
950
|
+
// If array is empty after removal, set back to undefined
|
|
951
|
+
if (newFormattedValue && newFormattedValue.length === 0) {
|
|
952
|
+
this.value = undefined;
|
|
953
|
+
} else {
|
|
954
|
+
this.value = JSON.stringify(newFormattedValue);
|
|
955
|
+
}
|
|
1006
956
|
|
|
1007
957
|
this.optionSelected = this.optionSelected.filter((val) => val !== option);
|
|
1008
958
|
if (this.optionSelected.length === 0) {
|
|
@@ -1049,11 +999,6 @@ class AuroMenu extends AuroElement {
|
|
|
1049
999
|
this.optionSelected = undefined;
|
|
1050
1000
|
this._index = -1;
|
|
1051
1001
|
|
|
1052
|
-
// Clear active option state so a follow-up open/navigation starts fresh
|
|
1053
|
-
// rather than reusing a stale reference from before the reset.
|
|
1054
|
-
this.items?.forEach((item) => item.classList.remove('active'));
|
|
1055
|
-
this.optionActive = undefined;
|
|
1056
|
-
|
|
1057
1002
|
// Reset UI state
|
|
1058
1003
|
this.updateItemsState(new Map([
|
|
1059
1004
|
[
|
|
@@ -1503,7 +1448,6 @@ let menuOptionIdCounter = 0;
|
|
|
1503
1448
|
* The `auro-menuoption` element provides users a way to define a menu option.
|
|
1504
1449
|
* @customElement auro-menuoption
|
|
1505
1450
|
*
|
|
1506
|
-
* @attr {Boolean} static - When present, marks the option as non-interactive — it renders but is skipped during keyboard navigation and cannot be selected. Useful for section headers, informational rows inside a menu, or attaching event listeners.
|
|
1507
1451
|
* @slot default - The default slot for the menu option text.
|
|
1508
1452
|
*
|
|
1509
1453
|
* @event auroMenuOption-mouseover - Notifies that this option has been hovered over.
|
|
@@ -1533,7 +1477,6 @@ class AuroMenuOption extends AuroElement {
|
|
|
1533
1477
|
this.noCheckmark = false;
|
|
1534
1478
|
this.disabled = false;
|
|
1535
1479
|
this.noMatch = false;
|
|
1536
|
-
this.persistent = false;
|
|
1537
1480
|
|
|
1538
1481
|
/**
|
|
1539
1482
|
* @private
|
|
@@ -1555,12 +1498,6 @@ class AuroMenuOption extends AuroElement {
|
|
|
1555
1498
|
type: Boolean,
|
|
1556
1499
|
reflect: true
|
|
1557
1500
|
},
|
|
1558
|
-
|
|
1559
|
-
/**
|
|
1560
|
-
* **Deprecated.** Use the `value` attribute on `auro-menu` to set the selected option when the menu renders (or call `menu.selectByValue(value)` programmatically). Support for the child-level `selected` attribute will be removed in a future major release.
|
|
1561
|
-
*
|
|
1562
|
-
* @deprecated Use the `value` attribute on `auro-menu` instead.
|
|
1563
|
-
*/
|
|
1564
1501
|
selected: {
|
|
1565
1502
|
type: Boolean,
|
|
1566
1503
|
reflect: true
|
|
@@ -1595,12 +1532,6 @@ class AuroMenuOption extends AuroElement {
|
|
|
1595
1532
|
reflect: true,
|
|
1596
1533
|
attribute: 'nomatch'
|
|
1597
1534
|
},
|
|
1598
|
-
|
|
1599
|
-
/** When true, this option is excluded from `matchWord` DOM rewriting — useful for utility rows (e.g., "Add new…") that must render identically regardless of the current filter. */
|
|
1600
|
-
persistent: {
|
|
1601
|
-
type: Boolean,
|
|
1602
|
-
reflect: true
|
|
1603
|
-
},
|
|
1604
1535
|
};
|
|
1605
1536
|
}
|
|
1606
1537
|
|
|
@@ -200,18 +200,6 @@ class AuroLibraryRuntimeUtils {
|
|
|
200
200
|
// See LICENSE in the project root for license information.
|
|
201
201
|
|
|
202
202
|
|
|
203
|
-
/**
|
|
204
|
-
* Serializes a multi-select value array back into the String `value` property.
|
|
205
|
-
* An empty (or missing) array collapses to `undefined` so an emptied selection
|
|
206
|
-
* clears `value` rather than reflecting a `"[]"` attribute.
|
|
207
|
-
* @private
|
|
208
|
-
* @param {Array<string>|undefined} values - The selected values.
|
|
209
|
-
* @returns {string|undefined} JSON string of the values, or undefined when empty.
|
|
210
|
-
*/
|
|
211
|
-
function serializeMultiSelectValue(values) {
|
|
212
|
-
return values && values.length > 0 ? JSON.stringify(values) : undefined;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
203
|
/**
|
|
216
204
|
* Validates if an option can be interacted with.
|
|
217
205
|
* @private
|
|
@@ -224,20 +212,6 @@ function isOptionInteractive(option) {
|
|
|
224
212
|
!option.hasAttribute('static');
|
|
225
213
|
}
|
|
226
214
|
|
|
227
|
-
/**
|
|
228
|
-
* Validates if an option may be selected by matching a programmatic value.
|
|
229
|
-
* Unlike `isOptionInteractive`, `hidden` is allowed: the combobox toggles
|
|
230
|
-
* `hidden` as its type-ahead filter, so a filtered-out option is still a
|
|
231
|
-
* valid programmatic selection. Only disabled and static options — which are
|
|
232
|
-
* never selectable — are rejected.
|
|
233
|
-
* @param {HTMLElement} option - The option to check.
|
|
234
|
-
* @returns {boolean} True if option can be selected by value.
|
|
235
|
-
*/
|
|
236
|
-
function isSelectableByValue(option) {
|
|
237
|
-
return !option.hasAttribute('disabled') &&
|
|
238
|
-
!option.hasAttribute('static');
|
|
239
|
-
}
|
|
240
|
-
|
|
241
215
|
/**
|
|
242
216
|
* Helper method to dispatch custom events.
|
|
243
217
|
* @param {HTMLElement} element - Element to dispatch event from.
|
|
@@ -407,7 +381,6 @@ class AuroMenu extends AuroElement {
|
|
|
407
381
|
|
|
408
382
|
/**
|
|
409
383
|
* Specifies the current active menuOption.
|
|
410
|
-
* @readonly
|
|
411
384
|
*/
|
|
412
385
|
optionActive: {
|
|
413
386
|
type: Object,
|
|
@@ -415,18 +388,15 @@ class AuroMenu extends AuroElement {
|
|
|
415
388
|
},
|
|
416
389
|
|
|
417
390
|
/**
|
|
418
|
-
*
|
|
419
|
-
* @readonly
|
|
391
|
+
* An array of currently selected menu options, type `HTMLElement` by default. In multi-select mode, `optionSelected` is an array of HTML elements.
|
|
420
392
|
*/
|
|
421
393
|
optionSelected: {
|
|
422
394
|
// Allow HTMLElement, HTMLElement[] arrays and undefined
|
|
423
|
-
type: Object
|
|
424
|
-
attribute: false
|
|
395
|
+
type: Object
|
|
425
396
|
},
|
|
426
397
|
|
|
427
398
|
/**
|
|
428
399
|
* The value of the selected option. In multi-select mode, this is a JSON stringified array of selected option values.
|
|
429
|
-
* Options marked `disabled` or `static` are not selectable by value; `hidden` options remain selectable. In single-select mode, if the value matches a non-selectable option the selection is cleared (`optionSelected` becomes `undefined`) and `auroMenu-selectValueFailure` is dispatched. In multi-select mode, non-selectable entries are dropped from the value and the remaining selectable entries are selected; `auroMenu-selectValueFailure` is dispatched only when none of the entries match a selectable option.
|
|
430
400
|
*/
|
|
431
401
|
value: {
|
|
432
402
|
type: String,
|
|
@@ -550,7 +520,7 @@ class AuroMenu extends AuroElement {
|
|
|
550
520
|
}
|
|
551
521
|
|
|
552
522
|
/**
|
|
553
|
-
* Selects options by value.
|
|
523
|
+
* Selects options by value.
|
|
554
524
|
* @param {string|string[]|undefined|null} value - The value(s) to select.
|
|
555
525
|
* @public
|
|
556
526
|
*/
|
|
@@ -635,11 +605,6 @@ class AuroMenu extends AuroElement {
|
|
|
635
605
|
this.initItems();
|
|
636
606
|
}
|
|
637
607
|
|
|
638
|
-
// Set when reconciliation reassigns `value` below. That reassignment schedules a
|
|
639
|
-
// second updated() cycle, so the `event`-attribute dispatch is deferred to that
|
|
640
|
-
// cycle to avoid firing option custom events twice on the same selection.
|
|
641
|
-
let valueReconciled = false;
|
|
642
|
-
|
|
643
608
|
// Handle null/undefined/empty case — empty/whitespace strings clear selection
|
|
644
609
|
// consistently with selectByValue(''), and avoid downstream `.includes('')` matches.
|
|
645
610
|
if (this.value === undefined || this.value === null || (typeof this.value === 'string' && this.value.trim() === '')) {
|
|
@@ -652,31 +617,11 @@ class AuroMenu extends AuroElement {
|
|
|
652
617
|
// Defensive default: `formattedValue` can be undefined for unexpected value types,
|
|
653
618
|
// and calling `.includes` on undefined would throw during reconciliation.
|
|
654
619
|
const valueArray = this.formattedValue || [];
|
|
655
|
-
const matchingOptions = this.items ? this.items.filter((item) =>
|
|
620
|
+
const matchingOptions = this.items ? this.items.filter((item) => valueArray.includes(item.value)) : [];
|
|
656
621
|
newSelected = matchingOptions.length > 0 ? matchingOptions : undefined;
|
|
657
|
-
|
|
658
|
-
// Reconcile `value` with the selectable set. Drop only entries whose option is
|
|
659
|
-
// loaded but non-selectable (disabled/static) — leaving them would desync `value`
|
|
660
|
-
// from `optionSelected`, and the toggle handlers rebuild `value` from `formattedValue`,
|
|
661
|
-
// so the rejected entry would resurface on the next select/deselect. Entries with no
|
|
662
|
-
// matching item yet are preserved so async preselection still works once options render.
|
|
663
|
-
const rejectedValues = this.items
|
|
664
|
-
? this.items.filter((item) => !isSelectableByValue(item) && valueArray.includes(item.value)).map((item) => item.value)
|
|
665
|
-
: [];
|
|
666
|
-
if (rejectedValues.length > 0) {
|
|
667
|
-
const reconciled = valueArray.filter((val) => !rejectedValues.includes(val));
|
|
668
|
-
this.value = serializeMultiSelectValue(reconciled);
|
|
669
|
-
valueReconciled = true;
|
|
670
|
-
}
|
|
671
622
|
} else {
|
|
672
|
-
// In single-select mode, this.value should be a string
|
|
673
|
-
|
|
674
|
-
// non-selectable option falls through to the no-match path below
|
|
675
|
-
// (dispatching auroMenu-selectValueFailure) instead of pinning it.
|
|
676
|
-
// `hidden` is intentionally NOT excluded: the combobox toggles
|
|
677
|
-
// `hidden` as its type-ahead filter, so a filtered-out option is
|
|
678
|
-
// still a valid programmatic selection.
|
|
679
|
-
const matchingOption = this.items ? this.items.find((item) => isSelectableByValue(item) && item.value === this.value) : undefined;
|
|
623
|
+
// In single-select mode, this.value should be a string
|
|
624
|
+
const matchingOption = this.items ? this.items.find((item) => item.value === this.value) : undefined;
|
|
680
625
|
|
|
681
626
|
if (matchingOption) {
|
|
682
627
|
newSelected = matchingOption;
|
|
@@ -718,9 +663,8 @@ class AuroMenu extends AuroElement {
|
|
|
718
663
|
]
|
|
719
664
|
]));
|
|
720
665
|
|
|
721
|
-
// Notify of changes
|
|
722
|
-
|
|
723
|
-
if (this.optionSelected !== undefined && !valueReconciled) {
|
|
666
|
+
// Notify of changes
|
|
667
|
+
if (this.optionSelected !== undefined) {
|
|
724
668
|
const selected = Array.isArray(this.optionSelected) ? this.optionSelected : [this.optionSelected];
|
|
725
669
|
selected.forEach((opt) => {
|
|
726
670
|
if (opt.hasAttribute('event')) {
|
|
@@ -933,7 +877,7 @@ class AuroMenu extends AuroElement {
|
|
|
933
877
|
const currentSelected = this.optionSelected || [];
|
|
934
878
|
|
|
935
879
|
if (!currentValue.includes(option.value)) {
|
|
936
|
-
this.value =
|
|
880
|
+
this.value = JSON.stringify([
|
|
937
881
|
...currentValue,
|
|
938
882
|
option.value
|
|
939
883
|
]);
|
|
@@ -959,9 +903,15 @@ class AuroMenu extends AuroElement {
|
|
|
959
903
|
*/
|
|
960
904
|
handleDeselectState(option) {
|
|
961
905
|
if (this.multiSelect) {
|
|
962
|
-
// Remove this option from array
|
|
906
|
+
// Remove this option from array
|
|
963
907
|
const newFormattedValue = (this.formattedValue || []).filter((val) => val !== option.value);
|
|
964
|
-
|
|
908
|
+
|
|
909
|
+
// If array is empty after removal, set back to undefined
|
|
910
|
+
if (newFormattedValue && newFormattedValue.length === 0) {
|
|
911
|
+
this.value = undefined;
|
|
912
|
+
} else {
|
|
913
|
+
this.value = JSON.stringify(newFormattedValue);
|
|
914
|
+
}
|
|
965
915
|
|
|
966
916
|
this.optionSelected = this.optionSelected.filter((val) => val !== option);
|
|
967
917
|
if (this.optionSelected.length === 0) {
|
|
@@ -1008,11 +958,6 @@ class AuroMenu extends AuroElement {
|
|
|
1008
958
|
this.optionSelected = undefined;
|
|
1009
959
|
this._index = -1;
|
|
1010
960
|
|
|
1011
|
-
// Clear active option state so a follow-up open/navigation starts fresh
|
|
1012
|
-
// rather than reusing a stale reference from before the reset.
|
|
1013
|
-
this.items?.forEach((item) => item.classList.remove('active'));
|
|
1014
|
-
this.optionActive = undefined;
|
|
1015
|
-
|
|
1016
961
|
// Reset UI state
|
|
1017
962
|
this.updateItemsState(new Map([
|
|
1018
963
|
[
|
|
@@ -1462,7 +1407,6 @@ let menuOptionIdCounter = 0;
|
|
|
1462
1407
|
* The `auro-menuoption` element provides users a way to define a menu option.
|
|
1463
1408
|
* @customElement auro-menuoption
|
|
1464
1409
|
*
|
|
1465
|
-
* @attr {Boolean} static - When present, marks the option as non-interactive — it renders but is skipped during keyboard navigation and cannot be selected. Useful for section headers, informational rows inside a menu, or attaching event listeners.
|
|
1466
1410
|
* @slot default - The default slot for the menu option text.
|
|
1467
1411
|
*
|
|
1468
1412
|
* @event auroMenuOption-mouseover - Notifies that this option has been hovered over.
|
|
@@ -1492,7 +1436,6 @@ class AuroMenuOption extends AuroElement {
|
|
|
1492
1436
|
this.noCheckmark = false;
|
|
1493
1437
|
this.disabled = false;
|
|
1494
1438
|
this.noMatch = false;
|
|
1495
|
-
this.persistent = false;
|
|
1496
1439
|
|
|
1497
1440
|
/**
|
|
1498
1441
|
* @private
|
|
@@ -1514,12 +1457,6 @@ class AuroMenuOption extends AuroElement {
|
|
|
1514
1457
|
type: Boolean,
|
|
1515
1458
|
reflect: true
|
|
1516
1459
|
},
|
|
1517
|
-
|
|
1518
|
-
/**
|
|
1519
|
-
* **Deprecated.** Use the `value` attribute on `auro-menu` to set the selected option when the menu renders (or call `menu.selectByValue(value)` programmatically). Support for the child-level `selected` attribute will be removed in a future major release.
|
|
1520
|
-
*
|
|
1521
|
-
* @deprecated Use the `value` attribute on `auro-menu` instead.
|
|
1522
|
-
*/
|
|
1523
1460
|
selected: {
|
|
1524
1461
|
type: Boolean,
|
|
1525
1462
|
reflect: true
|
|
@@ -1554,12 +1491,6 @@ class AuroMenuOption extends AuroElement {
|
|
|
1554
1491
|
reflect: true,
|
|
1555
1492
|
attribute: 'nomatch'
|
|
1556
1493
|
},
|
|
1557
|
-
|
|
1558
|
-
/** When true, this option is excluded from `matchWord` DOM rewriting — useful for utility rows (e.g., "Add new…") that must render identically regardless of the current filter. */
|
|
1559
|
-
persistent: {
|
|
1560
|
-
type: Boolean,
|
|
1561
|
-
reflect: true
|
|
1562
|
-
},
|
|
1563
1494
|
};
|
|
1564
1495
|
}
|
|
1565
1496
|
|
|
@@ -1227,7 +1227,7 @@ class AuroHelpText extends i$2 {
|
|
|
1227
1227
|
}
|
|
1228
1228
|
}
|
|
1229
1229
|
|
|
1230
|
-
var formkitVersion = '
|
|
1230
|
+
var formkitVersion = '202607082142';
|
|
1231
1231
|
|
|
1232
1232
|
// Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
|
|
1233
1233
|
// See LICENSE in the project root for license information.
|
|
@@ -1227,7 +1227,7 @@ class AuroHelpText extends i$2 {
|
|
|
1227
1227
|
}
|
|
1228
1228
|
}
|
|
1229
1229
|
|
|
1230
|
-
var formkitVersion = '
|
|
1230
|
+
var formkitVersion = '202607082142';
|
|
1231
1231
|
|
|
1232
1232
|
// Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
|
|
1233
1233
|
// See LICENSE in the project root for license information.
|
|
@@ -1227,7 +1227,7 @@ class AuroHelpText extends i$2 {
|
|
|
1227
1227
|
}
|
|
1228
1228
|
}
|
|
1229
1229
|
|
|
1230
|
-
var formkitVersion = '
|
|
1230
|
+
var formkitVersion = '202607082142';
|
|
1231
1231
|
|
|
1232
1232
|
// Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
|
|
1233
1233
|
// See LICENSE in the project root for license information.
|
|
@@ -1166,7 +1166,7 @@ class AuroHelpText extends LitElement {
|
|
|
1166
1166
|
}
|
|
1167
1167
|
}
|
|
1168
1168
|
|
|
1169
|
-
var formkitVersion = '
|
|
1169
|
+
var formkitVersion = '202607082142';
|
|
1170
1170
|
|
|
1171
1171
|
// Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
|
|
1172
1172
|
// See LICENSE in the project root for license information.
|
|
@@ -1166,7 +1166,7 @@ class AuroHelpText extends LitElement {
|
|
|
1166
1166
|
}
|
|
1167
1167
|
}
|
|
1168
1168
|
|
|
1169
|
-
var formkitVersion = '
|
|
1169
|
+
var formkitVersion = '202607082142';
|
|
1170
1170
|
|
|
1171
1171
|
// Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
|
|
1172
1172
|
// See LICENSE in the project root for license information.
|