@aurodesignsystem-dev/auro-formkit 0.0.0-pr1346.3 → 0.0.0-pr1346.4
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/dist/index.js +1 -1
- package/components/checkbox/dist/registered.js +1 -1
- package/components/combobox/demo/api.min.js +224 -45
- package/components/combobox/demo/index.min.js +224 -45
- package/components/combobox/dist/auro-combobox.d.ts +2 -1
- package/components/combobox/dist/index.js +217 -42
- package/components/combobox/dist/registered.js +217 -42
- package/components/counter/demo/api.min.js +123 -11
- package/components/counter/demo/index.min.js +123 -11
- package/components/counter/dist/index.js +123 -11
- package/components/counter/dist/registered.js +123 -11
- package/components/datepicker/demo/api.min.js +133 -20
- package/components/datepicker/demo/index.min.js +133 -20
- package/components/datepicker/dist/index.js +133 -20
- package/components/datepicker/dist/registered.js +133 -20
- package/components/dropdown/demo/api.min.js +122 -10
- package/components/dropdown/demo/index.min.js +122 -10
- package/components/dropdown/dist/auro-dropdownBib.d.ts +18 -2
- package/components/dropdown/dist/index.js +122 -10
- package/components/dropdown/dist/registered.js +122 -10
- package/components/input/demo/api.min.js +10 -9
- package/components/input/demo/index.min.js +10 -9
- package/components/input/dist/index.js +10 -9
- package/components/input/dist/registered.js +10 -9
- package/components/menu/demo/api.min.js +7 -3
- package/components/menu/demo/index.min.js +7 -3
- package/components/menu/dist/index.js +7 -3
- package/components/menu/dist/registered.js +7 -3
- 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 +159 -17
- package/components/select/demo/index.min.js +159 -17
- package/components/select/dist/index.js +152 -14
- package/components/select/dist/registered.js +152 -14
- package/custom-elements.json +35 -10
- package/package.json +1 -1
|
@@ -3873,7 +3873,7 @@ let p$4 = class p{registerComponent(t,a){customElements.get(t)||customElements.d
|
|
|
3873
3873
|
|
|
3874
3874
|
var iconVersion$3 = '9.1.2';
|
|
3875
3875
|
|
|
3876
|
-
var styleCss$2$1 = i$7`:host{position:fixed;z-index:var(--depth-tooltip, 400);display:none;isolation:isolate}:host dialog{max-width:none;max-height:none;padding:0;border:none;margin:0;outline:none;transform:translateZ(0)}:host dialog::backdrop{background:transparent}:host(:not([isfullscreen])) dialog{position:absolute;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([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}`;
|
|
3876
|
+
var styleCss$2$1 = i$7`:host{position:fixed;z-index:var(--depth-tooltip, 400);display:none;isolation:isolate}:host dialog{max-width:none;max-height:none;padding:0;border:none;margin:0;outline:none;transform:translateZ(0)}:host dialog::backdrop{background:transparent}:host(:not([isfullscreen])) dialog{position:absolute;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([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}`;
|
|
3877
3877
|
|
|
3878
3878
|
var colorCss$2$1 = i$7`.container{background-color:var(--ds-auro-dropdownbib-container-color);box-shadow:var(--ds-auro-dropdownbib-boxshadow-color);color:var(--ds-auro-dropdownbib-text-color)}`;
|
|
3879
3879
|
|
|
@@ -3881,6 +3881,8 @@ var tokensCss$1$2 = i$7`:host(:not([ondark])),:host(:not([appearance=inverse])){
|
|
|
3881
3881
|
|
|
3882
3882
|
// Copyright (c) 2020 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
|
|
3883
3883
|
// See LICENSE in the project root for license information.
|
|
3884
|
+
/* eslint-disable max-lines */
|
|
3885
|
+
// ---------------------------------------------------------------------
|
|
3884
3886
|
|
|
3885
3887
|
|
|
3886
3888
|
const DESIGN_TOKEN_BREAKPOINT_PREFIX = '--ds-grid-breakpoint-';
|
|
@@ -4056,22 +4058,63 @@ class AuroDropdownBib extends i$4 {
|
|
|
4056
4058
|
// Handle ESC key via dialog's cancel event
|
|
4057
4059
|
const dialog = this.shadowRoot.querySelector('dialog');
|
|
4058
4060
|
dialog.addEventListener('cancel', (event) => {
|
|
4059
|
-
|
|
4061
|
+
// Let parent handle closing
|
|
4062
|
+
event.preventDefault();
|
|
4060
4063
|
this.dispatchEvent(new CustomEvent('auro-bib-cancel', {
|
|
4061
4064
|
bubbles: true,
|
|
4062
4065
|
composed: true
|
|
4063
4066
|
}));
|
|
4064
4067
|
});
|
|
4065
4068
|
|
|
4066
|
-
//
|
|
4067
|
-
//
|
|
4068
|
-
//
|
|
4069
|
-
//
|
|
4070
|
-
|
|
4069
|
+
// showModal() creates a closed focus scope — keyboard events inside
|
|
4070
|
+
// the dialog's shadow DOM do NOT bubble out to the combobox/select
|
|
4071
|
+
// keydown handlers in the parent shadow DOM. This handler bridges
|
|
4072
|
+
// that gap by re-dispatching navigation keys so they cross the
|
|
4073
|
+
// shadow boundary and reach the menu navigation logic in the parent
|
|
4074
|
+
// component.
|
|
4075
|
+
//
|
|
4076
|
+
// The trade-off: intercepting these keys means native keyboard
|
|
4077
|
+
// behaviors that would normally "just work" must be manually
|
|
4078
|
+
// re-implemented here:
|
|
4079
|
+
//
|
|
4080
|
+
// - Enter on buttons: Custom elements (auro-button) don't get the
|
|
4081
|
+
// native Enter→click that <button> provides, so we call .click()
|
|
4082
|
+
// directly when Enter is pressed on a button-like element.
|
|
4083
|
+
//
|
|
4084
|
+
// - Tab: NOT intercepted — left to the browser's native focus trap
|
|
4085
|
+
// provided by showModal(), which cycles Tab between focusable
|
|
4086
|
+
// elements inside the dialog (e.g. the input and close button).
|
|
4087
|
+
// Intercepting Tab would kill the native focus trap and break
|
|
4088
|
+
// focus management inside the dialog.
|
|
4089
|
+
//
|
|
4090
|
+
// - Escape: The native <dialog> fires a `cancel` event on ESC
|
|
4091
|
+
// (handled above), so the re-dispatched Escape is a secondary
|
|
4092
|
+
// path for parent components that also listen for Escape keydown.
|
|
4093
|
+
const navKeys = new Set([
|
|
4094
|
+
'ArrowUp',
|
|
4095
|
+
'ArrowDown',
|
|
4096
|
+
'Enter',
|
|
4097
|
+
'Escape'
|
|
4098
|
+
]);
|
|
4071
4099
|
dialog.addEventListener('keydown', (event) => {
|
|
4072
4100
|
if (!navKeys.has(event.key)) {
|
|
4073
4101
|
return;
|
|
4074
4102
|
}
|
|
4103
|
+
|
|
4104
|
+
// Custom elements (auro-button) don't get the native Enter→click
|
|
4105
|
+
// behavior that <button> has. Find the button in the composed path
|
|
4106
|
+
// and click it directly.
|
|
4107
|
+
if (event.key === 'Enter') {
|
|
4108
|
+
const buttonSelector = 'button, [role="button"], auro-button, [auro-button]';
|
|
4109
|
+
const btn = event.composedPath().find((el) => el.matches && el.matches(buttonSelector));
|
|
4110
|
+
if (btn) {
|
|
4111
|
+
event.preventDefault();
|
|
4112
|
+
event.stopPropagation();
|
|
4113
|
+
btn.click();
|
|
4114
|
+
return;
|
|
4115
|
+
}
|
|
4116
|
+
}
|
|
4117
|
+
|
|
4075
4118
|
event.preventDefault();
|
|
4076
4119
|
event.stopPropagation();
|
|
4077
4120
|
const newEvent = new KeyboardEvent('keydown', {
|
|
@@ -4095,9 +4138,55 @@ class AuroDropdownBib extends i$4 {
|
|
|
4095
4138
|
}
|
|
4096
4139
|
|
|
4097
4140
|
/**
|
|
4098
|
-
*
|
|
4099
|
-
*
|
|
4141
|
+
* Blocks touch-driven page scroll while a fullscreen modal dialog is open.
|
|
4142
|
+
*
|
|
4143
|
+
* The showModal() function places the dialog in the browser's **top layer**,
|
|
4144
|
+
* which is a separate rendering layer above the normal DOM. On mobile, the
|
|
4145
|
+
* compositor processes visual-viewport panning before top-layer touch
|
|
4146
|
+
* handling. This means the entire viewport — including the top-layer dialog
|
|
4147
|
+
* — can be panned by a touch gesture, causing the page behind the dialog to
|
|
4148
|
+
* scroll into view. To prevent this, we add a touchmove listener that cancels
|
|
4149
|
+
* the event if the touch started outside the dialog or any scrollable child within it.
|
|
4150
|
+
*
|
|
4151
|
+
* @private
|
|
4152
|
+
*/
|
|
4153
|
+
_lockTouchScroll() {
|
|
4154
|
+
const dialog = this.shadowRoot.querySelector('dialog');
|
|
4155
|
+
|
|
4156
|
+
this._touchMoveHandler = (event) => {
|
|
4157
|
+
// Walk the composed path (which crosses shadow DOM boundaries) to
|
|
4158
|
+
// check whether the touch started inside a scrollable element that
|
|
4159
|
+
// lives within the dialog. If so, allow the scroll.
|
|
4160
|
+
for (const el of event.composedPath()) {
|
|
4161
|
+
if (el === dialog) {
|
|
4162
|
+
// Reached the dialog boundary without finding a scrollable child.
|
|
4163
|
+
break;
|
|
4164
|
+
}
|
|
4165
|
+
if (el instanceof HTMLElement && el.scrollHeight > el.clientHeight) {
|
|
4166
|
+
const { overflowY } = getComputedStyle(el);
|
|
4167
|
+
if (overflowY === 'auto' || overflowY === 'scroll') {
|
|
4168
|
+
return;
|
|
4169
|
+
}
|
|
4170
|
+
}
|
|
4171
|
+
}
|
|
4172
|
+
|
|
4173
|
+
event.preventDefault();
|
|
4174
|
+
};
|
|
4175
|
+
|
|
4176
|
+
document.addEventListener('touchmove', this._touchMoveHandler, { passive: false });
|
|
4177
|
+
}
|
|
4178
|
+
|
|
4179
|
+
/**
|
|
4180
|
+
* Removes the touchmove listener added by _lockTouchScroll().
|
|
4181
|
+
* @private
|
|
4100
4182
|
*/
|
|
4183
|
+
_unlockTouchScroll() {
|
|
4184
|
+
if (this._touchMoveHandler) {
|
|
4185
|
+
document.removeEventListener('touchmove', this._touchMoveHandler);
|
|
4186
|
+
this._touchMoveHandler = undefined;
|
|
4187
|
+
}
|
|
4188
|
+
}
|
|
4189
|
+
|
|
4101
4190
|
open(modal = true) {
|
|
4102
4191
|
const dialog = this.shadowRoot.querySelector('dialog');
|
|
4103
4192
|
if (dialog && !dialog.open) {
|
|
@@ -4114,6 +4203,8 @@ class AuroDropdownBib extends i$4 {
|
|
|
4114
4203
|
|
|
4115
4204
|
documentElement.style.overflow = prevOverflow;
|
|
4116
4205
|
|
|
4206
|
+
this._lockTouchScroll();
|
|
4207
|
+
|
|
4117
4208
|
} else {
|
|
4118
4209
|
// Use setAttribute instead of dialog.show() to avoid the dialog
|
|
4119
4210
|
// focusing steps which steal focus from the trigger and cause
|
|
@@ -4129,6 +4220,7 @@ class AuroDropdownBib extends i$4 {
|
|
|
4129
4220
|
close() {
|
|
4130
4221
|
const dialog = this.shadowRoot.querySelector('dialog');
|
|
4131
4222
|
if (dialog && dialog.open) {
|
|
4223
|
+
this._unlockTouchScroll();
|
|
4132
4224
|
dialog.close();
|
|
4133
4225
|
}
|
|
4134
4226
|
}
|
|
@@ -4394,7 +4486,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$4 {
|
|
|
4394
4486
|
}
|
|
4395
4487
|
};
|
|
4396
4488
|
|
|
4397
|
-
var formkitVersion$2 = '
|
|
4489
|
+
var formkitVersion$2 = '202602260152';
|
|
4398
4490
|
|
|
4399
4491
|
let AuroElement$2 = class AuroElement extends i$4 {
|
|
4400
4492
|
static get properties() {
|
|
@@ -4667,6 +4759,18 @@ class AuroDropdown extends AuroElement$2 {
|
|
|
4667
4759
|
*/
|
|
4668
4760
|
show() {
|
|
4669
4761
|
this.floater.showBib();
|
|
4762
|
+
|
|
4763
|
+
// Open dialog synchronously so callers remain in the user gesture
|
|
4764
|
+
// chain. This is critical for mobile browsers (iOS Safari) to keep
|
|
4765
|
+
// the virtual keyboard open when transitioning from the trigger
|
|
4766
|
+
// input to an input inside the fullscreen dialog. Without this,
|
|
4767
|
+
// showModal() fires asynchronously via Lit's update cycle, which
|
|
4768
|
+
// falls outside the user activation window and causes iOS to
|
|
4769
|
+
// dismiss the keyboard.
|
|
4770
|
+
if (this.isBibFullscreen && this.bibElement && this.bibElement.value) {
|
|
4771
|
+
const useModal = !this.disableFocusTrap;
|
|
4772
|
+
this.bibElement.value.open(useModal);
|
|
4773
|
+
}
|
|
4670
4774
|
}
|
|
4671
4775
|
|
|
4672
4776
|
/**
|
|
@@ -5053,6 +5157,14 @@ class AuroDropdown extends AuroElement$2 {
|
|
|
5053
5157
|
this.bibElement.value.close();
|
|
5054
5158
|
}
|
|
5055
5159
|
}
|
|
5160
|
+
|
|
5161
|
+
// When fullscreen strategy changes while open, re-open dialog with correct mode
|
|
5162
|
+
// (e.g. resizing from desktop → mobile while dropdown is open)
|
|
5163
|
+
if (changedProperties.has('isBibFullscreen') && this.isPopoverVisible && this.bibElement.value) {
|
|
5164
|
+
const useModal = this.isBibFullscreen && !this.disableFocusTrap;
|
|
5165
|
+
this.bibElement.value.close();
|
|
5166
|
+
this.bibElement.value.open(useModal);
|
|
5167
|
+
}
|
|
5056
5168
|
}
|
|
5057
5169
|
|
|
5058
5170
|
/**
|
|
@@ -10554,6 +10666,15 @@ class BaseInput extends AuroElement$1 {
|
|
|
10554
10666
|
constructor() {
|
|
10555
10667
|
super();
|
|
10556
10668
|
|
|
10669
|
+
// Delegate focus to the native <input> inside the shadow root so that
|
|
10670
|
+
// showModal()'s dialog focusing steps reach the input element.
|
|
10671
|
+
// This keeps the mobile virtual keyboard open when the fullscreen dialog
|
|
10672
|
+
// opens, because the browser sees an input-to-input focus transfer.
|
|
10673
|
+
this.constructor.shadowRootOptions = {
|
|
10674
|
+
...AuroElement$1.shadowRootOptions,
|
|
10675
|
+
delegatesFocus: true,
|
|
10676
|
+
};
|
|
10677
|
+
|
|
10557
10678
|
this._initializeDefaults();
|
|
10558
10679
|
}
|
|
10559
10680
|
|
|
@@ -10675,14 +10796,6 @@ class BaseInput extends AuroElement$1 {
|
|
|
10675
10796
|
reflect: true
|
|
10676
10797
|
},
|
|
10677
10798
|
|
|
10678
|
-
/**
|
|
10679
|
-
* The value for the aria-controls attribute.
|
|
10680
|
-
*/
|
|
10681
|
-
a11yControls: {
|
|
10682
|
-
type: String,
|
|
10683
|
-
reflect: true
|
|
10684
|
-
},
|
|
10685
|
-
|
|
10686
10799
|
/**
|
|
10687
10800
|
* The value for the aria-activedescendant attribute.
|
|
10688
10801
|
* Points to the ID of the currently active/highlighted option in a listbox.
|
|
@@ -12102,7 +12215,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$4 {
|
|
|
12102
12215
|
}
|
|
12103
12216
|
};
|
|
12104
12217
|
|
|
12105
|
-
var formkitVersion$1 = '
|
|
12218
|
+
var formkitVersion$1 = '202602260152';
|
|
12106
12219
|
|
|
12107
12220
|
// Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
|
|
12108
12221
|
// See LICENSE in the project root for license information.
|
|
@@ -13129,7 +13242,7 @@ class AuroBibtemplate extends i$4 {
|
|
|
13129
13242
|
}
|
|
13130
13243
|
}
|
|
13131
13244
|
|
|
13132
|
-
var formkitVersion = '
|
|
13245
|
+
var formkitVersion = '202602260152';
|
|
13133
13246
|
|
|
13134
13247
|
var styleCss$3 = i$7`.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock{display:block}.util_displayFlex{display:flex}.util_displayHidden{display:none}.util_displayHiddenVisually{position:absolute;overflow:hidden;clip:rect(1px, 1px, 1px, 1px);width:1px;height:1px;padding:0;border:0}:host{display:block;text-align:left}:host [auro-dropdown]{--ds-auro-dropdown-trigger-background-color: transparent}:host #inputInBib::part(wrapper){box-shadow:none}:host #inputInBib::part(accent-left){display:none}:host([layout*=classic]) [auro-input]{width:100%}:host([layout*=classic]) [auro-input]::part(helpText){display:none}:host([layout*=classic]) #slotHolder{display:none}`;
|
|
13135
13248
|
|
|
@@ -13547,6 +13660,7 @@ class AuroCombobox extends AuroElement {
|
|
|
13547
13660
|
this.dropdownOpen = false;
|
|
13548
13661
|
this.triggerExpandedState = false;
|
|
13549
13662
|
this._expandedTimeout = null;
|
|
13663
|
+
this._inFullscreenTransition = false;
|
|
13550
13664
|
this.errorMessage = null;
|
|
13551
13665
|
this.isHiddenWhileLoading = false;
|
|
13552
13666
|
this.largeFullscreenHeadline = false;
|
|
@@ -13567,7 +13681,7 @@ class AuroCombobox extends AuroElement {
|
|
|
13567
13681
|
|
|
13568
13682
|
/**
|
|
13569
13683
|
* Defines whether the component will be on lighter or darker backgrounds.
|
|
13570
|
-
* @property {'default' | 'inverse'}
|
|
13684
|
+
* @property {'default' | 'inverse'} appearance - The visual appearance of the component.
|
|
13571
13685
|
* @default 'default'
|
|
13572
13686
|
*/
|
|
13573
13687
|
appearance: {
|
|
@@ -14122,7 +14236,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14122
14236
|
* @returns {void}
|
|
14123
14237
|
*/
|
|
14124
14238
|
showBib() {
|
|
14125
|
-
if (!this.input.value) {
|
|
14239
|
+
if (!this.input.value && !this.dropdown.isBibFullscreen) {
|
|
14126
14240
|
this.dropdown.hide();
|
|
14127
14241
|
return;
|
|
14128
14242
|
}
|
|
@@ -14191,6 +14305,18 @@ class AuroCombobox extends AuroElement {
|
|
|
14191
14305
|
|
|
14192
14306
|
// Restore trigger accessibility when closing fullscreen
|
|
14193
14307
|
this.dropdown.trigger.inert = false;
|
|
14308
|
+
|
|
14309
|
+
// Restore focus to the trigger input after closing the
|
|
14310
|
+
// fullscreen dialog. The browser's native dialog focus restoration
|
|
14311
|
+
// fails because the trigger was set to inert before showModal().
|
|
14312
|
+
// Use rAF to run after Lit's microtask update cycle calls dialog.close().
|
|
14313
|
+
if (this.dropdown.isBibFullscreen) {
|
|
14314
|
+
requestAnimationFrame(() => {
|
|
14315
|
+
if (!this.dropdown.isPopoverVisible) {
|
|
14316
|
+
this.input.focus();
|
|
14317
|
+
}
|
|
14318
|
+
});
|
|
14319
|
+
}
|
|
14194
14320
|
}
|
|
14195
14321
|
|
|
14196
14322
|
if (this.dropdownOpen) {
|
|
@@ -14200,6 +14326,19 @@ class AuroCombobox extends AuroElement {
|
|
|
14200
14326
|
this.updateBibDialogRole();
|
|
14201
14327
|
|
|
14202
14328
|
if (this.dropdown.isBibFullscreen) {
|
|
14329
|
+
// Guard against spurious validation during the focus transition
|
|
14330
|
+
// from trigger to bib input. Setting trigger.inert = true removes
|
|
14331
|
+
// focus, which fires focusout on the child auro-input before the
|
|
14332
|
+
// bib input receives focus. That focusout triggers the input's own
|
|
14333
|
+
// validate(), which dispatches a composed auroFormElement-validated
|
|
14334
|
+
// event. Because composed events are retargetted at each shadow DOM
|
|
14335
|
+
// boundary, the event appears to originate from the combobox itself
|
|
14336
|
+
// and its listener unconditionally sets this.validity — causing
|
|
14337
|
+
// premature validation. This flag suppresses all validation paths
|
|
14338
|
+
// (focusout handler, handleInputValueChange, validate(), and the
|
|
14339
|
+
// auroFormElement-validated listener) until focus settles in the bib.
|
|
14340
|
+
this._inFullscreenTransition = true;
|
|
14341
|
+
|
|
14203
14342
|
// Hide the trigger from assistive technology so VoiceOver cannot reach it
|
|
14204
14343
|
// behind the fullscreen dialog
|
|
14205
14344
|
this.dropdown.trigger.inert = true;
|
|
@@ -14231,6 +14370,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14231
14370
|
requestAnimationFrame(() => {
|
|
14232
14371
|
requestAnimationFrame(() => {
|
|
14233
14372
|
this.setInputFocus();
|
|
14373
|
+
this._inFullscreenTransition = false;
|
|
14234
14374
|
});
|
|
14235
14375
|
});
|
|
14236
14376
|
} else {
|
|
@@ -14325,7 +14465,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14325
14465
|
* @private
|
|
14326
14466
|
*/
|
|
14327
14467
|
updateBibDialogRole() {
|
|
14328
|
-
const bibEl = this.dropdown.bibElement
|
|
14468
|
+
const bibEl = this.dropdown.bibElement && this.dropdown.bibElement.value;
|
|
14329
14469
|
if (!bibEl) {
|
|
14330
14470
|
return;
|
|
14331
14471
|
}
|
|
@@ -14454,9 +14594,10 @@ class AuroCombobox extends AuroElement {
|
|
|
14454
14594
|
// Announce the selection after the dropdown closes so it isn't
|
|
14455
14595
|
// overridden by VoiceOver's "collapsed" announcement from aria-expanded.
|
|
14456
14596
|
const selectedValue = event.detail.stringValue;
|
|
14597
|
+
const announcementDelay = 300;
|
|
14457
14598
|
setTimeout(() => {
|
|
14458
14599
|
this.announceToScreenReader(`${selectedValue}, selected`);
|
|
14459
|
-
},
|
|
14600
|
+
}, announcementDelay);
|
|
14460
14601
|
}
|
|
14461
14602
|
});
|
|
14462
14603
|
|
|
@@ -14504,7 +14645,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14504
14645
|
* Validate every time we remove focus from the combo box.
|
|
14505
14646
|
*/
|
|
14506
14647
|
this.addEventListener('focusout', () => {
|
|
14507
|
-
if (!this.componentHasFocus) {
|
|
14648
|
+
if (!this.componentHasFocus && !this._inFullscreenTransition) {
|
|
14508
14649
|
this.validate();
|
|
14509
14650
|
}
|
|
14510
14651
|
});
|
|
@@ -14555,8 +14696,11 @@ class AuroCombobox extends AuroElement {
|
|
|
14555
14696
|
}
|
|
14556
14697
|
this.handleMenuOptions();
|
|
14557
14698
|
|
|
14558
|
-
// Validate only if the value was set programmatically
|
|
14559
|
-
|
|
14699
|
+
// Validate only if the value was set programmatically (not during user
|
|
14700
|
+
// interaction). In fullscreen dialog mode, componentHasFocus returns false
|
|
14701
|
+
// because focus is inside the top-layer dialog, so also check
|
|
14702
|
+
// dropdownOpen and the fullscreen transition flag.
|
|
14703
|
+
if (!this.componentHasFocus && !this.dropdownOpen && !this._inFullscreenTransition) {
|
|
14560
14704
|
this.validate();
|
|
14561
14705
|
}
|
|
14562
14706
|
|
|
@@ -14571,6 +14715,22 @@ class AuroCombobox extends AuroElement {
|
|
|
14571
14715
|
this.hideBib();
|
|
14572
14716
|
}
|
|
14573
14717
|
|
|
14718
|
+
// iOS virtual keyboard retention: when in fullscreen mode, ensure the
|
|
14719
|
+
// dialog opens and the bib input is focused synchronously within the
|
|
14720
|
+
// input event (user gesture) chain. Without this, Lit's async update
|
|
14721
|
+
// cycle delays showModal() past the user activation window, causing
|
|
14722
|
+
// iOS Safari to dismiss the virtual keyboard when the fullscreen
|
|
14723
|
+
// dialog opens — the user then has to tap the input again to resume
|
|
14724
|
+
// typing.
|
|
14725
|
+
if (this.dropdown.isBibFullscreen && this.input.value && this.input.value.length > 0) {
|
|
14726
|
+
if (!this.dropdown.isPopoverVisible) {
|
|
14727
|
+
this.showBib();
|
|
14728
|
+
}
|
|
14729
|
+
if (this.dropdown.isPopoverVisible) {
|
|
14730
|
+
this.setInputFocus();
|
|
14731
|
+
}
|
|
14732
|
+
}
|
|
14733
|
+
|
|
14574
14734
|
this.dispatchEvent(new CustomEvent('inputValue', { detail: { value: this.inputValue } }));
|
|
14575
14735
|
}
|
|
14576
14736
|
|
|
@@ -14596,23 +14756,20 @@ class AuroCombobox extends AuroElement {
|
|
|
14596
14756
|
}
|
|
14597
14757
|
|
|
14598
14758
|
if (evt.key === 'Tab' && this.dropdown.isPopoverVisible) {
|
|
14599
|
-
|
|
14600
|
-
|
|
14601
|
-
|
|
14602
|
-
|
|
14603
|
-
|
|
14604
|
-
|
|
14605
|
-
|
|
14606
|
-
|
|
14759
|
+
// Non-fullscreen (combobox pattern per WAI-ARIA APG):
|
|
14760
|
+
// Tab accepts the focused option and closes the popup, moving focus
|
|
14761
|
+
// to the next focusable element on the page.
|
|
14762
|
+
// https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-select-only/
|
|
14763
|
+
//
|
|
14764
|
+
// Fullscreen (dialog / modal pattern): Tab navigates between
|
|
14765
|
+
// focusable elements inside the modal (e.g. the close button) via
|
|
14766
|
+
// the native focus trap provided by showModal(). The dropdown is
|
|
14767
|
+
// closed by the close button or Escape instead.
|
|
14768
|
+
if (!this.dropdown.isBibFullscreen) {
|
|
14607
14769
|
if (this.menu.optionActive && this.menu.optionActive.value) {
|
|
14608
14770
|
this.menu.value = this.menu.optionActive.value;
|
|
14609
14771
|
}
|
|
14610
|
-
|
|
14611
|
-
setTimeout(() => {
|
|
14612
|
-
if (!this.componentHasFocus) {
|
|
14613
|
-
this.hideBib();
|
|
14614
|
-
}
|
|
14615
|
-
}, 0);
|
|
14772
|
+
this.hideBib();
|
|
14616
14773
|
}
|
|
14617
14774
|
}
|
|
14618
14775
|
|
|
@@ -14643,6 +14800,14 @@ class AuroCombobox extends AuroElement {
|
|
|
14643
14800
|
});
|
|
14644
14801
|
|
|
14645
14802
|
this.addEventListener('auroFormElement-validated', (evt) => {
|
|
14803
|
+
// During the fullscreen transition, child elements (auro-input) may fire
|
|
14804
|
+
// their own validation events when the trigger becomes inert and loses
|
|
14805
|
+
// focus. Those composed events bubble up through shadow DOM boundaries
|
|
14806
|
+
// and would incorrectly set combobox validity. Ignore them.
|
|
14807
|
+
if (this._inFullscreenTransition) {
|
|
14808
|
+
return;
|
|
14809
|
+
}
|
|
14810
|
+
|
|
14646
14811
|
this.input.validity = evt.detail.validity;
|
|
14647
14812
|
this.input.errorMessage = evt.detail.message;
|
|
14648
14813
|
this.validity = evt.detail.validity;
|
|
@@ -14746,6 +14911,9 @@ class AuroCombobox extends AuroElement {
|
|
|
14746
14911
|
* @param {boolean} [force=false] - Whether to force validation.
|
|
14747
14912
|
*/
|
|
14748
14913
|
validate(force = false) {
|
|
14914
|
+
if (this._inFullscreenTransition) {
|
|
14915
|
+
return;
|
|
14916
|
+
}
|
|
14749
14917
|
this.validation.validate(this, force);
|
|
14750
14918
|
}
|
|
14751
14919
|
|
|
@@ -14799,7 +14967,13 @@ class AuroCombobox extends AuroElement {
|
|
|
14799
14967
|
}
|
|
14800
14968
|
|
|
14801
14969
|
if (changedProperties.has('availableOptions')) {
|
|
14802
|
-
|
|
14970
|
+
// dropdownOpen is set synchronously by the auroDropdown-toggled event
|
|
14971
|
+
// handler during showBib() → floater.showBib() → dispatchEventDropdownToggle(),
|
|
14972
|
+
// so it's already true by the time updated() runs. This prevents the else
|
|
14973
|
+
// branch from calling hideBib() when the dropdown was just opened but
|
|
14974
|
+
// :focus-within hasn't propagated through the top-layer dialog's nested
|
|
14975
|
+
// shadow DOM boundaries.
|
|
14976
|
+
if ((this.availableOptions.length > 0 && (this.componentHasFocus || this.dropdownOpen)) || this.menu.loading || (this.availableOptions.length === 0 && this.noMatchOption)) {
|
|
14803
14977
|
this.showBib();
|
|
14804
14978
|
} else {
|
|
14805
14979
|
this.hideBib();
|
|
@@ -14974,6 +15148,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14974
15148
|
<slot @slotchange="${this.handleSlotChange}"></slot>
|
|
14975
15149
|
<${this.inputTag}
|
|
14976
15150
|
id="inputInBib"
|
|
15151
|
+
autofocus
|
|
14977
15152
|
@input="${this.handleInputValueChange}"
|
|
14978
15153
|
.a11yActivedescendant="${this.dropdownOpen && this.optionActive ? this.optionActive.id : undefined}"
|
|
14979
15154
|
.a11yControls=${`${this.dropdownId}-floater-bib`}
|
|
@@ -15312,7 +15487,11 @@ class AuroMenuOption extends AuroElement {
|
|
|
15312
15487
|
|
|
15313
15488
|
// Generate unique ID if not already set (required for aria-activedescendant)
|
|
15314
15489
|
if (!this.id) {
|
|
15315
|
-
|
|
15490
|
+
const idBase = 36;
|
|
15491
|
+
const sliceStart = 2;
|
|
15492
|
+
const sliceEnd = 8;
|
|
15493
|
+
this.id = `menuoption-${Math.random().toString(idBase).
|
|
15494
|
+
slice(sliceStart, sliceEnd)}`;
|
|
15316
15495
|
}
|
|
15317
15496
|
|
|
15318
15497
|
this.setAttribute('role', 'option');
|
|
@@ -16219,7 +16398,7 @@ class MenuService {
|
|
|
16219
16398
|
|
|
16220
16399
|
const MenuContext = n('menu-context');
|
|
16221
16400
|
|
|
16222
|
-
/* eslint-disable no-underscore-dangle
|
|
16401
|
+
/* eslint-disable no-underscore-dangle */
|
|
16223
16402
|
// Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
|
|
16224
16403
|
// See LICENSE in the project root for license information.
|
|
16225
16404
|
|
|
@@ -16240,7 +16419,7 @@ const MenuContext = n('menu-context');
|
|
|
16240
16419
|
* @slot - Slot for insertion of menu options.
|
|
16241
16420
|
*/
|
|
16242
16421
|
|
|
16243
|
-
/* eslint-disable
|
|
16422
|
+
/* eslint-disable max-lines */
|
|
16244
16423
|
|
|
16245
16424
|
class AuroMenu extends AuroElement {
|
|
16246
16425
|
|
|
@@ -19,7 +19,7 @@ export class AuroCombobox extends AuroElement {
|
|
|
19
19
|
static get properties(): {
|
|
20
20
|
/**
|
|
21
21
|
* Defines whether the component will be on lighter or darker backgrounds.
|
|
22
|
-
* @property {'default' | 'inverse'}
|
|
22
|
+
* @property {'default' | 'inverse'} appearance - The visual appearance of the component.
|
|
23
23
|
* @default 'default'
|
|
24
24
|
*/
|
|
25
25
|
appearance: {
|
|
@@ -360,6 +360,7 @@ export class AuroCombobox extends AuroElement {
|
|
|
360
360
|
dropdownOpen: any;
|
|
361
361
|
triggerExpandedState: boolean;
|
|
362
362
|
_expandedTimeout: NodeJS.Timeout;
|
|
363
|
+
_inFullscreenTransition: boolean;
|
|
363
364
|
errorMessage: any;
|
|
364
365
|
isHiddenWhileLoading: boolean;
|
|
365
366
|
largeFullscreenHeadline: boolean;
|