@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
|
@@ -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.
|
|
@@ -12032,7 +12145,7 @@ let AuroHelpText$1 = class AuroHelpText extends LitElement {
|
|
|
12032
12145
|
}
|
|
12033
12146
|
};
|
|
12034
12147
|
|
|
12035
|
-
var formkitVersion$1 = '
|
|
12148
|
+
var formkitVersion$1 = '202602260152';
|
|
12036
12149
|
|
|
12037
12150
|
// Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
|
|
12038
12151
|
// See LICENSE in the project root for license information.
|
|
@@ -13059,7 +13172,7 @@ class AuroBibtemplate extends LitElement {
|
|
|
13059
13172
|
}
|
|
13060
13173
|
}
|
|
13061
13174
|
|
|
13062
|
-
var formkitVersion = '
|
|
13175
|
+
var formkitVersion = '202602260152';
|
|
13063
13176
|
|
|
13064
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}`;
|
|
13065
13178
|
|
|
@@ -13477,6 +13590,7 @@ class AuroCombobox extends AuroElement {
|
|
|
13477
13590
|
this.dropdownOpen = false;
|
|
13478
13591
|
this.triggerExpandedState = false;
|
|
13479
13592
|
this._expandedTimeout = null;
|
|
13593
|
+
this._inFullscreenTransition = false;
|
|
13480
13594
|
this.errorMessage = null;
|
|
13481
13595
|
this.isHiddenWhileLoading = false;
|
|
13482
13596
|
this.largeFullscreenHeadline = false;
|
|
@@ -13497,7 +13611,7 @@ class AuroCombobox extends AuroElement {
|
|
|
13497
13611
|
|
|
13498
13612
|
/**
|
|
13499
13613
|
* Defines whether the component will be on lighter or darker backgrounds.
|
|
13500
|
-
* @property {'default' | 'inverse'}
|
|
13614
|
+
* @property {'default' | 'inverse'} appearance - The visual appearance of the component.
|
|
13501
13615
|
* @default 'default'
|
|
13502
13616
|
*/
|
|
13503
13617
|
appearance: {
|
|
@@ -14052,7 +14166,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14052
14166
|
* @returns {void}
|
|
14053
14167
|
*/
|
|
14054
14168
|
showBib() {
|
|
14055
|
-
if (!this.input.value) {
|
|
14169
|
+
if (!this.input.value && !this.dropdown.isBibFullscreen) {
|
|
14056
14170
|
this.dropdown.hide();
|
|
14057
14171
|
return;
|
|
14058
14172
|
}
|
|
@@ -14121,6 +14235,18 @@ class AuroCombobox extends AuroElement {
|
|
|
14121
14235
|
|
|
14122
14236
|
// Restore trigger accessibility when closing fullscreen
|
|
14123
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
|
+
}
|
|
14124
14250
|
}
|
|
14125
14251
|
|
|
14126
14252
|
if (this.dropdownOpen) {
|
|
@@ -14130,6 +14256,19 @@ class AuroCombobox extends AuroElement {
|
|
|
14130
14256
|
this.updateBibDialogRole();
|
|
14131
14257
|
|
|
14132
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
|
+
|
|
14133
14272
|
// Hide the trigger from assistive technology so VoiceOver cannot reach it
|
|
14134
14273
|
// behind the fullscreen dialog
|
|
14135
14274
|
this.dropdown.trigger.inert = true;
|
|
@@ -14161,6 +14300,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14161
14300
|
requestAnimationFrame(() => {
|
|
14162
14301
|
requestAnimationFrame(() => {
|
|
14163
14302
|
this.setInputFocus();
|
|
14303
|
+
this._inFullscreenTransition = false;
|
|
14164
14304
|
});
|
|
14165
14305
|
});
|
|
14166
14306
|
} else {
|
|
@@ -14255,7 +14395,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14255
14395
|
* @private
|
|
14256
14396
|
*/
|
|
14257
14397
|
updateBibDialogRole() {
|
|
14258
|
-
const bibEl = this.dropdown.bibElement
|
|
14398
|
+
const bibEl = this.dropdown.bibElement && this.dropdown.bibElement.value;
|
|
14259
14399
|
if (!bibEl) {
|
|
14260
14400
|
return;
|
|
14261
14401
|
}
|
|
@@ -14384,9 +14524,10 @@ class AuroCombobox extends AuroElement {
|
|
|
14384
14524
|
// Announce the selection after the dropdown closes so it isn't
|
|
14385
14525
|
// overridden by VoiceOver's "collapsed" announcement from aria-expanded.
|
|
14386
14526
|
const selectedValue = event.detail.stringValue;
|
|
14527
|
+
const announcementDelay = 300;
|
|
14387
14528
|
setTimeout(() => {
|
|
14388
14529
|
this.announceToScreenReader(`${selectedValue}, selected`);
|
|
14389
|
-
},
|
|
14530
|
+
}, announcementDelay);
|
|
14390
14531
|
}
|
|
14391
14532
|
});
|
|
14392
14533
|
|
|
@@ -14434,7 +14575,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14434
14575
|
* Validate every time we remove focus from the combo box.
|
|
14435
14576
|
*/
|
|
14436
14577
|
this.addEventListener('focusout', () => {
|
|
14437
|
-
if (!this.componentHasFocus) {
|
|
14578
|
+
if (!this.componentHasFocus && !this._inFullscreenTransition) {
|
|
14438
14579
|
this.validate();
|
|
14439
14580
|
}
|
|
14440
14581
|
});
|
|
@@ -14485,8 +14626,11 @@ class AuroCombobox extends AuroElement {
|
|
|
14485
14626
|
}
|
|
14486
14627
|
this.handleMenuOptions();
|
|
14487
14628
|
|
|
14488
|
-
// Validate only if the value was set programmatically
|
|
14489
|
-
|
|
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) {
|
|
14490
14634
|
this.validate();
|
|
14491
14635
|
}
|
|
14492
14636
|
|
|
@@ -14501,6 +14645,22 @@ class AuroCombobox extends AuroElement {
|
|
|
14501
14645
|
this.hideBib();
|
|
14502
14646
|
}
|
|
14503
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
|
+
|
|
14504
14664
|
this.dispatchEvent(new CustomEvent('inputValue', { detail: { value: this.inputValue } }));
|
|
14505
14665
|
}
|
|
14506
14666
|
|
|
@@ -14526,23 +14686,20 @@ class AuroCombobox extends AuroElement {
|
|
|
14526
14686
|
}
|
|
14527
14687
|
|
|
14528
14688
|
if (evt.key === 'Tab' && this.dropdown.isPopoverVisible) {
|
|
14529
|
-
|
|
14530
|
-
|
|
14531
|
-
|
|
14532
|
-
|
|
14533
|
-
|
|
14534
|
-
|
|
14535
|
-
|
|
14536
|
-
|
|
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) {
|
|
14537
14699
|
if (this.menu.optionActive && this.menu.optionActive.value) {
|
|
14538
14700
|
this.menu.value = this.menu.optionActive.value;
|
|
14539
14701
|
}
|
|
14540
|
-
|
|
14541
|
-
setTimeout(() => {
|
|
14542
|
-
if (!this.componentHasFocus) {
|
|
14543
|
-
this.hideBib();
|
|
14544
|
-
}
|
|
14545
|
-
}, 0);
|
|
14702
|
+
this.hideBib();
|
|
14546
14703
|
}
|
|
14547
14704
|
}
|
|
14548
14705
|
|
|
@@ -14573,6 +14730,14 @@ class AuroCombobox extends AuroElement {
|
|
|
14573
14730
|
});
|
|
14574
14731
|
|
|
14575
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
|
+
|
|
14576
14741
|
this.input.validity = evt.detail.validity;
|
|
14577
14742
|
this.input.errorMessage = evt.detail.message;
|
|
14578
14743
|
this.validity = evt.detail.validity;
|
|
@@ -14676,6 +14841,9 @@ class AuroCombobox extends AuroElement {
|
|
|
14676
14841
|
* @param {boolean} [force=false] - Whether to force validation.
|
|
14677
14842
|
*/
|
|
14678
14843
|
validate(force = false) {
|
|
14844
|
+
if (this._inFullscreenTransition) {
|
|
14845
|
+
return;
|
|
14846
|
+
}
|
|
14679
14847
|
this.validation.validate(this, force);
|
|
14680
14848
|
}
|
|
14681
14849
|
|
|
@@ -14729,7 +14897,13 @@ class AuroCombobox extends AuroElement {
|
|
|
14729
14897
|
}
|
|
14730
14898
|
|
|
14731
14899
|
if (changedProperties.has('availableOptions')) {
|
|
14732
|
-
|
|
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)) {
|
|
14733
14907
|
this.showBib();
|
|
14734
14908
|
} else {
|
|
14735
14909
|
this.hideBib();
|
|
@@ -14904,6 +15078,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14904
15078
|
<slot @slotchange="${this.handleSlotChange}"></slot>
|
|
14905
15079
|
<${this.inputTag}
|
|
14906
15080
|
id="inputInBib"
|
|
15081
|
+
autofocus
|
|
14907
15082
|
@input="${this.handleInputValueChange}"
|
|
14908
15083
|
.a11yActivedescendant="${this.dropdownOpen && this.optionActive ? this.optionActive.id : undefined}"
|
|
14909
15084
|
.a11yControls=${`${this.dropdownId}-floater-bib`}
|