@aurodesignsystem-dev/auro-formkit 0.0.0-pr1346.2 → 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 +252 -65
- package/components/combobox/demo/index.min.js +252 -65
- package/components/combobox/dist/auro-combobox.d.ts +2 -1
- package/components/combobox/dist/index.js +245 -62
- package/components/combobox/dist/registered.js +245 -62
- package/components/counter/demo/api.min.js +124 -12
- package/components/counter/demo/index.min.js +124 -12
- package/components/counter/dist/index.js +124 -12
- package/components/counter/dist/registered.js +124 -12
- package/components/datepicker/demo/api.min.js +161 -40
- package/components/datepicker/demo/index.min.js +161 -40
- package/components/datepicker/dist/index.js +161 -40
- package/components/datepicker/dist/registered.js +161 -40
- 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 +38 -29
- package/components/input/demo/index.min.js +38 -29
- package/components/input/dist/index.js +38 -29
- package/components/input/dist/registered.js +38 -29
- 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.
|
|
@@ -11375,31 +11488,34 @@ class BaseInput extends AuroElement$1 {
|
|
|
11375
11488
|
// Process credit card type detection and formatting during input
|
|
11376
11489
|
if (this.type === 'credit-card') {
|
|
11377
11490
|
this.processCreditCard();
|
|
11378
|
-
|
|
11491
|
+
this.touched = true;
|
|
11492
|
+
this.validation.validate(this);
|
|
11493
|
+
} else {
|
|
11379
11494
|
|
|
11380
|
-
|
|
11381
|
-
|
|
11495
|
+
// Sets value property to value of element value (el.value).
|
|
11496
|
+
this.value = this.inputElement.value;
|
|
11382
11497
|
|
|
11383
|
-
|
|
11384
|
-
|
|
11498
|
+
// Determine if the value change was programmatic, including autofill.
|
|
11499
|
+
const inputWasProgrammatic = !this.matches(":focus") || event.isProgrammatic;
|
|
11385
11500
|
|
|
11386
|
-
|
|
11387
|
-
|
|
11388
|
-
|
|
11389
|
-
|
|
11390
|
-
|
|
11501
|
+
// Validation on input or programmatic value change (including autofill).
|
|
11502
|
+
if (this.validateOnInput || inputWasProgrammatic) {
|
|
11503
|
+
this.touched = true;
|
|
11504
|
+
this.validation.validate(this);
|
|
11505
|
+
}
|
|
11391
11506
|
|
|
11392
|
-
|
|
11393
|
-
|
|
11507
|
+
// Prevents cursor jumping in Safari.
|
|
11508
|
+
const { selectionStart } = this.inputElement;
|
|
11394
11509
|
|
|
11395
|
-
|
|
11396
|
-
|
|
11397
|
-
|
|
11398
|
-
|
|
11399
|
-
|
|
11400
|
-
|
|
11401
|
-
|
|
11402
|
-
|
|
11510
|
+
if (this.setSelectionInputTypes.includes(this.type)) {
|
|
11511
|
+
this.updateComplete.then(() => {
|
|
11512
|
+
try {
|
|
11513
|
+
this.inputElement.setSelectionRange(selectionStart, selectionStart);
|
|
11514
|
+
} catch (error) { // eslint-disable-line
|
|
11515
|
+
// do nothing
|
|
11516
|
+
}
|
|
11517
|
+
});
|
|
11518
|
+
}
|
|
11403
11519
|
}
|
|
11404
11520
|
}
|
|
11405
11521
|
|
|
@@ -11432,6 +11548,11 @@ class BaseInput extends AuroElement$1 {
|
|
|
11432
11548
|
this.inputElement.scrollLeft = 100;
|
|
11433
11549
|
|
|
11434
11550
|
if (!this.noValidate) {
|
|
11551
|
+
// For credit card inputs with mask, ensure value is synced from mask instance
|
|
11552
|
+
if (this.type === 'credit-card' && this.maskInstance) {
|
|
11553
|
+
this.value = this.maskInstance.value;
|
|
11554
|
+
}
|
|
11555
|
+
|
|
11435
11556
|
this.validation.validate(this);
|
|
11436
11557
|
}
|
|
11437
11558
|
}
|
|
@@ -12094,7 +12215,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$4 {
|
|
|
12094
12215
|
}
|
|
12095
12216
|
};
|
|
12096
12217
|
|
|
12097
|
-
var formkitVersion$1 = '
|
|
12218
|
+
var formkitVersion$1 = '202602260152';
|
|
12098
12219
|
|
|
12099
12220
|
// Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
|
|
12100
12221
|
// See LICENSE in the project root for license information.
|
|
@@ -13121,7 +13242,7 @@ class AuroBibtemplate extends i$4 {
|
|
|
13121
13242
|
}
|
|
13122
13243
|
}
|
|
13123
13244
|
|
|
13124
|
-
var formkitVersion = '
|
|
13245
|
+
var formkitVersion = '202602260152';
|
|
13125
13246
|
|
|
13126
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}`;
|
|
13127
13248
|
|
|
@@ -13539,6 +13660,7 @@ class AuroCombobox extends AuroElement {
|
|
|
13539
13660
|
this.dropdownOpen = false;
|
|
13540
13661
|
this.triggerExpandedState = false;
|
|
13541
13662
|
this._expandedTimeout = null;
|
|
13663
|
+
this._inFullscreenTransition = false;
|
|
13542
13664
|
this.errorMessage = null;
|
|
13543
13665
|
this.isHiddenWhileLoading = false;
|
|
13544
13666
|
this.largeFullscreenHeadline = false;
|
|
@@ -13559,7 +13681,7 @@ class AuroCombobox extends AuroElement {
|
|
|
13559
13681
|
|
|
13560
13682
|
/**
|
|
13561
13683
|
* Defines whether the component will be on lighter or darker backgrounds.
|
|
13562
|
-
* @property {'default' | 'inverse'}
|
|
13684
|
+
* @property {'default' | 'inverse'} appearance - The visual appearance of the component.
|
|
13563
13685
|
* @default 'default'
|
|
13564
13686
|
*/
|
|
13565
13687
|
appearance: {
|
|
@@ -14114,7 +14236,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14114
14236
|
* @returns {void}
|
|
14115
14237
|
*/
|
|
14116
14238
|
showBib() {
|
|
14117
|
-
if (!this.input.value) {
|
|
14239
|
+
if (!this.input.value && !this.dropdown.isBibFullscreen) {
|
|
14118
14240
|
this.dropdown.hide();
|
|
14119
14241
|
return;
|
|
14120
14242
|
}
|
|
@@ -14183,6 +14305,18 @@ class AuroCombobox extends AuroElement {
|
|
|
14183
14305
|
|
|
14184
14306
|
// Restore trigger accessibility when closing fullscreen
|
|
14185
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
|
+
}
|
|
14186
14320
|
}
|
|
14187
14321
|
|
|
14188
14322
|
if (this.dropdownOpen) {
|
|
@@ -14192,6 +14326,19 @@ class AuroCombobox extends AuroElement {
|
|
|
14192
14326
|
this.updateBibDialogRole();
|
|
14193
14327
|
|
|
14194
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
|
+
|
|
14195
14342
|
// Hide the trigger from assistive technology so VoiceOver cannot reach it
|
|
14196
14343
|
// behind the fullscreen dialog
|
|
14197
14344
|
this.dropdown.trigger.inert = true;
|
|
@@ -14223,6 +14370,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14223
14370
|
requestAnimationFrame(() => {
|
|
14224
14371
|
requestAnimationFrame(() => {
|
|
14225
14372
|
this.setInputFocus();
|
|
14373
|
+
this._inFullscreenTransition = false;
|
|
14226
14374
|
});
|
|
14227
14375
|
});
|
|
14228
14376
|
} else {
|
|
@@ -14317,7 +14465,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14317
14465
|
* @private
|
|
14318
14466
|
*/
|
|
14319
14467
|
updateBibDialogRole() {
|
|
14320
|
-
const bibEl = this.dropdown.bibElement
|
|
14468
|
+
const bibEl = this.dropdown.bibElement && this.dropdown.bibElement.value;
|
|
14321
14469
|
if (!bibEl) {
|
|
14322
14470
|
return;
|
|
14323
14471
|
}
|
|
@@ -14446,9 +14594,10 @@ class AuroCombobox extends AuroElement {
|
|
|
14446
14594
|
// Announce the selection after the dropdown closes so it isn't
|
|
14447
14595
|
// overridden by VoiceOver's "collapsed" announcement from aria-expanded.
|
|
14448
14596
|
const selectedValue = event.detail.stringValue;
|
|
14597
|
+
const announcementDelay = 300;
|
|
14449
14598
|
setTimeout(() => {
|
|
14450
14599
|
this.announceToScreenReader(`${selectedValue}, selected`);
|
|
14451
|
-
},
|
|
14600
|
+
}, announcementDelay);
|
|
14452
14601
|
}
|
|
14453
14602
|
});
|
|
14454
14603
|
|
|
@@ -14496,7 +14645,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14496
14645
|
* Validate every time we remove focus from the combo box.
|
|
14497
14646
|
*/
|
|
14498
14647
|
this.addEventListener('focusout', () => {
|
|
14499
|
-
if (!this.componentHasFocus) {
|
|
14648
|
+
if (!this.componentHasFocus && !this._inFullscreenTransition) {
|
|
14500
14649
|
this.validate();
|
|
14501
14650
|
}
|
|
14502
14651
|
});
|
|
@@ -14547,8 +14696,11 @@ class AuroCombobox extends AuroElement {
|
|
|
14547
14696
|
}
|
|
14548
14697
|
this.handleMenuOptions();
|
|
14549
14698
|
|
|
14550
|
-
// Validate only if the value was set programmatically
|
|
14551
|
-
|
|
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) {
|
|
14552
14704
|
this.validate();
|
|
14553
14705
|
}
|
|
14554
14706
|
|
|
@@ -14563,6 +14715,22 @@ class AuroCombobox extends AuroElement {
|
|
|
14563
14715
|
this.hideBib();
|
|
14564
14716
|
}
|
|
14565
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
|
+
|
|
14566
14734
|
this.dispatchEvent(new CustomEvent('inputValue', { detail: { value: this.inputValue } }));
|
|
14567
14735
|
}
|
|
14568
14736
|
|
|
@@ -14588,23 +14756,20 @@ class AuroCombobox extends AuroElement {
|
|
|
14588
14756
|
}
|
|
14589
14757
|
|
|
14590
14758
|
if (evt.key === 'Tab' && this.dropdown.isPopoverVisible) {
|
|
14591
|
-
|
|
14592
|
-
|
|
14593
|
-
|
|
14594
|
-
|
|
14595
|
-
|
|
14596
|
-
|
|
14597
|
-
|
|
14598
|
-
|
|
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) {
|
|
14599
14769
|
if (this.menu.optionActive && this.menu.optionActive.value) {
|
|
14600
14770
|
this.menu.value = this.menu.optionActive.value;
|
|
14601
14771
|
}
|
|
14602
|
-
|
|
14603
|
-
setTimeout(() => {
|
|
14604
|
-
if (!this.componentHasFocus) {
|
|
14605
|
-
this.hideBib();
|
|
14606
|
-
}
|
|
14607
|
-
}, 0);
|
|
14772
|
+
this.hideBib();
|
|
14608
14773
|
}
|
|
14609
14774
|
}
|
|
14610
14775
|
|
|
@@ -14635,6 +14800,14 @@ class AuroCombobox extends AuroElement {
|
|
|
14635
14800
|
});
|
|
14636
14801
|
|
|
14637
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
|
+
|
|
14638
14811
|
this.input.validity = evt.detail.validity;
|
|
14639
14812
|
this.input.errorMessage = evt.detail.message;
|
|
14640
14813
|
this.validity = evt.detail.validity;
|
|
@@ -14738,6 +14911,9 @@ class AuroCombobox extends AuroElement {
|
|
|
14738
14911
|
* @param {boolean} [force=false] - Whether to force validation.
|
|
14739
14912
|
*/
|
|
14740
14913
|
validate(force = false) {
|
|
14914
|
+
if (this._inFullscreenTransition) {
|
|
14915
|
+
return;
|
|
14916
|
+
}
|
|
14741
14917
|
this.validation.validate(this, force);
|
|
14742
14918
|
}
|
|
14743
14919
|
|
|
@@ -14791,7 +14967,13 @@ class AuroCombobox extends AuroElement {
|
|
|
14791
14967
|
}
|
|
14792
14968
|
|
|
14793
14969
|
if (changedProperties.has('availableOptions')) {
|
|
14794
|
-
|
|
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)) {
|
|
14795
14977
|
this.showBib();
|
|
14796
14978
|
} else {
|
|
14797
14979
|
this.hideBib();
|
|
@@ -14966,6 +15148,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14966
15148
|
<slot @slotchange="${this.handleSlotChange}"></slot>
|
|
14967
15149
|
<${this.inputTag}
|
|
14968
15150
|
id="inputInBib"
|
|
15151
|
+
autofocus
|
|
14969
15152
|
@input="${this.handleInputValueChange}"
|
|
14970
15153
|
.a11yActivedescendant="${this.dropdownOpen && this.optionActive ? this.optionActive.id : undefined}"
|
|
14971
15154
|
.a11yControls=${`${this.dropdownId}-floater-bib`}
|
|
@@ -15304,7 +15487,11 @@ class AuroMenuOption extends AuroElement {
|
|
|
15304
15487
|
|
|
15305
15488
|
// Generate unique ID if not already set (required for aria-activedescendant)
|
|
15306
15489
|
if (!this.id) {
|
|
15307
|
-
|
|
15490
|
+
const idBase = 36;
|
|
15491
|
+
const sliceStart = 2;
|
|
15492
|
+
const sliceEnd = 8;
|
|
15493
|
+
this.id = `menuoption-${Math.random().toString(idBase).
|
|
15494
|
+
slice(sliceStart, sliceEnd)}`;
|
|
15308
15495
|
}
|
|
15309
15496
|
|
|
15310
15497
|
this.setAttribute('role', 'option');
|
|
@@ -16211,7 +16398,7 @@ class MenuService {
|
|
|
16211
16398
|
|
|
16212
16399
|
const MenuContext = n('menu-context');
|
|
16213
16400
|
|
|
16214
|
-
/* eslint-disable no-underscore-dangle
|
|
16401
|
+
/* eslint-disable no-underscore-dangle */
|
|
16215
16402
|
// Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
|
|
16216
16403
|
// See LICENSE in the project root for license information.
|
|
16217
16404
|
|
|
@@ -16232,7 +16419,7 @@ const MenuContext = n('menu-context');
|
|
|
16232
16419
|
* @slot - Slot for insertion of menu options.
|
|
16233
16420
|
*/
|
|
16234
16421
|
|
|
16235
|
-
/* eslint-disable
|
|
16422
|
+
/* eslint-disable max-lines */
|
|
16236
16423
|
|
|
16237
16424
|
class AuroMenu extends AuroElement {
|
|
16238
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;
|