@aurodesignsystem-dev/auro-formkit 0.0.0-pr1533.13 → 0.0.0-pr1533.14
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 +110 -22
- package/components/combobox/demo/getting-started.min.js +110 -22
- package/components/combobox/demo/index.md +1 -0
- package/components/combobox/demo/index.min.js +110 -22
- 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 +125 -33
- package/components/form/demo/getting-started.min.js +125 -33
- package/components/form/demo/index.min.js +125 -33
- package/components/form/demo/registerDemoDeps.min.js +125 -33
- 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 +26 -19
- package/components/menu/demo/css-only.md +26 -19
- package/components/menu/demo/customize.md +307 -47
- package/components/menu/demo/design.md +1 -1
- package/components/menu/demo/getting-started.md +144 -7
- package/components/menu/demo/index.min.js +214 -19
- package/components/menu/demo/keyboard-behavior.md +83 -4
- package/components/menu/demo/voiceover.md +12 -8
- package/components/menu/demo/why-menu.md +8 -9
- package/components/menu/dist/auro-menu-utils.d.ts +19 -0
- package/components/menu/dist/auro-menu.d.ts +4 -8
- package/components/menu/dist/auro-menuoption.d.ts +12 -0
- package/components/menu/dist/index.js +87 -18
- package/components/menu/dist/registered.js +87 -18
- 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 +5 -2
- package/components/select/demo/customize.min.js +94 -21
- 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 +94 -21
- package/components/select/demo/index.md +2 -2
- package/components/select/demo/index.min.js +94 -21
- package/components/select/demo/keyboard-behavior.md +49 -18
- package/components/select/dist/auro-select.d.ts +6 -2
- package/components/select/dist/index.js +7 -3
- package/components/select/dist/registered.js +7 -3
- package/custom-elements.json +1608 -1534
- package/package.json +1 -1
|
@@ -22,10 +22,13 @@
|
|
|
22
22
|
<auro-anchorlink fluid href="#options" class="level2 body-xs">options</auro-anchorlink>
|
|
23
23
|
<auro-anchorlink fluid href="#index" class="level2 body-xs">index</auro-anchorlink>
|
|
24
24
|
<auro-anchorlink fluid href="#functions">Functions</auro-anchorlink>
|
|
25
|
-
<auro-anchorlink fluid href="#makeSelection" class="level2 body-xs">makeSelection()</auro-anchorlink>
|
|
26
25
|
<auro-anchorlink fluid href="#reset" class="level2 body-xs">reset()</auro-anchorlink>
|
|
26
|
+
<auro-anchorlink fluid href="#selectByValue" class="level2 body-xs">selectByValue()</auro-anchorlink>
|
|
27
27
|
<auro-anchorlink fluid href="#updateActiveOption" class="level2 body-xs">updateActiveOption()</auro-anchorlink>
|
|
28
28
|
<auro-anchorlink fluid href="#navigateOptions" class="level2 body-xs">navigateOptions()</auro-anchorlink>
|
|
29
|
+
<auro-anchorlink fluid href="#events">Events</auro-anchorlink>
|
|
30
|
+
<auro-anchorlink fluid href="#eventList" class="level2 body-xs">Event List</auro-anchorlink>
|
|
31
|
+
<auro-anchorlink fluid href="#eventAttribute" class="level2 body-xs">Option event attribute</auro-anchorlink>
|
|
29
32
|
</auro-nav>
|
|
30
33
|
</nav>
|
|
31
34
|
<div class="mainContent">
|
|
@@ -293,7 +296,7 @@ Ensure your `tsconfig.json` uses `"moduleResolution": "bundler"` so TypeScript c
|
|
|
293
296
|
<auro-header level="2" id="stateManagement">State Management</auro-header>
|
|
294
297
|
<p>The following properties reflect the current state of the menu and can be accessed via JavaScript.</p>
|
|
295
298
|
<auro-header level="3" id="value">value</auro-header>
|
|
296
|
-
<p>Gets or sets the selected value. In multi-select mode, this is a JSON stringified array of selected option values (e.g., <code>'["stops","duration"]'</code>).</p>
|
|
299
|
+
<p>Gets or sets the selected value. In multi-select mode, this is a JSON stringified array of selected option values (e.g., <code>'["stops","duration"]'</code>). If the value matches an option marked <code>disabled</code> or <code>static</code>, the selection is cleared (<code>optionSelected</code> becomes <code>undefined</code>) and <code>auroMenu-selectValueFailure</code> is dispatched. <code>hidden</code> options remain selectable by value.</p>
|
|
297
300
|
<auro-header level="3" id="optionSelected">optionSelected</auro-header>
|
|
298
301
|
<p>Returns the currently selected <code><auro-menuoption></code> element, or <code>undefined</code> if no option is selected. When <code>multiSelect</code> is enabled, returns an array of selected elements.</p>
|
|
299
302
|
<auro-header level="3" id="optionActive">optionActive</auro-header>
|
|
@@ -308,14 +311,148 @@ Ensure your `tsconfig.json` uses `"moduleResolution": "bundler"` so TypeScript c
|
|
|
308
311
|
<section>
|
|
309
312
|
<auro-header level="2" id="functions">Functions</auro-header>
|
|
310
313
|
<p>The following public methods are available on the <code><auro-menu></code> element.</p>
|
|
311
|
-
<auro-header level="3" id="makeSelection">makeSelection()</auro-header>
|
|
312
|
-
<p>Selects the currently active menu option. This is the programmatic equivalent of clicking on an option or pressing Enter while an option is focused.</p>
|
|
313
314
|
<auro-header level="3" id="reset">reset()</auro-header>
|
|
314
315
|
<p>Resets the menu to its initial state, clearing all selected options and restoring the value to <code>undefined</code>.</p>
|
|
315
|
-
<
|
|
316
|
-
|
|
316
|
+
<div class="exampleWrapper">
|
|
317
|
+
<!-- AURO-GENERATED-CONTENT:START (FILE:src=./../apiExamples/reset.html) -->
|
|
318
|
+
<!-- The below content is automatically added from ./../apiExamples/reset.html -->
|
|
319
|
+
<auro-menu id="resetExample" value="duration">
|
|
320
|
+
<auro-menuoption value="stops">Stops</auro-menuoption>
|
|
321
|
+
<auro-menuoption value="price">Price</auro-menuoption>
|
|
322
|
+
<auro-menuoption value="duration">Duration</auro-menuoption>
|
|
323
|
+
<auro-menuoption value="departure">Departure</auro-menuoption>
|
|
324
|
+
<auro-menuoption value="arrival">Arrival</auro-menuoption>
|
|
325
|
+
</auro-menu>
|
|
326
|
+
<br/><br/>
|
|
327
|
+
<auro-button id="resetExampleBtn">RESET</auro-button>
|
|
328
|
+
<!-- AURO-GENERATED-CONTENT:END -->
|
|
329
|
+
</div>
|
|
330
|
+
<auro-accordion alignRight>
|
|
331
|
+
<span slot="trigger">See code</span>
|
|
332
|
+
<!-- AURO-GENERATED-CONTENT:START (CODE:src=./../apiExamples/reset.html) -->
|
|
333
|
+
<!-- The below code snippet is automatically added from ./../apiExamples/reset.html -->
|
|
334
|
+
<pre class="language-html"><code class="language-html"><auro-menu id="resetExample" value="duration">
|
|
335
|
+
<auro-menuoption value="stops">Stops</auro-menuoption>
|
|
336
|
+
<auro-menuoption value="price">Price</auro-menuoption>
|
|
337
|
+
<auro-menuoption value="duration">Duration</auro-menuoption>
|
|
338
|
+
<auro-menuoption value="departure">Departure</auro-menuoption>
|
|
339
|
+
<auro-menuoption value="arrival">Arrival</auro-menuoption>
|
|
340
|
+
</auro-menu>
|
|
341
|
+
<br/><br/>
|
|
342
|
+
<auro-button id="resetExampleBtn">RESET</auro-button></code></pre>
|
|
343
|
+
<!-- AURO-GENERATED-CONTENT:END -->
|
|
344
|
+
</auro-accordion>
|
|
345
|
+
<auro-header level="3" id="selectByValue">selectByValue(value)</auro-header>
|
|
346
|
+
<p>Selects the option(s) whose <code>value</code> matches the argument. Accepts a string in single-select mode or an array of strings in multi-select mode; passing <code>undefined</code>, <code>null</code>, an empty string, or an empty array clears the selection.</p>
|
|
347
|
+
<div class="exampleWrapper">
|
|
348
|
+
<!-- AURO-GENERATED-CONTENT:START (FILE:src=./../apiExamples/select-by-value.html) -->
|
|
349
|
+
<!-- The below content is automatically added from ./../apiExamples/select-by-value.html -->
|
|
350
|
+
<auro-menu id="selectByValueMenu">
|
|
351
|
+
<auro-menuoption value="stops">Stops</auro-menuoption>
|
|
352
|
+
<auro-menuoption value="price">Price</auro-menuoption>
|
|
353
|
+
<auro-menuoption value="duration">Duration</auro-menuoption>
|
|
354
|
+
<auro-menuoption value="departure">Departure</auro-menuoption>
|
|
355
|
+
<auro-menuoption value="arrival">Arrival</auro-menuoption>
|
|
356
|
+
</auro-menu>
|
|
357
|
+
<br />
|
|
358
|
+
<auro-button id="selectByValueStops">Select "Stops"</auro-button>
|
|
359
|
+
<auro-button id="selectByValueDuration">Select "Duration"</auro-button>
|
|
360
|
+
<auro-button id="selectByValueClear">Clear selection</auro-button>
|
|
361
|
+
<!-- AURO-GENERATED-CONTENT:END -->
|
|
362
|
+
</div>
|
|
363
|
+
<auro-accordion alignRight>
|
|
364
|
+
<span slot="trigger">See code</span>
|
|
365
|
+
<!-- AURO-GENERATED-CONTENT:START (CODE:src=./../apiExamples/select-by-value.html) -->
|
|
366
|
+
<!-- The below code snippet is automatically added from ./../apiExamples/select-by-value.html -->
|
|
367
|
+
<pre class="language-html"><code class="language-html"><auro-menu id="selectByValueMenu">
|
|
368
|
+
<auro-menuoption value="stops">Stops</auro-menuoption>
|
|
369
|
+
<auro-menuoption value="price">Price</auro-menuoption>
|
|
370
|
+
<auro-menuoption value="duration">Duration</auro-menuoption>
|
|
371
|
+
<auro-menuoption value="departure">Departure</auro-menuoption>
|
|
372
|
+
<auro-menuoption value="arrival">Arrival</auro-menuoption>
|
|
373
|
+
</auro-menu>
|
|
374
|
+
<br />
|
|
375
|
+
<auro-button id="selectByValueStops">Select "Stops"</auro-button>
|
|
376
|
+
<auro-button id="selectByValueDuration">Select "Duration"</auro-button>
|
|
377
|
+
<auro-button id="selectByValueClear">Clear selection</auro-button></code></pre>
|
|
378
|
+
<!-- AURO-GENERATED-CONTENT:END -->
|
|
379
|
+
</auro-accordion>
|
|
380
|
+
<auro-header level="3" id="updateActiveOption">updateActiveOption(indexOrOption)</auro-header>
|
|
381
|
+
<p>Sets the specified option as the currently active (highlighted) option. Accepts either a numeric index into <code>options</code> or an <code><auro-menuoption></code> element reference.</p>
|
|
317
382
|
<auro-header level="3" id="navigateOptions">navigateOptions(direction)</auro-header>
|
|
318
|
-
<p>Moves the
|
|
383
|
+
<p>Moves the active option to the next or previous option. Accepts <code>'up'</code> or <code>'down'</code> as the direction parameter.</p>
|
|
384
|
+
</section>
|
|
385
|
+
<section>
|
|
386
|
+
<auro-header level="2" id="events">Events</auro-header>
|
|
387
|
+
<p>The <code><auro-menu></code> element dispatches custom events that consumers can subscribe to via <code>addEventListener</code>. The example below wires listeners for the full event set and logs each firing.</p>
|
|
388
|
+
<auro-header level="3" id="eventList">Event List</auro-header>
|
|
389
|
+
<ul>
|
|
390
|
+
<li><code>auroMenu-selectedOption</code> — a new selection has been made.</li>
|
|
391
|
+
<li><code>auroMenu-activatedOption</code> — the active (highlighted) option changed via keyboard or hover.</li>
|
|
392
|
+
<li><code>auroMenu-optionsChange</code> — the set of available options was updated (e.g., after a slot change).</li>
|
|
393
|
+
<li><code>auroMenu-selectValueReset</code> — the menu's <code>value</code> was reset via <code>reset()</code>.</li>
|
|
394
|
+
<li><code>auroMenu-selectValueFailure</code> — a value selection (via <code>selectByValue()</code>, the <code>value</code> attribute, or setting the <code>value</code> property) found no matching selectable option. This includes values that match an option marked <code>disabled</code> or <code>static</code>, which are never selectable.</li>
|
|
395
|
+
</ul>
|
|
396
|
+
<div class="exampleWrapper">
|
|
397
|
+
<!-- AURO-GENERATED-CONTENT:START (FILE:src=./../apiExamples/events.html) -->
|
|
398
|
+
<!-- The below content is automatically added from ./../apiExamples/events.html -->
|
|
399
|
+
<auro-menu id="eventsExampleMenu">
|
|
400
|
+
<auro-menuoption value="stops">Stops</auro-menuoption>
|
|
401
|
+
<auro-menuoption value="price">Price</auro-menuoption>
|
|
402
|
+
<auro-menuoption value="duration">Duration</auro-menuoption>
|
|
403
|
+
<auro-menuoption value="departure">Departure</auro-menuoption>
|
|
404
|
+
<auro-menuoption value="arrival">Arrival</auro-menuoption>
|
|
405
|
+
</auro-menu>
|
|
406
|
+
<br />
|
|
407
|
+
<auro-button id="eventsExampleReset">reset()</auro-button>
|
|
408
|
+
<auro-button id="eventsExampleBadValue">selectByValue("nonexistent")</auro-button>
|
|
409
|
+
<auro-button id="eventsExampleClearLog">Clear log</auro-button>
|
|
410
|
+
<pre id="eventsExampleLog" style="max-height: 200px; overflow: auto; padding: var(--ds-size-100, 8px); background: var(--ds-color-container-secondary, #f5f5f5); border-radius: 4px;">(interact with the menu above)</pre>
|
|
411
|
+
<!-- AURO-GENERATED-CONTENT:END -->
|
|
412
|
+
</div>
|
|
413
|
+
<auro-accordion alignRight>
|
|
414
|
+
<span slot="trigger">See code</span>
|
|
415
|
+
<!-- AURO-GENERATED-CONTENT:START (CODE:src=./../apiExamples/events.html) -->
|
|
416
|
+
<!-- The below code snippet is automatically added from ./../apiExamples/events.html -->
|
|
417
|
+
<pre class="language-html"><code class="language-html"><auro-menu id="eventsExampleMenu">
|
|
418
|
+
<auro-menuoption value="stops">Stops</auro-menuoption>
|
|
419
|
+
<auro-menuoption value="price">Price</auro-menuoption>
|
|
420
|
+
<auro-menuoption value="duration">Duration</auro-menuoption>
|
|
421
|
+
<auro-menuoption value="departure">Departure</auro-menuoption>
|
|
422
|
+
<auro-menuoption value="arrival">Arrival</auro-menuoption>
|
|
423
|
+
</auro-menu>
|
|
424
|
+
<br />
|
|
425
|
+
<auro-button id="eventsExampleReset">reset()</auro-button>
|
|
426
|
+
<auro-button id="eventsExampleBadValue">selectByValue("nonexistent")</auro-button>
|
|
427
|
+
<auro-button id="eventsExampleClearLog">Clear log</auro-button>
|
|
428
|
+
<pre id="eventsExampleLog" style="max-height: 200px; overflow: auto; padding: var(--ds-size-100, 8px); background: var(--ds-color-container-secondary, #f5f5f5); border-radius: 4px;">(interact with the menu above)</pre></code></pre>
|
|
429
|
+
<!-- AURO-GENERATED-CONTENT:END -->
|
|
430
|
+
</auro-accordion>
|
|
431
|
+
<auro-header level="3" id="eventAttribute">Option event attribute</auro-header>
|
|
432
|
+
<p>Attach an <code>event</code> attribute to any <code>auro-menuoption</code> to dispatch a named custom event from the menu when that option is selected. The generic <code>auroMenu-customEventFired</code> event is also dispatched on every firing — its <code>detail.option</code> references the option that triggered it, so a single listener can route on the <code>event</code> attribute value.</p>
|
|
433
|
+
<div class="exampleWrapper">
|
|
434
|
+
<!-- AURO-GENERATED-CONTENT:START (FILE:src=./../apiExamples/event-attribute.html) -->
|
|
435
|
+
<!-- The below content is automatically added from ./../apiExamples/event-attribute.html -->
|
|
436
|
+
<auro-menu id="eventAttrExample">
|
|
437
|
+
<auro-menuoption value="search" event="custom-flight-search">Search flights</auro-menuoption>
|
|
438
|
+
<auro-menuoption value="clear" event="custom-clear-filters">Clear filters</auro-menuoption>
|
|
439
|
+
<auro-menuoption value="save" event="custom-save-preferences">Save preferences</auro-menuoption>
|
|
440
|
+
</auro-menu>
|
|
441
|
+
<p>Last custom event: <output id="eventAttrOutput">(none)</output></p>
|
|
442
|
+
<!-- AURO-GENERATED-CONTENT:END -->
|
|
443
|
+
</div>
|
|
444
|
+
<auro-accordion alignRight>
|
|
445
|
+
<span slot="trigger">See code</span>
|
|
446
|
+
<!-- AURO-GENERATED-CONTENT:START (CODE:src=./../apiExamples/event-attribute.html) -->
|
|
447
|
+
<!-- The below code snippet is automatically added from ./../apiExamples/event-attribute.html -->
|
|
448
|
+
<pre class="language-html"><code class="language-html"><auro-menu id="eventAttrExample">
|
|
449
|
+
<auro-menuoption value="search" event="custom-flight-search">Search flights</auro-menuoption>
|
|
450
|
+
<auro-menuoption value="clear" event="custom-clear-filters">Clear filters</auro-menuoption>
|
|
451
|
+
<auro-menuoption value="save" event="custom-save-preferences">Save preferences</auro-menuoption>
|
|
452
|
+
</auro-menu>
|
|
453
|
+
<p>Last custom event: <output id="eventAttrOutput">(none)</output></p></code></pre>
|
|
454
|
+
<!-- AURO-GENERATED-CONTENT:END -->
|
|
455
|
+
</auro-accordion>
|
|
319
456
|
</section>
|
|
320
457
|
</div>
|
|
321
458
|
</div>
|
|
@@ -221,6 +221,18 @@ class AuroLibraryRuntimeUtils {
|
|
|
221
221
|
// See LICENSE in the project root for license information.
|
|
222
222
|
|
|
223
223
|
|
|
224
|
+
/**
|
|
225
|
+
* Serializes a multi-select value array back into the String `value` property.
|
|
226
|
+
* An empty (or missing) array collapses to `undefined` so an emptied selection
|
|
227
|
+
* clears `value` rather than reflecting a `"[]"` attribute.
|
|
228
|
+
* @private
|
|
229
|
+
* @param {Array<string>|undefined} values - The selected values.
|
|
230
|
+
* @returns {string|undefined} JSON string of the values, or undefined when empty.
|
|
231
|
+
*/
|
|
232
|
+
function serializeMultiSelectValue(values) {
|
|
233
|
+
return values && values.length > 0 ? JSON.stringify(values) : undefined;
|
|
234
|
+
}
|
|
235
|
+
|
|
224
236
|
/**
|
|
225
237
|
* Validates if an option can be interacted with.
|
|
226
238
|
* @private
|
|
@@ -233,6 +245,20 @@ function isOptionInteractive(option) {
|
|
|
233
245
|
!option.hasAttribute('static');
|
|
234
246
|
}
|
|
235
247
|
|
|
248
|
+
/**
|
|
249
|
+
* Validates if an option may be selected by matching a programmatic value.
|
|
250
|
+
* Unlike `isOptionInteractive`, `hidden` is allowed: the combobox toggles
|
|
251
|
+
* `hidden` as its type-ahead filter, so a filtered-out option is still a
|
|
252
|
+
* valid programmatic selection. Only disabled and static options — which are
|
|
253
|
+
* never selectable — are rejected.
|
|
254
|
+
* @param {HTMLElement} option - The option to check.
|
|
255
|
+
* @returns {boolean} True if option can be selected by value.
|
|
256
|
+
*/
|
|
257
|
+
function isSelectableByValue(option) {
|
|
258
|
+
return !option.hasAttribute('disabled') &&
|
|
259
|
+
!option.hasAttribute('static');
|
|
260
|
+
}
|
|
261
|
+
|
|
236
262
|
/**
|
|
237
263
|
* Helper method to dispatch custom events.
|
|
238
264
|
* @param {HTMLElement} element - Element to dispatch event from.
|
|
@@ -415,22 +441,26 @@ class AuroMenu extends AuroElement {
|
|
|
415
441
|
|
|
416
442
|
/**
|
|
417
443
|
* Specifies the current active menuOption.
|
|
444
|
+
* @readonly
|
|
418
445
|
*/
|
|
419
446
|
optionActive: {
|
|
420
447
|
type: Object,
|
|
421
|
-
attribute:
|
|
448
|
+
attribute: false
|
|
422
449
|
},
|
|
423
450
|
|
|
424
451
|
/**
|
|
425
|
-
*
|
|
452
|
+
* The currently selected menu option(s). In single-select mode this is a single `HTMLElement` (or `undefined` when nothing is selected). In multi-select mode this is an array of `HTMLElement`s.
|
|
453
|
+
* @readonly
|
|
426
454
|
*/
|
|
427
455
|
optionSelected: {
|
|
428
456
|
// Allow HTMLElement, HTMLElement[] arrays and undefined
|
|
429
|
-
type: Object
|
|
457
|
+
type: Object,
|
|
458
|
+
attribute: false
|
|
430
459
|
},
|
|
431
460
|
|
|
432
461
|
/**
|
|
433
462
|
* The value of the selected option. In multi-select mode, this is a JSON stringified array of selected option values.
|
|
463
|
+
* 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.
|
|
434
464
|
*/
|
|
435
465
|
value: {
|
|
436
466
|
type: String,
|
|
@@ -554,7 +584,7 @@ class AuroMenu extends AuroElement {
|
|
|
554
584
|
}
|
|
555
585
|
|
|
556
586
|
/**
|
|
557
|
-
* Selects options by value.
|
|
587
|
+
* Selects options by value. Options marked `disabled` or `static` are not selectable; `hidden` options remain selectable. In single-select mode, if the value matches a non-selectable option the selection is cleared and `auroMenu-selectValueFailure` is dispatched. In multi-select mode, non-selectable entries are dropped and the remaining selectable entries are selected; `auroMenu-selectValueFailure` is dispatched only when none of the entries match a selectable option. Passing `undefined`, `null`, an empty string, or an empty array clears the selection without dispatching a failure.
|
|
558
588
|
* @param {string|string[]|undefined|null} value - The value(s) to select.
|
|
559
589
|
* @public
|
|
560
590
|
*/
|
|
@@ -639,6 +669,11 @@ class AuroMenu extends AuroElement {
|
|
|
639
669
|
this.initItems();
|
|
640
670
|
}
|
|
641
671
|
|
|
672
|
+
// Set when reconciliation reassigns `value` below. That reassignment schedules a
|
|
673
|
+
// second updated() cycle, so the `event`-attribute dispatch is deferred to that
|
|
674
|
+
// cycle to avoid firing option custom events twice on the same selection.
|
|
675
|
+
let valueReconciled = false;
|
|
676
|
+
|
|
642
677
|
// Handle null/undefined/empty case — empty/whitespace strings clear selection
|
|
643
678
|
// consistently with selectByValue(''), and avoid downstream `.includes('')` matches.
|
|
644
679
|
if (this.value === undefined || this.value === null || (typeof this.value === 'string' && this.value.trim() === '')) {
|
|
@@ -651,11 +686,31 @@ class AuroMenu extends AuroElement {
|
|
|
651
686
|
// Defensive default: `formattedValue` can be undefined for unexpected value types,
|
|
652
687
|
// and calling `.includes` on undefined would throw during reconciliation.
|
|
653
688
|
const valueArray = this.formattedValue || [];
|
|
654
|
-
const matchingOptions = this.items ? this.items.filter((item) => valueArray.includes(item.value)) : [];
|
|
689
|
+
const matchingOptions = this.items ? this.items.filter((item) => isSelectableByValue(item) && valueArray.includes(item.value)) : [];
|
|
655
690
|
newSelected = matchingOptions.length > 0 ? matchingOptions : undefined;
|
|
691
|
+
|
|
692
|
+
// Reconcile `value` with the selectable set. Drop only entries whose option is
|
|
693
|
+
// loaded but non-selectable (disabled/static) — leaving them would desync `value`
|
|
694
|
+
// from `optionSelected`, and the toggle handlers rebuild `value` from `formattedValue`,
|
|
695
|
+
// so the rejected entry would resurface on the next select/deselect. Entries with no
|
|
696
|
+
// matching item yet are preserved so async preselection still works once options render.
|
|
697
|
+
const rejectedValues = this.items
|
|
698
|
+
? this.items.filter((item) => !isSelectableByValue(item) && valueArray.includes(item.value)).map((item) => item.value)
|
|
699
|
+
: [];
|
|
700
|
+
if (rejectedValues.length > 0) {
|
|
701
|
+
const reconciled = valueArray.filter((val) => !rejectedValues.includes(val));
|
|
702
|
+
this.value = serializeMultiSelectValue(reconciled);
|
|
703
|
+
valueReconciled = true;
|
|
704
|
+
}
|
|
656
705
|
} else {
|
|
657
|
-
// In single-select mode, this.value should be a string
|
|
658
|
-
|
|
706
|
+
// In single-select mode, this.value should be a string. Reject
|
|
707
|
+
// disabled/static options so a programmatic value pointing at a
|
|
708
|
+
// non-selectable option falls through to the no-match path below
|
|
709
|
+
// (dispatching auroMenu-selectValueFailure) instead of pinning it.
|
|
710
|
+
// `hidden` is intentionally NOT excluded: the combobox toggles
|
|
711
|
+
// `hidden` as its type-ahead filter, so a filtered-out option is
|
|
712
|
+
// still a valid programmatic selection.
|
|
713
|
+
const matchingOption = this.items ? this.items.find((item) => isSelectableByValue(item) && item.value === this.value) : undefined;
|
|
659
714
|
|
|
660
715
|
if (matchingOption) {
|
|
661
716
|
newSelected = matchingOption;
|
|
@@ -697,8 +752,9 @@ class AuroMenu extends AuroElement {
|
|
|
697
752
|
]
|
|
698
753
|
]));
|
|
699
754
|
|
|
700
|
-
// Notify of changes
|
|
701
|
-
|
|
755
|
+
// Notify of changes. Skip when reconciliation just reassigned `value`: the
|
|
756
|
+
// follow-on update cycle re-runs this branch and fires the events exactly once.
|
|
757
|
+
if (this.optionSelected !== undefined && !valueReconciled) {
|
|
702
758
|
const selected = Array.isArray(this.optionSelected) ? this.optionSelected : [this.optionSelected];
|
|
703
759
|
selected.forEach((opt) => {
|
|
704
760
|
if (opt.hasAttribute('event')) {
|
|
@@ -911,7 +967,7 @@ class AuroMenu extends AuroElement {
|
|
|
911
967
|
const currentSelected = this.optionSelected || [];
|
|
912
968
|
|
|
913
969
|
if (!currentValue.includes(option.value)) {
|
|
914
|
-
this.value =
|
|
970
|
+
this.value = serializeMultiSelectValue([
|
|
915
971
|
...currentValue,
|
|
916
972
|
option.value
|
|
917
973
|
]);
|
|
@@ -937,15 +993,9 @@ class AuroMenu extends AuroElement {
|
|
|
937
993
|
*/
|
|
938
994
|
handleDeselectState(option) {
|
|
939
995
|
if (this.multiSelect) {
|
|
940
|
-
// Remove this option from array
|
|
996
|
+
// Remove this option from array; an empty result collapses `value` to undefined.
|
|
941
997
|
const newFormattedValue = (this.formattedValue || []).filter((val) => val !== option.value);
|
|
942
|
-
|
|
943
|
-
// If array is empty after removal, set back to undefined
|
|
944
|
-
if (newFormattedValue && newFormattedValue.length === 0) {
|
|
945
|
-
this.value = undefined;
|
|
946
|
-
} else {
|
|
947
|
-
this.value = JSON.stringify(newFormattedValue);
|
|
948
|
-
}
|
|
998
|
+
this.value = serializeMultiSelectValue(newFormattedValue);
|
|
949
999
|
|
|
950
1000
|
this.optionSelected = this.optionSelected.filter((val) => val !== option);
|
|
951
1001
|
if (this.optionSelected.length === 0) {
|
|
@@ -992,6 +1042,11 @@ class AuroMenu extends AuroElement {
|
|
|
992
1042
|
this.optionSelected = undefined;
|
|
993
1043
|
this._index = -1;
|
|
994
1044
|
|
|
1045
|
+
// Clear active option state so a follow-up open/navigation starts fresh
|
|
1046
|
+
// rather than reusing a stale reference from before the reset.
|
|
1047
|
+
this.items?.forEach((item) => item.classList.remove('active'));
|
|
1048
|
+
this.optionActive = undefined;
|
|
1049
|
+
|
|
995
1050
|
// Reset UI state
|
|
996
1051
|
this.updateItemsState(new Map([
|
|
997
1052
|
[
|
|
@@ -1454,6 +1509,7 @@ let menuOptionIdCounter = 0;
|
|
|
1454
1509
|
* The `auro-menuoption` element provides users a way to define a menu option.
|
|
1455
1510
|
* @customElement auro-menuoption
|
|
1456
1511
|
*
|
|
1512
|
+
* @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.
|
|
1457
1513
|
* @slot default - The default slot for the menu option text.
|
|
1458
1514
|
*
|
|
1459
1515
|
* @event auroMenuOption-mouseover - Notifies that this option has been hovered over.
|
|
@@ -1483,6 +1539,7 @@ class AuroMenuOption extends AuroElement {
|
|
|
1483
1539
|
this.noCheckmark = false;
|
|
1484
1540
|
this.disabled = false;
|
|
1485
1541
|
this.noMatch = false;
|
|
1542
|
+
this.persistent = false;
|
|
1486
1543
|
|
|
1487
1544
|
/**
|
|
1488
1545
|
* @private
|
|
@@ -1504,6 +1561,12 @@ class AuroMenuOption extends AuroElement {
|
|
|
1504
1561
|
type: Boolean,
|
|
1505
1562
|
reflect: true
|
|
1506
1563
|
},
|
|
1564
|
+
|
|
1565
|
+
/**
|
|
1566
|
+
* **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.
|
|
1567
|
+
*
|
|
1568
|
+
* @deprecated Use the `value` attribute on `auro-menu` instead.
|
|
1569
|
+
*/
|
|
1507
1570
|
selected: {
|
|
1508
1571
|
type: Boolean,
|
|
1509
1572
|
reflect: true
|
|
@@ -1538,6 +1601,12 @@ class AuroMenuOption extends AuroElement {
|
|
|
1538
1601
|
reflect: true,
|
|
1539
1602
|
attribute: 'nomatch'
|
|
1540
1603
|
},
|
|
1604
|
+
|
|
1605
|
+
/** 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. */
|
|
1606
|
+
persistent: {
|
|
1607
|
+
type: Boolean,
|
|
1608
|
+
reflect: true
|
|
1609
|
+
},
|
|
1541
1610
|
};
|
|
1542
1611
|
}
|
|
1543
1612
|
|
|
@@ -1712,6 +1781,103 @@ class AuroMenuOption extends AuroElement {
|
|
|
1712
1781
|
}
|
|
1713
1782
|
}
|
|
1714
1783
|
|
|
1784
|
+
function auroMenuLoadingExample() {
|
|
1785
|
+
document.querySelector("#loadingExampleToggleButton").addEventListener("click", () => {
|
|
1786
|
+
document.querySelectorAll("#loadingExampleTable auro-menu").forEach(menu => menu.toggleAttribute("loading"));
|
|
1787
|
+
});
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
function updateMatch() {
|
|
1791
|
+
let matchWordMenu = document.querySelector('#matchWordMenu');
|
|
1792
|
+
|
|
1793
|
+
matchWordMenu.matchWord = matchWordInput.value;
|
|
1794
|
+
}
|
|
1795
|
+
|
|
1796
|
+
function auroMenuMatchWordExample() {
|
|
1797
|
+
let matchWordInput = document.querySelector('#matchWordInput');
|
|
1798
|
+
|
|
1799
|
+
matchWordInput.addEventListener('keyup', updateMatch);
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1802
|
+
function auroMenuResetExample() {
|
|
1803
|
+
const resetExampleBtnElem = document.querySelector('#resetExampleBtn');
|
|
1804
|
+
const resetExampleElem = document.querySelector('#resetExample');
|
|
1805
|
+
|
|
1806
|
+
if (resetExampleElem && resetExampleBtnElem) {
|
|
1807
|
+
resetExampleBtnElem.addEventListener('click', () => {
|
|
1808
|
+
resetExampleElem.reset();
|
|
1809
|
+
});
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
function auroMenuEventAttributeExample() {
|
|
1814
|
+
const menu = document.querySelector('#eventAttrExample');
|
|
1815
|
+
const output = document.querySelector('#eventAttrOutput');
|
|
1816
|
+
|
|
1817
|
+
menu.addEventListener('auroMenu-customEventFired', (evt) => {
|
|
1818
|
+
const eventName = evt.detail.option.getAttribute('event');
|
|
1819
|
+
output.textContent = `${eventName} (from "${evt.detail.option.textContent}")`;
|
|
1820
|
+
});
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
function auroMenuEventsExample() {
|
|
1824
|
+
const menu = document.querySelector('#eventsExampleMenu');
|
|
1825
|
+
const log = document.querySelector('#eventsExampleLog');
|
|
1826
|
+
const resetBtn = document.querySelector('#eventsExampleReset');
|
|
1827
|
+
const badValueBtn = document.querySelector('#eventsExampleBadValue');
|
|
1828
|
+
const clearBtn = document.querySelector('#eventsExampleClearLog');
|
|
1829
|
+
|
|
1830
|
+
let entries = [];
|
|
1831
|
+
const write = (name, detail) => {
|
|
1832
|
+
const label = detail && detail.tagName ? detail.tagName.toLowerCase() : JSON.stringify(detail);
|
|
1833
|
+
entries.unshift(`${name}: ${label}`);
|
|
1834
|
+
log.textContent = entries.slice(0, 10).join('\n');
|
|
1835
|
+
};
|
|
1836
|
+
|
|
1837
|
+
menu.addEventListener('auroMenu-selectedOption', () => {
|
|
1838
|
+
write('auroMenu-selectedOption', menu.optionSelected);
|
|
1839
|
+
});
|
|
1840
|
+
menu.addEventListener('auroMenu-activatedOption', (evt) => {
|
|
1841
|
+
write('auroMenu-activatedOption', evt.detail);
|
|
1842
|
+
});
|
|
1843
|
+
menu.addEventListener('auroMenu-optionsChange', (evt) => {
|
|
1844
|
+
write('auroMenu-optionsChange', { count: (evt.detail.options || []).length });
|
|
1845
|
+
});
|
|
1846
|
+
menu.addEventListener('auroMenu-selectValueReset', () => {
|
|
1847
|
+
write('auroMenu-selectValueReset', { value: menu.value });
|
|
1848
|
+
});
|
|
1849
|
+
menu.addEventListener('auroMenu-selectValueFailure', (evt) => {
|
|
1850
|
+
write('auroMenu-selectValueFailure', evt.detail);
|
|
1851
|
+
});
|
|
1852
|
+
|
|
1853
|
+
resetBtn.addEventListener('click', () => menu.reset());
|
|
1854
|
+
badValueBtn.addEventListener('click', () => menu.selectByValue('nonexistent'));
|
|
1855
|
+
clearBtn.addEventListener('click', () => {
|
|
1856
|
+
entries = [];
|
|
1857
|
+
log.textContent = '(interact with the menu above)';
|
|
1858
|
+
});
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
function auroMenuPersistentExample() {
|
|
1862
|
+
const input = document.querySelector('#persistentExampleInput');
|
|
1863
|
+
const menu = document.querySelector('#persistentExampleMenu');
|
|
1864
|
+
|
|
1865
|
+
input.addEventListener('keyup', () => {
|
|
1866
|
+
menu.matchWord = input.value;
|
|
1867
|
+
});
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
function auroMenuSelectByValueExample() {
|
|
1871
|
+
const menu = document.querySelector('#selectByValueMenu');
|
|
1872
|
+
const stopsBtn = document.querySelector('#selectByValueStops');
|
|
1873
|
+
const durationBtn = document.querySelector('#selectByValueDuration');
|
|
1874
|
+
const clearBtn = document.querySelector('#selectByValueClear');
|
|
1875
|
+
|
|
1876
|
+
stopsBtn.addEventListener('click', () => menu.selectByValue('stops'));
|
|
1877
|
+
durationBtn.addEventListener('click', () => menu.selectByValue('duration'));
|
|
1878
|
+
clearBtn.addEventListener('click', () => menu.selectByValue(undefined));
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1715
1881
|
/* eslint-disable jsdoc/require-jsdoc, no-magic-numbers, no-param-reassign */
|
|
1716
1882
|
|
|
1717
1883
|
|
|
@@ -1720,7 +1886,36 @@ AuroMenuOption.register();
|
|
|
1720
1886
|
AuroMenu.register('custom-menu');
|
|
1721
1887
|
AuroMenuOption.register('custom-menuoption');
|
|
1722
1888
|
|
|
1723
|
-
|
|
1889
|
+
const examples = [
|
|
1890
|
+
auroMenuLoadingExample,
|
|
1891
|
+
auroMenuMatchWordExample,
|
|
1892
|
+
auroMenuResetExample,
|
|
1893
|
+
auroMenuEventAttributeExample,
|
|
1894
|
+
auroMenuEventsExample,
|
|
1895
|
+
auroMenuPersistentExample,
|
|
1896
|
+
auroMenuSelectByValueExample
|
|
1897
|
+
];
|
|
1898
|
+
|
|
1899
|
+
function initExamples(pending, initCount) {
|
|
1900
|
+
pending = pending || examples.slice();
|
|
1901
|
+
initCount = initCount || 0;
|
|
1902
|
+
const stillPending = [];
|
|
1903
|
+
|
|
1904
|
+
for (const fn of pending) {
|
|
1905
|
+
try {
|
|
1906
|
+
fn();
|
|
1907
|
+
} catch {
|
|
1908
|
+
stillPending.push(fn);
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
|
|
1912
|
+
if (stillPending.length && initCount <= 20) {
|
|
1913
|
+
setTimeout(() => {
|
|
1914
|
+
initExamples(stillPending, initCount + 1);
|
|
1915
|
+
}, 100);
|
|
1916
|
+
}
|
|
1724
1917
|
}
|
|
1725
1918
|
|
|
1919
|
+
initExamples();
|
|
1920
|
+
|
|
1726
1921
|
export { initExamples };
|
|
@@ -7,11 +7,90 @@
|
|
|
7
7
|
<auro-header level="2" id="keyEvents">Key Events</auro-header>
|
|
8
8
|
<!-- AURO-GENERATED-CONTENT:START (FILE:src=./../docs/partials/keyEvents.md) -->
|
|
9
9
|
<!-- The below content is automatically added from ./../docs/partials/keyEvents.md -->
|
|
10
|
-
<!-- auro-menu does not implement direct keyboard event handling. -->
|
|
11
|
-
<!-- Keyboard navigation is delegated to parent components (auro-select, auro-combobox) via their keyboard strategy files. -->
|
|
12
10
|
<div class="note">
|
|
13
|
-
<p><strong>Note:</strong>
|
|
14
|
-
|
|
11
|
+
<p><strong>Note:</strong> <code><auro-menu></code> registers a <code>keydown</code> listener on its host. By default the menu is not focusable — no <code>tabindex</code> on the host, and menuoptions are <code>tabindex="-1"</code> — so the listener does not fire on its own. It fires whenever a <code>keydown</code> reaches the host, which happens in any of the following ways:</p>
|
|
12
|
+
<ul>
|
|
13
|
+
<li>A wrapping component focuses something inside the menu subtree and the event bubbles up to the host. In the standard integrations (<code><auro-select></code>, <code><auro-combobox></code>), keyboard behavior is primarily parent-managed rather than bubble-driven: focus stays on the parent's trigger/input, and the parent captures keys there and drives the menu directly via its public <code>navigateOptions()</code> / <code>updateActiveOption()</code> methods and the menu's internal <code>makeSelection()</code> routine (<code>@private</code>, not part of the public menu API).</li>
|
|
14
|
+
<li>A wrapping component dispatches or reroutes a <code>KeyboardEvent</code> at the menu programmatically (for example, <code>menu.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }))</code>).</li>
|
|
15
|
+
<li>The author makes the host focusable (for example, by adding <code>tabindex="0"</code> to the <code><auro-menu></code> element) and focuses it. The host already has <code>role="listbox"</code>, so this yields a bare, focusable listbox that responds to the keys in the table below. For full combobox semantics use <code><auro-select></code> or <code><auro-combobox></code>, or replicate their <code>aria-activedescendant</code> wiring from a separate trigger.</li>
|
|
16
|
+
</ul>
|
|
17
|
+
<p>Keys not listed below (<code>Home</code>, <code>End</code>, <code>Escape</code>, type-ahead) are handled by the parent — see the <code><auro-select></code> and <code><auro-combobox></code> keyboard behavior docs. An "interactive option" is one that is not <code>disabled</code>, <code>hidden</code>, or <code>static</code> — these are always skipped during navigation and selection, along with <code><hr></code> dividers.</p>
|
|
18
|
+
</div>
|
|
19
|
+
<table>
|
|
20
|
+
<thead>
|
|
21
|
+
<tr>
|
|
22
|
+
<th>Key</th>
|
|
23
|
+
<th>Current State</th>
|
|
24
|
+
<th>Behavior</th>
|
|
25
|
+
</tr>
|
|
26
|
+
</thead>
|
|
27
|
+
<tbody>
|
|
28
|
+
<tr>
|
|
29
|
+
<td rowspan="5">ArrowDown</td>
|
|
30
|
+
<td>No option is active</td>
|
|
31
|
+
<td>The first interactive option becomes active.</td>
|
|
32
|
+
</tr>
|
|
33
|
+
<tr>
|
|
34
|
+
<td>An option is active, followed by interactive options</td>
|
|
35
|
+
<td>Advances the active option to the next interactive option.</td>
|
|
36
|
+
</tr>
|
|
37
|
+
<tr>
|
|
38
|
+
<td>The last interactive option is active</td>
|
|
39
|
+
<td>Wraps to the first interactive option.</td>
|
|
40
|
+
</tr>
|
|
41
|
+
<tr>
|
|
42
|
+
<td>Menu has no options or all options are non-interactive</td>
|
|
43
|
+
<td>No option becomes active; no <code>auroMenu-activatedOption</code> event fires.</td>
|
|
44
|
+
</tr>
|
|
45
|
+
<tr>
|
|
46
|
+
<td>Menu is in <code>loading</code> state</td>
|
|
47
|
+
<td>The rendered loading placeholder is inert (marked <code>disabled</code>) and is not part of <code>items</code>, so it cannot become active.</td>
|
|
48
|
+
</tr>
|
|
49
|
+
<tr>
|
|
50
|
+
<td rowspan="4">ArrowUp</td>
|
|
51
|
+
<td>No option is active</td>
|
|
52
|
+
<td>The last interactive option becomes active.</td>
|
|
53
|
+
</tr>
|
|
54
|
+
<tr>
|
|
55
|
+
<td>An option is active, preceded by interactive options</td>
|
|
56
|
+
<td>Advances the active option to the previous interactive option.</td>
|
|
57
|
+
</tr>
|
|
58
|
+
<tr>
|
|
59
|
+
<td>The first interactive option is active</td>
|
|
60
|
+
<td>Wraps to the last interactive option.</td>
|
|
61
|
+
</tr>
|
|
62
|
+
<tr>
|
|
63
|
+
<td>Menu has no options or all options are non-interactive</td>
|
|
64
|
+
<td>No option becomes active.</td>
|
|
65
|
+
</tr>
|
|
66
|
+
<tr>
|
|
67
|
+
<td rowspan="4">Enter</td>
|
|
68
|
+
<td>Single-select, active option is not currently selected</td>
|
|
69
|
+
<td>The active option is selected. Any previous selection is cleared. <code>auroMenu-selectedOption</code> fires.</td>
|
|
70
|
+
</tr>
|
|
71
|
+
<tr>
|
|
72
|
+
<td>Single-select, active option is already selected</td>
|
|
73
|
+
<td>No selection change, but <code>auroMenu-selectedOption</code> still fires so the parent can react (for example, close the dropdown).</td>
|
|
74
|
+
</tr>
|
|
75
|
+
<tr>
|
|
76
|
+
<td>Multi-select</td>
|
|
77
|
+
<td>The active option toggles selected. Other selections are preserved.</td>
|
|
78
|
+
</tr>
|
|
79
|
+
<tr>
|
|
80
|
+
<td>Active option is disabled, hidden, or static</td>
|
|
81
|
+
<td>Selection is a no-op.</td>
|
|
82
|
+
</tr>
|
|
83
|
+
<tr>
|
|
84
|
+
<td rowspan="2">Tab</td>
|
|
85
|
+
<td>An option is active</td>
|
|
86
|
+
<td>The active option is selected (same behavior as <code>Enter</code>).<div class="note"><strong>Note:</strong> <code>Tab</code> does not <code>preventDefault</code>, so focus continues to the next element in the tabindex sequence after selection.</div></td>
|
|
87
|
+
</tr>
|
|
88
|
+
<tr>
|
|
89
|
+
<td>No option is active</td>
|
|
90
|
+
<td>Focus moves to the next tabbable element; no selection change.</td>
|
|
91
|
+
</tr>
|
|
92
|
+
</tbody>
|
|
93
|
+
</table>
|
|
15
94
|
<!-- AURO-GENERATED-CONTENT:END -->
|
|
16
95
|
</div>
|
|
17
96
|
</div>
|