@aurodesignsystem-dev/auro-formkit 0.0.0-pr1408.8 → 0.0.0-pr1411.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/api.min.js +1 -1
- package/components/checkbox/demo/index.min.js +1 -1
- package/components/checkbox/demo/keyboardBehavior.md +0 -0
- package/components/checkbox/dist/index.js +1 -1
- package/components/checkbox/dist/registered.js +1 -1
- package/components/combobox/demo/api.min.js +121 -144
- package/components/combobox/demo/index.min.js +121 -144
- package/components/combobox/demo/keyboardBehavior.html +1 -0
- package/components/combobox/demo/keyboardBehavior.md +21 -22
- package/components/combobox/dist/index.js +87 -117
- package/components/combobox/dist/registered.js +87 -117
- package/components/counter/demo/api.md +1 -1
- package/components/counter/demo/api.min.js +184 -148
- package/components/counter/demo/index.min.js +184 -148
- package/components/counter/demo/keyboardBehavior.html +1 -0
- package/components/counter/demo/keyboardBehavior.md +1 -1
- package/components/counter/dist/auro-counter.d.ts +11 -8
- package/components/counter/dist/index.js +184 -148
- package/components/counter/dist/keyboardStrategy.d.ts +4 -0
- package/components/counter/dist/registered.js +184 -148
- package/components/datepicker/demo/api.min.js +89 -120
- package/components/datepicker/demo/index.min.js +89 -120
- package/components/datepicker/demo/keyboardBehavior.html +1 -0
- package/components/datepicker/demo/keyboardBehavior.md +14 -13
- package/components/datepicker/dist/index.js +84 -115
- package/components/datepicker/dist/registered.js +84 -115
- package/components/dropdown/demo/api.md +0 -1
- package/components/dropdown/demo/api.min.js +99 -123
- package/components/dropdown/demo/index.md +2 -2
- package/components/dropdown/demo/index.min.js +99 -123
- package/components/dropdown/demo/keyboardBehavior.html +1 -0
- package/components/dropdown/dist/auro-dropdown.d.ts +0 -8
- package/components/dropdown/dist/auro-dropdownBib.d.ts +1 -40
- package/components/dropdown/dist/dropdownBibKeyboardStrategy.d.ts +7 -0
- package/components/dropdown/dist/index.js +83 -111
- package/components/dropdown/dist/registered.js +83 -111
- package/components/form/demo/api.min.js +542 -564
- package/components/form/demo/index.min.js +542 -564
- package/components/form/demo/keyboardBehavior.md +0 -0
- package/components/input/demo/api.min.js +1 -1
- package/components/input/demo/index.min.js +1 -1
- package/components/input/demo/keyboardBehavior.md +0 -0
- package/components/input/dist/index.js +1 -1
- package/components/input/dist/registered.js +1 -1
- package/components/menu/demo/api.min.js +34 -27
- package/components/menu/demo/index.min.js +34 -27
- package/components/menu/dist/auro-menu.d.ts +0 -6
- package/components/menu/dist/index.js +34 -27
- package/components/menu/dist/registered.js +34 -27
- package/components/radio/demo/api.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.min.js +181 -178
- package/components/select/demo/index.min.js +181 -178
- package/components/select/demo/keyboardBehavior.html +1 -0
- package/components/select/demo/keyboardBehavior.md +240 -239
- package/components/select/dist/index.js +147 -151
- package/components/select/dist/registered.js +147 -151
- package/components/select/dist/selectKeyboardStrategy.d.ts +3 -1
- package/custom-elements.json +1521 -1503
- package/package.json +5 -3
|
@@ -3,6 +3,8 @@ import { classMap } from 'lit/directives/class-map.js';
|
|
|
3
3
|
import { createRef, ref } from 'lit/directives/ref.js';
|
|
4
4
|
import { css, html, LitElement } from 'lit';
|
|
5
5
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
6
|
+
import 'lit-html';
|
|
7
|
+
import 'lit-html/directives/unsafe-html.js';
|
|
6
8
|
|
|
7
9
|
// Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
|
|
8
10
|
// See LICENSE in the project root for license information.
|
|
@@ -2053,11 +2055,10 @@ class AuroFloatingUI {
|
|
|
2053
2055
|
return;
|
|
2054
2056
|
}
|
|
2055
2057
|
|
|
2056
|
-
const { activeElement } = document;
|
|
2057
2058
|
// if focus is still inside of trigger or bib, do not close
|
|
2058
2059
|
if (
|
|
2059
|
-
this.element.
|
|
2060
|
-
this.element.
|
|
2060
|
+
this.element.matches(":focus") ||
|
|
2061
|
+
this.element.matches(":focus-within")
|
|
2061
2062
|
) {
|
|
2062
2063
|
return;
|
|
2063
2064
|
}
|
|
@@ -2896,12 +2897,83 @@ class p{registerComponent(t,a){customElements.get(t)||customElements.define(t,cl
|
|
|
2896
2897
|
|
|
2897
2898
|
var iconVersion = '9.1.2';
|
|
2898
2899
|
|
|
2900
|
+
/**
|
|
2901
|
+
* Computes display state once per keydown event.
|
|
2902
|
+
* Centralizes null-safety checks and makes the shared/modal/popover branching explicit.
|
|
2903
|
+
*
|
|
2904
|
+
* @param {HTMLElement} component - The component with a dropdown reference.
|
|
2905
|
+
* @param {Object} [options] - Optional config.
|
|
2906
|
+
* @param {HTMLElement} [options.dropdown] - Explicit dropdown reference. Falls back to component.dropdown.
|
|
2907
|
+
* @param {Function} [options.inputResolver] - Called with (component, ctx) to resolve the active input element.
|
|
2908
|
+
* @returns {{isExpanded: boolean, isModal: boolean, isPopover: boolean, activeInput: HTMLElement|null}}
|
|
2909
|
+
* isModal and isPopover reflect the display mode (fullscreen vs not) regardless of expanded state.
|
|
2910
|
+
*/
|
|
2911
|
+
function createDisplayContext(component, options = {}) {
|
|
2912
|
+
const dd = options.dropdown || component.dropdown;
|
|
2913
|
+
// isPopoverVisible reflects as the `open` attribute.
|
|
2914
|
+
// It reports whether the bib is open in any mode (popover or modal).
|
|
2915
|
+
const isExpanded = Boolean(dd && dd.isPopoverVisible);
|
|
2916
|
+
const isFullscreen = Boolean(dd && dd.isBibFullscreen);
|
|
2917
|
+
|
|
2918
|
+
const ctx = {
|
|
2919
|
+
isExpanded,
|
|
2920
|
+
isModal: isFullscreen,
|
|
2921
|
+
isPopover: !isFullscreen,
|
|
2922
|
+
activeInput: null,
|
|
2923
|
+
};
|
|
2924
|
+
|
|
2925
|
+
if (options.inputResolver) {
|
|
2926
|
+
const resolvedInput = options.inputResolver(component, ctx);
|
|
2927
|
+
// Guard against resolvers returning undefined or non-HTMLElement values.
|
|
2928
|
+
ctx.activeInput = resolvedInput instanceof HTMLElement ? resolvedInput : null;
|
|
2929
|
+
}
|
|
2930
|
+
|
|
2931
|
+
return ctx;
|
|
2932
|
+
}
|
|
2933
|
+
|
|
2934
|
+
/**
|
|
2935
|
+
* Wires up a keydown listener that dispatches to strategy[evt.key] or strategy.default.
|
|
2936
|
+
* Handles both sync and async handlers.
|
|
2937
|
+
* @param {HTMLElement} component - The component to attach the listener to.
|
|
2938
|
+
* @param {Object} strategy - Map of key names to handler functions.
|
|
2939
|
+
* @param {Object} [options] - Optional config passed to createDisplayContext.
|
|
2940
|
+
*/
|
|
2941
|
+
function applyKeyboardStrategy(component, strategy, options = {}) {
|
|
2942
|
+
component.addEventListener('keydown', async (evt) => {
|
|
2943
|
+
const handler = strategy[evt.key] || strategy.default;
|
|
2944
|
+
if (typeof handler === 'function') {
|
|
2945
|
+
const ctx = createDisplayContext(component, options);
|
|
2946
|
+
await handler(component, evt, ctx);
|
|
2947
|
+
}
|
|
2948
|
+
});
|
|
2949
|
+
}
|
|
2950
|
+
|
|
2899
2951
|
var styleCss$2 = css`:host{position:fixed;z-index:var(--depth-tooltip, 400);display:none;isolation:isolate}:host dialog{width:auto;max-width:none;height:auto;max-height:none;padding:0;border:none;margin:0;outline:none;transform:translateZ(0)}:host dialog::backdrop{background:transparent}:host(:not([isfullscreen])) dialog{position:relative;inset:unset}:host(:not([isfullscreen])) .container.shape-box{border-radius:unset}:host(:not([isfullscreen])) .container[class*=shape-pill],:host(:not([isfullscreen])) .container[class*=shape-snowflake]{border-radius:30px}:host(:not([isfullscreen])) .container[class*=shape-rounded]{border-radius:16px}:host(:not([matchWidth])) .container{min-width:fit-content}:host([isfullscreen]){position:fixed;top:0;left:0}:host([isfullscreen]) .container{width:100dvw;max-width:none;height:100dvh;max-height:none;border-radius:unset;margin-top:0;box-shadow:unset;overscroll-behavior:contain}:host([isfullscreen]) .container::backdrop{background:var(--ds-color-background-primary, #fff)}:host(:popover-open){position:fixed;overflow:visible;padding:0;border:none;margin:0;background:transparent;inset:unset;outline:none}:host([data-show]){display:flex}:host([common]:not([isfullscreen])) .container,:host([rounded]:not([isfullscreen])) .container{border-radius:var(--ds-border-radius, 0.375rem)}:host([common][isfullscreen]) .container,:host([rounded][isfullscreen]) .container{border-radius:unset;box-shadow:unset}.container{display:inline-block;overflow:auto;box-sizing:border-box;border-radius:var(--ds-border-radius, 0.375rem);margin:var(--ds-size-50, 0.25rem) 0}.util_displayHiddenVisually{position:absolute;overflow:hidden;width:1px;height:1px;padding:0;border:0;margin:-1px;clip-path:inset(50%);white-space:nowrap}`;
|
|
2900
2952
|
|
|
2901
2953
|
var colorCss$2 = css`.container{background-color:var(--ds-auro-dropdownbib-container-color);box-shadow:var(--ds-auro-dropdownbib-boxshadow-color);color:var(--ds-auro-dropdownbib-text-color)}`;
|
|
2902
2954
|
|
|
2903
2955
|
var tokensCss$1 = css`:host(:not([ondark])),:host(:not([appearance=inverse])){--ds-auro-dropdown-label-text-color: var(--ds-basic-color-texticon-muted, #676767);--ds-auro-dropdown-trigger-background-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-dropdown-trigger-hover-background-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-dropdown-trigger-container-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-dropdown-trigger-border-color: var(--ds-basic-color-border-bold, #585e67);--ds-auro-dropdown-trigger-outline-color: transparent;--ds-auro-dropdown-trigger-text-color: var(--ds-basic-color-texticon-default, #2a2a2a);--ds-auro-dropdownbib-boxshadow-color: var(--ds-elevation-200, 0px 0px 10px rgba(0, 0, 0, 0.15));--ds-auro-dropdownbib-background-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-dropdownbib-container-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-dropdownbib-text-color: var(--ds-basic-color-texticon-default, #2a2a2a)}:host([ondark]),:host([appearance=inverse]){--ds-auro-dropdown-label-text-color: var(--ds-basic-color-texticon-inverse-muted, #ccd2db);--ds-auro-dropdown-trigger-background-color: var(--ds-advanced-color-shared-background-inverse, rgba(255, 255, 255, 0.15));--ds-auro-dropdown-trigger-hover-background-color: var(--ds-advanced-color-shared-background-inverse, rgba(255, 255, 255, 0.15));--ds-auro-dropdown-trigger-container-color: var(--ds-advanced-color-shared-background-inverse, rgba(255, 255, 255, 0.15));--ds-auro-dropdown-trigger-border-color: var(--ds-basic-color-border-inverse, #ffffff);--ds-auro-dropdown-trigger-outline-color: transparent;--ds-auro-dropdown-trigger-text-color: var(--ds-basic-color-texticon-inverse, #ffffff);--ds-auro-dropdownbib-boxshadow-color: var(--ds-elevation-200, 0px 0px 10px rgba(0, 0, 0, 0.15));--ds-auro-dropdownbib-background-color: var(--ds-advanced-color-shared-background-inverse, rgba(255, 255, 255, 0.15));--ds-auro-dropdownbib-container-color: var(--ds-advanced-color-shared-background-inverse, rgba(255, 255, 255, 0.15));--ds-auro-dropdownbib-text-color: var(--ds-basic-color-texticon-inverse, #ffffff)}`;
|
|
2904
2956
|
|
|
2957
|
+
/**
|
|
2958
|
+
* Creates a keyboard strategy for dialog-specific key handling.
|
|
2959
|
+
* All other keydown behavior is left to the browser's native bubbling path.
|
|
2960
|
+
* @param {HTMLElement} bib - The dropdown bib element.
|
|
2961
|
+
* @returns {Object} Keyboard handlers keyed by `event.key`.
|
|
2962
|
+
*/
|
|
2963
|
+
// eslint-disable-next-line no-unused-vars
|
|
2964
|
+
function createDropdownBibKeyboardStrategy(bib) {
|
|
2965
|
+
return {
|
|
2966
|
+
// eslint-disable-next-line no-unused-vars
|
|
2967
|
+
Enter(_dialog, event) {
|
|
2968
|
+
// Floating UI handles Enter key to open the dropdown
|
|
2969
|
+
},
|
|
2970
|
+
// eslint-disable-next-line no-unused-vars
|
|
2971
|
+
Escape(_dialog, event) {
|
|
2972
|
+
// Floating UI handles Escape key to close the dropdown
|
|
2973
|
+
}
|
|
2974
|
+
};
|
|
2975
|
+
}
|
|
2976
|
+
|
|
2905
2977
|
// Copyright (c) 2020 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
|
|
2906
2978
|
// See LICENSE in the project root for license information.
|
|
2907
2979
|
/* eslint-disable max-lines */
|
|
@@ -3026,11 +3098,7 @@ class AuroDropdownBib extends LitElement {
|
|
|
3026
3098
|
},
|
|
3027
3099
|
|
|
3028
3100
|
/**
|
|
3029
|
-
*
|
|
3030
|
-
* aria-activedescendant. The dialog keyboard bridge checks this
|
|
3031
|
-
* flag so that Enter selects the highlighted option instead of
|
|
3032
|
-
* activating the focused interactive element (e.g. the trigger
|
|
3033
|
-
* button, or the bibtemplate close button in fullscreen).
|
|
3101
|
+
* Tracks whether a menu option is currently highlighted.
|
|
3034
3102
|
* @private
|
|
3035
3103
|
*/
|
|
3036
3104
|
hasActiveDescendant: {
|
|
@@ -3104,7 +3172,7 @@ class AuroDropdownBib extends LitElement {
|
|
|
3104
3172
|
|
|
3105
3173
|
const dialog = this.shadowRoot.querySelector('dialog');
|
|
3106
3174
|
this._setupCancelHandler(dialog);
|
|
3107
|
-
|
|
3175
|
+
applyKeyboardStrategy(dialog, createDropdownBibKeyboardStrategy());
|
|
3108
3176
|
|
|
3109
3177
|
this.dispatchEvent(new CustomEvent('auro-dropdownbib-connected', {
|
|
3110
3178
|
bubbles: true,
|
|
@@ -3131,92 +3199,6 @@ class AuroDropdownBib extends LitElement {
|
|
|
3131
3199
|
});
|
|
3132
3200
|
}
|
|
3133
3201
|
|
|
3134
|
-
/**
|
|
3135
|
-
* showModal() creates a closed focus scope — keyboard events inside
|
|
3136
|
-
* the dialog's shadow DOM do NOT bubble out to the combobox/select
|
|
3137
|
-
* keydown handlers in the parent shadow DOM. This handler bridges
|
|
3138
|
-
* that gap by re-dispatching navigation keys so they cross the
|
|
3139
|
-
* shadow boundary and reach the menu navigation logic in the parent
|
|
3140
|
-
* component.
|
|
3141
|
-
*
|
|
3142
|
-
* The trade-off: intercepting these keys means native keyboard
|
|
3143
|
-
* behaviors that would normally "just work" must be manually
|
|
3144
|
-
* re-implemented here:
|
|
3145
|
-
*
|
|
3146
|
-
* - Enter on buttons: Custom elements (auro-button) don't get the
|
|
3147
|
-
* native Enter→click that <button> provides, so we call .click()
|
|
3148
|
-
* directly when Enter is pressed on a button-like element.
|
|
3149
|
-
*
|
|
3150
|
-
* - Tab: Intercepted and re-dispatched so parent components
|
|
3151
|
-
* (select/combobox) can select the active option and close the
|
|
3152
|
-
* dialog. The <dialog> provides containment and isolation
|
|
3153
|
-
* (inert background, VoiceOver focus trapping, top layer), while
|
|
3154
|
-
* the content inside is a role="listbox" navigated via
|
|
3155
|
-
* aria-activedescendant (options are not focusable). Tab keyboard
|
|
3156
|
-
* behavior follows listbox conventions (select + close) because
|
|
3157
|
-
* the dialog's native Tab trap only cycles between the close
|
|
3158
|
-
* button and browser chrome.
|
|
3159
|
-
*
|
|
3160
|
-
* - Escape: The native <dialog> fires a `cancel` event on ESC
|
|
3161
|
-
* (handled by _setupCancelHandler), so the re-dispatched Escape
|
|
3162
|
-
* is a secondary path for parent components that also listen for
|
|
3163
|
-
* Escape keydown.
|
|
3164
|
-
*
|
|
3165
|
-
* @param {HTMLDialogElement} dialog - The dialog element to attach the keyboard bridge to.
|
|
3166
|
-
* @private
|
|
3167
|
-
*/
|
|
3168
|
-
_setupKeyboardBridge(dialog) {
|
|
3169
|
-
const navKeys = new Set([
|
|
3170
|
-
'ArrowUp',
|
|
3171
|
-
'ArrowDown',
|
|
3172
|
-
'Enter',
|
|
3173
|
-
'Escape',
|
|
3174
|
-
'Tab'
|
|
3175
|
-
]);
|
|
3176
|
-
|
|
3177
|
-
dialog.addEventListener('keydown', (event) => {
|
|
3178
|
-
if (!navKeys.has(event.key)) {
|
|
3179
|
-
return;
|
|
3180
|
-
}
|
|
3181
|
-
|
|
3182
|
-
// Custom elements (auro-button) don't get the native Enter→click
|
|
3183
|
-
// behavior that <button> has. Find the button in the composed path
|
|
3184
|
-
// and click it directly — but only when no menu option is
|
|
3185
|
-
// highlighted. In fullscreen mode focus stays on the close button
|
|
3186
|
-
// while arrow keys move the active-descendant highlight through
|
|
3187
|
-
// the listbox. If the user presses Enter with an option
|
|
3188
|
-
// highlighted, the intent is to select that option, not to click
|
|
3189
|
-
// the close button. In that case we fall through and bridge the
|
|
3190
|
-
// Enter key to the parent component's keyboard strategy.
|
|
3191
|
-
if (event.key === 'Enter') {
|
|
3192
|
-
if (!this.hasActiveDescendant) {
|
|
3193
|
-
const buttonSelector = 'button, [role="button"], auro-button, [auro-button]';
|
|
3194
|
-
const btn = event.composedPath().find((el) => el.matches && el.matches(buttonSelector));
|
|
3195
|
-
if (btn) {
|
|
3196
|
-
event.preventDefault();
|
|
3197
|
-
event.stopPropagation();
|
|
3198
|
-
btn.click();
|
|
3199
|
-
return;
|
|
3200
|
-
}
|
|
3201
|
-
}
|
|
3202
|
-
}
|
|
3203
|
-
|
|
3204
|
-
event.preventDefault();
|
|
3205
|
-
event.stopPropagation();
|
|
3206
|
-
const newEvent = new KeyboardEvent('keydown', {
|
|
3207
|
-
key: event.key,
|
|
3208
|
-
code: event.code,
|
|
3209
|
-
shiftKey: event.shiftKey,
|
|
3210
|
-
altKey: event.altKey,
|
|
3211
|
-
ctrlKey: event.ctrlKey,
|
|
3212
|
-
metaKey: event.metaKey,
|
|
3213
|
-
bubbles: true,
|
|
3214
|
-
composed: true,
|
|
3215
|
-
cancelable: true
|
|
3216
|
-
});
|
|
3217
|
-
this.dispatchEvent(newEvent);
|
|
3218
|
-
});
|
|
3219
|
-
}
|
|
3220
3202
|
|
|
3221
3203
|
/**
|
|
3222
3204
|
* Blocks touch-driven page scroll while a fullscreen modal dialog is open.
|
|
@@ -3591,7 +3573,7 @@ class AuroHelpText extends LitElement {
|
|
|
3591
3573
|
}
|
|
3592
3574
|
}
|
|
3593
3575
|
|
|
3594
|
-
var formkitVersion = '
|
|
3576
|
+
var formkitVersion = '202604021512';
|
|
3595
3577
|
|
|
3596
3578
|
class AuroElement extends LitElement {
|
|
3597
3579
|
static get properties() {
|
|
@@ -3772,7 +3754,6 @@ class AuroDropdown extends AuroElement {
|
|
|
3772
3754
|
this.appearance = 'default';
|
|
3773
3755
|
this.chevron = false;
|
|
3774
3756
|
this.disabled = false;
|
|
3775
|
-
this.disableFocusTrap = false;
|
|
3776
3757
|
this.error = false;
|
|
3777
3758
|
this.tabIndex = 0;
|
|
3778
3759
|
this.noToggle = false;
|
|
@@ -3870,9 +3851,8 @@ class AuroDropdown extends AuroElement {
|
|
|
3870
3851
|
// showModal() fires asynchronously via Lit's update cycle, which
|
|
3871
3852
|
// falls outside the user activation window and causes iOS to
|
|
3872
3853
|
// dismiss the keyboard.
|
|
3873
|
-
if (this.
|
|
3874
|
-
|
|
3875
|
-
this.bibElement.value.open(useModal);
|
|
3854
|
+
if (this.bibElement && this.bibElement.value) {
|
|
3855
|
+
this.bibElement.value.open(this.isBibFullscreen);
|
|
3876
3856
|
}
|
|
3877
3857
|
}
|
|
3878
3858
|
|
|
@@ -3985,14 +3965,6 @@ class AuroDropdown extends AuroElement {
|
|
|
3985
3965
|
reflect: true
|
|
3986
3966
|
},
|
|
3987
3967
|
|
|
3988
|
-
/**
|
|
3989
|
-
* If declared, the focus trap inside of bib will be turned off.
|
|
3990
|
-
*/
|
|
3991
|
-
disableFocusTrap: {
|
|
3992
|
-
type: Boolean,
|
|
3993
|
-
reflect: true
|
|
3994
|
-
},
|
|
3995
|
-
|
|
3996
3968
|
/**
|
|
3997
3969
|
* @private
|
|
3998
3970
|
*/
|
|
@@ -4266,7 +4238,7 @@ class AuroDropdown extends AuroElement {
|
|
|
4266
4238
|
if (this.isPopoverVisible) {
|
|
4267
4239
|
// Fullscreen: use showModal() for native accessibility (inert outside, focus trap)
|
|
4268
4240
|
// Desktop: use show() for Floating UI positioning + FocusTrap for focus management
|
|
4269
|
-
const useModal = this.isBibFullscreen
|
|
4241
|
+
const useModal = this.isBibFullscreen;
|
|
4270
4242
|
this.bibElement.value.open(useModal);
|
|
4271
4243
|
} else {
|
|
4272
4244
|
this.bibElement.value.close();
|
|
@@ -4276,7 +4248,7 @@ class AuroDropdown extends AuroElement {
|
|
|
4276
4248
|
// When fullscreen strategy changes while open, re-open dialog with correct mode
|
|
4277
4249
|
// (e.g. resizing from desktop → mobile while dropdown is open)
|
|
4278
4250
|
if (changedProperties.has('isBibFullscreen') && this.isPopoverVisible && this.bibElement.value) {
|
|
4279
|
-
const useModal = this.isBibFullscreen
|
|
4251
|
+
const useModal = this.isBibFullscreen;
|
|
4280
4252
|
this.bibElement.value.close();
|
|
4281
4253
|
this.bibElement.value.open(useModal);
|
|
4282
4254
|
}
|
|
@@ -4388,7 +4360,7 @@ class AuroDropdown extends AuroElement {
|
|
|
4388
4360
|
* @private
|
|
4389
4361
|
*/
|
|
4390
4362
|
updateFocusTrap() {
|
|
4391
|
-
if (this.isPopoverVisible
|
|
4363
|
+
if (this.isPopoverVisible) {
|
|
4392
4364
|
if (!this.isBibFullscreen) {
|
|
4393
4365
|
// Desktop: show() doesn't trap focus, so use FocusTrap
|
|
4394
4366
|
this.focusTrap = new FocusTrap(this.bibContent);
|
|
@@ -3,6 +3,8 @@ import { classMap } from 'lit/directives/class-map.js';
|
|
|
3
3
|
import { createRef, ref } from 'lit/directives/ref.js';
|
|
4
4
|
import { css, html, LitElement } from 'lit';
|
|
5
5
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
6
|
+
import 'lit-html';
|
|
7
|
+
import 'lit-html/directives/unsafe-html.js';
|
|
6
8
|
|
|
7
9
|
// Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
|
|
8
10
|
// See LICENSE in the project root for license information.
|
|
@@ -2053,11 +2055,10 @@ class AuroFloatingUI {
|
|
|
2053
2055
|
return;
|
|
2054
2056
|
}
|
|
2055
2057
|
|
|
2056
|
-
const { activeElement } = document;
|
|
2057
2058
|
// if focus is still inside of trigger or bib, do not close
|
|
2058
2059
|
if (
|
|
2059
|
-
this.element.
|
|
2060
|
-
this.element.
|
|
2060
|
+
this.element.matches(":focus") ||
|
|
2061
|
+
this.element.matches(":focus-within")
|
|
2061
2062
|
) {
|
|
2062
2063
|
return;
|
|
2063
2064
|
}
|
|
@@ -2896,12 +2897,83 @@ class p{registerComponent(t,a){customElements.get(t)||customElements.define(t,cl
|
|
|
2896
2897
|
|
|
2897
2898
|
var iconVersion = '9.1.2';
|
|
2898
2899
|
|
|
2900
|
+
/**
|
|
2901
|
+
* Computes display state once per keydown event.
|
|
2902
|
+
* Centralizes null-safety checks and makes the shared/modal/popover branching explicit.
|
|
2903
|
+
*
|
|
2904
|
+
* @param {HTMLElement} component - The component with a dropdown reference.
|
|
2905
|
+
* @param {Object} [options] - Optional config.
|
|
2906
|
+
* @param {HTMLElement} [options.dropdown] - Explicit dropdown reference. Falls back to component.dropdown.
|
|
2907
|
+
* @param {Function} [options.inputResolver] - Called with (component, ctx) to resolve the active input element.
|
|
2908
|
+
* @returns {{isExpanded: boolean, isModal: boolean, isPopover: boolean, activeInput: HTMLElement|null}}
|
|
2909
|
+
* isModal and isPopover reflect the display mode (fullscreen vs not) regardless of expanded state.
|
|
2910
|
+
*/
|
|
2911
|
+
function createDisplayContext(component, options = {}) {
|
|
2912
|
+
const dd = options.dropdown || component.dropdown;
|
|
2913
|
+
// isPopoverVisible reflects as the `open` attribute.
|
|
2914
|
+
// It reports whether the bib is open in any mode (popover or modal).
|
|
2915
|
+
const isExpanded = Boolean(dd && dd.isPopoverVisible);
|
|
2916
|
+
const isFullscreen = Boolean(dd && dd.isBibFullscreen);
|
|
2917
|
+
|
|
2918
|
+
const ctx = {
|
|
2919
|
+
isExpanded,
|
|
2920
|
+
isModal: isFullscreen,
|
|
2921
|
+
isPopover: !isFullscreen,
|
|
2922
|
+
activeInput: null,
|
|
2923
|
+
};
|
|
2924
|
+
|
|
2925
|
+
if (options.inputResolver) {
|
|
2926
|
+
const resolvedInput = options.inputResolver(component, ctx);
|
|
2927
|
+
// Guard against resolvers returning undefined or non-HTMLElement values.
|
|
2928
|
+
ctx.activeInput = resolvedInput instanceof HTMLElement ? resolvedInput : null;
|
|
2929
|
+
}
|
|
2930
|
+
|
|
2931
|
+
return ctx;
|
|
2932
|
+
}
|
|
2933
|
+
|
|
2934
|
+
/**
|
|
2935
|
+
* Wires up a keydown listener that dispatches to strategy[evt.key] or strategy.default.
|
|
2936
|
+
* Handles both sync and async handlers.
|
|
2937
|
+
* @param {HTMLElement} component - The component to attach the listener to.
|
|
2938
|
+
* @param {Object} strategy - Map of key names to handler functions.
|
|
2939
|
+
* @param {Object} [options] - Optional config passed to createDisplayContext.
|
|
2940
|
+
*/
|
|
2941
|
+
function applyKeyboardStrategy(component, strategy, options = {}) {
|
|
2942
|
+
component.addEventListener('keydown', async (evt) => {
|
|
2943
|
+
const handler = strategy[evt.key] || strategy.default;
|
|
2944
|
+
if (typeof handler === 'function') {
|
|
2945
|
+
const ctx = createDisplayContext(component, options);
|
|
2946
|
+
await handler(component, evt, ctx);
|
|
2947
|
+
}
|
|
2948
|
+
});
|
|
2949
|
+
}
|
|
2950
|
+
|
|
2899
2951
|
var styleCss$2 = css`:host{position:fixed;z-index:var(--depth-tooltip, 400);display:none;isolation:isolate}:host dialog{width:auto;max-width:none;height:auto;max-height:none;padding:0;border:none;margin:0;outline:none;transform:translateZ(0)}:host dialog::backdrop{background:transparent}:host(:not([isfullscreen])) dialog{position:relative;inset:unset}:host(:not([isfullscreen])) .container.shape-box{border-radius:unset}:host(:not([isfullscreen])) .container[class*=shape-pill],:host(:not([isfullscreen])) .container[class*=shape-snowflake]{border-radius:30px}:host(:not([isfullscreen])) .container[class*=shape-rounded]{border-radius:16px}:host(:not([matchWidth])) .container{min-width:fit-content}:host([isfullscreen]){position:fixed;top:0;left:0}:host([isfullscreen]) .container{width:100dvw;max-width:none;height:100dvh;max-height:none;border-radius:unset;margin-top:0;box-shadow:unset;overscroll-behavior:contain}:host([isfullscreen]) .container::backdrop{background:var(--ds-color-background-primary, #fff)}:host(:popover-open){position:fixed;overflow:visible;padding:0;border:none;margin:0;background:transparent;inset:unset;outline:none}:host([data-show]){display:flex}:host([common]:not([isfullscreen])) .container,:host([rounded]:not([isfullscreen])) .container{border-radius:var(--ds-border-radius, 0.375rem)}:host([common][isfullscreen]) .container,:host([rounded][isfullscreen]) .container{border-radius:unset;box-shadow:unset}.container{display:inline-block;overflow:auto;box-sizing:border-box;border-radius:var(--ds-border-radius, 0.375rem);margin:var(--ds-size-50, 0.25rem) 0}.util_displayHiddenVisually{position:absolute;overflow:hidden;width:1px;height:1px;padding:0;border:0;margin:-1px;clip-path:inset(50%);white-space:nowrap}`;
|
|
2900
2952
|
|
|
2901
2953
|
var colorCss$2 = css`.container{background-color:var(--ds-auro-dropdownbib-container-color);box-shadow:var(--ds-auro-dropdownbib-boxshadow-color);color:var(--ds-auro-dropdownbib-text-color)}`;
|
|
2902
2954
|
|
|
2903
2955
|
var tokensCss$1 = css`:host(:not([ondark])),:host(:not([appearance=inverse])){--ds-auro-dropdown-label-text-color: var(--ds-basic-color-texticon-muted, #676767);--ds-auro-dropdown-trigger-background-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-dropdown-trigger-hover-background-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-dropdown-trigger-container-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-dropdown-trigger-border-color: var(--ds-basic-color-border-bold, #585e67);--ds-auro-dropdown-trigger-outline-color: transparent;--ds-auro-dropdown-trigger-text-color: var(--ds-basic-color-texticon-default, #2a2a2a);--ds-auro-dropdownbib-boxshadow-color: var(--ds-elevation-200, 0px 0px 10px rgba(0, 0, 0, 0.15));--ds-auro-dropdownbib-background-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-dropdownbib-container-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-dropdownbib-text-color: var(--ds-basic-color-texticon-default, #2a2a2a)}:host([ondark]),:host([appearance=inverse]){--ds-auro-dropdown-label-text-color: var(--ds-basic-color-texticon-inverse-muted, #ccd2db);--ds-auro-dropdown-trigger-background-color: var(--ds-advanced-color-shared-background-inverse, rgba(255, 255, 255, 0.15));--ds-auro-dropdown-trigger-hover-background-color: var(--ds-advanced-color-shared-background-inverse, rgba(255, 255, 255, 0.15));--ds-auro-dropdown-trigger-container-color: var(--ds-advanced-color-shared-background-inverse, rgba(255, 255, 255, 0.15));--ds-auro-dropdown-trigger-border-color: var(--ds-basic-color-border-inverse, #ffffff);--ds-auro-dropdown-trigger-outline-color: transparent;--ds-auro-dropdown-trigger-text-color: var(--ds-basic-color-texticon-inverse, #ffffff);--ds-auro-dropdownbib-boxshadow-color: var(--ds-elevation-200, 0px 0px 10px rgba(0, 0, 0, 0.15));--ds-auro-dropdownbib-background-color: var(--ds-advanced-color-shared-background-inverse, rgba(255, 255, 255, 0.15));--ds-auro-dropdownbib-container-color: var(--ds-advanced-color-shared-background-inverse, rgba(255, 255, 255, 0.15));--ds-auro-dropdownbib-text-color: var(--ds-basic-color-texticon-inverse, #ffffff)}`;
|
|
2904
2956
|
|
|
2957
|
+
/**
|
|
2958
|
+
* Creates a keyboard strategy for dialog-specific key handling.
|
|
2959
|
+
* All other keydown behavior is left to the browser's native bubbling path.
|
|
2960
|
+
* @param {HTMLElement} bib - The dropdown bib element.
|
|
2961
|
+
* @returns {Object} Keyboard handlers keyed by `event.key`.
|
|
2962
|
+
*/
|
|
2963
|
+
// eslint-disable-next-line no-unused-vars
|
|
2964
|
+
function createDropdownBibKeyboardStrategy(bib) {
|
|
2965
|
+
return {
|
|
2966
|
+
// eslint-disable-next-line no-unused-vars
|
|
2967
|
+
Enter(_dialog, event) {
|
|
2968
|
+
// Floating UI handles Enter key to open the dropdown
|
|
2969
|
+
},
|
|
2970
|
+
// eslint-disable-next-line no-unused-vars
|
|
2971
|
+
Escape(_dialog, event) {
|
|
2972
|
+
// Floating UI handles Escape key to close the dropdown
|
|
2973
|
+
}
|
|
2974
|
+
};
|
|
2975
|
+
}
|
|
2976
|
+
|
|
2905
2977
|
// Copyright (c) 2020 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
|
|
2906
2978
|
// See LICENSE in the project root for license information.
|
|
2907
2979
|
/* eslint-disable max-lines */
|
|
@@ -3026,11 +3098,7 @@ class AuroDropdownBib extends LitElement {
|
|
|
3026
3098
|
},
|
|
3027
3099
|
|
|
3028
3100
|
/**
|
|
3029
|
-
*
|
|
3030
|
-
* aria-activedescendant. The dialog keyboard bridge checks this
|
|
3031
|
-
* flag so that Enter selects the highlighted option instead of
|
|
3032
|
-
* activating the focused interactive element (e.g. the trigger
|
|
3033
|
-
* button, or the bibtemplate close button in fullscreen).
|
|
3101
|
+
* Tracks whether a menu option is currently highlighted.
|
|
3034
3102
|
* @private
|
|
3035
3103
|
*/
|
|
3036
3104
|
hasActiveDescendant: {
|
|
@@ -3104,7 +3172,7 @@ class AuroDropdownBib extends LitElement {
|
|
|
3104
3172
|
|
|
3105
3173
|
const dialog = this.shadowRoot.querySelector('dialog');
|
|
3106
3174
|
this._setupCancelHandler(dialog);
|
|
3107
|
-
|
|
3175
|
+
applyKeyboardStrategy(dialog, createDropdownBibKeyboardStrategy());
|
|
3108
3176
|
|
|
3109
3177
|
this.dispatchEvent(new CustomEvent('auro-dropdownbib-connected', {
|
|
3110
3178
|
bubbles: true,
|
|
@@ -3131,92 +3199,6 @@ class AuroDropdownBib extends LitElement {
|
|
|
3131
3199
|
});
|
|
3132
3200
|
}
|
|
3133
3201
|
|
|
3134
|
-
/**
|
|
3135
|
-
* showModal() creates a closed focus scope — keyboard events inside
|
|
3136
|
-
* the dialog's shadow DOM do NOT bubble out to the combobox/select
|
|
3137
|
-
* keydown handlers in the parent shadow DOM. This handler bridges
|
|
3138
|
-
* that gap by re-dispatching navigation keys so they cross the
|
|
3139
|
-
* shadow boundary and reach the menu navigation logic in the parent
|
|
3140
|
-
* component.
|
|
3141
|
-
*
|
|
3142
|
-
* The trade-off: intercepting these keys means native keyboard
|
|
3143
|
-
* behaviors that would normally "just work" must be manually
|
|
3144
|
-
* re-implemented here:
|
|
3145
|
-
*
|
|
3146
|
-
* - Enter on buttons: Custom elements (auro-button) don't get the
|
|
3147
|
-
* native Enter→click that <button> provides, so we call .click()
|
|
3148
|
-
* directly when Enter is pressed on a button-like element.
|
|
3149
|
-
*
|
|
3150
|
-
* - Tab: Intercepted and re-dispatched so parent components
|
|
3151
|
-
* (select/combobox) can select the active option and close the
|
|
3152
|
-
* dialog. The <dialog> provides containment and isolation
|
|
3153
|
-
* (inert background, VoiceOver focus trapping, top layer), while
|
|
3154
|
-
* the content inside is a role="listbox" navigated via
|
|
3155
|
-
* aria-activedescendant (options are not focusable). Tab keyboard
|
|
3156
|
-
* behavior follows listbox conventions (select + close) because
|
|
3157
|
-
* the dialog's native Tab trap only cycles between the close
|
|
3158
|
-
* button and browser chrome.
|
|
3159
|
-
*
|
|
3160
|
-
* - Escape: The native <dialog> fires a `cancel` event on ESC
|
|
3161
|
-
* (handled by _setupCancelHandler), so the re-dispatched Escape
|
|
3162
|
-
* is a secondary path for parent components that also listen for
|
|
3163
|
-
* Escape keydown.
|
|
3164
|
-
*
|
|
3165
|
-
* @param {HTMLDialogElement} dialog - The dialog element to attach the keyboard bridge to.
|
|
3166
|
-
* @private
|
|
3167
|
-
*/
|
|
3168
|
-
_setupKeyboardBridge(dialog) {
|
|
3169
|
-
const navKeys = new Set([
|
|
3170
|
-
'ArrowUp',
|
|
3171
|
-
'ArrowDown',
|
|
3172
|
-
'Enter',
|
|
3173
|
-
'Escape',
|
|
3174
|
-
'Tab'
|
|
3175
|
-
]);
|
|
3176
|
-
|
|
3177
|
-
dialog.addEventListener('keydown', (event) => {
|
|
3178
|
-
if (!navKeys.has(event.key)) {
|
|
3179
|
-
return;
|
|
3180
|
-
}
|
|
3181
|
-
|
|
3182
|
-
// Custom elements (auro-button) don't get the native Enter→click
|
|
3183
|
-
// behavior that <button> has. Find the button in the composed path
|
|
3184
|
-
// and click it directly — but only when no menu option is
|
|
3185
|
-
// highlighted. In fullscreen mode focus stays on the close button
|
|
3186
|
-
// while arrow keys move the active-descendant highlight through
|
|
3187
|
-
// the listbox. If the user presses Enter with an option
|
|
3188
|
-
// highlighted, the intent is to select that option, not to click
|
|
3189
|
-
// the close button. In that case we fall through and bridge the
|
|
3190
|
-
// Enter key to the parent component's keyboard strategy.
|
|
3191
|
-
if (event.key === 'Enter') {
|
|
3192
|
-
if (!this.hasActiveDescendant) {
|
|
3193
|
-
const buttonSelector = 'button, [role="button"], auro-button, [auro-button]';
|
|
3194
|
-
const btn = event.composedPath().find((el) => el.matches && el.matches(buttonSelector));
|
|
3195
|
-
if (btn) {
|
|
3196
|
-
event.preventDefault();
|
|
3197
|
-
event.stopPropagation();
|
|
3198
|
-
btn.click();
|
|
3199
|
-
return;
|
|
3200
|
-
}
|
|
3201
|
-
}
|
|
3202
|
-
}
|
|
3203
|
-
|
|
3204
|
-
event.preventDefault();
|
|
3205
|
-
event.stopPropagation();
|
|
3206
|
-
const newEvent = new KeyboardEvent('keydown', {
|
|
3207
|
-
key: event.key,
|
|
3208
|
-
code: event.code,
|
|
3209
|
-
shiftKey: event.shiftKey,
|
|
3210
|
-
altKey: event.altKey,
|
|
3211
|
-
ctrlKey: event.ctrlKey,
|
|
3212
|
-
metaKey: event.metaKey,
|
|
3213
|
-
bubbles: true,
|
|
3214
|
-
composed: true,
|
|
3215
|
-
cancelable: true
|
|
3216
|
-
});
|
|
3217
|
-
this.dispatchEvent(newEvent);
|
|
3218
|
-
});
|
|
3219
|
-
}
|
|
3220
3202
|
|
|
3221
3203
|
/**
|
|
3222
3204
|
* Blocks touch-driven page scroll while a fullscreen modal dialog is open.
|
|
@@ -3591,7 +3573,7 @@ class AuroHelpText extends LitElement {
|
|
|
3591
3573
|
}
|
|
3592
3574
|
}
|
|
3593
3575
|
|
|
3594
|
-
var formkitVersion = '
|
|
3576
|
+
var formkitVersion = '202604021512';
|
|
3595
3577
|
|
|
3596
3578
|
class AuroElement extends LitElement {
|
|
3597
3579
|
static get properties() {
|
|
@@ -3772,7 +3754,6 @@ class AuroDropdown extends AuroElement {
|
|
|
3772
3754
|
this.appearance = 'default';
|
|
3773
3755
|
this.chevron = false;
|
|
3774
3756
|
this.disabled = false;
|
|
3775
|
-
this.disableFocusTrap = false;
|
|
3776
3757
|
this.error = false;
|
|
3777
3758
|
this.tabIndex = 0;
|
|
3778
3759
|
this.noToggle = false;
|
|
@@ -3870,9 +3851,8 @@ class AuroDropdown extends AuroElement {
|
|
|
3870
3851
|
// showModal() fires asynchronously via Lit's update cycle, which
|
|
3871
3852
|
// falls outside the user activation window and causes iOS to
|
|
3872
3853
|
// dismiss the keyboard.
|
|
3873
|
-
if (this.
|
|
3874
|
-
|
|
3875
|
-
this.bibElement.value.open(useModal);
|
|
3854
|
+
if (this.bibElement && this.bibElement.value) {
|
|
3855
|
+
this.bibElement.value.open(this.isBibFullscreen);
|
|
3876
3856
|
}
|
|
3877
3857
|
}
|
|
3878
3858
|
|
|
@@ -3985,14 +3965,6 @@ class AuroDropdown extends AuroElement {
|
|
|
3985
3965
|
reflect: true
|
|
3986
3966
|
},
|
|
3987
3967
|
|
|
3988
|
-
/**
|
|
3989
|
-
* If declared, the focus trap inside of bib will be turned off.
|
|
3990
|
-
*/
|
|
3991
|
-
disableFocusTrap: {
|
|
3992
|
-
type: Boolean,
|
|
3993
|
-
reflect: true
|
|
3994
|
-
},
|
|
3995
|
-
|
|
3996
3968
|
/**
|
|
3997
3969
|
* @private
|
|
3998
3970
|
*/
|
|
@@ -4266,7 +4238,7 @@ class AuroDropdown extends AuroElement {
|
|
|
4266
4238
|
if (this.isPopoverVisible) {
|
|
4267
4239
|
// Fullscreen: use showModal() for native accessibility (inert outside, focus trap)
|
|
4268
4240
|
// Desktop: use show() for Floating UI positioning + FocusTrap for focus management
|
|
4269
|
-
const useModal = this.isBibFullscreen
|
|
4241
|
+
const useModal = this.isBibFullscreen;
|
|
4270
4242
|
this.bibElement.value.open(useModal);
|
|
4271
4243
|
} else {
|
|
4272
4244
|
this.bibElement.value.close();
|
|
@@ -4276,7 +4248,7 @@ class AuroDropdown extends AuroElement {
|
|
|
4276
4248
|
// When fullscreen strategy changes while open, re-open dialog with correct mode
|
|
4277
4249
|
// (e.g. resizing from desktop → mobile while dropdown is open)
|
|
4278
4250
|
if (changedProperties.has('isBibFullscreen') && this.isPopoverVisible && this.bibElement.value) {
|
|
4279
|
-
const useModal = this.isBibFullscreen
|
|
4251
|
+
const useModal = this.isBibFullscreen;
|
|
4280
4252
|
this.bibElement.value.close();
|
|
4281
4253
|
this.bibElement.value.open(useModal);
|
|
4282
4254
|
}
|
|
@@ -4388,7 +4360,7 @@ class AuroDropdown extends AuroElement {
|
|
|
4388
4360
|
* @private
|
|
4389
4361
|
*/
|
|
4390
4362
|
updateFocusTrap() {
|
|
4391
|
-
if (this.isPopoverVisible
|
|
4363
|
+
if (this.isPopoverVisible) {
|
|
4392
4364
|
if (!this.isBibFullscreen) {
|
|
4393
4365
|
// Desktop: show() doesn't trap focus, so use FocusTrap
|
|
4394
4366
|
this.focusTrap = new FocusTrap(this.bibContent);
|