@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
|
@@ -3810,7 +3810,7 @@ let p$3 = class p{registerComponent(t,a){customElements.get(t)||customElements.d
|
|
|
3810
3810
|
|
|
3811
3811
|
var iconVersion$2 = '9.1.2';
|
|
3812
3812
|
|
|
3813
|
-
var styleCss$2$1 = css`: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}`;
|
|
3813
|
+
var styleCss$2$1 = css`: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}`;
|
|
3814
3814
|
|
|
3815
3815
|
var colorCss$2$1 = 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)}`;
|
|
3816
3816
|
|
|
@@ -3818,6 +3818,8 @@ var tokensCss$1$1 = css`:host(:not([ondark])),:host(:not([appearance=inverse])){
|
|
|
3818
3818
|
|
|
3819
3819
|
// Copyright (c) 2020 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
|
|
3820
3820
|
// See LICENSE in the project root for license information.
|
|
3821
|
+
/* eslint-disable max-lines */
|
|
3822
|
+
// ---------------------------------------------------------------------
|
|
3821
3823
|
|
|
3822
3824
|
|
|
3823
3825
|
const DESIGN_TOKEN_BREAKPOINT_PREFIX = '--ds-grid-breakpoint-';
|
|
@@ -3993,22 +3995,63 @@ class AuroDropdownBib extends LitElement {
|
|
|
3993
3995
|
// Handle ESC key via dialog's cancel event
|
|
3994
3996
|
const dialog = this.shadowRoot.querySelector('dialog');
|
|
3995
3997
|
dialog.addEventListener('cancel', (event) => {
|
|
3996
|
-
|
|
3998
|
+
// Let parent handle closing
|
|
3999
|
+
event.preventDefault();
|
|
3997
4000
|
this.dispatchEvent(new CustomEvent('auro-bib-cancel', {
|
|
3998
4001
|
bubbles: true,
|
|
3999
4002
|
composed: true
|
|
4000
4003
|
}));
|
|
4001
4004
|
});
|
|
4002
4005
|
|
|
4003
|
-
//
|
|
4004
|
-
//
|
|
4005
|
-
//
|
|
4006
|
-
//
|
|
4007
|
-
|
|
4006
|
+
// showModal() creates a closed focus scope — keyboard events inside
|
|
4007
|
+
// the dialog's shadow DOM do NOT bubble out to the combobox/select
|
|
4008
|
+
// keydown handlers in the parent shadow DOM. This handler bridges
|
|
4009
|
+
// that gap by re-dispatching navigation keys so they cross the
|
|
4010
|
+
// shadow boundary and reach the menu navigation logic in the parent
|
|
4011
|
+
// component.
|
|
4012
|
+
//
|
|
4013
|
+
// The trade-off: intercepting these keys means native keyboard
|
|
4014
|
+
// behaviors that would normally "just work" must be manually
|
|
4015
|
+
// re-implemented here:
|
|
4016
|
+
//
|
|
4017
|
+
// - Enter on buttons: Custom elements (auro-button) don't get the
|
|
4018
|
+
// native Enter→click that <button> provides, so we call .click()
|
|
4019
|
+
// directly when Enter is pressed on a button-like element.
|
|
4020
|
+
//
|
|
4021
|
+
// - Tab: NOT intercepted — left to the browser's native focus trap
|
|
4022
|
+
// provided by showModal(), which cycles Tab between focusable
|
|
4023
|
+
// elements inside the dialog (e.g. the input and close button).
|
|
4024
|
+
// Intercepting Tab would kill the native focus trap and break
|
|
4025
|
+
// focus management inside the dialog.
|
|
4026
|
+
//
|
|
4027
|
+
// - Escape: The native <dialog> fires a `cancel` event on ESC
|
|
4028
|
+
// (handled above), so the re-dispatched Escape is a secondary
|
|
4029
|
+
// path for parent components that also listen for Escape keydown.
|
|
4030
|
+
const navKeys = new Set([
|
|
4031
|
+
'ArrowUp',
|
|
4032
|
+
'ArrowDown',
|
|
4033
|
+
'Enter',
|
|
4034
|
+
'Escape'
|
|
4035
|
+
]);
|
|
4008
4036
|
dialog.addEventListener('keydown', (event) => {
|
|
4009
4037
|
if (!navKeys.has(event.key)) {
|
|
4010
4038
|
return;
|
|
4011
4039
|
}
|
|
4040
|
+
|
|
4041
|
+
// Custom elements (auro-button) don't get the native Enter→click
|
|
4042
|
+
// behavior that <button> has. Find the button in the composed path
|
|
4043
|
+
// and click it directly.
|
|
4044
|
+
if (event.key === 'Enter') {
|
|
4045
|
+
const buttonSelector = 'button, [role="button"], auro-button, [auro-button]';
|
|
4046
|
+
const btn = event.composedPath().find((el) => el.matches && el.matches(buttonSelector));
|
|
4047
|
+
if (btn) {
|
|
4048
|
+
event.preventDefault();
|
|
4049
|
+
event.stopPropagation();
|
|
4050
|
+
btn.click();
|
|
4051
|
+
return;
|
|
4052
|
+
}
|
|
4053
|
+
}
|
|
4054
|
+
|
|
4012
4055
|
event.preventDefault();
|
|
4013
4056
|
event.stopPropagation();
|
|
4014
4057
|
const newEvent = new KeyboardEvent('keydown', {
|
|
@@ -4032,9 +4075,55 @@ class AuroDropdownBib extends LitElement {
|
|
|
4032
4075
|
}
|
|
4033
4076
|
|
|
4034
4077
|
/**
|
|
4035
|
-
*
|
|
4036
|
-
*
|
|
4078
|
+
* Blocks touch-driven page scroll while a fullscreen modal dialog is open.
|
|
4079
|
+
*
|
|
4080
|
+
* The showModal() function places the dialog in the browser's **top layer**,
|
|
4081
|
+
* which is a separate rendering layer above the normal DOM. On mobile, the
|
|
4082
|
+
* compositor processes visual-viewport panning before top-layer touch
|
|
4083
|
+
* handling. This means the entire viewport — including the top-layer dialog
|
|
4084
|
+
* — can be panned by a touch gesture, causing the page behind the dialog to
|
|
4085
|
+
* scroll into view. To prevent this, we add a touchmove listener that cancels
|
|
4086
|
+
* the event if the touch started outside the dialog or any scrollable child within it.
|
|
4087
|
+
*
|
|
4088
|
+
* @private
|
|
4089
|
+
*/
|
|
4090
|
+
_lockTouchScroll() {
|
|
4091
|
+
const dialog = this.shadowRoot.querySelector('dialog');
|
|
4092
|
+
|
|
4093
|
+
this._touchMoveHandler = (event) => {
|
|
4094
|
+
// Walk the composed path (which crosses shadow DOM boundaries) to
|
|
4095
|
+
// check whether the touch started inside a scrollable element that
|
|
4096
|
+
// lives within the dialog. If so, allow the scroll.
|
|
4097
|
+
for (const el of event.composedPath()) {
|
|
4098
|
+
if (el === dialog) {
|
|
4099
|
+
// Reached the dialog boundary without finding a scrollable child.
|
|
4100
|
+
break;
|
|
4101
|
+
}
|
|
4102
|
+
if (el instanceof HTMLElement && el.scrollHeight > el.clientHeight) {
|
|
4103
|
+
const { overflowY } = getComputedStyle(el);
|
|
4104
|
+
if (overflowY === 'auto' || overflowY === 'scroll') {
|
|
4105
|
+
return;
|
|
4106
|
+
}
|
|
4107
|
+
}
|
|
4108
|
+
}
|
|
4109
|
+
|
|
4110
|
+
event.preventDefault();
|
|
4111
|
+
};
|
|
4112
|
+
|
|
4113
|
+
document.addEventListener('touchmove', this._touchMoveHandler, { passive: false });
|
|
4114
|
+
}
|
|
4115
|
+
|
|
4116
|
+
/**
|
|
4117
|
+
* Removes the touchmove listener added by _lockTouchScroll().
|
|
4118
|
+
* @private
|
|
4037
4119
|
*/
|
|
4120
|
+
_unlockTouchScroll() {
|
|
4121
|
+
if (this._touchMoveHandler) {
|
|
4122
|
+
document.removeEventListener('touchmove', this._touchMoveHandler);
|
|
4123
|
+
this._touchMoveHandler = undefined;
|
|
4124
|
+
}
|
|
4125
|
+
}
|
|
4126
|
+
|
|
4038
4127
|
open(modal = true) {
|
|
4039
4128
|
const dialog = this.shadowRoot.querySelector('dialog');
|
|
4040
4129
|
if (dialog && !dialog.open) {
|
|
@@ -4051,6 +4140,8 @@ class AuroDropdownBib extends LitElement {
|
|
|
4051
4140
|
|
|
4052
4141
|
documentElement.style.overflow = prevOverflow;
|
|
4053
4142
|
|
|
4143
|
+
this._lockTouchScroll();
|
|
4144
|
+
|
|
4054
4145
|
} else {
|
|
4055
4146
|
// Use setAttribute instead of dialog.show() to avoid the dialog
|
|
4056
4147
|
// focusing steps which steal focus from the trigger and cause
|
|
@@ -4066,6 +4157,7 @@ class AuroDropdownBib extends LitElement {
|
|
|
4066
4157
|
close() {
|
|
4067
4158
|
const dialog = this.shadowRoot.querySelector('dialog');
|
|
4068
4159
|
if (dialog && dialog.open) {
|
|
4160
|
+
this._unlockTouchScroll();
|
|
4069
4161
|
dialog.close();
|
|
4070
4162
|
}
|
|
4071
4163
|
}
|
|
@@ -4331,7 +4423,7 @@ let AuroHelpText$2 = class AuroHelpText extends LitElement {
|
|
|
4331
4423
|
}
|
|
4332
4424
|
};
|
|
4333
4425
|
|
|
4334
|
-
var formkitVersion$2 = '
|
|
4426
|
+
var formkitVersion$2 = '202602260152';
|
|
4335
4427
|
|
|
4336
4428
|
let AuroElement$2 = class AuroElement extends LitElement {
|
|
4337
4429
|
static get properties() {
|
|
@@ -4604,6 +4696,18 @@ class AuroDropdown extends AuroElement$2 {
|
|
|
4604
4696
|
*/
|
|
4605
4697
|
show() {
|
|
4606
4698
|
this.floater.showBib();
|
|
4699
|
+
|
|
4700
|
+
// Open dialog synchronously so callers remain in the user gesture
|
|
4701
|
+
// chain. This is critical for mobile browsers (iOS Safari) to keep
|
|
4702
|
+
// the virtual keyboard open when transitioning from the trigger
|
|
4703
|
+
// input to an input inside the fullscreen dialog. Without this,
|
|
4704
|
+
// showModal() fires asynchronously via Lit's update cycle, which
|
|
4705
|
+
// falls outside the user activation window and causes iOS to
|
|
4706
|
+
// dismiss the keyboard.
|
|
4707
|
+
if (this.isBibFullscreen && this.bibElement && this.bibElement.value) {
|
|
4708
|
+
const useModal = !this.disableFocusTrap;
|
|
4709
|
+
this.bibElement.value.open(useModal);
|
|
4710
|
+
}
|
|
4607
4711
|
}
|
|
4608
4712
|
|
|
4609
4713
|
/**
|
|
@@ -4990,6 +5094,14 @@ class AuroDropdown extends AuroElement$2 {
|
|
|
4990
5094
|
this.bibElement.value.close();
|
|
4991
5095
|
}
|
|
4992
5096
|
}
|
|
5097
|
+
|
|
5098
|
+
// When fullscreen strategy changes while open, re-open dialog with correct mode
|
|
5099
|
+
// (e.g. resizing from desktop → mobile while dropdown is open)
|
|
5100
|
+
if (changedProperties.has('isBibFullscreen') && this.isPopoverVisible && this.bibElement.value) {
|
|
5101
|
+
const useModal = this.isBibFullscreen && !this.disableFocusTrap;
|
|
5102
|
+
this.bibElement.value.close();
|
|
5103
|
+
this.bibElement.value.open(useModal);
|
|
5104
|
+
}
|
|
4993
5105
|
}
|
|
4994
5106
|
|
|
4995
5107
|
/**
|
|
@@ -10484,6 +10596,15 @@ class BaseInput extends AuroElement$1 {
|
|
|
10484
10596
|
constructor() {
|
|
10485
10597
|
super();
|
|
10486
10598
|
|
|
10599
|
+
// Delegate focus to the native <input> inside the shadow root so that
|
|
10600
|
+
// showModal()'s dialog focusing steps reach the input element.
|
|
10601
|
+
// This keeps the mobile virtual keyboard open when the fullscreen dialog
|
|
10602
|
+
// opens, because the browser sees an input-to-input focus transfer.
|
|
10603
|
+
this.constructor.shadowRootOptions = {
|
|
10604
|
+
...AuroElement$1.shadowRootOptions,
|
|
10605
|
+
delegatesFocus: true,
|
|
10606
|
+
};
|
|
10607
|
+
|
|
10487
10608
|
this._initializeDefaults();
|
|
10488
10609
|
}
|
|
10489
10610
|
|
|
@@ -10605,14 +10726,6 @@ class BaseInput extends AuroElement$1 {
|
|
|
10605
10726
|
reflect: true
|
|
10606
10727
|
},
|
|
10607
10728
|
|
|
10608
|
-
/**
|
|
10609
|
-
* The value for the aria-controls attribute.
|
|
10610
|
-
*/
|
|
10611
|
-
a11yControls: {
|
|
10612
|
-
type: String,
|
|
10613
|
-
reflect: true
|
|
10614
|
-
},
|
|
10615
|
-
|
|
10616
10729
|
/**
|
|
10617
10730
|
* The value for the aria-activedescendant attribute.
|
|
10618
10731
|
* Points to the ID of the currently active/highlighted option in a listbox.
|
|
@@ -11305,31 +11418,34 @@ class BaseInput extends AuroElement$1 {
|
|
|
11305
11418
|
// Process credit card type detection and formatting during input
|
|
11306
11419
|
if (this.type === 'credit-card') {
|
|
11307
11420
|
this.processCreditCard();
|
|
11308
|
-
|
|
11421
|
+
this.touched = true;
|
|
11422
|
+
this.validation.validate(this);
|
|
11423
|
+
} else {
|
|
11309
11424
|
|
|
11310
|
-
|
|
11311
|
-
|
|
11425
|
+
// Sets value property to value of element value (el.value).
|
|
11426
|
+
this.value = this.inputElement.value;
|
|
11312
11427
|
|
|
11313
|
-
|
|
11314
|
-
|
|
11428
|
+
// Determine if the value change was programmatic, including autofill.
|
|
11429
|
+
const inputWasProgrammatic = !this.matches(":focus") || event.isProgrammatic;
|
|
11315
11430
|
|
|
11316
|
-
|
|
11317
|
-
|
|
11318
|
-
|
|
11319
|
-
|
|
11320
|
-
|
|
11431
|
+
// Validation on input or programmatic value change (including autofill).
|
|
11432
|
+
if (this.validateOnInput || inputWasProgrammatic) {
|
|
11433
|
+
this.touched = true;
|
|
11434
|
+
this.validation.validate(this);
|
|
11435
|
+
}
|
|
11321
11436
|
|
|
11322
|
-
|
|
11323
|
-
|
|
11437
|
+
// Prevents cursor jumping in Safari.
|
|
11438
|
+
const { selectionStart } = this.inputElement;
|
|
11324
11439
|
|
|
11325
|
-
|
|
11326
|
-
|
|
11327
|
-
|
|
11328
|
-
|
|
11329
|
-
|
|
11330
|
-
|
|
11331
|
-
|
|
11332
|
-
|
|
11440
|
+
if (this.setSelectionInputTypes.includes(this.type)) {
|
|
11441
|
+
this.updateComplete.then(() => {
|
|
11442
|
+
try {
|
|
11443
|
+
this.inputElement.setSelectionRange(selectionStart, selectionStart);
|
|
11444
|
+
} catch (error) { // eslint-disable-line
|
|
11445
|
+
// do nothing
|
|
11446
|
+
}
|
|
11447
|
+
});
|
|
11448
|
+
}
|
|
11333
11449
|
}
|
|
11334
11450
|
}
|
|
11335
11451
|
|
|
@@ -11362,6 +11478,11 @@ class BaseInput extends AuroElement$1 {
|
|
|
11362
11478
|
this.inputElement.scrollLeft = 100;
|
|
11363
11479
|
|
|
11364
11480
|
if (!this.noValidate) {
|
|
11481
|
+
// For credit card inputs with mask, ensure value is synced from mask instance
|
|
11482
|
+
if (this.type === 'credit-card' && this.maskInstance) {
|
|
11483
|
+
this.value = this.maskInstance.value;
|
|
11484
|
+
}
|
|
11485
|
+
|
|
11365
11486
|
this.validation.validate(this);
|
|
11366
11487
|
}
|
|
11367
11488
|
}
|
|
@@ -12024,7 +12145,7 @@ let AuroHelpText$1 = class AuroHelpText extends LitElement {
|
|
|
12024
12145
|
}
|
|
12025
12146
|
};
|
|
12026
12147
|
|
|
12027
|
-
var formkitVersion$1 = '
|
|
12148
|
+
var formkitVersion$1 = '202602260152';
|
|
12028
12149
|
|
|
12029
12150
|
// Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
|
|
12030
12151
|
// See LICENSE in the project root for license information.
|
|
@@ -13051,7 +13172,7 @@ class AuroBibtemplate extends LitElement {
|
|
|
13051
13172
|
}
|
|
13052
13173
|
}
|
|
13053
13174
|
|
|
13054
|
-
var formkitVersion = '
|
|
13175
|
+
var formkitVersion = '202602260152';
|
|
13055
13176
|
|
|
13056
13177
|
var styleCss$1 = css`.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}`;
|
|
13057
13178
|
|
|
@@ -13469,6 +13590,7 @@ class AuroCombobox extends AuroElement {
|
|
|
13469
13590
|
this.dropdownOpen = false;
|
|
13470
13591
|
this.triggerExpandedState = false;
|
|
13471
13592
|
this._expandedTimeout = null;
|
|
13593
|
+
this._inFullscreenTransition = false;
|
|
13472
13594
|
this.errorMessage = null;
|
|
13473
13595
|
this.isHiddenWhileLoading = false;
|
|
13474
13596
|
this.largeFullscreenHeadline = false;
|
|
@@ -13489,7 +13611,7 @@ class AuroCombobox extends AuroElement {
|
|
|
13489
13611
|
|
|
13490
13612
|
/**
|
|
13491
13613
|
* Defines whether the component will be on lighter or darker backgrounds.
|
|
13492
|
-
* @property {'default' | 'inverse'}
|
|
13614
|
+
* @property {'default' | 'inverse'} appearance - The visual appearance of the component.
|
|
13493
13615
|
* @default 'default'
|
|
13494
13616
|
*/
|
|
13495
13617
|
appearance: {
|
|
@@ -14044,7 +14166,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14044
14166
|
* @returns {void}
|
|
14045
14167
|
*/
|
|
14046
14168
|
showBib() {
|
|
14047
|
-
if (!this.input.value) {
|
|
14169
|
+
if (!this.input.value && !this.dropdown.isBibFullscreen) {
|
|
14048
14170
|
this.dropdown.hide();
|
|
14049
14171
|
return;
|
|
14050
14172
|
}
|
|
@@ -14113,6 +14235,18 @@ class AuroCombobox extends AuroElement {
|
|
|
14113
14235
|
|
|
14114
14236
|
// Restore trigger accessibility when closing fullscreen
|
|
14115
14237
|
this.dropdown.trigger.inert = false;
|
|
14238
|
+
|
|
14239
|
+
// Restore focus to the trigger input after closing the
|
|
14240
|
+
// fullscreen dialog. The browser's native dialog focus restoration
|
|
14241
|
+
// fails because the trigger was set to inert before showModal().
|
|
14242
|
+
// Use rAF to run after Lit's microtask update cycle calls dialog.close().
|
|
14243
|
+
if (this.dropdown.isBibFullscreen) {
|
|
14244
|
+
requestAnimationFrame(() => {
|
|
14245
|
+
if (!this.dropdown.isPopoverVisible) {
|
|
14246
|
+
this.input.focus();
|
|
14247
|
+
}
|
|
14248
|
+
});
|
|
14249
|
+
}
|
|
14116
14250
|
}
|
|
14117
14251
|
|
|
14118
14252
|
if (this.dropdownOpen) {
|
|
@@ -14122,6 +14256,19 @@ class AuroCombobox extends AuroElement {
|
|
|
14122
14256
|
this.updateBibDialogRole();
|
|
14123
14257
|
|
|
14124
14258
|
if (this.dropdown.isBibFullscreen) {
|
|
14259
|
+
// Guard against spurious validation during the focus transition
|
|
14260
|
+
// from trigger to bib input. Setting trigger.inert = true removes
|
|
14261
|
+
// focus, which fires focusout on the child auro-input before the
|
|
14262
|
+
// bib input receives focus. That focusout triggers the input's own
|
|
14263
|
+
// validate(), which dispatches a composed auroFormElement-validated
|
|
14264
|
+
// event. Because composed events are retargetted at each shadow DOM
|
|
14265
|
+
// boundary, the event appears to originate from the combobox itself
|
|
14266
|
+
// and its listener unconditionally sets this.validity — causing
|
|
14267
|
+
// premature validation. This flag suppresses all validation paths
|
|
14268
|
+
// (focusout handler, handleInputValueChange, validate(), and the
|
|
14269
|
+
// auroFormElement-validated listener) until focus settles in the bib.
|
|
14270
|
+
this._inFullscreenTransition = true;
|
|
14271
|
+
|
|
14125
14272
|
// Hide the trigger from assistive technology so VoiceOver cannot reach it
|
|
14126
14273
|
// behind the fullscreen dialog
|
|
14127
14274
|
this.dropdown.trigger.inert = true;
|
|
@@ -14153,6 +14300,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14153
14300
|
requestAnimationFrame(() => {
|
|
14154
14301
|
requestAnimationFrame(() => {
|
|
14155
14302
|
this.setInputFocus();
|
|
14303
|
+
this._inFullscreenTransition = false;
|
|
14156
14304
|
});
|
|
14157
14305
|
});
|
|
14158
14306
|
} else {
|
|
@@ -14247,7 +14395,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14247
14395
|
* @private
|
|
14248
14396
|
*/
|
|
14249
14397
|
updateBibDialogRole() {
|
|
14250
|
-
const bibEl = this.dropdown.bibElement
|
|
14398
|
+
const bibEl = this.dropdown.bibElement && this.dropdown.bibElement.value;
|
|
14251
14399
|
if (!bibEl) {
|
|
14252
14400
|
return;
|
|
14253
14401
|
}
|
|
@@ -14376,9 +14524,10 @@ class AuroCombobox extends AuroElement {
|
|
|
14376
14524
|
// Announce the selection after the dropdown closes so it isn't
|
|
14377
14525
|
// overridden by VoiceOver's "collapsed" announcement from aria-expanded.
|
|
14378
14526
|
const selectedValue = event.detail.stringValue;
|
|
14527
|
+
const announcementDelay = 300;
|
|
14379
14528
|
setTimeout(() => {
|
|
14380
14529
|
this.announceToScreenReader(`${selectedValue}, selected`);
|
|
14381
|
-
},
|
|
14530
|
+
}, announcementDelay);
|
|
14382
14531
|
}
|
|
14383
14532
|
});
|
|
14384
14533
|
|
|
@@ -14426,7 +14575,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14426
14575
|
* Validate every time we remove focus from the combo box.
|
|
14427
14576
|
*/
|
|
14428
14577
|
this.addEventListener('focusout', () => {
|
|
14429
|
-
if (!this.componentHasFocus) {
|
|
14578
|
+
if (!this.componentHasFocus && !this._inFullscreenTransition) {
|
|
14430
14579
|
this.validate();
|
|
14431
14580
|
}
|
|
14432
14581
|
});
|
|
@@ -14477,8 +14626,11 @@ class AuroCombobox extends AuroElement {
|
|
|
14477
14626
|
}
|
|
14478
14627
|
this.handleMenuOptions();
|
|
14479
14628
|
|
|
14480
|
-
// Validate only if the value was set programmatically
|
|
14481
|
-
|
|
14629
|
+
// Validate only if the value was set programmatically (not during user
|
|
14630
|
+
// interaction). In fullscreen dialog mode, componentHasFocus returns false
|
|
14631
|
+
// because focus is inside the top-layer dialog, so also check
|
|
14632
|
+
// dropdownOpen and the fullscreen transition flag.
|
|
14633
|
+
if (!this.componentHasFocus && !this.dropdownOpen && !this._inFullscreenTransition) {
|
|
14482
14634
|
this.validate();
|
|
14483
14635
|
}
|
|
14484
14636
|
|
|
@@ -14493,6 +14645,22 @@ class AuroCombobox extends AuroElement {
|
|
|
14493
14645
|
this.hideBib();
|
|
14494
14646
|
}
|
|
14495
14647
|
|
|
14648
|
+
// iOS virtual keyboard retention: when in fullscreen mode, ensure the
|
|
14649
|
+
// dialog opens and the bib input is focused synchronously within the
|
|
14650
|
+
// input event (user gesture) chain. Without this, Lit's async update
|
|
14651
|
+
// cycle delays showModal() past the user activation window, causing
|
|
14652
|
+
// iOS Safari to dismiss the virtual keyboard when the fullscreen
|
|
14653
|
+
// dialog opens — the user then has to tap the input again to resume
|
|
14654
|
+
// typing.
|
|
14655
|
+
if (this.dropdown.isBibFullscreen && this.input.value && this.input.value.length > 0) {
|
|
14656
|
+
if (!this.dropdown.isPopoverVisible) {
|
|
14657
|
+
this.showBib();
|
|
14658
|
+
}
|
|
14659
|
+
if (this.dropdown.isPopoverVisible) {
|
|
14660
|
+
this.setInputFocus();
|
|
14661
|
+
}
|
|
14662
|
+
}
|
|
14663
|
+
|
|
14496
14664
|
this.dispatchEvent(new CustomEvent('inputValue', { detail: { value: this.inputValue } }));
|
|
14497
14665
|
}
|
|
14498
14666
|
|
|
@@ -14518,23 +14686,20 @@ class AuroCombobox extends AuroElement {
|
|
|
14518
14686
|
}
|
|
14519
14687
|
|
|
14520
14688
|
if (evt.key === 'Tab' && this.dropdown.isPopoverVisible) {
|
|
14521
|
-
|
|
14522
|
-
|
|
14523
|
-
|
|
14524
|
-
|
|
14525
|
-
|
|
14526
|
-
|
|
14527
|
-
|
|
14528
|
-
|
|
14689
|
+
// Non-fullscreen (combobox pattern per WAI-ARIA APG):
|
|
14690
|
+
// Tab accepts the focused option and closes the popup, moving focus
|
|
14691
|
+
// to the next focusable element on the page.
|
|
14692
|
+
// https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-select-only/
|
|
14693
|
+
//
|
|
14694
|
+
// Fullscreen (dialog / modal pattern): Tab navigates between
|
|
14695
|
+
// focusable elements inside the modal (e.g. the close button) via
|
|
14696
|
+
// the native focus trap provided by showModal(). The dropdown is
|
|
14697
|
+
// closed by the close button or Escape instead.
|
|
14698
|
+
if (!this.dropdown.isBibFullscreen) {
|
|
14529
14699
|
if (this.menu.optionActive && this.menu.optionActive.value) {
|
|
14530
14700
|
this.menu.value = this.menu.optionActive.value;
|
|
14531
14701
|
}
|
|
14532
|
-
|
|
14533
|
-
setTimeout(() => {
|
|
14534
|
-
if (!this.componentHasFocus) {
|
|
14535
|
-
this.hideBib();
|
|
14536
|
-
}
|
|
14537
|
-
}, 0);
|
|
14702
|
+
this.hideBib();
|
|
14538
14703
|
}
|
|
14539
14704
|
}
|
|
14540
14705
|
|
|
@@ -14565,6 +14730,14 @@ class AuroCombobox extends AuroElement {
|
|
|
14565
14730
|
});
|
|
14566
14731
|
|
|
14567
14732
|
this.addEventListener('auroFormElement-validated', (evt) => {
|
|
14733
|
+
// During the fullscreen transition, child elements (auro-input) may fire
|
|
14734
|
+
// their own validation events when the trigger becomes inert and loses
|
|
14735
|
+
// focus. Those composed events bubble up through shadow DOM boundaries
|
|
14736
|
+
// and would incorrectly set combobox validity. Ignore them.
|
|
14737
|
+
if (this._inFullscreenTransition) {
|
|
14738
|
+
return;
|
|
14739
|
+
}
|
|
14740
|
+
|
|
14568
14741
|
this.input.validity = evt.detail.validity;
|
|
14569
14742
|
this.input.errorMessage = evt.detail.message;
|
|
14570
14743
|
this.validity = evt.detail.validity;
|
|
@@ -14668,6 +14841,9 @@ class AuroCombobox extends AuroElement {
|
|
|
14668
14841
|
* @param {boolean} [force=false] - Whether to force validation.
|
|
14669
14842
|
*/
|
|
14670
14843
|
validate(force = false) {
|
|
14844
|
+
if (this._inFullscreenTransition) {
|
|
14845
|
+
return;
|
|
14846
|
+
}
|
|
14671
14847
|
this.validation.validate(this, force);
|
|
14672
14848
|
}
|
|
14673
14849
|
|
|
@@ -14721,7 +14897,13 @@ class AuroCombobox extends AuroElement {
|
|
|
14721
14897
|
}
|
|
14722
14898
|
|
|
14723
14899
|
if (changedProperties.has('availableOptions')) {
|
|
14724
|
-
|
|
14900
|
+
// dropdownOpen is set synchronously by the auroDropdown-toggled event
|
|
14901
|
+
// handler during showBib() → floater.showBib() → dispatchEventDropdownToggle(),
|
|
14902
|
+
// so it's already true by the time updated() runs. This prevents the else
|
|
14903
|
+
// branch from calling hideBib() when the dropdown was just opened but
|
|
14904
|
+
// :focus-within hasn't propagated through the top-layer dialog's nested
|
|
14905
|
+
// shadow DOM boundaries.
|
|
14906
|
+
if ((this.availableOptions.length > 0 && (this.componentHasFocus || this.dropdownOpen)) || this.menu.loading || (this.availableOptions.length === 0 && this.noMatchOption)) {
|
|
14725
14907
|
this.showBib();
|
|
14726
14908
|
} else {
|
|
14727
14909
|
this.hideBib();
|
|
@@ -14896,6 +15078,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14896
15078
|
<slot @slotchange="${this.handleSlotChange}"></slot>
|
|
14897
15079
|
<${this.inputTag}
|
|
14898
15080
|
id="inputInBib"
|
|
15081
|
+
autofocus
|
|
14899
15082
|
@input="${this.handleInputValueChange}"
|
|
14900
15083
|
.a11yActivedescendant="${this.dropdownOpen && this.optionActive ? this.optionActive.id : undefined}"
|
|
14901
15084
|
.a11yControls=${`${this.dropdownId}-floater-bib`}
|