@aurodesignsystem-dev/auro-formkit 0.0.0-pr1503.3 → 0.0.0-pr1503.5
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/bibtemplate/dist/index.js +1 -1
- package/components/bibtemplate/dist/registered.js +1 -1
- package/components/checkbox/demo/accessibility.md +1 -1
- package/components/checkbox/demo/customize.html +1 -2
- package/components/checkbox/demo/customize.min.js +23 -8
- package/components/checkbox/demo/getting-started.min.js +23 -8
- package/components/checkbox/demo/index.min.js +23 -8
- package/components/checkbox/dist/index.js +23 -8
- package/components/checkbox/dist/registered.js +23 -8
- package/components/combobox/README.md +1 -1
- package/components/combobox/demo/accessibility.md +1 -1
- package/components/combobox/demo/api.md +2 -2
- package/components/combobox/demo/customize.html +1 -2
- package/components/combobox/demo/customize.md +166 -142
- package/components/combobox/demo/customize.min.js +2515 -2316
- package/components/combobox/demo/getting-started.min.js +2515 -2312
- package/components/combobox/demo/index.md +2 -1
- package/components/combobox/demo/index.min.js +2515 -2312
- package/components/combobox/demo/keyboard-behavior.md +3 -146
- package/components/combobox/demo/readme.md +1 -1
- package/components/combobox/demo/why-combobox.md +2 -2
- package/components/combobox/dist/auro-combobox.d.ts +49 -15
- package/components/combobox/dist/index.js +1462 -753
- package/components/combobox/dist/registered.js +1462 -753
- package/components/counter/demo/customize.min.js +188 -244
- package/components/counter/demo/index.min.js +188 -244
- package/components/counter/dist/auro-counter.d.ts +0 -8
- package/components/counter/dist/index.js +188 -244
- package/components/counter/dist/registered.js +188 -244
- package/components/datepicker/demo/accessibility.md +20 -10
- package/components/datepicker/demo/api.md +65 -62
- package/components/datepicker/demo/customize.md +180 -40
- package/components/datepicker/demo/customize.min.js +1690 -777
- package/components/datepicker/demo/getting-started.md +118 -2
- package/components/datepicker/demo/index.min.js +1690 -759
- package/components/datepicker/demo/keyboard-behavior.md +3 -3
- package/components/datepicker/demo/voiceover.md +4 -4
- package/components/datepicker/demo/why-datepicker.md +2 -2
- package/components/datepicker/dist/{src/auro-calendar-cell.d.ts → auro-calendar-cell.d.ts} +48 -3
- package/components/datepicker/dist/{src/auro-calendar.d.ts → auro-calendar.d.ts} +188 -10
- package/components/datepicker/dist/{src/auro-datepicker.d.ts → auro-datepicker.d.ts} +89 -6
- package/components/datepicker/dist/blackoutUtils.d.ts +43 -0
- package/components/datepicker/dist/index.js +1690 -759
- package/components/datepicker/dist/registered.js +1690 -759
- package/components/dropdown/demo/customize.html +3 -0
- package/components/dropdown/demo/customize.min.js +142 -208
- package/components/dropdown/demo/getting-started.min.js +131 -207
- package/components/dropdown/demo/index.min.js +131 -207
- package/components/dropdown/dist/auro-dropdown.d.ts +17 -1
- package/components/dropdown/dist/index.js +131 -207
- package/components/dropdown/dist/registered.js +131 -207
- package/components/form/demo/api.md +3 -3
- package/components/form/demo/customize.html +6 -6
- package/components/form/demo/customize.md +535 -135
- package/components/form/demo/customize.min.js +6307 -4378
- package/components/form/demo/getting-started.md +344 -96
- package/components/form/demo/getting-started.min.js +6255 -4378
- package/components/form/demo/index.min.js +6206 -4378
- package/components/form/demo/registerDemoDeps.min.js +5827 -4333
- package/components/form/dist/auro-form.d.ts +128 -10
- package/components/form/dist/index.js +377 -43
- package/components/form/dist/registered.js +377 -43
- package/components/input/demo/accessibility.md +1 -1
- package/components/input/demo/api.md +58 -57
- package/components/input/demo/customize.html +1 -2
- package/components/input/demo/customize.md +62 -61
- package/components/input/demo/customize.min.js +396 -275
- package/components/input/demo/getting-started.min.js +396 -275
- package/components/input/demo/index.min.js +396 -275
- package/components/input/dist/auro-input.d.ts +1 -1
- package/components/input/dist/base-input.d.ts +60 -81
- package/components/input/dist/index.js +409 -276
- package/components/input/dist/registered.js +396 -275
- package/components/input/dist/utilities.d.ts +10 -1
- package/components/menu/demo/accessibility.md +9 -4
- package/components/menu/demo/api.md +48 -45
- package/components/menu/demo/css-only.md +26 -19
- package/components/menu/demo/customize.md +307 -75
- package/components/menu/demo/design.md +1 -1
- package/components/menu/demo/getting-started.md +144 -7
- package/components/menu/demo/index.min.js +961 -1341
- package/components/menu/demo/keyboard-behavior.md +83 -4
- package/components/menu/demo/voiceover.md +21 -14
- package/components/menu/demo/why-menu.md +8 -9
- package/components/menu/dist/auro-menu-utils.d.ts +19 -0
- package/components/menu/dist/auro-menu.d.ts +97 -116
- package/components/menu/dist/auro-menuoption.d.ts +39 -133
- package/components/menu/dist/index.js +823 -1309
- package/components/menu/dist/registered.js +835 -1309
- package/components/radio/demo/accessibility.md +1 -1
- package/components/radio/demo/customize.min.js +23 -8
- package/components/radio/demo/getting-started.min.js +23 -8
- package/components/radio/demo/index.min.js +23 -8
- package/components/radio/dist/index.js +23 -8
- package/components/radio/dist/registered.js +23 -8
- package/components/select/demo/accessibility.md +6 -1
- package/components/select/demo/api.md +3 -2
- package/components/select/demo/customize.html +1 -2
- package/components/select/demo/customize.md +210 -5
- package/components/select/demo/customize.min.js +1613 -1854
- package/components/select/demo/design.md +10 -10
- package/components/select/demo/getting-started.md +1 -1
- package/components/select/demo/getting-started.min.js +1617 -1903
- package/components/select/demo/index.md +2 -2
- package/components/select/demo/index.min.js +1613 -1854
- package/components/select/demo/keyboard-behavior.md +81 -54
- package/components/select/demo/voiceover.md +28 -15
- package/components/select/dist/auro-select.d.ts +70 -12
- package/components/select/dist/index.js +580 -315
- package/components/select/dist/registered.js +580 -315
- package/components/select/dist/selectUtils.d.ts +24 -0
- package/custom-elements.json +8071 -7919
- package/package.json +7 -3
- package/components/checkbox/demo/customize.js +0 -22
- package/components/checkbox/demo/demo-support.js +0 -1
- package/components/checkbox/demo/getting-started.js +0 -22
- package/components/checkbox/demo/index.js +0 -8
- package/components/checkbox/demo/styles.scss +0 -1
- package/components/combobox/demo/customize.js +0 -24
- package/components/combobox/demo/demo-support.js +0 -1
- package/components/combobox/demo/getting-started.js +0 -21
- package/components/combobox/demo/index.js +0 -23
- package/components/combobox/demo/styles.scss +0 -1
- package/components/counter/demo/customize.js +0 -21
- package/components/counter/demo/demo-support.js +0 -1
- package/components/counter/demo/index.js +0 -21
- package/components/counter/demo/styles.scss +0 -1
- package/components/datepicker/demo/customize.js +0 -19
- package/components/datepicker/demo/demo-support.js +0 -1
- package/components/datepicker/demo/index.js +0 -23
- package/components/datepicker/demo/styles.scss +0 -1
- package/components/dropdown/demo/customize.js +0 -9
- package/components/dropdown/demo/demo-support.js +0 -1
- package/components/dropdown/demo/getting-started.js +0 -9
- package/components/dropdown/demo/index.js +0 -16
- package/components/dropdown/demo/styles.scss +0 -1
- package/components/form/demo/customize.js +0 -9
- package/components/form/demo/demo-support.js +0 -1
- package/components/form/demo/getting-started.js +0 -9
- package/components/form/demo/index.js +0 -5
- package/components/form/demo/registerDemoDeps.js +0 -23
- package/components/form/demo/styles.scss +0 -1
- package/components/input/demo/customize.js +0 -25
- package/components/input/demo/demo-support.js +0 -1
- package/components/input/demo/getting-started.js +0 -8
- package/components/input/demo/index.js +0 -8
- package/components/input/demo/styles.css +0 -974
- package/components/input/demo/styles.scss +0 -1
- package/components/menu/demo/demo-support.js +0 -1
- package/components/menu/demo/index.js +0 -25
- package/components/menu/demo/styles.scss +0 -1
- package/components/menu/dist/auro-menu.context.d.ts +0 -238
- package/components/radio/demo/customize.js +0 -22
- package/components/radio/demo/demo-support.js +0 -1
- package/components/radio/demo/getting-started.js +0 -24
- package/components/radio/demo/index.js +0 -8
- package/components/radio/demo/styles.scss +0 -1
- package/components/select/demo/customize.js +0 -11
- package/components/select/demo/demo-support.js +0 -1
- package/components/select/demo/getting-started.js +0 -26
- package/components/select/demo/index.js +0 -11
- package/components/select/demo/styles.scss +0 -1
- /package/components/counter/dist/styles/{counter-wrapper-color-css.d.ts → counter-group-color-css.d.ts} +0 -0
- /package/components/datepicker/dist/{src/auro-calendar-month.d.ts → auro-calendar-month.d.ts} +0 -0
- /package/components/datepicker/dist/{src/buttonVersion.d.ts → buttonVersion.d.ts} +0 -0
- /package/components/datepicker/dist/{src/datepickerKeyboardStrategy.d.ts → datepickerKeyboardStrategy.d.ts} +0 -0
- /package/components/datepicker/dist/{src/iconVersion.d.ts → iconVersion.d.ts} +0 -0
- /package/components/datepicker/dist/{src/index.d.ts → index.d.ts} +0 -0
- /package/components/datepicker/dist/{src/popoverVersion.d.ts → popoverVersion.d.ts} +0 -0
- /package/components/datepicker/dist/{src/styles → styles}/classic/color-css.d.ts +0 -0
- /package/components/datepicker/dist/{src/styles → styles}/classic/style-css.d.ts +0 -0
- /package/components/datepicker/dist/{src/styles → styles}/color-calendar-css.d.ts +0 -0
- /package/components/datepicker/dist/{src/styles → styles}/color-cell-css.d.ts +0 -0
- /package/components/datepicker/dist/{src/styles → styles}/color-css.d.ts +0 -0
- /package/components/datepicker/dist/{src/styles → styles}/color-month-css.d.ts +0 -0
- /package/components/datepicker/dist/{src/styles → styles}/shapeSize-css.d.ts +0 -0
- /package/components/datepicker/dist/{src/styles → styles}/snowflake/color-css.d.ts +0 -0
- /package/components/datepicker/dist/{src/styles → styles}/snowflake/style-css.d.ts +0 -0
- /package/components/datepicker/dist/{src/styles → styles}/style-auro-calendar-cell-css.d.ts +0 -0
- /package/components/datepicker/dist/{src/styles → styles}/style-auro-calendar-css.d.ts +0 -0
- /package/components/datepicker/dist/{src/styles → styles}/style-auro-calendar-month-css.d.ts +0 -0
- /package/components/datepicker/dist/{src/styles → styles}/style-css.d.ts +0 -0
- /package/components/datepicker/dist/{src/styles → styles}/tokens-css.d.ts +0 -0
- /package/components/datepicker/dist/{src/utilities.d.ts → utilities.d.ts} +0 -0
- /package/components/datepicker/dist/{src/utilitiesCalendar.d.ts → utilitiesCalendar.d.ts} +0 -0
- /package/components/datepicker/dist/{src/utilitiesCalendarRender.d.ts → utilitiesCalendarRender.d.ts} +0 -0
- /package/components/datepicker/dist/{src/vendor → vendor}/wc-range-datepicker/day.d.ts +0 -0
- /package/components/datepicker/dist/{src/vendor → vendor}/wc-range-datepicker/range-datepicker-calendar.d.ts +0 -0
- /package/components/datepicker/dist/{src/vendor → vendor}/wc-range-datepicker/range-datepicker-cell.d.ts +0 -0
- /package/components/datepicker/dist/{src/vendor → vendor}/wc-range-datepicker/range-datepicker.d.ts +0 -0
|
@@ -350,8 +350,21 @@ let AuroFormValidation$1 = class AuroFormValidation {
|
|
|
350
350
|
return;
|
|
351
351
|
}
|
|
352
352
|
|
|
353
|
-
// Validate that the date passed was the correct format and is a valid date
|
|
353
|
+
// Validate that the date passed was the correct format and is a valid date.
|
|
354
|
+
// For partial date formats, valueObject is never populated; validate them directly.
|
|
354
355
|
if (elem.value && !elem.valueObject) {
|
|
356
|
+
const isPartialDateFormat = elem.util && !elem.util.isFullDateFormat(elem.type, elem.format);
|
|
357
|
+
|
|
358
|
+
if (isPartialDateFormat) {
|
|
359
|
+
if (!elem.util.isValidPartialDate(elem.value, elem.format)) {
|
|
360
|
+
elem.validity = 'patternMismatch';
|
|
361
|
+
elem.errorMessage = elem.setCustomValidityPatternMismatch || elem.setCustomValidity || 'Invalid Date Format Entered';
|
|
362
|
+
}
|
|
363
|
+
// Partial date format — validate directly and skip max/min checks since valueObject is undefined.
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Full date format with no valueObject means the value is not a valid calendar date.
|
|
355
368
|
elem.validity = 'patternMismatch';
|
|
356
369
|
elem.errorMessage = elem.setCustomValidityPatternMismatch || elem.setCustomValidity || 'Invalid Date Format Entered';
|
|
357
370
|
return;
|
|
@@ -448,15 +461,17 @@ let AuroFormValidation$1 = class AuroFormValidation {
|
|
|
448
461
|
);
|
|
449
462
|
}
|
|
450
463
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
464
|
+
const isCombobox = this.runtimeUtils.elementMatch(elem, 'auro-combobox');
|
|
465
|
+
|
|
466
|
+
// If there is a second input in the elem and that value is undefined or an empty string set hasValue to false.
|
|
467
|
+
// Skip for combobox: its second auro-input is the fullscreen-bib mirror of the same value, not an independent
|
|
468
|
+
// field (datepicker is the intended consumer — start/end are independently required).
|
|
469
|
+
if (this.auroInputElements?.length === 2 && !isCombobox) {
|
|
470
|
+
if (!this.auroInputElements[1].value || this.auroInputElements[1].value.length === 0) {
|
|
454
471
|
hasValue = false;
|
|
455
472
|
}
|
|
456
473
|
}
|
|
457
474
|
|
|
458
|
-
const isCombobox = this.runtimeUtils.elementMatch(elem, 'auro-combobox');
|
|
459
|
-
|
|
460
475
|
if (isCombobox) {
|
|
461
476
|
|
|
462
477
|
if (!elem.persistInput || elem.behavior === "filter") {
|
|
@@ -555,7 +570,7 @@ let AuroFormValidation$1 = class AuroFormValidation {
|
|
|
555
570
|
} else if (this.runtimeUtils.elementMatch(elem, 'auro-input') && elem.errorMessage === '') {
|
|
556
571
|
const input = elem.renderRoot.querySelector('input');
|
|
557
572
|
|
|
558
|
-
if (input.validationMessage.length > 0) {
|
|
573
|
+
if (input && input.validationMessage.length > 0) {
|
|
559
574
|
elem.errorMessage = input.validationMessage;
|
|
560
575
|
}
|
|
561
576
|
} else if (this.runtimeUtils.elementMatch(elem, 'auro-combobox') && elem.errorMessage === '') {
|
|
@@ -770,6 +785,190 @@ function navigateArrow(component, direction, options = {}) {
|
|
|
770
785
|
/* es-module-lexer 1.7.0 */
|
|
771
786
|
var ImportType$1;!function(A){A[A.Static=1]="Static",A[A.Dynamic=2]="Dynamic",A[A.ImportMeta=3]="ImportMeta",A[A.StaticSourcePhase=4]="StaticSourcePhase",A[A.DynamicSourcePhase=5]="DynamicSourcePhase",A[A.StaticDeferPhase=6]="StaticDeferPhase",A[A.DynamicDeferPhase=7]="DynamicDeferPhase";}(ImportType$1||(ImportType$1={}));1===new Uint8Array(new Uint16Array([1]).buffer)[0];const E$1=()=>{return A="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GzYCHAtBAEEAKAKwCkECajYCsAoCQAJAAkACQEEAECkiAUHhAEYNACABQfcARg0BQQAoArAKIQEMAgtBACgCsAoiAUECakHACEEKEC8NAUEGIQIMAgtBACgCsAoiAS8BAkHpAEcNACABLwEEQfQARw0AQQQhAiABLwEGQegARg0BC0EAIAFBfmo2ArAKDwtBACABIAJBAXRqNgKwCgJAQQEQKUH7AEYNAEEAIAE2ArAKDwtBACgCsAoiACECA0BBACACQQJqNgKwCgJAAkACQEEBECkiAkEiRg0AIAJBJ0cNAUEnEBpBAEEAKAKwCkECajYCsApBARApIQIMAgtBIhAaQQBBACgCsApBAmo2ArAKQQEQKSECDAELIAIQLCECCwJAIAJBOkYNAEEAIAE2ArAKDwtBAEEAKAKwCkECajYCsAoCQEEBECkiAkEiRg0AIAJBJ0YNAEEAIAE2ArAKDwsgAhAaQQBBACgCsApBAmo2ArAKAkACQEEBECkiAkEsRg0AIAJB/QBGDQFBACABNgKwCg8LQQBBACgCsApBAmo2ArAKQQEQKUH9AEYNAEEAKAKwCiECDAELC0EAKALwCSIBIAA2AhAgAUEAKAKwCkECajYCDAttAQJ/AkACQANAAkAgAEH//wNxIgFBd2oiAkEXSw0AQQEgAnRBn4CABHENAgsgAUGgAUYNASAAIQIgARAoDQJBACECQQBBACgCsAoiAEECajYCsAogAC8BAiIADQAMAgsLIAAhAgsgAkH//wNxC6sBAQR/AkACQEEAKAKwCiICLwEAIgNB4QBGDQAgASEEIAAhBQwBC0EAIAJBBGo2ArAKQQEQKSECQQAoArAKIQUCQAJAIAJBIkYNACACQSdGDQAgAhAsGkEAKAKwCiEEDAELIAIQGkEAQQAoArAKQQJqIgQ2ArAKC0EBECkhA0EAKAKwCiECCwJAIAIgBUYNACAFIARBACAAIAAgAUYiAhtBACABIAIbEAILIAMLcgEEf0EAKAKwCiEAQQAoArQKIQECQAJAA0AgAEECaiECIAAgAU8NAQJAAkAgAi8BACIDQaR/ag4CAQQACyACIQAgA0F2ag4EAgEBAgELIABBBGohAAwACwtBACACNgKwChAlQQAPC0EAIAI2ArAKQd0AC0kBA39BACEDAkAgAkUNAAJAA0AgAC0AACIEIAEtAAAiBUcNASABQQFqIQEgAEEBaiEAIAJBf2oiAg0ADAILCyAEIAVrIQMLIAMLC+wBAgBBgAgLzgEAAHgAcABvAHIAdABtAHAAbwByAHQAZgBvAHIAZQB0AGEAbwB1AHIAYwBlAHIAbwBtAHUAbgBjAHQAaQBvAG4AcwBzAGUAcgB0AHYAbwB5AGkAZQBkAGUAbABlAGMAbwBuAHQAaQBuAGkAbgBzAHQAYQBuAHQAeQBiAHIAZQBhAHIAZQB0AHUAcgBkAGUAYgB1AGcAZwBlAGEAdwBhAGkAdABoAHIAdwBoAGkAbABlAGkAZgBjAGEAdABjAGYAaQBuAGEAbABsAGUAbABzAABB0AkLEAEAAAACAAAAAAQAAEA5AAA=","undefined"!=typeof Buffer?Buffer.from(A,"base64"):Uint8Array.from(atob(A),(A=>A.charCodeAt(0)));var A;};WebAssembly.compile(E$1()).then(WebAssembly.instantiate).then((({exports:A})=>{}));
|
|
772
787
|
|
|
788
|
+
// Selectors for focusable elements
|
|
789
|
+
const FOCUSABLE_SELECTORS$1 = [
|
|
790
|
+
"a[href]",
|
|
791
|
+
"button:not([disabled])",
|
|
792
|
+
"textarea:not([disabled])",
|
|
793
|
+
"input:not([disabled])",
|
|
794
|
+
"select:not([disabled])",
|
|
795
|
+
'[role="tab"]:not([disabled])',
|
|
796
|
+
'[role="link"]:not([disabled])',
|
|
797
|
+
'[role="button"]:not([disabled])',
|
|
798
|
+
'[tabindex]:not([tabindex="-1"])',
|
|
799
|
+
'[contenteditable]:not([contenteditable="false"])',
|
|
800
|
+
];
|
|
801
|
+
|
|
802
|
+
// List of custom components that are known to be focusable
|
|
803
|
+
const FOCUSABLE_COMPONENTS$1 = [
|
|
804
|
+
"auro-checkbox",
|
|
805
|
+
"auro-radio",
|
|
806
|
+
"auro-dropdown",
|
|
807
|
+
"auro-button",
|
|
808
|
+
"auro-combobox",
|
|
809
|
+
"auro-input",
|
|
810
|
+
"auro-counter",
|
|
811
|
+
// 'auro-menu', // Auro menu is not focusable by default, it uses a different interaction model
|
|
812
|
+
"auro-select",
|
|
813
|
+
"auro-datepicker",
|
|
814
|
+
"auro-hyperlink",
|
|
815
|
+
"auro-accordion",
|
|
816
|
+
];
|
|
817
|
+
|
|
818
|
+
/**
|
|
819
|
+
* Determines if a given element is a custom focusable component.
|
|
820
|
+
* Returns true if the element matches a known focusable component and is not disabled.
|
|
821
|
+
*
|
|
822
|
+
* @param {HTMLElement} element The element to check for focusability.
|
|
823
|
+
* @returns {boolean} True if the element is a focusable custom component, false otherwise.
|
|
824
|
+
*/
|
|
825
|
+
function isFocusableComponent$1(element) {
|
|
826
|
+
const componentName = element.tagName.toLowerCase();
|
|
827
|
+
|
|
828
|
+
// Guard Clause: Element is a focusable component
|
|
829
|
+
if (
|
|
830
|
+
!FOCUSABLE_COMPONENTS$1.some(
|
|
831
|
+
(name) => element.hasAttribute(name) || componentName === name,
|
|
832
|
+
)
|
|
833
|
+
)
|
|
834
|
+
return false;
|
|
835
|
+
|
|
836
|
+
// Guard Clause: Element is not disabled
|
|
837
|
+
if (element.hasAttribute("disabled")) return false;
|
|
838
|
+
|
|
839
|
+
// Guard Clause: The element is a hyperlink and has no href attribute
|
|
840
|
+
if (componentName.match("hyperlink") && !element.hasAttribute("href"))
|
|
841
|
+
return false;
|
|
842
|
+
|
|
843
|
+
// If all guard clauses pass, the element is a focusable component
|
|
844
|
+
return true;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
/**
|
|
848
|
+
* Safely get a numeric tabindex for an element.
|
|
849
|
+
* Returns a number if the tabindex is a valid integer, otherwise null.
|
|
850
|
+
*
|
|
851
|
+
* @param {HTMLElement} element The element whose tabindex to read.
|
|
852
|
+
* @returns {?number} The numeric tabindex or null if missing/invalid.
|
|
853
|
+
*/
|
|
854
|
+
function getNumericTabIndex$1(element) {
|
|
855
|
+
const raw = element.getAttribute("tabindex");
|
|
856
|
+
if (raw == null) return null;
|
|
857
|
+
|
|
858
|
+
const value = Number.parseInt(raw, 10);
|
|
859
|
+
return Number.isNaN(value) ? null : value;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
/**
|
|
863
|
+
* Retrieves all focusable elements within the container in DOM order, including those in shadow DOM and slots.
|
|
864
|
+
* Returns a unique, ordered array of elements that can receive focus.
|
|
865
|
+
* Also sorts elements with tabindex first, preserving their order.
|
|
866
|
+
*
|
|
867
|
+
* @param {HTMLElement} container The container to search within
|
|
868
|
+
* @returns {Array<HTMLElement>} An array of focusable elements within the container.
|
|
869
|
+
*/
|
|
870
|
+
function getFocusableElements$1(container) {
|
|
871
|
+
// Get elements in DOM order by walking the tree
|
|
872
|
+
const orderedFocusableElements = [];
|
|
873
|
+
|
|
874
|
+
// Define a recursive function to collect focusable elements in DOM order
|
|
875
|
+
const collectFocusableElements = (root) => {
|
|
876
|
+
// Check if current element is focusable
|
|
877
|
+
if (root.nodeType === Node.ELEMENT_NODE) {
|
|
878
|
+
// Check if this is a custom component that is focusable
|
|
879
|
+
const isComponentFocusable = isFocusableComponent$1(root);
|
|
880
|
+
|
|
881
|
+
if (isComponentFocusable) {
|
|
882
|
+
// Add the component itself as a focusable element and don't traverse its shadow DOM
|
|
883
|
+
orderedFocusableElements.push(root);
|
|
884
|
+
return; // Skip traversing inside this component
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
// Check if the element itself matches any selector
|
|
888
|
+
for (const selector of FOCUSABLE_SELECTORS$1) {
|
|
889
|
+
if (root.matches?.(selector)) {
|
|
890
|
+
orderedFocusableElements.push(root);
|
|
891
|
+
break; // Once we know it's focusable, no need to check other selectors
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
// Process shadow DOM only for non-Auro components
|
|
896
|
+
if (root.shadowRoot) {
|
|
897
|
+
// Process shadow DOM children in order
|
|
898
|
+
if (root.shadowRoot.children) {
|
|
899
|
+
Array.from(root.shadowRoot.children).forEach((child) => {
|
|
900
|
+
collectFocusableElements(child);
|
|
901
|
+
});
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
// Process slots and their assigned nodes in order
|
|
906
|
+
if (root.tagName === "SLOT") {
|
|
907
|
+
const assignedNodes = root.assignedNodes({ flatten: true });
|
|
908
|
+
for (const node of assignedNodes) {
|
|
909
|
+
collectFocusableElements(node);
|
|
910
|
+
}
|
|
911
|
+
} else {
|
|
912
|
+
// Process light DOM children in order
|
|
913
|
+
if (root.children) {
|
|
914
|
+
Array.from(root.children).forEach((child) => {
|
|
915
|
+
collectFocusableElements(child);
|
|
916
|
+
});
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
};
|
|
921
|
+
|
|
922
|
+
// Start the traversal from the container
|
|
923
|
+
collectFocusableElements(container);
|
|
924
|
+
|
|
925
|
+
// Remove duplicates that might have been collected through different paths
|
|
926
|
+
// while preserving order
|
|
927
|
+
const uniqueElements = [];
|
|
928
|
+
const seen = new Set();
|
|
929
|
+
|
|
930
|
+
for (const element of orderedFocusableElements) {
|
|
931
|
+
if (!seen.has(element)) {
|
|
932
|
+
seen.add(element);
|
|
933
|
+
uniqueElements.push(element);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
// Move tab-indexed elements to the front while preserving their order
|
|
938
|
+
// This ensures that elements with tabindex are prioritized in the focus order
|
|
939
|
+
|
|
940
|
+
// First extract elements with valid positive tabindex
|
|
941
|
+
const elementsWithTabindex = uniqueElements.filter((el) => {
|
|
942
|
+
const tabindex = getNumericTabIndex$1(el);
|
|
943
|
+
return tabindex !== null && tabindex > 0;
|
|
944
|
+
});
|
|
945
|
+
|
|
946
|
+
// Sort these elements by their tabindex value
|
|
947
|
+
elementsWithTabindex.sort((a, b) => {
|
|
948
|
+
const aIndex = getNumericTabIndex$1(a) ?? 0;
|
|
949
|
+
const bIndex = getNumericTabIndex$1(b) ?? 0;
|
|
950
|
+
return aIndex - bIndex;
|
|
951
|
+
});
|
|
952
|
+
|
|
953
|
+
// Elements without tabindex (preserving their original order)
|
|
954
|
+
const elementsWithoutTabindex = uniqueElements.filter((el) => {
|
|
955
|
+
const tabindex = getNumericTabIndex$1(el);
|
|
956
|
+
|
|
957
|
+
// Elements without tabindex or with tabindex of 0 stay in DOM order
|
|
958
|
+
return tabindex === null || tabindex === 0;
|
|
959
|
+
});
|
|
960
|
+
|
|
961
|
+
// Combine both arrays with tabindex elements first
|
|
962
|
+
const tabIndexedUniqueElements = [
|
|
963
|
+
...elementsWithTabindex,
|
|
964
|
+
...elementsWithoutTabindex,
|
|
965
|
+
];
|
|
966
|
+
|
|
967
|
+
return tabIndexedUniqueElements;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
/* eslint-disable no-underscore-dangle */
|
|
971
|
+
|
|
773
972
|
/**
|
|
774
973
|
* Returns the clear button element from the active input's shadow
|
|
775
974
|
* DOM, if available.
|
|
@@ -800,6 +999,95 @@ function isClearBtnFocused(ctx, clearBtn = getClearBtn(ctx)) {
|
|
|
800
999
|
return isFocused;
|
|
801
1000
|
}
|
|
802
1001
|
|
|
1002
|
+
/**
|
|
1003
|
+
* Reconcile the menu `_index` from `optionActive` so subsequent `makeSelection` calls find the correct option after async clearSelection has reset it.
|
|
1004
|
+
* @param {Object} menu - The menu component.
|
|
1005
|
+
*/
|
|
1006
|
+
function reconcileMenuIndex(menu) {
|
|
1007
|
+
if (menu._index < 0 && menu.optionActive && menu.items) {
|
|
1008
|
+
const idx = menu.items.indexOf(menu.optionActive);
|
|
1009
|
+
if (idx >= 0) {
|
|
1010
|
+
menu._index = idx;
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
/**
|
|
1016
|
+
* Commit the highlighted option and close the bib.
|
|
1017
|
+
* @param {Element} component - The auro-combobox host element.
|
|
1018
|
+
*/
|
|
1019
|
+
function selectAndClose(component) {
|
|
1020
|
+
reconcileMenuIndex(component.menu);
|
|
1021
|
+
component.menu.makeSelection();
|
|
1022
|
+
component.hideBib();
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
/**
|
|
1026
|
+
* Whether `el` is currently visible enough to receive focus. Prefers the
|
|
1027
|
+
* browser's `checkVisibility()` (Chrome/Safari; Firefox behind a flag until
|
|
1028
|
+
* recently); otherwise combines a display/visibility check with an
|
|
1029
|
+
* ancestor-hidden probe that keeps position:fixed elements visible.
|
|
1030
|
+
* @param {Element} el - The element to test.
|
|
1031
|
+
* @returns {boolean}
|
|
1032
|
+
*/
|
|
1033
|
+
function isVisibleForFocus(el) {
|
|
1034
|
+
if (typeof el.checkVisibility === 'function') {
|
|
1035
|
+
return el.checkVisibility();
|
|
1036
|
+
}
|
|
1037
|
+
const style = el.ownerDocument.defaultView.getComputedStyle(el);
|
|
1038
|
+
if (style.display === 'none' || style.visibility === 'hidden') {
|
|
1039
|
+
return false;
|
|
1040
|
+
}
|
|
1041
|
+
return el.offsetParent !== null || style.position === 'fixed';
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
/**
|
|
1045
|
+
* Return the tab stop that comes before `component` in page tab order,
|
|
1046
|
+
* skipping any hidden entries the walker doesn't filter itself.
|
|
1047
|
+
* @param {Element} component - The auro-combobox host element.
|
|
1048
|
+
* @returns {Element|null}
|
|
1049
|
+
*/
|
|
1050
|
+
function getPreviousTabStop(component) {
|
|
1051
|
+
const tabStops = getFocusableElements$1(component.ownerDocument.body);
|
|
1052
|
+
const componentIndex = tabStops.indexOf(component);
|
|
1053
|
+
for (let index = componentIndex - 1; index >= 0; index -= 1) {
|
|
1054
|
+
if (isVisibleForFocus(tabStops[index])) {
|
|
1055
|
+
return tabStops[index];
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
return null;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
/**
|
|
1062
|
+
* Commit the highlighted option, close the bib, and move focus to the tab
|
|
1063
|
+
* stop before the combobox — the Shift+Tab exit path (AB#1592239).
|
|
1064
|
+
* Returns true when this function moved focus and the caller should
|
|
1065
|
+
* preventDefault; false when no previous tab stop was found and the browser's
|
|
1066
|
+
* native traversal should run.
|
|
1067
|
+
* @param {Element} component - The auro-combobox host element.
|
|
1068
|
+
* @returns {boolean}
|
|
1069
|
+
*/
|
|
1070
|
+
function selectAndExitBackward(component) {
|
|
1071
|
+
const previousTabStop = getPreviousTabStop(component);
|
|
1072
|
+
|
|
1073
|
+
// Opts this selection out of setClearBtnFocus so the focus move below
|
|
1074
|
+
// isn't clobbered. Consumed by auro-combobox's selection listener; also
|
|
1075
|
+
// cleared via microtask in case makeSelection is a no-op and the listener
|
|
1076
|
+
// never fires (microtasks run before the next user event, so this can't
|
|
1077
|
+
// leak into an unrelated selection).
|
|
1078
|
+
component._suppressClearBtnFocusOnSelection = true;
|
|
1079
|
+
selectAndClose(component);
|
|
1080
|
+
queueMicrotask(() => {
|
|
1081
|
+
component._suppressClearBtnFocusOnSelection = false;
|
|
1082
|
+
});
|
|
1083
|
+
|
|
1084
|
+
if (!previousTabStop) {
|
|
1085
|
+
return false;
|
|
1086
|
+
}
|
|
1087
|
+
doubleRaf(() => previousTabStop.focus());
|
|
1088
|
+
return true;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
803
1091
|
const comboboxKeyboardStrategy = {
|
|
804
1092
|
ArrowDown(component, evt, ctx) {
|
|
805
1093
|
// If the clear button has focus, let the browser handle ArrowDown normally.
|
|
@@ -813,11 +1101,7 @@ const comboboxKeyboardStrategy = {
|
|
|
813
1101
|
|
|
814
1102
|
// navigate if bib is open otherwise open it
|
|
815
1103
|
if (component.dropdown.isPopoverVisible) {
|
|
816
|
-
|
|
817
|
-
component.activateLastEnabledAvailableOption();
|
|
818
|
-
} else {
|
|
819
|
-
navigateArrow(component, 'down');
|
|
820
|
-
}
|
|
1104
|
+
navigateArrow(component, 'down');
|
|
821
1105
|
} else {
|
|
822
1106
|
component.showBib();
|
|
823
1107
|
}
|
|
@@ -836,11 +1120,7 @@ const comboboxKeyboardStrategy = {
|
|
|
836
1120
|
|
|
837
1121
|
// navigate if bib is open otherwise open it
|
|
838
1122
|
if (component.dropdown.isPopoverVisible) {
|
|
839
|
-
|
|
840
|
-
component.activateFirstEnabledAvailableOption();
|
|
841
|
-
} else {
|
|
842
|
-
navigateArrow(component, 'up');
|
|
843
|
-
}
|
|
1123
|
+
navigateArrow(component, 'up');
|
|
844
1124
|
} else {
|
|
845
1125
|
component.showBib();
|
|
846
1126
|
}
|
|
@@ -856,13 +1136,19 @@ const comboboxKeyboardStrategy = {
|
|
|
856
1136
|
},
|
|
857
1137
|
|
|
858
1138
|
Enter(component, evt, ctx) {
|
|
1139
|
+
// Forms should not submit on Enter from a combobox, regardless of which
|
|
1140
|
+
// child element (input, clear button, menu) is focused.
|
|
1141
|
+
evt.stopPropagation();
|
|
1142
|
+
|
|
859
1143
|
if (isClearBtnFocused(ctx)) {
|
|
860
|
-
//
|
|
861
|
-
//
|
|
862
|
-
//
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
1144
|
+
// Let the browser dispatch Enter to the focused clear button so its
|
|
1145
|
+
// built-in activation fires and clears the selection. Do NOT call
|
|
1146
|
+
// preventDefault — that would block the activation.
|
|
1147
|
+
return;
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
if (ctx.isExpanded && component.menu.optionActive) {
|
|
1151
|
+
reconcileMenuIndex(component.menu);
|
|
866
1152
|
component.menu.makeSelection();
|
|
867
1153
|
|
|
868
1154
|
if (ctx.isModal) {
|
|
@@ -870,14 +1156,8 @@ const comboboxKeyboardStrategy = {
|
|
|
870
1156
|
}
|
|
871
1157
|
|
|
872
1158
|
evt.preventDefault();
|
|
873
|
-
evt.stopPropagation();
|
|
874
1159
|
} else {
|
|
875
|
-
// Prevent the keypress from bubbling to parent containers (e.g., forms)
|
|
876
|
-
// which could interpret Enter as a submit or trigger other unintended behavior.
|
|
877
|
-
// This is safe because showBib() opens the dialog programmatically,
|
|
878
|
-
// not via event propagation.
|
|
879
1160
|
evt.preventDefault();
|
|
880
|
-
evt.stopPropagation();
|
|
881
1161
|
component.showBib();
|
|
882
1162
|
}
|
|
883
1163
|
},
|
|
@@ -907,21 +1187,21 @@ const comboboxKeyboardStrategy = {
|
|
|
907
1187
|
|
|
908
1188
|
Tab(component, evt, ctx) {
|
|
909
1189
|
if (ctx.isExpanded && !isClearBtnFocused(ctx)) {
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
1190
|
+
if (evt.shiftKey) {
|
|
1191
|
+
if (selectAndExitBackward(component)) {
|
|
1192
|
+
evt.preventDefault();
|
|
1193
|
+
}
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
915
1196
|
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
if (ctx.isModal && !evt.shiftKey) {
|
|
1197
|
+
selectAndClose(component);
|
|
1198
|
+
|
|
1199
|
+
if (ctx.isModal) {
|
|
1200
|
+
// Fullscreen close does not automatically restore focus to the input.
|
|
921
1201
|
component.setClearBtnFocus();
|
|
922
1202
|
}
|
|
923
1203
|
}
|
|
924
|
-
}
|
|
1204
|
+
}
|
|
925
1205
|
};
|
|
926
1206
|
|
|
927
1207
|
// Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
|
|
@@ -3176,12 +3456,40 @@ class AuroFloatingUI {
|
|
|
3176
3456
|
return;
|
|
3177
3457
|
}
|
|
3178
3458
|
|
|
3459
|
+
// Chrome-specific: during popover top-layer promotion after a click on a
|
|
3460
|
+
// slotted focusable, :focus-within can briefly evaluate false while the
|
|
3461
|
+
// active element is still structurally inside the trigger/bib. Fall back
|
|
3462
|
+
// to a shadow-piercing ancestry walk from the deep active element before
|
|
3463
|
+
// treating this as a real focus loss.
|
|
3464
|
+
try {
|
|
3465
|
+
let active = document.activeElement;
|
|
3466
|
+
while (active && active.shadowRoot && active.shadowRoot.activeElement) {
|
|
3467
|
+
active = active.shadowRoot.activeElement;
|
|
3468
|
+
}
|
|
3469
|
+
const targets = [element, element.trigger, element.bib].filter(Boolean);
|
|
3470
|
+
let node = active;
|
|
3471
|
+
while (node) {
|
|
3472
|
+
if (targets.includes(node)) {
|
|
3473
|
+
return;
|
|
3474
|
+
}
|
|
3475
|
+
node =
|
|
3476
|
+
node.parentElement ||
|
|
3477
|
+
(node.getRootNode && node.getRootNode().host) ||
|
|
3478
|
+
null;
|
|
3479
|
+
}
|
|
3480
|
+
} catch (e) {
|
|
3481
|
+
// Defensive: fall through to the existing close path if traversal fails.
|
|
3482
|
+
}
|
|
3483
|
+
|
|
3179
3484
|
// if fullscreen bib is in fullscreen mode, do not close
|
|
3180
3485
|
if (element.bib.hasAttribute("isfullscreen")) {
|
|
3181
3486
|
return;
|
|
3182
3487
|
}
|
|
3183
3488
|
|
|
3184
|
-
|
|
3489
|
+
// eventType "focusloss" distinguishes a Tab/click-driven close from an
|
|
3490
|
+
// Escape keydown close. Consumers use this to decide whether to restore
|
|
3491
|
+
// focus to the trigger (Escape) or let it advance naturally (Tab).
|
|
3492
|
+
this.hideBib("focusloss");
|
|
3185
3493
|
}
|
|
3186
3494
|
|
|
3187
3495
|
setupHideHandlers() {
|
|
@@ -3838,210 +4146,17 @@ function getFocusableElements(container) {
|
|
|
3838
4146
|
const elementsWithoutTabindex = uniqueElements.filter((el) => {
|
|
3839
4147
|
const tabindex = getNumericTabIndex(el);
|
|
3840
4148
|
|
|
3841
|
-
// Elements without tabindex or with tabindex of 0 stay in DOM order
|
|
3842
|
-
return tabindex === null || tabindex === 0;
|
|
3843
|
-
});
|
|
3844
|
-
|
|
3845
|
-
// Combine both arrays with tabindex elements first
|
|
3846
|
-
const tabIndexedUniqueElements = [
|
|
3847
|
-
...elementsWithTabindex,
|
|
3848
|
-
...elementsWithoutTabindex,
|
|
3849
|
-
];
|
|
3850
|
-
|
|
3851
|
-
return tabIndexedUniqueElements;
|
|
3852
|
-
}
|
|
3853
|
-
|
|
3854
|
-
/**
|
|
3855
|
-
* FocusTrap manages keyboard focus within a specified container element, ensuring that focus does not leave the container when tabbing.
|
|
3856
|
-
* It is commonly used for modal dialogs or overlays to improve accessibility by trapping focus within interactive UI components.
|
|
3857
|
-
*/
|
|
3858
|
-
class FocusTrap {
|
|
3859
|
-
/**
|
|
3860
|
-
* Creates a new FocusTrap instance for the given container element.
|
|
3861
|
-
* Initializes event listeners and prepares the container for focus management.
|
|
3862
|
-
*
|
|
3863
|
-
* @param {HTMLElement} container The DOM element to trap focus within.
|
|
3864
|
-
* @param {boolean} [controlTabOrder=false] If true enables manual control of the tab order by the FocusTrap.
|
|
3865
|
-
* @throws {Error} If the provided container is not a valid HTMLElement.
|
|
3866
|
-
*/
|
|
3867
|
-
constructor(container, controlTabOrder = false) {
|
|
3868
|
-
if (!container || !(container instanceof HTMLElement)) {
|
|
3869
|
-
throw new Error("FocusTrap requires a valid HTMLElement.");
|
|
3870
|
-
}
|
|
3871
|
-
|
|
3872
|
-
this.container = container;
|
|
3873
|
-
this.tabDirection = "forward"; // or 'backward';
|
|
3874
|
-
this.controlTabOrder = controlTabOrder;
|
|
3875
|
-
|
|
3876
|
-
this._init();
|
|
3877
|
-
}
|
|
3878
|
-
|
|
3879
|
-
/**
|
|
3880
|
-
* Initializes the focus trap by setting up event listeners and attributes on the container.
|
|
3881
|
-
* Prepares the container for focus management, including support for shadow DOM and inert attributes.
|
|
3882
|
-
*
|
|
3883
|
-
* @private
|
|
3884
|
-
*/
|
|
3885
|
-
_init() {
|
|
3886
|
-
// Add inert attribute to prevent focusing programmatically as well (if supported)
|
|
3887
|
-
if ("inert" in HTMLElement.prototype) {
|
|
3888
|
-
this.container.inert = false; // Ensure the container isn't inert
|
|
3889
|
-
this.container.setAttribute("data-focus-trap-container", true); // Mark for identification
|
|
3890
|
-
}
|
|
3891
|
-
|
|
3892
|
-
// Track tab direction
|
|
3893
|
-
this.container.addEventListener("keydown", this._onKeydown);
|
|
3894
|
-
}
|
|
3895
|
-
|
|
3896
|
-
/**
|
|
3897
|
-
* Gets an array of currently active (focused) elements in the document and shadow DOM.
|
|
3898
|
-
* @returns {Array<HTMLElement>} An array of focusable elements within the container.
|
|
3899
|
-
* @private
|
|
3900
|
-
*/
|
|
3901
|
-
_getActiveElements() {
|
|
3902
|
-
// Get the active element(s) in the document and shadow root
|
|
3903
|
-
// This will include the active element in the shadow DOM if it exists
|
|
3904
|
-
// Active element may be inside the shadow DOM depending on delegatesFocus, so we need to check both
|
|
3905
|
-
let { activeElement } = document;
|
|
3906
|
-
const actives = [activeElement];
|
|
3907
|
-
while (activeElement?.shadowRoot?.activeElement) {
|
|
3908
|
-
actives.push(activeElement.shadowRoot.activeElement);
|
|
3909
|
-
activeElement = activeElement.shadowRoot.activeElement;
|
|
3910
|
-
}
|
|
3911
|
-
return actives;
|
|
3912
|
-
}
|
|
3913
|
-
|
|
3914
|
-
/**
|
|
3915
|
-
* Gets the next focus index based on the current index and focusable elements.
|
|
3916
|
-
* @param {number} currentIndex The current index of the focused element.
|
|
3917
|
-
* @param {Array<HTMLElement>} focusables The array of focusable elements.
|
|
3918
|
-
* @returns {number|null} The next focus index or null if not determined.
|
|
3919
|
-
*/
|
|
3920
|
-
_getNextFocusIndex(currentIndex, focusables, actives) {
|
|
3921
|
-
if (this.controlTabOrder) {
|
|
3922
|
-
// Calculate the new index based on the current index and tab direction
|
|
3923
|
-
let newFocusIndex =
|
|
3924
|
-
currentIndex + (this.tabDirection === "forward" ? 1 : -1);
|
|
3925
|
-
|
|
3926
|
-
// Wrap-around logic
|
|
3927
|
-
if (newFocusIndex < 0) newFocusIndex = focusables.length - 1;
|
|
3928
|
-
if (newFocusIndex >= focusables.length) newFocusIndex = 0;
|
|
3929
|
-
|
|
3930
|
-
// Early return with the new index
|
|
3931
|
-
return newFocusIndex;
|
|
3932
|
-
}
|
|
3933
|
-
|
|
3934
|
-
// Determine if we need to wrap
|
|
3935
|
-
const atFirst =
|
|
3936
|
-
actives.includes(focusables[0]) || actives.includes(this.container);
|
|
3937
|
-
const atLast = actives.includes(focusables[focusables.length - 1]);
|
|
3938
|
-
|
|
3939
|
-
// Only wrap if at the ends
|
|
3940
|
-
if (this.tabDirection === "backward" && atFirst) {
|
|
3941
|
-
return focusables.length - 1;
|
|
3942
|
-
}
|
|
3943
|
-
|
|
3944
|
-
if (this.tabDirection === "forward" && atLast) {
|
|
3945
|
-
return 0;
|
|
3946
|
-
}
|
|
3947
|
-
|
|
3948
|
-
// No wrap, so don't change focus, return early
|
|
3949
|
-
return null;
|
|
3950
|
-
}
|
|
3951
|
-
|
|
3952
|
-
/**
|
|
3953
|
-
* Handles the Tab key press event to manage focus within the container.
|
|
3954
|
-
* @param {KeyboardEvent} e The keyboard event triggered by the user.
|
|
3955
|
-
* @returns {void}
|
|
3956
|
-
*/
|
|
3957
|
-
_handleTabKey(e) {
|
|
3958
|
-
// Update the focusable elements
|
|
3959
|
-
const focusables = this._getFocusableElements();
|
|
3960
|
-
|
|
3961
|
-
// If there are no focusable elements, exit
|
|
3962
|
-
if (!focusables.length) return;
|
|
3963
|
-
|
|
3964
|
-
// Set the tab direction based on the key pressed
|
|
3965
|
-
this.tabDirection = e.shiftKey ? "backward" : "forward";
|
|
3966
|
-
|
|
3967
|
-
// Get the active elements that are currently focused
|
|
3968
|
-
const actives = this._getActiveElements();
|
|
3969
|
-
|
|
3970
|
-
// If we're at either end of the focusable elements, wrap around to the other end
|
|
3971
|
-
let focusIndex = focusables.findIndex((el) => actives.includes(el));
|
|
3972
|
-
|
|
3973
|
-
// Fallback if we have no focused element
|
|
3974
|
-
if (focusIndex === -1) focusIndex = 0;
|
|
3975
|
-
|
|
3976
|
-
// Get the next focus index based on the current focus index, tab direction, and controlTabOrder setting
|
|
3977
|
-
// Is null if no new focus index is determined
|
|
3978
|
-
const newFocusIndex = this._getNextFocusIndex(
|
|
3979
|
-
focusIndex,
|
|
3980
|
-
focusables,
|
|
3981
|
-
actives,
|
|
3982
|
-
);
|
|
3983
|
-
|
|
3984
|
-
// If we have a new focus index, set focus to that element
|
|
3985
|
-
if (newFocusIndex !== null) {
|
|
3986
|
-
e.preventDefault();
|
|
3987
|
-
focusables[newFocusIndex].focus();
|
|
3988
|
-
}
|
|
3989
|
-
}
|
|
3990
|
-
|
|
3991
|
-
/**
|
|
3992
|
-
* Catches the keydown event
|
|
3993
|
-
* @param {KeyboardEvent} e The keyboard event triggered by user interaction.
|
|
3994
|
-
* @private
|
|
3995
|
-
*/
|
|
3996
|
-
_onKeydown = (e) => {
|
|
3997
|
-
// Handle tab
|
|
3998
|
-
if (e.key === "Tab") this._handleTabKey(e);
|
|
3999
|
-
};
|
|
4000
|
-
|
|
4001
|
-
/**
|
|
4002
|
-
* Retrieves all focusable elements within the container in DOM order, including those in shadow DOM and slots.
|
|
4003
|
-
* Returns a unique, ordered array of elements that can receive focus.
|
|
4004
|
-
*
|
|
4005
|
-
* @returns {Array<HTMLElement>} An array of focusable elements within the container.
|
|
4006
|
-
* @private
|
|
4007
|
-
*/
|
|
4008
|
-
_getFocusableElements() {
|
|
4009
|
-
// Use the imported utility function to get focusable elements
|
|
4010
|
-
const elements = getFocusableElements(this.container);
|
|
4011
|
-
|
|
4012
|
-
// Return the elements found
|
|
4013
|
-
return elements;
|
|
4014
|
-
}
|
|
4015
|
-
|
|
4016
|
-
/**
|
|
4017
|
-
* Moves focus to the first focusable element within the container.
|
|
4018
|
-
* Useful for setting initial focus when activating the focus trap.
|
|
4019
|
-
*/
|
|
4020
|
-
focusFirstElement() {
|
|
4021
|
-
const focusables = this._getFocusableElements();
|
|
4022
|
-
if (focusables.length) focusables[0].focus();
|
|
4023
|
-
}
|
|
4024
|
-
|
|
4025
|
-
/**
|
|
4026
|
-
* Moves focus to the last focusable element within the container.
|
|
4027
|
-
* Useful for setting focus when deactivating or cycling focus in reverse.
|
|
4028
|
-
*/
|
|
4029
|
-
focusLastElement() {
|
|
4030
|
-
const focusables = this._getFocusableElements();
|
|
4031
|
-
if (focusables.length) focusables[focusables.length - 1].focus();
|
|
4032
|
-
}
|
|
4149
|
+
// Elements without tabindex or with tabindex of 0 stay in DOM order
|
|
4150
|
+
return tabindex === null || tabindex === 0;
|
|
4151
|
+
});
|
|
4033
4152
|
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
if (this.container.hasAttribute("data-focus-trap-container")) {
|
|
4040
|
-
this.container.removeAttribute("data-focus-trap-container");
|
|
4041
|
-
}
|
|
4153
|
+
// Combine both arrays with tabindex elements first
|
|
4154
|
+
const tabIndexedUniqueElements = [
|
|
4155
|
+
...elementsWithTabindex,
|
|
4156
|
+
...elementsWithoutTabindex,
|
|
4157
|
+
];
|
|
4042
4158
|
|
|
4043
|
-
|
|
4044
|
-
}
|
|
4159
|
+
return tabIndexedUniqueElements;
|
|
4045
4160
|
}
|
|
4046
4161
|
|
|
4047
4162
|
// Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
|
|
@@ -4544,7 +4659,7 @@ class AuroDropdownBib extends LitElement {
|
|
|
4544
4659
|
classes[`shape-${this.shape}`] = true;
|
|
4545
4660
|
|
|
4546
4661
|
return html`
|
|
4547
|
-
<dialog class="${classMap(classes)}" part="bibContainer" role="${ifDefined(this.dialogRole)}" aria-labelledby="${ifDefined(this.dialogLabel ? 'dialogLabel' : undefined)}">
|
|
4662
|
+
<dialog tabindex="-1" class="${classMap(classes)}" part="bibContainer" role="${ifDefined(this.dialogRole)}" aria-labelledby="${ifDefined(this.dialogLabel ? 'dialogLabel' : undefined)}">
|
|
4548
4663
|
${this.dialogLabel ? html`<span id="dialogLabel" class="util_displayHiddenVisually">${this.dialogLabel}</span>` : ''}
|
|
4549
4664
|
<slot></slot>
|
|
4550
4665
|
<span id="srAnnouncement" class="util_displayHiddenVisually" aria-live="polite" role="status"></span>
|
|
@@ -4795,7 +4910,7 @@ let AuroHelpText$2 = class AuroHelpText extends LitElement {
|
|
|
4795
4910
|
}
|
|
4796
4911
|
};
|
|
4797
4912
|
|
|
4798
|
-
var formkitVersion$2 = '
|
|
4913
|
+
var formkitVersion$2 = '202607221815';
|
|
4799
4914
|
|
|
4800
4915
|
let AuroElement$2 = class AuroElement extends LitElement {
|
|
4801
4916
|
static get properties() {
|
|
@@ -4924,7 +5039,6 @@ class AuroDropdown extends AuroElement$2 {
|
|
|
4924
5039
|
static get shadowRootOptions() {
|
|
4925
5040
|
return {
|
|
4926
5041
|
...AuroElement$2.shadowRootOptions,
|
|
4927
|
-
delegatesFocus: true,
|
|
4928
5042
|
};
|
|
4929
5043
|
}
|
|
4930
5044
|
|
|
@@ -4936,6 +5050,15 @@ class AuroDropdown extends AuroElement$2 {
|
|
|
4936
5050
|
this.matchWidth = false;
|
|
4937
5051
|
this.noHideOnThisFocusLoss = false;
|
|
4938
5052
|
|
|
5053
|
+
/**
|
|
5054
|
+
* When true, the dropdown skips its generic focus restoration on close.
|
|
5055
|
+
* Set by consumers (e.g. combobox) that manage their own focus routing
|
|
5056
|
+
* via setClearBtnFocus / setInputFocus / keyboard strategy.
|
|
5057
|
+
* Separate from noHideOnThisFocusLoss (which controls auto-close behavior).
|
|
5058
|
+
* @private
|
|
5059
|
+
*/
|
|
5060
|
+
this.noFocusRestoreOnClose = false;
|
|
5061
|
+
|
|
4939
5062
|
this.errorMessage = undefined; // TODO - check with Doug if there is still more to do here
|
|
4940
5063
|
|
|
4941
5064
|
// Layout Config
|
|
@@ -5091,7 +5214,49 @@ class AuroDropdown extends AuroElement$2 {
|
|
|
5091
5214
|
focusables[0].focus();
|
|
5092
5215
|
}
|
|
5093
5216
|
} else {
|
|
5217
|
+
this.focusTrigger();
|
|
5218
|
+
}
|
|
5219
|
+
}
|
|
5220
|
+
|
|
5221
|
+
/**
|
|
5222
|
+
* Focus the trigger content. When the trigger wrapper itself is focusable
|
|
5223
|
+
* (has tabindex), focus it directly. Otherwise, focus the first focusable
|
|
5224
|
+
* element slotted into the trigger slot (e.g. the auro-input).
|
|
5225
|
+
* @private
|
|
5226
|
+
*/
|
|
5227
|
+
focusTrigger() {
|
|
5228
|
+
if (this.trigger.hasAttribute('tabindex')) {
|
|
5094
5229
|
this.trigger.focus();
|
|
5230
|
+
} else {
|
|
5231
|
+
// Slotted content isn't a DOM child of the trigger div, so
|
|
5232
|
+
// getFocusableElements can't find it. Query assigned nodes directly.
|
|
5233
|
+
const slot = this.trigger.querySelector('slot[name="trigger"]');
|
|
5234
|
+
if (slot) {
|
|
5235
|
+
const assigned = slot.assignedElements();
|
|
5236
|
+
for (const el of assigned) {
|
|
5237
|
+
if (el.hasAttribute('disabled')) {
|
|
5238
|
+
continue; // eslint-disable-line no-continue
|
|
5239
|
+
}
|
|
5240
|
+
// Try finding a focusable descendant first (handles non-focusable
|
|
5241
|
+
// wrappers like <div> containing a <button>). If none found, try
|
|
5242
|
+
// focusing the element directly (works for custom elements like
|
|
5243
|
+
// auro-input that have delegatesFocus or a custom focus() method).
|
|
5244
|
+
const descendants = getFocusableElements(el);
|
|
5245
|
+
if (descendants.length > 0) {
|
|
5246
|
+
descendants[0].focus();
|
|
5247
|
+
return;
|
|
5248
|
+
}
|
|
5249
|
+
el.focus();
|
|
5250
|
+
if (document.activeElement === el) {
|
|
5251
|
+
return;
|
|
5252
|
+
}
|
|
5253
|
+
}
|
|
5254
|
+
}
|
|
5255
|
+
// Fallback: try DOM children (non-slotted content)
|
|
5256
|
+
const focusables = getFocusableElements(this.trigger);
|
|
5257
|
+
if (focusables.length > 0) {
|
|
5258
|
+
focusables[0].focus();
|
|
5259
|
+
}
|
|
5095
5260
|
}
|
|
5096
5261
|
}
|
|
5097
5262
|
|
|
@@ -5467,10 +5632,17 @@ class AuroDropdown extends AuroElement$2 {
|
|
|
5467
5632
|
this.clearTriggerFocusEventBinding();
|
|
5468
5633
|
}
|
|
5469
5634
|
|
|
5635
|
+
// eslint-disable-next-line complexity
|
|
5470
5636
|
updated(changedProperties) {
|
|
5471
5637
|
super.updated(changedProperties);
|
|
5472
5638
|
this.floater.handleUpdate(changedProperties);
|
|
5473
5639
|
|
|
5640
|
+
// Close the dropdown if the disabled property is set to true
|
|
5641
|
+
if (changedProperties.has('disabled') && this.disabled && this.isPopoverVisible) {
|
|
5642
|
+
this.hide();
|
|
5643
|
+
this.isPopoverVisible = false;
|
|
5644
|
+
}
|
|
5645
|
+
|
|
5474
5646
|
// Note: `disabled` is not a breakpoint (it is not a screen size),
|
|
5475
5647
|
// so it looks like we never consume this - however, dropdownBib handles this in the setter as "undefined"
|
|
5476
5648
|
if (changedProperties.has('fullscreenBreakpoint')) {
|
|
@@ -5544,8 +5716,30 @@ class AuroDropdown extends AuroElement$2 {
|
|
|
5544
5716
|
}
|
|
5545
5717
|
|
|
5546
5718
|
const eventType = event.detail.eventType || "unknown";
|
|
5547
|
-
if (!this.isPopoverVisible && this.hasFocus && eventType === "keydown") {
|
|
5548
|
-
this.
|
|
5719
|
+
if (!this.isPopoverVisible && this.hasFocus && eventType === "keydown" && !this.noFocusRestoreOnClose) {
|
|
5720
|
+
this.focusTrigger();
|
|
5721
|
+
}
|
|
5722
|
+
|
|
5723
|
+
|
|
5724
|
+
// On Tab-driven close (eventType "focusloss"), let focus advance naturally
|
|
5725
|
+
// — restoring to the trigger would trap the user on this dropdown, forcing
|
|
5726
|
+
// an extra Tab to move on. Escape and outside-click still restore.
|
|
5727
|
+
// When noFocusRestoreOnClose is true, the consumer (e.g. combobox) manages
|
|
5728
|
+
// its own focus restoration — skip the generic trigger focus to avoid races.
|
|
5729
|
+
if (!this.isPopoverVisible && eventType !== "focusloss" && !this.noFocusRestoreOnClose) {
|
|
5730
|
+
// wait til the bib gets fully closed and rendered
|
|
5731
|
+
setTimeout(() => {
|
|
5732
|
+
// Skip if the bib re-opened, or if focus moved intentionally outside the dropdown (not to body).
|
|
5733
|
+
// Restore focus to trigger when focus is still inside the bib (:focus-within) or fell to body.
|
|
5734
|
+
if (this.isPopoverVisible ||
|
|
5735
|
+
// eslint-disable-next-line no-extra-parens
|
|
5736
|
+
(!this.bibContent?.matches(':focus-within') &&
|
|
5737
|
+
document.activeElement !== document.body)) {
|
|
5738
|
+
return;
|
|
5739
|
+
}
|
|
5740
|
+
// Restore focus to the trigger.
|
|
5741
|
+
this.focusTrigger();
|
|
5742
|
+
});
|
|
5549
5743
|
}
|
|
5550
5744
|
}
|
|
5551
5745
|
|
|
@@ -5746,6 +5940,14 @@ class AuroDropdown extends AuroElement$2 {
|
|
|
5746
5940
|
};
|
|
5747
5941
|
this.addEventListener('keydown', this._bibTabHandler);
|
|
5748
5942
|
|
|
5943
|
+
// Suppress AuroFloatingUI's auto-hide-on-focus-loss while the
|
|
5944
|
+
// desktopModal trap owns focus management. Without this, the very
|
|
5945
|
+
// first focus move into the bib (from the RAF below) triggers
|
|
5946
|
+
// handleFocusLoss → hideBib, tearing down the trap before the
|
|
5947
|
+
// user can press Tab.
|
|
5948
|
+
this._priorNoHideOnFocusLoss = this.noHideOnThisFocusLoss;
|
|
5949
|
+
this.noHideOnThisFocusLoss = true;
|
|
5950
|
+
|
|
5749
5951
|
// Move initial focus into the bib content, matching FocusTrap behavior
|
|
5750
5952
|
requestAnimationFrame(() => {
|
|
5751
5953
|
const focusables = getFocusableElements(this.bibContent);
|
|
@@ -5754,15 +5956,16 @@ class AuroDropdown extends AuroElement$2 {
|
|
|
5754
5956
|
}
|
|
5755
5957
|
});
|
|
5756
5958
|
} else {
|
|
5757
|
-
// Normal desktop:
|
|
5758
|
-
//
|
|
5759
|
-
//
|
|
5760
|
-
//
|
|
5761
|
-
//
|
|
5762
|
-
|
|
5959
|
+
// Normal desktop (non-modal): move initial focus into the bib but
|
|
5960
|
+
// don't trap Tab. Tab should exit the bib and let the floater's
|
|
5961
|
+
// handleFocusLoss close it, matching native <select>/<details>
|
|
5962
|
+
// behavior. Deferred one frame because Floating UI positions the
|
|
5963
|
+
// popover asynchronously — a synchronous focus() would target
|
|
5964
|
+
// zero-dimension elements and be silently ignored.
|
|
5763
5965
|
requestAnimationFrame(() => {
|
|
5764
|
-
|
|
5765
|
-
|
|
5966
|
+
const focusables = getFocusableElements(this.bibContent);
|
|
5967
|
+
if (focusables.length) {
|
|
5968
|
+
focusables[0].focus();
|
|
5766
5969
|
}
|
|
5767
5970
|
});
|
|
5768
5971
|
}
|
|
@@ -6059,6 +6262,7 @@ class AuroDropdown extends AuroElement$2 {
|
|
|
6059
6262
|
role="${ifDefined(this.triggerContentFocusable ? undefined : this.a11yRole)}"
|
|
6060
6263
|
aria-expanded="${ifDefined(this.a11yRole === 'button' || this.triggerContentFocusable ? undefined : this.isPopoverVisible)}"
|
|
6061
6264
|
aria-controls="${ifDefined(this.a11yRole === 'button' || this.triggerContentFocusable ? undefined : this.dropdownId)}"
|
|
6265
|
+
aria-haspopup="${ifDefined(this.a11yRole === 'combobox' && !this.triggerContentFocusable ? 'listbox' : undefined)}"
|
|
6062
6266
|
aria-labelledby="${ifDefined(this.triggerContentFocusable ? undefined : 'triggerLabel')}"
|
|
6063
6267
|
aria-disabled="${ifDefined(this.disabled ? 'true' : undefined)}"
|
|
6064
6268
|
@focusin="${this.handleFocusin}"
|
|
@@ -6185,7 +6389,7 @@ class AuroDropdown extends AuroElement$2 {
|
|
|
6185
6389
|
|
|
6186
6390
|
var shapeSizeCss = css`.shape-classic-xl,.shape-classic-lg,.shape-classic-md,.shape-classic-sm,.shape-classic-xs{min-height:56px;max-height:56px;border-style:solid;border-width:1px;border-radius:var(--ds-border-radius, 0.375rem)}.shape-classic-xl.simple,.shape-classic-lg.simple,.shape-classic-md.simple,.shape-classic-sm.simple,.shape-classic-xs.simple{border-width:0px;min-height:58px;max-height:58px;background-color:unset;box-shadow:none}.shape-classic-xl.thin,.shape-classic-lg.thin,.shape-classic-md.thin,.shape-classic-sm.thin,.shape-classic-xs.thin{border-width:1px;min-height:56px;max-height:56px;background-color:unset}.shape-classic-xl.parentBorder,.shape-classic-lg.parentBorder,.shape-classic-md.parentBorder,.shape-classic-sm.parentBorder,.shape-classic-xs.parentBorder{border:0;box-shadow:unset;min-height:54px;max-height:54px}.shape-snowflake-xl,.shape-snowflake-lg,.shape-snowflake-md,.shape-snowflake-sm,.shape-snowflake-xs{min-height:56px;max-height:56px;border-style:solid;border-width:2px;border-color:transparent;border-radius:30px}.shape-snowflake-xl.simple,.shape-snowflake-lg.simple,.shape-snowflake-md.simple,.shape-snowflake-sm.simple,.shape-snowflake-xs.simple{border-width:0px;min-height:60px;max-height:60px;background-color:unset;box-shadow:none}.shape-snowflake-xl.thin,.shape-snowflake-lg.thin,.shape-snowflake-md.thin,.shape-snowflake-sm.thin,.shape-snowflake-xs.thin{border-width:1px;min-height:58px;max-height:58px;background-color:unset}.shape-snowflake-xl.parentBorder,.shape-snowflake-lg.parentBorder,.shape-snowflake-md.parentBorder,.shape-snowflake-sm.parentBorder,.shape-snowflake-xs.parentBorder{border:0;box-shadow:unset;min-height:56px;max-height:56px}.shape-box-xl{min-height:68px;max-height:68px;border-style:solid;border-width:2px;border-color:transparent}.shape-box-xl.simple{border-width:0px;min-height:72px;max-height:72px;background-color:unset;box-shadow:none}.shape-box-xl.thin{border-width:1px;min-height:70px;max-height:70px;background-color:unset}.shape-box-xl.parentBorder{border:0;box-shadow:unset;min-height:68px;max-height:68px}.shape-box-lg{min-height:52px;max-height:52px;border-style:solid;border-width:2px;border-color:transparent}.shape-box-lg.simple{border-width:0px;min-height:56px;max-height:56px;background-color:unset;box-shadow:none}.shape-box-lg.thin{border-width:1px;min-height:54px;max-height:54px;background-color:unset}.shape-box-lg.parentBorder{border:0;box-shadow:unset;min-height:52px;max-height:52px}.shape-box-md{min-height:44px;max-height:44px;border-style:solid;border-width:2px;border-color:transparent}.shape-box-md.simple{border-width:0px;min-height:48px;max-height:48px;background-color:unset;box-shadow:none}.shape-box-md.thin{border-width:1px;min-height:46px;max-height:46px;background-color:unset}.shape-box-md.parentBorder{border:0;box-shadow:unset;min-height:44px;max-height:44px}.shape-box-sm{min-height:32px;max-height:32px;border-style:solid;border-width:2px;border-color:transparent}.shape-box-sm.simple{border-width:0px;min-height:36px;max-height:36px;background-color:unset;box-shadow:none}.shape-box-sm.thin{border-width:1px;min-height:34px;max-height:34px;background-color:unset}.shape-box-sm.parentBorder{border:0;box-shadow:unset;min-height:32px;max-height:32px}.shape-box-xs{min-height:20px;max-height:20px;border-style:solid;border-width:2px;border-color:transparent}.shape-box-xs.simple{border-width:0px;min-height:24px;max-height:24px;background-color:unset;box-shadow:none}.shape-box-xs.thin{border-width:1px;min-height:22px;max-height:22px;background-color:unset}.shape-box-xs.parentBorder{border:0;box-shadow:unset;min-height:20px;max-height:20px}.shape-rounded-lg{min-height:56px;max-height:56px;border-style:solid;border-width:2px;border-color:transparent;border-radius:6px}.shape-rounded-lg.simple{border-width:0px;min-height:56px;max-height:56px;background-color:unset;box-shadow:none}.shape-rounded-lg.thin{border-width:1px;min-height:54px;max-height:54px;background-color:unset}.shape-rounded-lg.parentBorder{border:0;box-shadow:unset;min-height:52px;max-height:52px}.shape-pill-xl{min-height:68px;max-height:68px;border-style:solid;border-width:2px;border-color:transparent;border-radius:36px}.shape-pill-xl.simple{border-width:0px;min-height:72px;max-height:72px;background-color:unset;box-shadow:none}.shape-pill-xl.thin{border-width:1px;min-height:70px;max-height:70px;background-color:unset}.shape-pill-xl.parentBorder{border:0;box-shadow:unset;min-height:68px;max-height:68px}.shape-pill-left-xl{min-height:68px;max-height:68px;border-style:solid;border-width:2px;border-color:transparent;border-radius:36px 0 0 36px}.shape-pill-left-xl.simple{border-width:0px;min-height:72px;max-height:72px;background-color:unset;box-shadow:none}.shape-pill-left-xl.thin{border-width:1px;min-height:70px;max-height:70px;background-color:unset}.shape-pill-left-xl.parentBorder{border:0;box-shadow:unset;min-height:68px;max-height:68px}.shape-pill-right-xl{min-height:68px;max-height:68px;border-style:solid;border-width:2px;border-color:transparent;border-radius:0 36px 36px 0}.shape-pill-right-xl.simple{border-width:0px;min-height:72px;max-height:72px;background-color:unset;box-shadow:none}.shape-pill-right-xl.thin{border-width:1px;min-height:70px;max-height:70px;background-color:unset}.shape-pill-right-xl.parentBorder{border:0;box-shadow:unset;min-height:68px;max-height:68px}.shape-pill-md{min-height:44px;max-height:44px;border-style:solid;border-width:2px;border-color:transparent;border-radius:36px}.shape-pill-md.simple{border-width:0px;min-height:48px;max-height:48px;background-color:unset;box-shadow:none}.shape-pill-md.thin{border-width:1px;min-height:46px;max-height:46px;background-color:unset}.shape-pill-md.parentBorder{border:0;box-shadow:unset;min-height:44px;max-height:44px}.shape-pill-left-md{min-height:44px;max-height:44px;border-style:solid;border-width:2px;border-color:transparent;border-radius:36px 0 0 36px}.shape-pill-left-md.simple{border-width:0px;min-height:48px;max-height:48px;background-color:unset;box-shadow:none}.shape-pill-left-md.thin{border-width:1px;min-height:46px;max-height:46px;background-color:unset}.shape-pill-left-md.parentBorder{border:0;box-shadow:unset;min-height:44px;max-height:44px}.shape-pill-right-md{min-height:44px;max-height:44px;border-style:solid;border-width:2px;border-color:transparent;border-radius:0 36px 36px 0}.shape-pill-right-md.simple{border-width:0px;min-height:48px;max-height:48px;background-color:unset;box-shadow:none}.shape-pill-right-md.thin{border-width:1px;min-height:46px;max-height:46px;background-color:unset}.shape-pill-right-md.parentBorder{border:0;box-shadow:unset;min-height:44px;max-height:44px}`;
|
|
6187
6391
|
|
|
6188
|
-
var styleCss$1$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}.body-default{font-size:var(--wcss-body-default-font-size, 1rem);font-weight:var(--wcss-body-default-weight, );line-height:var(--wcss-body-default-line-height, 1.5rem)}.body-default,.body-default-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-default-emphasized{font-size:var(--wcss-body-default-emphasized-font-size, 1rem);font-weight:var(--wcss-body-default-emphasized-weight, );line-height:var(--wcss-body-default-emphasized-line-height, 1.5rem)}.body-lg{font-size:var(--wcss-body-lg-font-size, 1.125rem);font-weight:var(--wcss-body-lg-weight, );line-height:var(--wcss-body-lg-line-height, 1.625rem)}.body-lg,.body-lg-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-lg-emphasized{font-size:var(--wcss-body-lg-emphasized-font-size, 1.125rem);font-weight:var(--wcss-body-lg-emphasized-weight, );line-height:var(--wcss-body-lg-emphasized-line-height, 1.625rem)}.body-sm{font-size:var(--wcss-body-sm-font-size, 0.875rem);font-weight:var(--wcss-body-sm-weight, );line-height:var(--wcss-body-sm-line-height, 1.25rem)}.body-sm,.body-sm-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-sm-emphasized{font-size:var(--wcss-body-sm-emphasized-font-size, 0.875rem);font-weight:var(--wcss-body-sm-emphasized-weight, );line-height:var(--wcss-body-sm-emphasized-line-height, 1.25rem)}.body-xs{font-size:var(--wcss-body-xs-font-size, 0.75rem);font-weight:var(--wcss-body-xs-weight, );line-height:var(--wcss-body-xs-line-height, 1rem)}.body-xs,.body-xs-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-xs-emphasized{font-size:var(--wcss-body-xs-emphasized-font-size, 0.75rem);font-weight:var(--wcss-body-xs-emphasized-weight, );line-height:var(--wcss-body-xs-emphasized-line-height, 1rem)}.body-2xs{font-size:var(--wcss-body-2xs-font-size, 0.625rem);font-weight:var(--wcss-body-2xs-weight, );line-height:var(--wcss-body-2xs-line-height, 0.875rem)}.body-2xs,.body-2xs-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-2xs-emphasized{font-size:var(--wcss-body-2xs-emphasized-font-size, 0.625rem);font-weight:var(--wcss-body-2xs-emphasized-weight, );line-height:var(--wcss-body-2xs-emphasized-line-height, 0.875rem)}.display-2xl{font-family:var(--wcss-display-2xl-family, "AS Circular"),var(--wcss-display-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-2xl-font-size, clamp(3.5rem, 6vw, 5.375rem));font-weight:var(--wcss-display-2xl-weight, 300);letter-spacing:var(--wcss-display-2xl-letter-spacing, 0);line-height:var(--wcss-display-2xl-line-height, 1.3)}.display-xl{font-family:var(--wcss-display-xl-family, "AS Circular"),var(--wcss-display-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-xl-font-size, clamp(3rem, 5.3333333333vw, 4.5rem));font-weight:var(--wcss-display-xl-weight, 300);letter-spacing:var(--wcss-display-xl-letter-spacing, 0);line-height:var(--wcss-display-xl-line-height, 1.3)}.display-lg{font-family:var(--wcss-display-lg-family, "AS Circular"),var(--wcss-display-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-lg-font-size, clamp(2.75rem, 4.6666666667vw, 4rem));font-weight:var(--wcss-display-lg-weight, 300);letter-spacing:var(--wcss-display-lg-letter-spacing, 0);line-height:var(--wcss-display-lg-line-height, 1.3)}.display-md{font-family:var(--wcss-display-md-family, "AS Circular"),var(--wcss-display-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-md-font-size, clamp(2.5rem, 4vw, 3.5rem));font-weight:var(--wcss-display-md-weight, 300);letter-spacing:var(--wcss-display-md-letter-spacing, 0);line-height:var(--wcss-display-md-line-height, 1.3)}.display-sm{font-family:var(--wcss-display-sm-family, "AS Circular"),var(--wcss-display-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-sm-font-size, clamp(2rem, 3.6666666667vw, 3rem));font-weight:var(--wcss-display-sm-weight, 300);letter-spacing:var(--wcss-display-sm-letter-spacing, 0);line-height:var(--wcss-display-sm-line-height, 1.3)}.display-xs{font-family:var(--wcss-display-xs-family, "AS Circular"),var(--wcss-display-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-xs-font-size, clamp(1.75rem, 3vw, 2.375rem));font-weight:var(--wcss-display-xs-weight, 300);letter-spacing:var(--wcss-display-xs-letter-spacing, 0);line-height:var(--wcss-display-xs-line-height, 1.3)}.heading-xl{font-family:var(--wcss-heading-xl-family, "AS Circular"),var(--wcss-heading-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-xl-font-size, clamp(2rem, 3vw, 2.5rem));font-weight:var(--wcss-heading-xl-weight, 300);letter-spacing:var(--wcss-heading-xl-letter-spacing, 0);line-height:var(--wcss-heading-xl-line-height, 1.3)}.heading-lg{font-family:var(--wcss-heading-lg-family, "AS Circular"),var(--wcss-heading-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-lg-font-size, clamp(1.75rem, 2.6666666667vw, 2.25rem));font-weight:var(--wcss-heading-lg-weight, 300);letter-spacing:var(--wcss-heading-lg-letter-spacing, 0);line-height:var(--wcss-heading-lg-line-height, 1.3)}.heading-md{font-family:var(--wcss-heading-md-family, "AS Circular"),var(--wcss-heading-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-md-font-size, clamp(1.625rem, 2.3333333333vw, 1.75rem));font-weight:var(--wcss-heading-md-weight, 300);letter-spacing:var(--wcss-heading-md-letter-spacing, 0);line-height:var(--wcss-heading-md-line-height, 1.3)}.heading-sm{font-family:var(--wcss-heading-sm-family, "AS Circular"),var(--wcss-heading-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-sm-font-size, clamp(1.375rem, 2vw, 1.5rem));font-weight:var(--wcss-heading-sm-weight, 300);letter-spacing:var(--wcss-heading-sm-letter-spacing, 0);line-height:var(--wcss-heading-sm-line-height, 1.3)}.heading-xs{font-family:var(--wcss-heading-xs-family, "AS Circular"),var(--wcss-heading-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-xs-font-size, clamp(1.25rem, 1.6666666667vw, 1.25rem));font-weight:var(--wcss-heading-xs-weight, 300);letter-spacing:var(--wcss-heading-xs-letter-spacing, 0);line-height:var(--wcss-heading-xs-line-height, 1.3)}.heading-2xs{font-family:var(--wcss-heading-2xs-family, "AS Circular"),var(--wcss-heading-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-2xs-font-size, clamp(1.125rem, 1.5vw, 1.125rem));font-weight:var(--wcss-heading-2xs-weight, 300);letter-spacing:var(--wcss-heading-2xs-letter-spacing, 0);line-height:var(--wcss-heading-2xs-line-height, 1.3)}.accent-2xl{font-family:var(--wcss-accent-2xl-family, "Good OT"),var(--wcss-accent-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-2xl-font-size, clamp(2rem, 3.1666666667vw, 2.375rem));font-weight:var(--wcss-accent-2xl-weight, 450);letter-spacing:var(--wcss-accent-2xl-letter-spacing, 0.05em);line-height:var(--wcss-accent-2xl-line-height, 1)}.accent-2xl,.accent-xl{text-transform:uppercase}.accent-xl{font-family:var(--wcss-accent-xl-family, "Good OT"),var(--wcss-accent-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-xl-font-size, clamp(1.625rem, 2.3333333333vw, 2rem));font-weight:var(--wcss-accent-xl-weight, 450);letter-spacing:var(--wcss-accent-xl-letter-spacing, 0.05em);line-height:var(--wcss-accent-xl-line-height, 1.3)}.accent-lg{font-family:var(--wcss-accent-lg-family, "Good OT"),var(--wcss-accent-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-lg-font-size, clamp(1.5rem, 2.1666666667vw, 1.75rem));font-weight:var(--wcss-accent-lg-weight, 450);letter-spacing:var(--wcss-accent-lg-letter-spacing, 0.05em);line-height:var(--wcss-accent-lg-line-height, 1.3)}.accent-lg,.accent-md{text-transform:uppercase}.accent-md{font-family:var(--wcss-accent-md-family, "Good OT"),var(--wcss-accent-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-md-font-size, clamp(1.375rem, 1.8333333333vw, 1.5rem));font-weight:var(--wcss-accent-md-weight, 500);letter-spacing:var(--wcss-accent-md-letter-spacing, 0.05em);line-height:var(--wcss-accent-md-line-height, 1.3)}.accent-sm{font-family:var(--wcss-accent-sm-family, "Good OT"),var(--wcss-accent-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-sm-font-size, clamp(1.125rem, 1.5vw, 1.25rem));font-weight:var(--wcss-accent-sm-weight, 500);letter-spacing:var(--wcss-accent-sm-letter-spacing, 0.05em);line-height:var(--wcss-accent-sm-line-height, 1.3)}.accent-sm,.accent-xs{text-transform:uppercase}.accent-xs{font-family:var(--wcss-accent-xs-family, "Good OT"),var(--wcss-accent-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-xs-font-size, clamp(1rem, 1.3333333333vw, 1rem));font-weight:var(--wcss-accent-xs-weight, 500);letter-spacing:var(--wcss-accent-xs-letter-spacing, 0.1em);line-height:var(--wcss-accent-xs-line-height, 1.3)}.accent-2xs{font-family:var(--wcss-accent-2xs-family, "Good OT"),var(--wcss-accent-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-2xs-font-size, clamp(0.875rem, 1.1666666667vw, 0.875rem));font-weight:var(--wcss-accent-2xs-weight, 450);letter-spacing:var(--wcss-accent-2xs-letter-spacing, 0.1em);line-height:var(--wcss-accent-2xs-line-height, 1.3);text-transform:uppercase}:host{display:block}.wrapper:has(:enabled){cursor:text}.wrapper:has(:enabled) label{cursor:text}.helpTextClasses{cursor:default}input{overflow:clip !important;width:100%;padding:0;border:0;background:unset;outline:none;overflow-clip-margin:0 !important;text-overflow:ellipsis}input::-webkit-inner-spin-button{margin:0;-webkit-appearance:none}.displayValue{display:none}.displayValue.hasContent:is(.withValue):not(.hasFocus){display:flex;align-items:center}.accents:not(.util_displayHidden){display:flex;flex-direction:row;align-items:center;justify-content:center;gap:8px}.wrapper:not(:focus-within):not(:hover) .notificationBtn.passwordBtn,.wrapper:not(:focus-within):not(:hover) .notification.clear{display:none}.notification{display:flex;align-items:center;justify-content:center}`;
|
|
6392
|
+
var styleCss$1$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}.body-default{font-size:var(--wcss-body-default-font-size, 1rem);font-weight:var(--wcss-body-default-weight, );line-height:var(--wcss-body-default-line-height, 1.5rem)}.body-default,.body-default-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-default-emphasized{font-size:var(--wcss-body-default-emphasized-font-size, 1rem);font-weight:var(--wcss-body-default-emphasized-weight, );line-height:var(--wcss-body-default-emphasized-line-height, 1.5rem)}.body-lg{font-size:var(--wcss-body-lg-font-size, 1.125rem);font-weight:var(--wcss-body-lg-weight, );line-height:var(--wcss-body-lg-line-height, 1.625rem)}.body-lg,.body-lg-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-lg-emphasized{font-size:var(--wcss-body-lg-emphasized-font-size, 1.125rem);font-weight:var(--wcss-body-lg-emphasized-weight, );line-height:var(--wcss-body-lg-emphasized-line-height, 1.625rem)}.body-sm{font-size:var(--wcss-body-sm-font-size, 0.875rem);font-weight:var(--wcss-body-sm-weight, );line-height:var(--wcss-body-sm-line-height, 1.25rem)}.body-sm,.body-sm-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-sm-emphasized{font-size:var(--wcss-body-sm-emphasized-font-size, 0.875rem);font-weight:var(--wcss-body-sm-emphasized-weight, );line-height:var(--wcss-body-sm-emphasized-line-height, 1.25rem)}.body-xs{font-size:var(--wcss-body-xs-font-size, 0.75rem);font-weight:var(--wcss-body-xs-weight, );line-height:var(--wcss-body-xs-line-height, 1rem)}.body-xs,.body-xs-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-xs-emphasized{font-size:var(--wcss-body-xs-emphasized-font-size, 0.75rem);font-weight:var(--wcss-body-xs-emphasized-weight, );line-height:var(--wcss-body-xs-emphasized-line-height, 1rem)}.body-2xs{font-size:var(--wcss-body-2xs-font-size, 0.625rem);font-weight:var(--wcss-body-2xs-weight, );line-height:var(--wcss-body-2xs-line-height, 0.875rem)}.body-2xs,.body-2xs-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-2xs-emphasized{font-size:var(--wcss-body-2xs-emphasized-font-size, 0.625rem);font-weight:var(--wcss-body-2xs-emphasized-weight, );line-height:var(--wcss-body-2xs-emphasized-line-height, 0.875rem)}.display-2xl{font-family:var(--wcss-display-2xl-family, "AS Circular"),var(--wcss-display-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-2xl-font-size, clamp(3.5rem, 6vw, 5.375rem));font-weight:var(--wcss-display-2xl-weight, 300);letter-spacing:var(--wcss-display-2xl-letter-spacing, 0);line-height:var(--wcss-display-2xl-line-height, 1.3)}.display-xl{font-family:var(--wcss-display-xl-family, "AS Circular"),var(--wcss-display-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-xl-font-size, clamp(3rem, 5.3333333333vw, 4.5rem));font-weight:var(--wcss-display-xl-weight, 300);letter-spacing:var(--wcss-display-xl-letter-spacing, 0);line-height:var(--wcss-display-xl-line-height, 1.3)}.display-lg{font-family:var(--wcss-display-lg-family, "AS Circular"),var(--wcss-display-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-lg-font-size, clamp(2.75rem, 4.6666666667vw, 4rem));font-weight:var(--wcss-display-lg-weight, 300);letter-spacing:var(--wcss-display-lg-letter-spacing, 0);line-height:var(--wcss-display-lg-line-height, 1.3)}.display-md{font-family:var(--wcss-display-md-family, "AS Circular"),var(--wcss-display-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-md-font-size, clamp(2.5rem, 4vw, 3.5rem));font-weight:var(--wcss-display-md-weight, 300);letter-spacing:var(--wcss-display-md-letter-spacing, 0);line-height:var(--wcss-display-md-line-height, 1.3)}.display-sm{font-family:var(--wcss-display-sm-family, "AS Circular"),var(--wcss-display-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-sm-font-size, clamp(2rem, 3.6666666667vw, 3rem));font-weight:var(--wcss-display-sm-weight, 300);letter-spacing:var(--wcss-display-sm-letter-spacing, 0);line-height:var(--wcss-display-sm-line-height, 1.3)}.display-xs{font-family:var(--wcss-display-xs-family, "AS Circular"),var(--wcss-display-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-xs-font-size, clamp(1.75rem, 3vw, 2.375rem));font-weight:var(--wcss-display-xs-weight, 300);letter-spacing:var(--wcss-display-xs-letter-spacing, 0);line-height:var(--wcss-display-xs-line-height, 1.3)}.heading-xl{font-family:var(--wcss-heading-xl-family, "AS Circular"),var(--wcss-heading-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-xl-font-size, clamp(2rem, 3vw, 2.5rem));font-weight:var(--wcss-heading-xl-weight, 300);letter-spacing:var(--wcss-heading-xl-letter-spacing, 0);line-height:var(--wcss-heading-xl-line-height, 1.3)}.heading-lg{font-family:var(--wcss-heading-lg-family, "AS Circular"),var(--wcss-heading-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-lg-font-size, clamp(1.75rem, 2.6666666667vw, 2.25rem));font-weight:var(--wcss-heading-lg-weight, 300);letter-spacing:var(--wcss-heading-lg-letter-spacing, 0);line-height:var(--wcss-heading-lg-line-height, 1.3)}.heading-md{font-family:var(--wcss-heading-md-family, "AS Circular"),var(--wcss-heading-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-md-font-size, clamp(1.625rem, 2.3333333333vw, 1.75rem));font-weight:var(--wcss-heading-md-weight, 300);letter-spacing:var(--wcss-heading-md-letter-spacing, 0);line-height:var(--wcss-heading-md-line-height, 1.3)}.heading-sm{font-family:var(--wcss-heading-sm-family, "AS Circular"),var(--wcss-heading-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-sm-font-size, clamp(1.375rem, 2vw, 1.5rem));font-weight:var(--wcss-heading-sm-weight, 300);letter-spacing:var(--wcss-heading-sm-letter-spacing, 0);line-height:var(--wcss-heading-sm-line-height, 1.3)}.heading-xs{font-family:var(--wcss-heading-xs-family, "AS Circular"),var(--wcss-heading-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-xs-font-size, clamp(1.25rem, 1.6666666667vw, 1.25rem));font-weight:var(--wcss-heading-xs-weight, 300);letter-spacing:var(--wcss-heading-xs-letter-spacing, 0);line-height:var(--wcss-heading-xs-line-height, 1.3)}.heading-2xs{font-family:var(--wcss-heading-2xs-family, "AS Circular"),var(--wcss-heading-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-2xs-font-size, clamp(1.125rem, 1.5vw, 1.125rem));font-weight:var(--wcss-heading-2xs-weight, 300);letter-spacing:var(--wcss-heading-2xs-letter-spacing, 0);line-height:var(--wcss-heading-2xs-line-height, 1.3)}.accent-2xl{font-family:var(--wcss-accent-2xl-family, "Good OT"),var(--wcss-accent-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-2xl-font-size, clamp(2rem, 3.1666666667vw, 2.375rem));font-weight:var(--wcss-accent-2xl-weight, 450);letter-spacing:var(--wcss-accent-2xl-letter-spacing, 0.05em);line-height:var(--wcss-accent-2xl-line-height, 1)}.accent-2xl,.accent-xl{text-transform:uppercase}.accent-xl{font-family:var(--wcss-accent-xl-family, "Good OT"),var(--wcss-accent-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-xl-font-size, clamp(1.625rem, 2.3333333333vw, 2rem));font-weight:var(--wcss-accent-xl-weight, 450);letter-spacing:var(--wcss-accent-xl-letter-spacing, 0.05em);line-height:var(--wcss-accent-xl-line-height, 1.3)}.accent-lg{font-family:var(--wcss-accent-lg-family, "Good OT"),var(--wcss-accent-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-lg-font-size, clamp(1.5rem, 2.1666666667vw, 1.75rem));font-weight:var(--wcss-accent-lg-weight, 450);letter-spacing:var(--wcss-accent-lg-letter-spacing, 0.05em);line-height:var(--wcss-accent-lg-line-height, 1.3)}.accent-lg,.accent-md{text-transform:uppercase}.accent-md{font-family:var(--wcss-accent-md-family, "Good OT"),var(--wcss-accent-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-md-font-size, clamp(1.375rem, 1.8333333333vw, 1.5rem));font-weight:var(--wcss-accent-md-weight, 500);letter-spacing:var(--wcss-accent-md-letter-spacing, 0.05em);line-height:var(--wcss-accent-md-line-height, 1.3)}.accent-sm{font-family:var(--wcss-accent-sm-family, "Good OT"),var(--wcss-accent-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-sm-font-size, clamp(1.125rem, 1.5vw, 1.25rem));font-weight:var(--wcss-accent-sm-weight, 500);letter-spacing:var(--wcss-accent-sm-letter-spacing, 0.05em);line-height:var(--wcss-accent-sm-line-height, 1.3)}.accent-sm,.accent-xs{text-transform:uppercase}.accent-xs{font-family:var(--wcss-accent-xs-family, "Good OT"),var(--wcss-accent-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-xs-font-size, clamp(1rem, 1.3333333333vw, 1rem));font-weight:var(--wcss-accent-xs-weight, 500);letter-spacing:var(--wcss-accent-xs-letter-spacing, 0.1em);line-height:var(--wcss-accent-xs-line-height, 1.3)}.accent-2xs{font-family:var(--wcss-accent-2xs-family, "Good OT"),var(--wcss-accent-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-2xs-font-size, clamp(0.875rem, 1.1666666667vw, 0.875rem));font-weight:var(--wcss-accent-2xs-weight, 450);letter-spacing:var(--wcss-accent-2xs-letter-spacing, 0.1em);line-height:var(--wcss-accent-2xs-line-height, 1.3);text-transform:uppercase}:host{display:block}.wrapper:has(:enabled){cursor:text}.wrapper:has(:enabled) label{cursor:text}.helpTextClasses{cursor:default}input{overflow:clip !important;width:100%;padding:0;border:0;background:unset;outline:none;overflow-clip-margin:0 !important;text-overflow:ellipsis}input[type=number]{appearance:textfield}input::-webkit-inner-spin-button{margin:0;-webkit-appearance:none}.displayValue{display:none}.displayValue.hasContent:is(.withValue):not(.hasFocus){display:flex;align-items:center}.accents:not(.util_displayHidden){display:flex;flex-direction:row;align-items:center;justify-content:center;gap:8px}.wrapper:not(:focus-within):not(:hover) .notificationBtn.passwordBtn,.wrapper:not(:focus-within):not(:hover) .notification.clear{display:none}.notification{display:flex;align-items:center;justify-content:center}`;
|
|
6189
6393
|
|
|
6190
6394
|
var styleDefaultCss = css`.layoutDefault .typeIcon,:host(:not([layout])) .typeIcon{display:flex;flex-direction:row;align-items:center}.layoutDefault .typeIcon [auro-icon],:host(:not([layout])) .typeIcon [auro-icon]{--ds-auro-icon-size: var(--ds-size-300, 1.5rem);height:var(--ds-size-300, 1.5rem);margin-right:var(--ds-size-100, 0.5rem)}.layoutDefault .notificationIcons,:host(:not([layout])) .notificationIcons{display:flex;flex-direction:row;padding-right:var(--ds-size-100, 0.5rem)}:host([class=layoutDefault][bordered]) .typeIcon,:host(:not([layout])[bordered]) .typeIcon{padding-left:var(--ds-size-100, 0.5rem)}:host([class=layoutDefault][bordered]) .notificationIcons,:host(:not([layout])[bordered]) .notificationIcons{align-items:center}:host([class=layoutDefault][bordered]) .notification:not(:first-of-type),:host(:not([layout])[bordered]) .notification:not(:first-of-type){margin-left:var(--ds-size-100, 0.5rem)}:host([class=layoutDefault][bordered]) .alertNotification,:host(:not([layout])[bordered]) .alertNotification{width:calc(var(--ds-size-300, 1.5rem) + var(--ds-size-25, 0.125rem));height:calc(var(--ds-size-300, 1.5rem) + var(--ds-size-25, 0.125rem))}:host([class=layoutDefault][bordered]) .passwordBtn,:host(:not([layout])[bordered]) .passwordBtn{width:calc(var(--ds-size-300, 1.5rem));height:calc(var(--ds-size-300, 1.5rem))}:host([class=layoutDefault][bordered]) .notificationBtn,:host(:not([layout])[bordered]) .notificationBtn{display:block;width:var(--ds-size-300, 1.5rem);height:var(--ds-size-300, 1.5rem);padding:0;border:0;background:unset;cursor:pointer}:host([class=layoutDefault][bordered]) .notificationBtn [auro-icon],:host(:not([layout])[bordered]) .notificationBtn [auro-icon]{display:block;height:var(--ds-size-300, 1.5rem);--ds-auro-icon-size: var(--ds-size-300, 1.5rem)}:host([class=layoutDefault][bordered]) .notificationBtn [auro-icon][hidden],:host(:not([layout])[bordered]) .notificationBtn [auro-icon][hidden]{display:none}:host([class=layoutDefault]:not([bordered])) .typeIcon,:host([class=layoutDefault]:not([bordered])) .notificationIcons,:host(:not([layout]):not([bordered])) .typeIcon,:host(:not([layout]):not([bordered])) .notificationIcons{align-items:flex-end;padding-bottom:var(--ds-size-50, 0.25rem)}:host([class=layoutDefault]:not([bordered])) .clearBtn,:host(:not([layout]):not([bordered])) .clearBtn{transition:all .3s cubic-bezier(0.215, 0.61, 0.355, 1);overflow:hidden;width:0;opacity:0}.layoutDefault .wrapper:hover .clearBtn,.layoutDefault .wrapper:focus-within .clearBtn,:host(:not([layout])) .wrapper:hover .clearBtn,:host(:not([layout])) .wrapper:focus-within .clearBtn{width:calc(var(--ds-size-200, 1rem) + var(--ds-size-25, 0.125rem));height:calc(var(--ds-size-200, 1rem) + var(--ds-size-25, 0.125rem));opacity:1}:host([class=layoutDefault]:focus-within[type=password]) .notificationIcons[hasValue] .alertNotification,:host(:not([layout]):focus-within[type=password]) .notificationIcons[hasValue] .alertNotification{overflow:hidden;width:0;height:0;padding:0;margin:0;visibility:hidden}.layoutDefault input,:host(:not([layout])) input{border:unset}.layoutDefault .wrapper,:host(:not([layout])) .wrapper{position:relative;overflow:hidden;border-style:solid}:host([class=layoutDefault]:not([bordered],[borderless])) .wrapper,:host(:not([layout]):not([bordered],[borderless])) .wrapper{border-width:1px 0}:host([class=layoutDefault][bordered]) .wrapper,:host(:not([layout])[bordered]) .wrapper{border-width:1px;border-radius:var(--ds-border-radius, 0.375rem)}:host([class=layoutDefault]:not([borderless])) .wrapper:focus-within:before,:host(:not([layout]):not([borderless])) .wrapper:focus-within:before{position:absolute;display:block;border-bottom-width:1px;border-bottom-style:solid;content:"";inset:0;pointer-events:none}:host([class=layoutDefault][validity]:not([validity=valid])) .wrapper:before,:host(:not([layout])[validity]:not([validity=valid])) .wrapper:before{border-bottom:0}:focus:not(:focus-visible){outline:3px solid transparent}.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock,:host{display:block}.util_displayFlex{display:flex}.util_displayHidden,:host([hidden]:not(:focus):not(:active)){display:none}.util_displayHiddenVisually,:host([hiddenVisually]:not(:focus):not(:active)){position:absolute;overflow:hidden;clip:rect(1px, 1px, 1px, 1px);width:1px;height:1px;padding:0;border:0}:host{text-align:left}.layoutDefault :host,:host(:not([layout])) :host{position:relative;display:block}.layoutDefault .wrapper,:host(:not([layout])) .wrapper{display:flex;flex-direction:row}.layoutDefault .main,:host(:not([layout])) .main{display:flex;flex-direction:row;position:relative;flex:1}`;
|
|
6191
6395
|
|
|
@@ -10463,8 +10667,21 @@ class AuroFormValidation {
|
|
|
10463
10667
|
return;
|
|
10464
10668
|
}
|
|
10465
10669
|
|
|
10466
|
-
// Validate that the date passed was the correct format and is a valid date
|
|
10670
|
+
// Validate that the date passed was the correct format and is a valid date.
|
|
10671
|
+
// For partial date formats, valueObject is never populated; validate them directly.
|
|
10467
10672
|
if (elem.value && !elem.valueObject) {
|
|
10673
|
+
const isPartialDateFormat = elem.util && !elem.util.isFullDateFormat(elem.type, elem.format);
|
|
10674
|
+
|
|
10675
|
+
if (isPartialDateFormat) {
|
|
10676
|
+
if (!elem.util.isValidPartialDate(elem.value, elem.format)) {
|
|
10677
|
+
elem.validity = 'patternMismatch';
|
|
10678
|
+
elem.errorMessage = elem.setCustomValidityPatternMismatch || elem.setCustomValidity || 'Invalid Date Format Entered';
|
|
10679
|
+
}
|
|
10680
|
+
// Partial date format — validate directly and skip max/min checks since valueObject is undefined.
|
|
10681
|
+
return;
|
|
10682
|
+
}
|
|
10683
|
+
|
|
10684
|
+
// Full date format with no valueObject means the value is not a valid calendar date.
|
|
10468
10685
|
elem.validity = 'patternMismatch';
|
|
10469
10686
|
elem.errorMessage = elem.setCustomValidityPatternMismatch || elem.setCustomValidity || 'Invalid Date Format Entered';
|
|
10470
10687
|
return;
|
|
@@ -10561,15 +10778,17 @@ class AuroFormValidation {
|
|
|
10561
10778
|
);
|
|
10562
10779
|
}
|
|
10563
10780
|
|
|
10564
|
-
|
|
10565
|
-
|
|
10566
|
-
|
|
10781
|
+
const isCombobox = this.runtimeUtils.elementMatch(elem, 'auro-combobox');
|
|
10782
|
+
|
|
10783
|
+
// If there is a second input in the elem and that value is undefined or an empty string set hasValue to false.
|
|
10784
|
+
// Skip for combobox: its second auro-input is the fullscreen-bib mirror of the same value, not an independent
|
|
10785
|
+
// field (datepicker is the intended consumer — start/end are independently required).
|
|
10786
|
+
if (this.auroInputElements?.length === 2 && !isCombobox) {
|
|
10787
|
+
if (!this.auroInputElements[1].value || this.auroInputElements[1].value.length === 0) {
|
|
10567
10788
|
hasValue = false;
|
|
10568
10789
|
}
|
|
10569
10790
|
}
|
|
10570
10791
|
|
|
10571
|
-
const isCombobox = this.runtimeUtils.elementMatch(elem, 'auro-combobox');
|
|
10572
|
-
|
|
10573
10792
|
if (isCombobox) {
|
|
10574
10793
|
|
|
10575
10794
|
if (!elem.persistInput || elem.behavior === "filter") {
|
|
@@ -10668,7 +10887,7 @@ class AuroFormValidation {
|
|
|
10668
10887
|
} else if (this.runtimeUtils.elementMatch(elem, 'auro-input') && elem.errorMessage === '') {
|
|
10669
10888
|
const input = elem.renderRoot.querySelector('input');
|
|
10670
10889
|
|
|
10671
|
-
if (input.validationMessage.length > 0) {
|
|
10890
|
+
if (input && input.validationMessage.length > 0) {
|
|
10672
10891
|
elem.errorMessage = input.validationMessage;
|
|
10673
10892
|
}
|
|
10674
10893
|
} else if (this.runtimeUtils.elementMatch(elem, 'auro-combobox') && elem.errorMessage === '') {
|
|
@@ -16250,8 +16469,6 @@ function cleanEscapedString(input) {
|
|
|
16250
16469
|
return input.match(escapedStringRegExp)[1].replace(doubleQuoteRegExp, "'");
|
|
16251
16470
|
}
|
|
16252
16471
|
|
|
16253
|
-
/* eslint-disable max-lines */
|
|
16254
|
-
|
|
16255
16472
|
class AuroInputUtilities {
|
|
16256
16473
|
|
|
16257
16474
|
/**
|
|
@@ -16294,7 +16511,7 @@ class AuroInputUtilities {
|
|
|
16294
16511
|
/**
|
|
16295
16512
|
* Converts an IMask-style date mask to a date-fns compatible format string.
|
|
16296
16513
|
* @param {string} mask - IMask date mask (e.g. "MM/DD/YYYY").
|
|
16297
|
-
* @returns {string} date-fns format string (e.g. "MM/dd/yyyy").
|
|
16514
|
+
* @returns {string} A date-fns format string (e.g. "MM/dd/yyyy").
|
|
16298
16515
|
*/
|
|
16299
16516
|
toDateFnsMask(mask) {
|
|
16300
16517
|
return mask
|
|
@@ -16394,10 +16611,11 @@ class AuroInputUtilities {
|
|
|
16394
16611
|
const dateFormat = format$1 || this.overrideFormat || pattern || 'mm/dd/yyyy';
|
|
16395
16612
|
|
|
16396
16613
|
if (dateFormat === 'dd' || dateFormat === 'yy' || dateFormat === 'yyyy') {
|
|
16397
|
-
const
|
|
16614
|
+
const fromValue = dateFormat === 'yyyy' ? 1900 : (dateFormat === 'yy' ? 0 : 1);
|
|
16615
|
+
const maxValue = dateFormat === 'dd' ? 31 : (dateFormat === 'yy' ? 99 : 2100);
|
|
16398
16616
|
return {
|
|
16399
16617
|
mask: IMask.MaskedRange,
|
|
16400
|
-
from:
|
|
16618
|
+
from: fromValue,
|
|
16401
16619
|
to: maxValue,
|
|
16402
16620
|
lazy: true,
|
|
16403
16621
|
placeholderChar: '',
|
|
@@ -16405,7 +16623,8 @@ class AuroInputUtilities {
|
|
|
16405
16623
|
return value.toString().padStart(dateFormat.length, '0');
|
|
16406
16624
|
},
|
|
16407
16625
|
parse(str) {
|
|
16408
|
-
|
|
16626
|
+
const num = parseInt(str, 10);
|
|
16627
|
+
return isNaN(num) ? null : num;
|
|
16409
16628
|
}
|
|
16410
16629
|
};
|
|
16411
16630
|
}
|
|
@@ -16469,6 +16688,49 @@ class AuroInputUtilities {
|
|
|
16469
16688
|
return type === 'date' && normalizedFormat.includes('yy') && normalizedFormat.includes('mm') && normalizedFormat.includes('dd');
|
|
16470
16689
|
}
|
|
16471
16690
|
|
|
16691
|
+
/**
|
|
16692
|
+
* Validates a value against a partial date format (one that lacks yy/mm/dd all three).
|
|
16693
|
+
* Day- and year-only formats (dd/yy/yyyy) are checked as integer ranges; other partial formats use
|
|
16694
|
+
* a date-fns parse + round-trip to confirm both validity and exact formatting.
|
|
16695
|
+
* @param {string} value - The user-facing display value.
|
|
16696
|
+
* @param {string} format - The partial date format string (e.g. "mm/yyyy", "yyyy", "dd").
|
|
16697
|
+
* @returns {boolean}
|
|
16698
|
+
*/
|
|
16699
|
+
isValidPartialDate(value, format$1) {
|
|
16700
|
+
if (!value || !format$1) {
|
|
16701
|
+
return false;
|
|
16702
|
+
}
|
|
16703
|
+
const normalizedFormat = format$1.toLowerCase();
|
|
16704
|
+
|
|
16705
|
+
if (normalizedFormat === 'dd') {
|
|
16706
|
+
const num = Number(value);
|
|
16707
|
+
return (/^\d{2}$/u).test(value) && num >= 1 && num <= 31;
|
|
16708
|
+
}
|
|
16709
|
+
if (normalizedFormat === 'yy') {
|
|
16710
|
+
const num = Number(value);
|
|
16711
|
+
return (/^\d{2}$/u).test(value) && num >= 0 && num <= 99;
|
|
16712
|
+
}
|
|
16713
|
+
if (normalizedFormat === 'yyyy') {
|
|
16714
|
+
const num = Number(value);
|
|
16715
|
+
return (/^\d{4}$/u).test(value) && num >= 1900 && num <= 2100;
|
|
16716
|
+
}
|
|
16717
|
+
|
|
16718
|
+
const dateFnsMask = this.toDateFnsMask(normalizedFormat);
|
|
16719
|
+
// Use the 1st of the current month as the reference so that formats
|
|
16720
|
+
// omitting a day (e.g. MM/yyyy) never roll over on days 29–31.
|
|
16721
|
+
const referenceDate = new Date();
|
|
16722
|
+
referenceDate.setDate(1);
|
|
16723
|
+
const parsed = parse(value, dateFnsMask, referenceDate);
|
|
16724
|
+
if (!isValid(parsed) || format(parsed, dateFnsMask) !== value) {
|
|
16725
|
+
return false;
|
|
16726
|
+
}
|
|
16727
|
+
if (normalizedFormat.includes('yyyy')) {
|
|
16728
|
+
const year = parsed.getFullYear();
|
|
16729
|
+
return year >= 1900 && year <= 2100;
|
|
16730
|
+
}
|
|
16731
|
+
return true;
|
|
16732
|
+
}
|
|
16733
|
+
|
|
16472
16734
|
/**
|
|
16473
16735
|
* Converts a display string to its model value.
|
|
16474
16736
|
* For full date formats, converts the display string to an ISO date string.
|
|
@@ -16505,6 +16767,13 @@ class AuroInputUtilities {
|
|
|
16505
16767
|
* @returns {string | undefined}
|
|
16506
16768
|
*/
|
|
16507
16769
|
toFormattedValue(valueObject, format) {
|
|
16770
|
+
// Exposed publicly via `AuroInputUtil.toFormattedValue`, so a missing
|
|
16771
|
+
// `format` argument has to fail gracefully rather than throw on
|
|
16772
|
+
// `format.toLowerCase()`. Treat any falsy value (undefined, null, '')
|
|
16773
|
+
// as "no format → no display value".
|
|
16774
|
+
if (!format) {
|
|
16775
|
+
return undefined;
|
|
16776
|
+
}
|
|
16508
16777
|
const normalizedFormat = format.toLowerCase();
|
|
16509
16778
|
const maskOptions = this.getMaskOptions('date', normalizedFormat);
|
|
16510
16779
|
|
|
@@ -16643,9 +16912,10 @@ class DomHandler {
|
|
|
16643
16912
|
class BaseInput extends AuroElement$1 {
|
|
16644
16913
|
|
|
16645
16914
|
// Delegate focus to the native <input> inside the shadow root so that
|
|
16646
|
-
//
|
|
16647
|
-
//
|
|
16648
|
-
//
|
|
16915
|
+
// clicking anywhere on the input wrapper focuses the native input, and
|
|
16916
|
+
// programmatic .focus() calls on elements in the shadow DOM work correctly.
|
|
16917
|
+
// The initial-load focus theft was caused by the static `autofocus`
|
|
16918
|
+
// attribute on the bib input (now conditional), not by delegatesFocus.
|
|
16649
16919
|
static get shadowRootOptions() {
|
|
16650
16920
|
return {
|
|
16651
16921
|
...AuroElement$1.shadowRootOptions,
|
|
@@ -16656,79 +16926,19 @@ class BaseInput extends AuroElement$1 {
|
|
|
16656
16926
|
constructor() {
|
|
16657
16927
|
super();
|
|
16658
16928
|
|
|
16659
|
-
|
|
16660
|
-
|
|
16661
|
-
|
|
16662
|
-
|
|
16663
|
-
|
|
16664
|
-
|
|
16665
|
-
|
|
16666
|
-
|
|
16667
|
-
|
|
16668
|
-
|
|
16669
|
-
this.required = false;
|
|
16670
|
-
this.onDark = false;
|
|
16671
|
-
this.setCustomValidityForType = undefined;
|
|
16672
|
-
this.size = 'lg';
|
|
16673
|
-
this.shape = 'classic';
|
|
16674
|
-
this.value = undefined;
|
|
16675
|
-
this._valueObject = undefined;
|
|
16676
|
-
|
|
16677
|
-
this._initializePrivateDefaults();
|
|
16678
|
-
}
|
|
16679
|
-
|
|
16680
|
-
/**
|
|
16681
|
-
* Internal Defaults.
|
|
16682
|
-
* @private
|
|
16683
|
-
* @returns {void}
|
|
16684
|
-
*/
|
|
16685
|
-
_initializePrivateDefaults() {
|
|
16929
|
+
// Single-source initialization. Alphabetized so duplicate or stale
|
|
16930
|
+
// defaults are immediately obvious on a diff. Every field is assigned
|
|
16931
|
+
// exactly once here (previously the constructor + the old
|
|
16932
|
+
// `_initializePrivateDefaults` overlapped — both wrote ~14 of the same
|
|
16933
|
+
// fields and double-allocated `util` and `validation`, discarding the
|
|
16934
|
+
// first instance). `validation` is now allocated exactly once; `util`
|
|
16935
|
+
// is seeded here with an en-US default and then rebuilt in
|
|
16936
|
+
// `connectedCallback` once the consumer-resolved locale is available,
|
|
16937
|
+
// so a parent (datepicker/combobox) calling `validate()` synchronously
|
|
16938
|
+
// during its own update cycle sees a populated util instance.
|
|
16686
16939
|
this.activeLabel = false;
|
|
16687
|
-
this.appearance = "default";
|
|
16688
|
-
this.icon = false;
|
|
16689
|
-
this.disabled = false;
|
|
16690
|
-
this.dvInputOnly = false;
|
|
16691
|
-
this.hideLabelVisually = false;
|
|
16692
|
-
this.max = undefined;
|
|
16693
|
-
this.maxLength = undefined;
|
|
16694
|
-
this.min = undefined;
|
|
16695
|
-
this.minLength = undefined;
|
|
16696
|
-
this.noValidate = false;
|
|
16697
|
-
this.onDark = false;
|
|
16698
|
-
this.required = false;
|
|
16699
|
-
this.setCustomValidityForType = undefined;
|
|
16700
|
-
|
|
16701
|
-
// Used for storing raw values returned from input mask.
|
|
16702
|
-
this._rawMaskValue = undefined;
|
|
16703
|
-
|
|
16704
|
-
/**
|
|
16705
|
-
* @private
|
|
16706
|
-
*/
|
|
16707
|
-
this.layout = 'classic';
|
|
16708
|
-
|
|
16709
|
-
/**
|
|
16710
|
-
* @private
|
|
16711
|
-
*/
|
|
16712
|
-
this.shape = 'classic';
|
|
16713
|
-
|
|
16714
|
-
/**
|
|
16715
|
-
* @private
|
|
16716
|
-
*/
|
|
16717
|
-
this.size = 'lg';
|
|
16718
|
-
|
|
16719
|
-
this.touched = false;
|
|
16720
|
-
this.util = new AuroInputUtilities({
|
|
16721
|
-
locale: "en-US",
|
|
16722
|
-
format: this.format
|
|
16723
|
-
});
|
|
16724
|
-
this.validation = new AuroFormValidation();
|
|
16725
|
-
this.inputIconName = undefined;
|
|
16726
|
-
this.showPassword = false;
|
|
16727
|
-
this.validationCCLength = undefined;
|
|
16728
|
-
this.hasValue = false;
|
|
16729
|
-
this.label = 'Input label is undefined';
|
|
16730
|
-
|
|
16731
16940
|
|
|
16941
|
+
/** @private */
|
|
16732
16942
|
this.allowedInputTypes = [
|
|
16733
16943
|
"text",
|
|
16734
16944
|
"number",
|
|
@@ -16737,7 +16947,9 @@ class BaseInput extends AuroElement$1 {
|
|
|
16737
16947
|
"credit-card",
|
|
16738
16948
|
"tel"
|
|
16739
16949
|
];
|
|
16740
|
-
this.
|
|
16950
|
+
this.appearance = "default";
|
|
16951
|
+
|
|
16952
|
+
/** @private */
|
|
16741
16953
|
this.dateFormatMap = {
|
|
16742
16954
|
'mm/dd/yyyy': 'dateMMDDYYYY',
|
|
16743
16955
|
'dd/mm/yyyy': 'dateDDMMYYYY',
|
|
@@ -16754,27 +16966,64 @@ class BaseInput extends AuroElement$1 {
|
|
|
16754
16966
|
'dd/mm': 'dateDDMM',
|
|
16755
16967
|
'mm/dd': 'dateMMDD'
|
|
16756
16968
|
};
|
|
16969
|
+
this.disabled = false;
|
|
16970
|
+
|
|
16971
|
+
/** @private */
|
|
16757
16972
|
this.domHandler = new DomHandler();
|
|
16758
16973
|
this.dvInputOnly = false;
|
|
16759
16974
|
this.hasValue = false;
|
|
16975
|
+
this.hideLabelVisually = false;
|
|
16976
|
+
this.icon = false;
|
|
16977
|
+
|
|
16978
|
+
/** @private */
|
|
16760
16979
|
this.inputIconName = undefined;
|
|
16980
|
+
|
|
16981
|
+
/** @private */
|
|
16761
16982
|
this.label = 'Input label is undefined';
|
|
16983
|
+
this.layout = 'classic';
|
|
16984
|
+
this.locale = 'en-US';
|
|
16985
|
+
this._format = undefined;
|
|
16986
|
+
|
|
16987
|
+
/** @private */
|
|
16988
|
+
this._userSetFormat = false;
|
|
16989
|
+
this.max = undefined;
|
|
16990
|
+
this.maxLength = undefined;
|
|
16991
|
+
this.min = undefined;
|
|
16992
|
+
this.minLength = undefined;
|
|
16762
16993
|
this.noValidate = false;
|
|
16763
|
-
this.
|
|
16994
|
+
this.onDark = false;
|
|
16995
|
+
this.required = false;
|
|
16996
|
+
this.setCustomValidityForType = undefined;
|
|
16997
|
+
// Credit Card is intentionally excluded — its mask manages the cursor
|
|
16998
|
+
// itself, and listing it here caused cursor placement issues in Safari.
|
|
16999
|
+
/** @private */
|
|
16764
17000
|
this.setSelectionInputTypes = [
|
|
16765
17001
|
"text",
|
|
16766
17002
|
"password",
|
|
16767
17003
|
"email"
|
|
16768
|
-
];
|
|
17004
|
+
];
|
|
17005
|
+
this.shape = 'classic';
|
|
17006
|
+
|
|
17007
|
+
/** @private */
|
|
16769
17008
|
this.showPassword = false;
|
|
17009
|
+
this.size = 'lg';
|
|
16770
17010
|
this.touched = false;
|
|
17011
|
+
|
|
17012
|
+
/** @private */
|
|
16771
17013
|
this.uniqueId = new UniqueId().create();
|
|
17014
|
+
|
|
17015
|
+
/** @private */
|
|
16772
17016
|
this.util = new AuroInputUtilities({
|
|
16773
17017
|
locale: this.locale,
|
|
16774
17018
|
format: this.format
|
|
16775
17019
|
});
|
|
17020
|
+
|
|
17021
|
+
/** @private */
|
|
16776
17022
|
this.validation = new AuroFormValidation();
|
|
17023
|
+
|
|
17024
|
+
/** @private */
|
|
16777
17025
|
this.validationCCLength = undefined;
|
|
17026
|
+
this.value = undefined;
|
|
16778
17027
|
}
|
|
16779
17028
|
|
|
16780
17029
|
// function to define props used within the scope of this component
|
|
@@ -16900,7 +17149,8 @@ class BaseInput extends AuroElement$1 {
|
|
|
16900
17149
|
*/
|
|
16901
17150
|
format: {
|
|
16902
17151
|
type: String,
|
|
16903
|
-
reflect: true
|
|
17152
|
+
reflect: true,
|
|
17153
|
+
noAccessor: true
|
|
16904
17154
|
},
|
|
16905
17155
|
|
|
16906
17156
|
/**
|
|
@@ -17104,6 +17354,13 @@ class BaseInput extends AuroElement$1 {
|
|
|
17104
17354
|
type: String
|
|
17105
17355
|
},
|
|
17106
17356
|
|
|
17357
|
+
/**
|
|
17358
|
+
* Custom help text message to display when validity = `patternMismatch`.
|
|
17359
|
+
*/
|
|
17360
|
+
setCustomValidityPatternMismatch: {
|
|
17361
|
+
type: String
|
|
17362
|
+
},
|
|
17363
|
+
|
|
17107
17364
|
/**
|
|
17108
17365
|
* Custom help text message to display when validity = `rangeOverflow`.
|
|
17109
17366
|
*/
|
|
@@ -17174,7 +17431,7 @@ class BaseInput extends AuroElement$1 {
|
|
|
17174
17431
|
|
|
17175
17432
|
/**
|
|
17176
17433
|
* Populates the `type` attribute on the input.
|
|
17177
|
-
* @type {'text' | 'password' | 'email' | 'credit-card' | 'tel' | 'number'}
|
|
17434
|
+
* @type {'text' | 'password' | 'email' | 'credit-card' | 'tel' | 'number' | 'date'}
|
|
17178
17435
|
* @default 'text'
|
|
17179
17436
|
*/
|
|
17180
17437
|
type: {
|
|
@@ -17199,7 +17456,7 @@ class BaseInput extends AuroElement$1 {
|
|
|
17199
17456
|
|
|
17200
17457
|
/**
|
|
17201
17458
|
* Populates the `value` attribute on the input. Can also be read to retrieve the current value of the input.
|
|
17202
|
-
*
|
|
17459
|
+
* For `date` type inputs using a full date format (year/month/day), the `value` should be ISO (YYYY-MM-DD). Partial date formats use the display format.
|
|
17203
17460
|
*/
|
|
17204
17461
|
value: {
|
|
17205
17462
|
type: String
|
|
@@ -17212,7 +17469,7 @@ class BaseInput extends AuroElement$1 {
|
|
|
17212
17469
|
* @returns {Date|undefined}
|
|
17213
17470
|
*/
|
|
17214
17471
|
get valueObject() {
|
|
17215
|
-
return this.
|
|
17472
|
+
return this.value && dateFormatter.isValidDate(this.value) ? dateFormatter.stringToDateInstance(this.value) : undefined;
|
|
17216
17473
|
}
|
|
17217
17474
|
|
|
17218
17475
|
/**
|
|
@@ -17220,7 +17477,7 @@ class BaseInput extends AuroElement$1 {
|
|
|
17220
17477
|
* @returns {Date|undefined}
|
|
17221
17478
|
*/
|
|
17222
17479
|
get minObject() {
|
|
17223
|
-
return this.
|
|
17480
|
+
return this.min && dateFormatter.isValidDate(this.min) ? dateFormatter.stringToDateInstance(this.min) : undefined;
|
|
17224
17481
|
}
|
|
17225
17482
|
|
|
17226
17483
|
/**
|
|
@@ -17228,33 +17485,63 @@ class BaseInput extends AuroElement$1 {
|
|
|
17228
17485
|
* @returns {Date|undefined}
|
|
17229
17486
|
*/
|
|
17230
17487
|
get maxObject() {
|
|
17231
|
-
return this.
|
|
17488
|
+
return this.max && dateFormatter.isValidDate(this.max) ? dateFormatter.stringToDateInstance(this.max) : undefined;
|
|
17489
|
+
}
|
|
17490
|
+
|
|
17491
|
+
get format() {
|
|
17492
|
+
return this._format;
|
|
17232
17493
|
}
|
|
17233
17494
|
|
|
17234
17495
|
/**
|
|
17235
|
-
*
|
|
17236
|
-
*
|
|
17237
|
-
*
|
|
17238
|
-
* @param {Date|undefined} propertyValue - Value to assign.
|
|
17239
|
-
* @returns {void}
|
|
17496
|
+
* Overrides LitElement's generated accessor so we can track whether the
|
|
17497
|
+
* consumer explicitly set `format`. Locale-derived updates use
|
|
17498
|
+
* `_setFormatFromLocale` instead, which skips this flag.
|
|
17240
17499
|
*/
|
|
17241
|
-
|
|
17242
|
-
const
|
|
17243
|
-
|
|
17244
|
-
|
|
17245
|
-
|
|
17246
|
-
|
|
17247
|
-
}
|
|
17500
|
+
set format(value) {
|
|
17501
|
+
const oldValue = this._format;
|
|
17502
|
+
this._format = value ? value.toLowerCase() : value;
|
|
17503
|
+
this._userSetFormat = Boolean(value);
|
|
17504
|
+
this.requestUpdate('format', oldValue);
|
|
17505
|
+
}
|
|
17248
17506
|
|
|
17249
|
-
|
|
17250
|
-
|
|
17507
|
+
/**
|
|
17508
|
+
* Sets format without marking it as user-set. Used by locale auto-derive
|
|
17509
|
+
* so that a subsequent locale change can still update the format.
|
|
17510
|
+
* @private
|
|
17511
|
+
* @param {string} value
|
|
17512
|
+
*/
|
|
17513
|
+
_setFormatFromLocale(value) {
|
|
17514
|
+
const oldValue = this._format;
|
|
17515
|
+
this._format = value ? value.toLowerCase() : value;
|
|
17516
|
+
this.requestUpdate('format', oldValue);
|
|
17251
17517
|
}
|
|
17252
17518
|
|
|
17253
17519
|
connectedCallback() {
|
|
17254
17520
|
super.connectedCallback();
|
|
17255
17521
|
|
|
17522
|
+
// Mark for query selectors when registered under a versioned tag (e.g. inside
|
|
17523
|
+
// a datepicker/combobox). Must run before parent components call validate() on
|
|
17524
|
+
// their inner inputs — the validation framework matches via tag-or-attribute,
|
|
17525
|
+
// and parents trigger validation during their own updated() cycle, which can
|
|
17526
|
+
// precede this input's firstUpdated().
|
|
17527
|
+
if (this.tagName.toLowerCase() !== 'auro-input' && !this.hasAttribute('auro-input')) {
|
|
17528
|
+
this.setAttribute('auro-input', '');
|
|
17529
|
+
}
|
|
17530
|
+
|
|
17256
17531
|
this.locale = this.domHandler.getLocale(this);
|
|
17257
17532
|
notifyOnLangChange(this);
|
|
17533
|
+
|
|
17534
|
+
// Pre-compute lengthForType and date-object fields so a parent (e.g. datepicker)
|
|
17535
|
+
// calling our validate() synchronously during its own updated() cycle sees
|
|
17536
|
+
// populated values. Without this, range validation silently no-ops because
|
|
17537
|
+
// `max.length === lengthForType` fails when lengthForType is still undefined.
|
|
17538
|
+
// Rebuild util here (constructor seeded with en-US default) so configureDataForType's
|
|
17539
|
+
// locale-derived format lookup uses the actual locale just resolved above.
|
|
17540
|
+
this.util = new AuroInputUtilities({
|
|
17541
|
+
locale: this.locale,
|
|
17542
|
+
format: this.format
|
|
17543
|
+
});
|
|
17544
|
+
this.configureDataForType();
|
|
17258
17545
|
}
|
|
17259
17546
|
|
|
17260
17547
|
disconnectedCallback() {
|
|
@@ -17274,10 +17561,6 @@ class BaseInput extends AuroElement$1 {
|
|
|
17274
17561
|
this.wrapperElement.addEventListener('click', this.handleClick);
|
|
17275
17562
|
}
|
|
17276
17563
|
|
|
17277
|
-
// add attribute for query selectors when auro-input is registered under a custom name
|
|
17278
|
-
if (this.tagName.toLowerCase() !== 'auro-input') {
|
|
17279
|
-
this.setAttribute('auro-input', true);
|
|
17280
|
-
}
|
|
17281
17564
|
this.inputId = this.id ? `${this.id}-input` : window.crypto.randomUUID();
|
|
17282
17565
|
|
|
17283
17566
|
// use validity message override if declared when initializing the component
|
|
@@ -17288,7 +17571,6 @@ class BaseInput extends AuroElement$1 {
|
|
|
17288
17571
|
this.setCustomHelpTextMessage();
|
|
17289
17572
|
this.configureAutoFormatting();
|
|
17290
17573
|
this.configureDataForType();
|
|
17291
|
-
this.syncDateValues();
|
|
17292
17574
|
}
|
|
17293
17575
|
|
|
17294
17576
|
/**
|
|
@@ -17324,6 +17606,12 @@ class BaseInput extends AuroElement$1 {
|
|
|
17324
17606
|
return;
|
|
17325
17607
|
}
|
|
17326
17608
|
|
|
17609
|
+
// While configureAutoFormatting is running, imask's internal updateControl
|
|
17610
|
+
// writes el.value to align display with the masked value. A synthetic input
|
|
17611
|
+
// event from that write would re-enter handleInput → processCreditCard mid-setup
|
|
17612
|
+
// and clobber a Lit value that was just pushed by the parent combobox.
|
|
17613
|
+
if (component._configuringMask) return;
|
|
17614
|
+
|
|
17327
17615
|
// If all guard clauses are passed, dispatch the event
|
|
17328
17616
|
const inputEvent = new InputEvent('input', {
|
|
17329
17617
|
bubbles: true,
|
|
@@ -17340,7 +17628,7 @@ class BaseInput extends AuroElement$1 {
|
|
|
17340
17628
|
|
|
17341
17629
|
/**
|
|
17342
17630
|
* @private
|
|
17343
|
-
* @deprecated https://dev.azure.com/itsals/E_Retain_Content/_workitems/edit/1557296
|
|
17631
|
+
* @deprecated See https://dev.azure.com/itsals/E_Retain_Content/_workitems/edit/1557296.
|
|
17344
17632
|
* @returns {void} Sets the default help text for the input.
|
|
17345
17633
|
*/
|
|
17346
17634
|
setCustomHelpTextMessage() {
|
|
@@ -17358,6 +17646,13 @@ class BaseInput extends AuroElement$1 {
|
|
|
17358
17646
|
|
|
17359
17647
|
if (typeToI18n.includes(this.type)) {
|
|
17360
17648
|
this.setCustomValidityForType = i18n(this.lang, this.type);
|
|
17649
|
+
// COVERAGE: this `else if` branch is unreachable in WTR. connectedCallback
|
|
17650
|
+
// (L682) calls configureDataForType, which at L1266-1268 assigns
|
|
17651
|
+
// `this.format = this.util.getDateMaskFromLocale().toLowerCase()` for any
|
|
17652
|
+
// type=date input whose `format` attribute is unset. That runs before
|
|
17653
|
+
// firstUpdated invokes setCustomHelpTextMessage, so `!this.format` is
|
|
17654
|
+
// always false here. Retained as a defensive fallback; the whole function
|
|
17655
|
+
// is @deprecated per AB#1557296 and slated for removal.
|
|
17361
17656
|
} else if (!this.format && this.type === 'date') {
|
|
17362
17657
|
this.setCustomValidityForType = i18n(this.lang, 'dateMMDDYYYY');
|
|
17363
17658
|
} else if (this.dateFormatMap[this.format]) {
|
|
@@ -17374,12 +17669,10 @@ class BaseInput extends AuroElement$1 {
|
|
|
17374
17669
|
updated(changedProperties) {
|
|
17375
17670
|
super.updated(changedProperties);
|
|
17376
17671
|
|
|
17377
|
-
// When locale changes
|
|
17378
|
-
// Only runs if the current format is still the previous locale's default (not user-overridden).
|
|
17672
|
+
// When locale changes, auto-derive format unless the consumer explicitly set one.
|
|
17379
17673
|
if (changedProperties.has('locale') && !changedProperties.has('format') && this.type === 'date') {
|
|
17380
|
-
|
|
17381
|
-
|
|
17382
|
-
this.format = getDateFormatFromLocale(this.locale);
|
|
17674
|
+
if (!this._userSetFormat) {
|
|
17675
|
+
this._setFormatFromLocale(getDateFormatFromLocale(this.locale));
|
|
17383
17676
|
}
|
|
17384
17677
|
}
|
|
17385
17678
|
|
|
@@ -17419,8 +17712,6 @@ class BaseInput extends AuroElement$1 {
|
|
|
17419
17712
|
this.configureDataForType();
|
|
17420
17713
|
}
|
|
17421
17714
|
|
|
17422
|
-
this.syncDateValues(changedProperties);
|
|
17423
|
-
|
|
17424
17715
|
if (changedProperties.has('value')) {
|
|
17425
17716
|
if (this.value && this.value.length > 0) {
|
|
17426
17717
|
this.hasValue = true;
|
|
@@ -17442,7 +17733,16 @@ class BaseInput extends AuroElement$1 {
|
|
|
17442
17733
|
|
|
17443
17734
|
if (formattedValue !== this.inputElement.value) {
|
|
17444
17735
|
this.skipNextProgrammaticInputEvent = true;
|
|
17445
|
-
if (
|
|
17736
|
+
if (this.maskInstance && this.type !== 'date') {
|
|
17737
|
+
// Route through the mask so its _value and el.value stay in lock-step
|
|
17738
|
+
// (set value calls updateControl which writes el.value = displayValue).
|
|
17739
|
+
// Writing el.value directly leaves the mask thinking displayValue is
|
|
17740
|
+
// stale; _saveSelection on the next focus/click then warns. Date is
|
|
17741
|
+
// excluded because its formattedValue can be raw ISO when the calendar
|
|
17742
|
+
// is invalid, and re-masking through mm/dd/yyyy would truncate it and
|
|
17743
|
+
// flip validity from patternMismatch to tooShort.
|
|
17744
|
+
this.maskInstance.value = formattedValue || '';
|
|
17745
|
+
} else if (formattedValue) {
|
|
17446
17746
|
this.inputElement.value = formattedValue;
|
|
17447
17747
|
} else {
|
|
17448
17748
|
this.inputElement.value = '';
|
|
@@ -17462,87 +17762,24 @@ class BaseInput extends AuroElement$1 {
|
|
|
17462
17762
|
}
|
|
17463
17763
|
|
|
17464
17764
|
if (changedProperties.has('error')) {
|
|
17465
|
-
this.validate(true);
|
|
17466
|
-
}
|
|
17467
|
-
|
|
17468
|
-
if (changedProperties.has('validity')) {
|
|
17469
|
-
this.notifyValidityChange();
|
|
17470
|
-
}
|
|
17471
|
-
}
|
|
17472
|
-
|
|
17473
|
-
/**
|
|
17474
|
-
* @private
|
|
17475
|
-
* @returns {void} Notify validity state changed via event.
|
|
17476
|
-
*/
|
|
17477
|
-
notifyValidityChange() {
|
|
17478
|
-
this.dispatchEvent(new CustomEvent('auroInput-validityChange', {
|
|
17479
|
-
bubbles: true,
|
|
17480
|
-
cancelable: false,
|
|
17481
|
-
composed: true,
|
|
17482
|
-
}));
|
|
17483
|
-
}
|
|
17484
|
-
|
|
17485
|
-
|
|
17486
|
-
/**
|
|
17487
|
-
* Synchronizes the ISO string values and Date object representations for date-related properties.
|
|
17488
|
-
* This keeps the model and display values aligned when either side changes.
|
|
17489
|
-
*
|
|
17490
|
-
* When a full date format is in use, this method updates `value`, `min`, and `max` from their corresponding
|
|
17491
|
-
* Date objects or vice versa, based on which properties have changed. It only runs when the current configuration
|
|
17492
|
-
* represents a full year/month/day date format.
|
|
17493
|
-
*
|
|
17494
|
-
* @param {Map<string, unknown>|undefined} [changedProperties=undefined] - Optional map of changed properties used to limit which values are synchronized.
|
|
17495
|
-
* @returns {void}
|
|
17496
|
-
* @private
|
|
17497
|
-
*/
|
|
17498
|
-
syncDateValues(changedProperties = undefined) {
|
|
17499
|
-
if (!this.util.isFullDateFormat(this.type, this.format)) {
|
|
17500
|
-
return;
|
|
17501
|
-
}
|
|
17502
|
-
|
|
17503
|
-
this.syncSingleDateValue(changedProperties, 'valueObject', 'value');
|
|
17504
|
-
this.syncSingleDateValue(changedProperties, 'minObject', 'min');
|
|
17505
|
-
this.syncSingleDateValue(changedProperties, 'maxObject', 'max');
|
|
17506
|
-
}
|
|
17507
|
-
|
|
17508
|
-
/**
|
|
17509
|
-
* Synchronizes one date object/string property pair.
|
|
17510
|
-
* @private
|
|
17511
|
-
* @param {Map<string, unknown>|undefined} changedProperties - Map of changed properties from Lit.
|
|
17512
|
-
* @param {string} objectProperty - Date object property name.
|
|
17513
|
-
* @param {string} valueProperty - ISO string property name.
|
|
17514
|
-
* @returns {void}
|
|
17515
|
-
*/
|
|
17516
|
-
syncSingleDateValue(changedProperties, objectProperty, valueProperty) {
|
|
17517
|
-
const objectPropertyChanged = !changedProperties || changedProperties.has(objectProperty);
|
|
17518
|
-
|
|
17519
|
-
// objectProperty wins over valueProperty when both changed
|
|
17520
|
-
if (objectPropertyChanged && this[objectProperty]) {
|
|
17521
|
-
this[valueProperty] = dateFormatter.toISOFormatString(this[objectProperty]);
|
|
17522
|
-
return;
|
|
17523
|
-
}
|
|
17524
|
-
|
|
17525
|
-
const valuePropertyChanged = !changedProperties || changedProperties.has(valueProperty);
|
|
17526
|
-
if (!valuePropertyChanged) {
|
|
17527
|
-
return;
|
|
17765
|
+
this.validate(true);
|
|
17528
17766
|
}
|
|
17529
17767
|
|
|
17530
|
-
|
|
17531
|
-
|
|
17532
|
-
changedProperties &&
|
|
17533
|
-
valueProperty === 'value' &&
|
|
17534
|
-
changedProperties.get('value') === undefined &&
|
|
17535
|
-
this[objectProperty] instanceof Date &&
|
|
17536
|
-
this[valueProperty] === dateFormatter.toISOFormatString(this[objectProperty])
|
|
17537
|
-
) {
|
|
17538
|
-
return;
|
|
17768
|
+
if (changedProperties.has('validity')) {
|
|
17769
|
+
this.notifyValidityChange();
|
|
17539
17770
|
}
|
|
17771
|
+
}
|
|
17540
17772
|
|
|
17541
|
-
|
|
17542
|
-
|
|
17543
|
-
|
|
17544
|
-
|
|
17545
|
-
|
|
17773
|
+
/**
|
|
17774
|
+
* @private
|
|
17775
|
+
* @returns {void} Notify validity state changed via event.
|
|
17776
|
+
*/
|
|
17777
|
+
notifyValidityChange() {
|
|
17778
|
+
this.dispatchEvent(new CustomEvent('auroInput-validityChange', {
|
|
17779
|
+
bubbles: true,
|
|
17780
|
+
cancelable: false,
|
|
17781
|
+
composed: true,
|
|
17782
|
+
}));
|
|
17546
17783
|
}
|
|
17547
17784
|
|
|
17548
17785
|
/**
|
|
@@ -17551,58 +17788,79 @@ class BaseInput extends AuroElement$1 {
|
|
|
17551
17788
|
* @returns {void}
|
|
17552
17789
|
*/
|
|
17553
17790
|
configureAutoFormatting() {
|
|
17554
|
-
|
|
17555
|
-
|
|
17556
|
-
|
|
17791
|
+
// _configuringMask gates two things: external re-entry into this method
|
|
17792
|
+
// while setup is mid-flight (from property changes that call back here),
|
|
17793
|
+
// and the accept/complete listeners below — both need to ignore the mask
|
|
17794
|
+
// events fired by our own value-restore step.
|
|
17795
|
+
if (this._configuringMask) return;
|
|
17796
|
+
this._configuringMask = true;
|
|
17797
|
+
try {
|
|
17798
|
+
// Destroy any prior mask so IMask can attach fresh under the new format.
|
|
17799
|
+
// Null the reference too — if the new maskOptions.mask is falsy (e.g.
|
|
17800
|
+
// type switched from credit-card to text) the IMask() reassignment
|
|
17801
|
+
// below is skipped, and downstream writes at line ~823 would otherwise
|
|
17802
|
+
// route through the destroyed instance.
|
|
17803
|
+
if (this.maskInstance) {
|
|
17804
|
+
this.maskInstance.destroy();
|
|
17805
|
+
this.maskInstance = null;
|
|
17806
|
+
}
|
|
17557
17807
|
|
|
17558
|
-
|
|
17559
|
-
this.util.updateFormat(this.format);
|
|
17808
|
+
this.util.updateFormat(this.format);
|
|
17560
17809
|
|
|
17561
|
-
|
|
17810
|
+
const maskOptions = this.util.getMaskOptions(this.type, this.format);
|
|
17562
17811
|
|
|
17563
|
-
|
|
17812
|
+
if (this.inputElement && maskOptions.mask) {
|
|
17813
|
+
// Capture the current display so it can be re-applied after IMask
|
|
17814
|
+
// attaches. The restore at the bottom goes through maskInstance.value
|
|
17815
|
+
// (not inputElement.value directly) so the mask's internal state and
|
|
17816
|
+
// the input's displayed text stay in lock-step.
|
|
17817
|
+
let existingValue = this.inputElement.value;
|
|
17564
17818
|
|
|
17565
|
-
|
|
17566
|
-
|
|
17567
|
-
|
|
17568
|
-
|
|
17569
|
-
|
|
17570
|
-
|
|
17571
|
-
|
|
17572
|
-
|
|
17573
|
-
|
|
17574
|
-
|
|
17575
|
-
|
|
17576
|
-
|
|
17577
|
-
!Number.isNaN(this.valueObject.getTime()) &&
|
|
17578
|
-
typeof maskOptions.format === 'function'
|
|
17579
|
-
) {
|
|
17580
|
-
existingValue = maskOptions.format(this.valueObject);
|
|
17581
|
-
}
|
|
17819
|
+
// Format-change case (e.g. locale switch): existingValue is the OLD
|
|
17820
|
+
// mask's display string and may not parse under the new mask. When
|
|
17821
|
+
// we have a valid date model, rebuild the display from valueObject
|
|
17822
|
+
// (the canonical source) using the new mask's format function.
|
|
17823
|
+
if (
|
|
17824
|
+
this.util.isFullDateFormat(this.type, this.format) &&
|
|
17825
|
+
this.value &&
|
|
17826
|
+
this.valueObject &&
|
|
17827
|
+
typeof maskOptions.format === 'function'
|
|
17828
|
+
) {
|
|
17829
|
+
existingValue = maskOptions.format(this.valueObject);
|
|
17830
|
+
}
|
|
17582
17831
|
|
|
17583
|
-
|
|
17584
|
-
|
|
17832
|
+
// Clear before IMask attaches so the constructor seeds an empty
|
|
17833
|
+
// internal value. Otherwise IMask reads the stale unmasked string
|
|
17834
|
+
// and emits a spurious 'accept' before the restore below runs.
|
|
17835
|
+
this.skipNextProgrammaticInputEvent = true;
|
|
17836
|
+
this.inputElement.value = '';
|
|
17585
17837
|
|
|
17586
|
-
|
|
17838
|
+
this.maskInstance = IMask(this.inputElement, maskOptions);
|
|
17587
17839
|
|
|
17588
|
-
|
|
17589
|
-
|
|
17590
|
-
|
|
17591
|
-
|
|
17592
|
-
|
|
17593
|
-
|
|
17840
|
+
// Mask fires 'accept' on every value change, including the restore
|
|
17841
|
+
// step below. Skip events fired during configureAutoFormatting so
|
|
17842
|
+
// we don't overwrite a value the parent just pushed.
|
|
17843
|
+
this.maskInstance.on('accept', () => {
|
|
17844
|
+
if (this._configuringMask) return;
|
|
17845
|
+
this.value = this.util.toModelValue(this.maskInstance.value, this.format);
|
|
17846
|
+
});
|
|
17594
17847
|
|
|
17595
|
-
|
|
17596
|
-
|
|
17597
|
-
|
|
17598
|
-
this.
|
|
17599
|
-
|
|
17600
|
-
|
|
17848
|
+
// Mask fires 'complete' on the restore step below for any value that
|
|
17849
|
+
// happens to be a complete match. Same setup-suppression as 'accept'.
|
|
17850
|
+
this.maskInstance.on('complete', () => {
|
|
17851
|
+
if (this._configuringMask) return;
|
|
17852
|
+
this.value = this.util.toModelValue(this.maskInstance.value, this.format);
|
|
17853
|
+
});
|
|
17601
17854
|
|
|
17602
|
-
|
|
17603
|
-
|
|
17604
|
-
|
|
17855
|
+
// Write existingValue through the mask (not the input directly) so
|
|
17856
|
+
// the mask reformats it under the new rules and keeps its internal
|
|
17857
|
+
// _value aligned with the input's displayed text.
|
|
17858
|
+
if (existingValue) {
|
|
17859
|
+
this.maskInstance.value = existingValue;
|
|
17860
|
+
}
|
|
17605
17861
|
}
|
|
17862
|
+
} finally {
|
|
17863
|
+
this._configuringMask = false;
|
|
17606
17864
|
}
|
|
17607
17865
|
}
|
|
17608
17866
|
|
|
@@ -17612,14 +17870,17 @@ class BaseInput extends AuroElement$1 {
|
|
|
17612
17870
|
* @returns {void}
|
|
17613
17871
|
*/
|
|
17614
17872
|
notifyValueChanged() {
|
|
17615
|
-
|
|
17616
|
-
|
|
17617
|
-
|
|
17873
|
+
// This echoes Lit's reactive value update (and handleClickClear's
|
|
17874
|
+
// programmatic clear) — it is NOT a fresh user-input event. Mark it
|
|
17875
|
+
// `isProgrammatic` so consumers (e.g. auro-combobox) can distinguish
|
|
17876
|
+
// it from genuine user typing and skip clobbering their own
|
|
17877
|
+
// programmatic state during init-time renders.
|
|
17878
|
+
const inputEvent = new Event('input', {
|
|
17618
17879
|
bubbles: true,
|
|
17619
17880
|
composed: true,
|
|
17620
17881
|
});
|
|
17882
|
+
inputEvent.isProgrammatic = true;
|
|
17621
17883
|
|
|
17622
|
-
// Dispatched event to alert outside shadow DOM context of event firing.
|
|
17623
17884
|
this.dispatchEvent(inputEvent);
|
|
17624
17885
|
}
|
|
17625
17886
|
|
|
@@ -17676,6 +17937,38 @@ class BaseInput extends AuroElement$1 {
|
|
|
17676
17937
|
this.touched = true;
|
|
17677
17938
|
this.validation.validate(this);
|
|
17678
17939
|
}
|
|
17940
|
+
|
|
17941
|
+
// Prevents cursor jumping in Safari. Setting `this.value` triggers a Lit
|
|
17942
|
+
// update that can re-render the input and reset the native cursor; we
|
|
17943
|
+
// capture the caret position before that update commits and restore it
|
|
17944
|
+
// via `setSelectionRange` once the update has flushed. Gated on
|
|
17945
|
+
// `setSelectionInputTypes` so credit-card (and other masked types whose
|
|
17946
|
+
// formatter manages the cursor itself) doesn't get a competing write.
|
|
17947
|
+
// Capture the caret position INSIDE the gate — reading `selectionStart`
|
|
17948
|
+
// on input types that don't support text selection (number, email in
|
|
17949
|
+
// some browsers) throws InvalidStateError, which would crash all input
|
|
17950
|
+
// handling. Wrap the read in try/catch belt-and-suspenders even though
|
|
17951
|
+
// the gated types currently support it, since the list is a public
|
|
17952
|
+
// property a consumer could mutate.
|
|
17953
|
+
if (this.setSelectionInputTypes.includes(this.type)) {
|
|
17954
|
+
let selectionStart = null;
|
|
17955
|
+
try {
|
|
17956
|
+
({ selectionStart } = this.inputElement);
|
|
17957
|
+
} catch {
|
|
17958
|
+
return;
|
|
17959
|
+
}
|
|
17960
|
+
if (typeof selectionStart !== 'number') {
|
|
17961
|
+
return;
|
|
17962
|
+
}
|
|
17963
|
+
this.updateComplete.then(() => {
|
|
17964
|
+
try {
|
|
17965
|
+
this.inputElement.setSelectionRange(selectionStart, selectionStart);
|
|
17966
|
+
} catch {
|
|
17967
|
+
// Some input types (number/email in certain UAs) throw on
|
|
17968
|
+
// setSelectionRange; swallow and let the native cursor stand.
|
|
17969
|
+
}
|
|
17970
|
+
});
|
|
17971
|
+
}
|
|
17679
17972
|
}
|
|
17680
17973
|
|
|
17681
17974
|
/**
|
|
@@ -17764,7 +18057,6 @@ class BaseInput extends AuroElement$1 {
|
|
|
17764
18057
|
*/
|
|
17765
18058
|
reset() {
|
|
17766
18059
|
this.value = undefined;
|
|
17767
|
-
this.setDateObjectProperty('valueObject', undefined);
|
|
17768
18060
|
this.validation.reset(this);
|
|
17769
18061
|
}
|
|
17770
18062
|
|
|
@@ -17773,7 +18065,6 @@ class BaseInput extends AuroElement$1 {
|
|
|
17773
18065
|
*/
|
|
17774
18066
|
clear() {
|
|
17775
18067
|
this.value = undefined;
|
|
17776
|
-
this.setDateObjectProperty('valueObject', undefined);
|
|
17777
18068
|
}
|
|
17778
18069
|
|
|
17779
18070
|
/**
|
|
@@ -17798,8 +18089,7 @@ class BaseInput extends AuroElement$1 {
|
|
|
17798
18089
|
|
|
17799
18090
|
// Set default date format if type=date and no format is defined
|
|
17800
18091
|
if (this.type === "date" && !this.format) {
|
|
17801
|
-
|
|
17802
|
-
this.format = this.util.getDateMaskFromLocale().toLowerCase();
|
|
18092
|
+
this._setFormatFromLocale(this.util.getDateMaskFromLocale().toLowerCase());
|
|
17803
18093
|
this.util.updateFormat(this.format);
|
|
17804
18094
|
}
|
|
17805
18095
|
}
|
|
@@ -17811,7 +18101,7 @@ class BaseInput extends AuroElement$1 {
|
|
|
17811
18101
|
*/
|
|
17812
18102
|
get placeholderStr() {
|
|
17813
18103
|
if (!this.placeholder && this.type === 'date') {
|
|
17814
|
-
return this.format
|
|
18104
|
+
return this.format.toUpperCase();
|
|
17815
18105
|
}
|
|
17816
18106
|
return this.placeholder || "";
|
|
17817
18107
|
}
|
|
@@ -17828,7 +18118,7 @@ class BaseInput extends AuroElement$1 {
|
|
|
17828
18118
|
const creditCard = this.matchInputValueToCreditCard();
|
|
17829
18119
|
const previousFormat = this.format;
|
|
17830
18120
|
|
|
17831
|
-
this.
|
|
18121
|
+
this._setFormatFromLocale(creditCard.maskFormat);
|
|
17832
18122
|
|
|
17833
18123
|
this.maxLength = creditCard.formatLength;
|
|
17834
18124
|
this.minLength = creditCard.formatMinLength;
|
|
@@ -17848,7 +18138,7 @@ class BaseInput extends AuroElement$1 {
|
|
|
17848
18138
|
/**
|
|
17849
18139
|
* Function to support credit-card feature type.
|
|
17850
18140
|
* @private
|
|
17851
|
-
* @deprecated https://dev.azure.com/itsals/E_Retain_Content/_workitems/edit/1557296
|
|
18141
|
+
* @deprecated See https://dev.azure.com/itsals/E_Retain_Content/_workitems/edit/1557296.
|
|
17852
18142
|
* @returns {object} JSON with data for credit card formatting.
|
|
17853
18143
|
*/
|
|
17854
18144
|
matchInputValueToCreditCard() {
|
|
@@ -17889,10 +18179,10 @@ class BaseInput extends AuroElement$1 {
|
|
|
17889
18179
|
},
|
|
17890
18180
|
{
|
|
17891
18181
|
name: 'Diners club',
|
|
17892
|
-
regex: /^(?<num>36|38)\d{0}/u,
|
|
18182
|
+
regex: /^(?<num>30[0-5]|36|38)\d{0}/u,
|
|
17893
18183
|
formatLength: 16,
|
|
17894
18184
|
errorMessage: CreditCardValidationMessage,
|
|
17895
|
-
cardIcon: '
|
|
18185
|
+
cardIcon: 'cc-dinersclub',
|
|
17896
18186
|
maskFormat: "0000 000000 0000"
|
|
17897
18187
|
},
|
|
17898
18188
|
{
|
|
@@ -18302,7 +18592,7 @@ let AuroHelpText$1 = class AuroHelpText extends LitElement {
|
|
|
18302
18592
|
}
|
|
18303
18593
|
};
|
|
18304
18594
|
|
|
18305
|
-
var formkitVersion$1 = '
|
|
18595
|
+
var formkitVersion$1 = '202607221815';
|
|
18306
18596
|
|
|
18307
18597
|
// Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
|
|
18308
18598
|
// See LICENSE in the project root for license information.
|
|
@@ -18588,20 +18878,50 @@ class AuroInput extends BaseInput {
|
|
|
18588
18878
|
* @returns {void}
|
|
18589
18879
|
*/
|
|
18590
18880
|
checkDisplayValueSlotChange() {
|
|
18591
|
-
|
|
18592
|
-
|
|
18593
|
-
|
|
18594
|
-
|
|
18595
|
-
|
|
18881
|
+
const slot = this.shadowRoot?.querySelector('slot[name="displayValue"]');
|
|
18882
|
+
if (!slot) {
|
|
18883
|
+
// Shadow slot not yet rendered — fall back to checking light-DOM
|
|
18884
|
+
// children so hasDisplayValueContent isn't stuck false when called
|
|
18885
|
+
// before firstUpdated (e.g. from auro-combobox during mount).
|
|
18886
|
+
// Check for any element (including custom elements like <auro-icon>
|
|
18887
|
+
// that render via shadow DOM with no text content).
|
|
18888
|
+
const lightDomNodes = Array.from(this.querySelectorAll('[slot="displayValue"]:not(slot)'));
|
|
18889
|
+
const hasContent = lightDomNodes.some((node) => (
|
|
18890
|
+
node.textContent.trim().length > 0 ||
|
|
18891
|
+
node.children.length > 0 ||
|
|
18892
|
+
node.shadowRoot !== null
|
|
18893
|
+
));
|
|
18894
|
+
if (this.hasDisplayValueContent !== hasContent) {
|
|
18895
|
+
this.hasDisplayValueContent = hasContent;
|
|
18896
|
+
this.requestUpdate();
|
|
18897
|
+
}
|
|
18898
|
+
return;
|
|
18596
18899
|
}
|
|
18597
|
-
|
|
18598
|
-
|
|
18599
|
-
|
|
18600
|
-
|
|
18601
|
-
|
|
18900
|
+
const nodes = slot.assignedNodes({ flatten: true });
|
|
18901
|
+
|
|
18902
|
+
// Check for actual visible content, not just node existence.
|
|
18903
|
+
// An empty <span slot="displayValue"></span> forwarded from the
|
|
18904
|
+
// consumer should not be treated as "has content" — it causes the
|
|
18905
|
+
// displayValue wrapper to render (with hasContent class) but show
|
|
18906
|
+
// nothing, blocking the combobox's synthetic displayValue from
|
|
18907
|
+
// being visible on preset/deeplink load.
|
|
18908
|
+
// Custom elements (e.g. <auro-icon>) that render via shadow DOM are
|
|
18909
|
+
// treated as content even when they have no text or light-DOM children.
|
|
18910
|
+
const hasContent = nodes.some((node) => {
|
|
18911
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
18912
|
+
return node.textContent.trim().length > 0;
|
|
18913
|
+
}
|
|
18914
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
18915
|
+
return node.textContent.trim().length > 0 ||
|
|
18916
|
+
node.children.length > 0 ||
|
|
18917
|
+
node.shadowRoot !== null;
|
|
18918
|
+
}
|
|
18919
|
+
return false;
|
|
18920
|
+
});
|
|
18921
|
+
if (this.hasDisplayValueContent !== hasContent) {
|
|
18922
|
+
this.hasDisplayValueContent = hasContent;
|
|
18923
|
+
this.requestUpdate();
|
|
18602
18924
|
}
|
|
18603
|
-
|
|
18604
|
-
this.hasDisplayValueContent = hasContent;
|
|
18605
18925
|
}
|
|
18606
18926
|
|
|
18607
18927
|
firstUpdated() {
|
|
@@ -18625,7 +18945,7 @@ class AuroInput extends BaseInput {
|
|
|
18625
18945
|
/**
|
|
18626
18946
|
* Determines default help text string.
|
|
18627
18947
|
* @private
|
|
18628
|
-
* @deprecated https://dev.azure.com/itsals/E_Retain_Content/_workitems/edit/1557296
|
|
18948
|
+
* @deprecated See https://dev.azure.com/itsals/E_Retain_Content/_workitems/edit/1557296.
|
|
18629
18949
|
* @returns {string} Evaluates pre-determined help text.
|
|
18630
18950
|
*/
|
|
18631
18951
|
getHelpText() {
|
|
@@ -18805,6 +19125,7 @@ class AuroInput extends BaseInput {
|
|
|
18805
19125
|
<${this.buttonTag}
|
|
18806
19126
|
@click="${this.handleClickShowPassword}"
|
|
18807
19127
|
appearance="${this.onDark ? 'inverse' : this.appearance}"
|
|
19128
|
+
aria-pressed="${this.showPassword ? 'true' : 'false'}"
|
|
18808
19129
|
class="notificationBtn passwordBtn"
|
|
18809
19130
|
shape="circle"
|
|
18810
19131
|
size="sm"
|
|
@@ -18878,25 +19199,29 @@ class AuroInput extends BaseInput {
|
|
|
18878
19199
|
* @returns {html} - Returns HTML for the help text and error message.
|
|
18879
19200
|
*/
|
|
18880
19201
|
renderHtmlHelpText() {
|
|
19202
|
+
// Single `<p>` with stable identity across validity transitions —
|
|
19203
|
+
// previously two distinct templates (valid vs invalid) caused Lit to
|
|
19204
|
+
// replace the node entirely on a flip, and VoiceOver wouldn't
|
|
19205
|
+
// re-announce because the live-region element it was watching had been
|
|
19206
|
+
// removed and a new one inserted. Keeping one node means the `role`,
|
|
19207
|
+
// `aria-live`, and text content all change in-place, which AT does
|
|
19208
|
+
// observe and announce.
|
|
19209
|
+
const isError = this.validity && this.validity !== 'valid';
|
|
18881
19210
|
return html`
|
|
18882
|
-
|
|
18883
|
-
?
|
|
18884
|
-
|
|
18885
|
-
|
|
18886
|
-
|
|
18887
|
-
|
|
18888
|
-
|
|
18889
|
-
|
|
18890
|
-
|
|
18891
|
-
|
|
18892
|
-
|
|
18893
|
-
appearance="${this.onDark ? 'inverse' : this.appearance}">
|
|
18894
|
-
<p id="${this.uniqueId}" role="alert" aria-live="assertive" part="helpText">
|
|
18895
|
-
${this.errorMessage}
|
|
18896
|
-
</p>
|
|
18897
|
-
</${this.helpTextTag}>
|
|
18898
|
-
`
|
|
19211
|
+
<${this.helpTextTag}
|
|
19212
|
+
appearance="${this.onDark ? 'inverse' : this.appearance}"
|
|
19213
|
+
?error=${isError}>
|
|
19214
|
+
<p
|
|
19215
|
+
id="${this.uniqueId}"
|
|
19216
|
+
part="helpText"
|
|
19217
|
+
role="${ifDefined(isError ? 'alert' : undefined)}"
|
|
19218
|
+
aria-live="${ifDefined(isError ? 'assertive' : undefined)}">
|
|
19219
|
+
${isError
|
|
19220
|
+
? this.errorMessage
|
|
19221
|
+
: html`<slot name="helpText">${this.getHelpText()}</slot>`
|
|
18899
19222
|
}
|
|
19223
|
+
</p>
|
|
19224
|
+
</${this.helpTextTag}>
|
|
18900
19225
|
`;
|
|
18901
19226
|
}
|
|
18902
19227
|
|
|
@@ -19028,7 +19353,7 @@ class AuroInput extends BaseInput {
|
|
|
19028
19353
|
|
|
19029
19354
|
var colorCss$1 = css`#headerContainer{box-shadow:var(--ds-auro-dropdownbib-header-boxshadow-color)}#footerContainer{background-color:var(--ds-auro-dropdownbib-footer-container-color)}`;
|
|
19030
19355
|
|
|
19031
|
-
var styleCss$2 = css`#bibTemplate{display:flex;overflow:hidden;height:100%;max-height:100%;flex-direction:column}#headerContainer{display:flex;flex-direction:column;padding:var(--ds-size-200, 1rem);padding-top:var(--ds-size-400, 2rem);padding-bottom:0}#headerContainer .titleRow{display:flex;flex-direction:row;justify-content:space-between;gap:var(--ds-size-100, 0.5rem)}#headerContainer .header{max-width:calc(100vw - var(--ds-size-900, 4.5rem))
|
|
19356
|
+
var styleCss$2 = css`#bibTemplate{display:flex;overflow:hidden;height:100%;max-height:100%;flex-direction:column}#headerContainer{display:flex;flex-direction:column;padding:var(--ds-size-200, 1rem);padding-top:var(--ds-size-400, 2rem);padding-bottom:0}#headerContainer .titleRow{display:flex;flex-direction:row;justify-content:space-between;padding-bottom:var(--ds-size-200, 1rem);gap:var(--ds-size-100, 0.5rem)}#headerContainer .header{max-width:calc(100vw - var(--ds-size-900, 4.5rem))}#headerContainer .subheader{width:100%}#closeButton [auro-icon]{--ds-auro-icon-size: var(--ds-size-500, 2.5rem)}#bodyContainer{position:relative;overflow:auto;flex:1}:host([isfullscreen]) #bibTemplate{max-height:100dvh}:host([isfullscreen]) #bodyContainer{margin-top:var(--ds-size-100, 0.5rem)}#footerContainer{padding:var(--ds-size-200, 1rem)}`;
|
|
19032
19357
|
|
|
19033
19358
|
var tokenCss = css`:host{--ds-auro-dropdownbib-header-boxshadow-color: var(--ds-elevation-200, 0px 0px 10px rgba(0, 0, 0, 0.15));--ds-auro-dropdownbib-footer-container-color: var(--ds-basic-color-surface-default, #ffffff)}`;
|
|
19034
19359
|
|
|
@@ -19423,7 +19748,7 @@ class AuroBibtemplate extends LitElement {
|
|
|
19423
19748
|
}
|
|
19424
19749
|
}
|
|
19425
19750
|
|
|
19426
|
-
var formkitVersion = '
|
|
19751
|
+
var formkitVersion = '202607221815';
|
|
19427
19752
|
|
|
19428
19753
|
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}`;
|
|
19429
19754
|
|
|
@@ -19780,6 +20105,36 @@ function normalizeFilterValue(value) {
|
|
|
19780
20105
|
return raw.trim() ? raw.trimEnd() : raw;
|
|
19781
20106
|
}
|
|
19782
20107
|
|
|
20108
|
+
/**
|
|
20109
|
+
* Returns the option's plain-text label suitable for input.value, with
|
|
20110
|
+
* HTML-indentation whitespace collapsed and the displayValue slot text
|
|
20111
|
+
* removed (the slot renders separately in the trigger).
|
|
20112
|
+
* @param {HTMLElement} option - An auro-menuoption element.
|
|
20113
|
+
* @returns {string} Normalized label.
|
|
20114
|
+
*/
|
|
20115
|
+
function getOptionLabel(option) {
|
|
20116
|
+
if (!option) {
|
|
20117
|
+
return '';
|
|
20118
|
+
}
|
|
20119
|
+
|
|
20120
|
+
// Consumer-provided override: short-circuit the DOM walk entirely.
|
|
20121
|
+
if (option.dataset && option.dataset.label) {
|
|
20122
|
+
return option.dataset.label;
|
|
20123
|
+
}
|
|
20124
|
+
|
|
20125
|
+
// Walk direct children — the `slot` attribute only applies to direct children
|
|
20126
|
+
// of the slot host, so a shallow filter is sufficient. Avoids the cloneNode +
|
|
20127
|
+
// querySelector allocation that ran on every keystroke via syncValuesAndStates.
|
|
20128
|
+
let text = '';
|
|
20129
|
+
for (const node of option.childNodes) {
|
|
20130
|
+
const isDisplayValueSlot = node.nodeType === Node.ELEMENT_NODE && node.getAttribute('slot') === 'displayValue';
|
|
20131
|
+
if (!isDisplayValueSlot) {
|
|
20132
|
+
text += node.textContent || '';
|
|
20133
|
+
}
|
|
20134
|
+
}
|
|
20135
|
+
return text.replace(/\s+/gu, ' ').trim();
|
|
20136
|
+
}
|
|
20137
|
+
|
|
19783
20138
|
// See https://git.io/JJ6SJ for "How to document your components using JSDoc"
|
|
19784
20139
|
/**
|
|
19785
20140
|
* The `auro-combobox` element provides users with a way to select an option from a list of filtered or suggested options based on user input.
|
|
@@ -19852,8 +20207,6 @@ class AuroCombobox extends AuroElement {
|
|
|
19852
20207
|
this.availableOptions = [];
|
|
19853
20208
|
this.dropdownId = undefined;
|
|
19854
20209
|
this.dropdownOpen = false;
|
|
19855
|
-
this.triggerExpandedState = false;
|
|
19856
|
-
this._expandedTimeout = null;
|
|
19857
20210
|
this._inFullscreenTransition = false;
|
|
19858
20211
|
this.errorMessage = null;
|
|
19859
20212
|
this.isHiddenWhileLoading = false;
|
|
@@ -19864,6 +20217,30 @@ class AuroCombobox extends AuroElement {
|
|
|
19864
20217
|
this.touched = false;
|
|
19865
20218
|
this.validation = new AuroFormValidation$1();
|
|
19866
20219
|
this.validity = undefined;
|
|
20220
|
+
this._userTyped = false;
|
|
20221
|
+
// Tracks every setTimeout scheduled via _scheduleTimer so
|
|
20222
|
+
// disconnectedCallback can cancel them. Without this, a detached
|
|
20223
|
+
// combobox's pending timers still fire — most are no-ops, but
|
|
20224
|
+
// configureMenu's racing-condition retry would otherwise loop.
|
|
20225
|
+
this._pendingTimers = new Set();
|
|
20226
|
+
}
|
|
20227
|
+
|
|
20228
|
+
/**
|
|
20229
|
+
* Wraps setTimeout and records the timer id so disconnectedCallback
|
|
20230
|
+
* can cancel any outstanding callbacks. The id is removed from the set
|
|
20231
|
+
* once the callback fires so the set doesn't grow unbounded.
|
|
20232
|
+
* @param {Function} fn - Callback to run.
|
|
20233
|
+
* @param {number} ms - Delay in milliseconds.
|
|
20234
|
+
* @returns {number} The timer id.
|
|
20235
|
+
* @private
|
|
20236
|
+
*/
|
|
20237
|
+
_scheduleTimer(fn, ms) {
|
|
20238
|
+
const id = setTimeout(() => {
|
|
20239
|
+
this._pendingTimers.delete(id);
|
|
20240
|
+
fn();
|
|
20241
|
+
}, ms);
|
|
20242
|
+
this._pendingTimers.add(id);
|
|
20243
|
+
return id;
|
|
19867
20244
|
}
|
|
19868
20245
|
|
|
19869
20246
|
// This function is to define props used within the scope of this component
|
|
@@ -19907,7 +20284,19 @@ class AuroCombobox extends AuroElement {
|
|
|
19907
20284
|
availableOptions: {
|
|
19908
20285
|
state: true,
|
|
19909
20286
|
type: Array,
|
|
19910
|
-
reflect: false
|
|
20287
|
+
reflect: false,
|
|
20288
|
+
hasChanged(newVal, oldVal) {
|
|
20289
|
+
if (!oldVal && !newVal) {
|
|
20290
|
+
return false;
|
|
20291
|
+
}
|
|
20292
|
+
if (!oldVal || !newVal) {
|
|
20293
|
+
return true;
|
|
20294
|
+
}
|
|
20295
|
+
if (newVal.length !== oldVal.length) {
|
|
20296
|
+
return true;
|
|
20297
|
+
}
|
|
20298
|
+
return newVal.some((opt, idx) => opt !== oldVal[idx]);
|
|
20299
|
+
}
|
|
19911
20300
|
},
|
|
19912
20301
|
|
|
19913
20302
|
/**
|
|
@@ -20142,6 +20531,8 @@ class AuroCombobox extends AuroElement {
|
|
|
20142
20531
|
|
|
20143
20532
|
/**
|
|
20144
20533
|
* If set, the `icon` attribute will be applied to the trigger `auro-input` element.
|
|
20534
|
+
* Icon rendering is currently limited to `type="credit-card"`. Setting `triggerIcon`
|
|
20535
|
+
* without a supported `type` propagates the attribute but does not render a visible icon.
|
|
20145
20536
|
*/
|
|
20146
20537
|
triggerIcon: {
|
|
20147
20538
|
type: Boolean,
|
|
@@ -20173,7 +20564,7 @@ class AuroCombobox extends AuroElement {
|
|
|
20173
20564
|
},
|
|
20174
20565
|
|
|
20175
20566
|
/**
|
|
20176
|
-
* Value selected for the dropdown menu.
|
|
20567
|
+
* Value selected for the dropdown menu. When set programmatically or as a preset attribute, the value must match a selectable option. If it matches an option marked `disabled` or `static`, the selection is rejected: `value` and `optionSelected` are cleared to `undefined`. `hidden` options (including those filtered out by type-ahead) remain selectable by value.
|
|
20177
20568
|
*/
|
|
20178
20569
|
value: {
|
|
20179
20570
|
type: String
|
|
@@ -20213,17 +20604,6 @@ class AuroCombobox extends AuroElement {
|
|
|
20213
20604
|
attribute: false
|
|
20214
20605
|
},
|
|
20215
20606
|
|
|
20216
|
-
/**
|
|
20217
|
-
* Deferred aria-expanded state for the trigger input.
|
|
20218
|
-
* Delays the "true" transition so VoiceOver finishes its character echo
|
|
20219
|
-
* before announcing "expanded".
|
|
20220
|
-
* @private
|
|
20221
|
-
*/
|
|
20222
|
-
triggerExpandedState: {
|
|
20223
|
-
type: Boolean,
|
|
20224
|
-
reflect: false,
|
|
20225
|
-
attribute: false
|
|
20226
|
-
},
|
|
20227
20607
|
};
|
|
20228
20608
|
}
|
|
20229
20609
|
|
|
@@ -20246,13 +20626,6 @@ class AuroCombobox extends AuroElement {
|
|
|
20246
20626
|
return this.input.value;
|
|
20247
20627
|
}
|
|
20248
20628
|
|
|
20249
|
-
// /**
|
|
20250
|
-
// * Sets the value of the input element within the combobox.
|
|
20251
|
-
// */
|
|
20252
|
-
// set inputValue(value) {
|
|
20253
|
-
// this.input.value = value;
|
|
20254
|
-
// }
|
|
20255
|
-
|
|
20256
20629
|
/**
|
|
20257
20630
|
* Checks if the element is valid.
|
|
20258
20631
|
* @returns {boolean} - Returns true if the element is valid, false otherwise.
|
|
@@ -20338,18 +20711,15 @@ class AuroCombobox extends AuroElement {
|
|
|
20338
20711
|
matchString = `${matchString} ${option.getAttribute('suggest')}`.toLowerCase();
|
|
20339
20712
|
}
|
|
20340
20713
|
|
|
20341
|
-
|
|
20342
|
-
|
|
20343
|
-
|
|
20344
|
-
|
|
20345
|
-
|
|
20346
|
-
|
|
20347
|
-
} else if (matchString.includes(filterValue) && !option.hasAttribute('static')) {
|
|
20348
|
-
// only count options that match the typed input value AND are not static
|
|
20714
|
+
if (!filterValue && option.hasAttribute('static')) {
|
|
20715
|
+
// Static options are shown when the input is empty so consumers can
|
|
20716
|
+
// surface headers / "add new" rows when no filter is active.
|
|
20717
|
+
option.removeAttribute('hidden');
|
|
20718
|
+
this.availableOptions.push(option);
|
|
20719
|
+
} else if (filterValue && matchString.includes(filterValue) && !option.hasAttribute('static')) {
|
|
20349
20720
|
option.removeAttribute('hidden');
|
|
20350
20721
|
this.availableOptions.push(option);
|
|
20351
20722
|
} else if (!option.hasAttribute('persistent')) {
|
|
20352
|
-
// Hide all other non-persistent options
|
|
20353
20723
|
option.setAttribute('hidden', '');
|
|
20354
20724
|
option.removeAttribute('aria-setsize');
|
|
20355
20725
|
option.removeAttribute('aria-posinset');
|
|
@@ -20357,7 +20727,9 @@ class AuroCombobox extends AuroElement {
|
|
|
20357
20727
|
});
|
|
20358
20728
|
|
|
20359
20729
|
if (this.availableOptions.length === 0) {
|
|
20360
|
-
|
|
20730
|
+
// Only surface the nomatch option once the user has actually typed
|
|
20731
|
+
// something. Empty input is handled by the bib being closed.
|
|
20732
|
+
if (this.noMatchOption && filterValue) {
|
|
20361
20733
|
this.noMatchOption.removeAttribute('hidden');
|
|
20362
20734
|
} else if (!this.menu.loading || this.isHiddenWhileLoading) {
|
|
20363
20735
|
this.hideBib();
|
|
@@ -20373,11 +20745,14 @@ class AuroCombobox extends AuroElement {
|
|
|
20373
20745
|
* @returns {void}
|
|
20374
20746
|
*/
|
|
20375
20747
|
syncValuesAndStates() {
|
|
20376
|
-
//
|
|
20748
|
+
// Do NOT call setMenuValue here — the caller (handleMenuOptions) already
|
|
20749
|
+
// guards setMenuValue with an option-match check. Calling it unconditionally
|
|
20750
|
+
// sets free-form values on the menu, triggering clearSelection which resets
|
|
20751
|
+
// _index and breaks subsequent makeSelection calls.
|
|
20377
20752
|
if (this.menu) {
|
|
20378
20753
|
this.menu.matchWord = normalizeFilterValue(this.input.value);
|
|
20379
20754
|
}
|
|
20380
|
-
const label = this.menu.
|
|
20755
|
+
const label = getOptionLabel(this.menu.optionSelected);
|
|
20381
20756
|
this.updateTriggerTextDisplay(label || this.value);
|
|
20382
20757
|
}
|
|
20383
20758
|
|
|
@@ -20391,12 +20766,16 @@ class AuroCombobox extends AuroElement {
|
|
|
20391
20766
|
// in suggestion mode, do not override input value if no selection has been made and the input currently has focus
|
|
20392
20767
|
const isInputFocusedWithNoSelection = !this.menu.value && (this.input.matches(':focus-within') || (this.inputInBib && this.inputInBib.matches(':focus-within')));
|
|
20393
20768
|
|
|
20394
|
-
|
|
20395
|
-
|
|
20769
|
+
const suppressed = this.persistInput || (this.behavior === 'suggestion' && isInputFocusedWithNoSelection);
|
|
20770
|
+
if (!suppressed) {
|
|
20771
|
+
this.syncInputValuesAcrossTriggerAndBib(label || this.value);
|
|
20396
20772
|
}
|
|
20397
20773
|
|
|
20398
|
-
//
|
|
20399
|
-
|
|
20774
|
+
// Replace any previously appended displayValue clone in the trigger.
|
|
20775
|
+
// :not(slot) excludes the template's <slot name="displayValue"
|
|
20776
|
+
// slot="displayValue"> forwarder, which also has slot="displayValue"
|
|
20777
|
+
// and would otherwise be matched first and removed.
|
|
20778
|
+
const displayValueInTrigger = this.input.querySelector('[slot="displayValue"]:not(slot)');
|
|
20400
20779
|
|
|
20401
20780
|
if (displayValueInTrigger) {
|
|
20402
20781
|
displayValueInTrigger.remove();
|
|
@@ -20407,19 +20786,111 @@ class AuroCombobox extends AuroElement {
|
|
|
20407
20786
|
if (displayValueEl) {
|
|
20408
20787
|
this.input.appendChild(displayValueEl.cloneNode(true));
|
|
20409
20788
|
}
|
|
20789
|
+
|
|
20790
|
+
// auro-input's hasDisplayValueContent is non-reactive; nudge it to
|
|
20791
|
+
// re-evaluate the slot and re-render so the displayValue wrapper
|
|
20792
|
+
// gets its hasContent class. Without this, the apple/icon stays
|
|
20793
|
+
// hidden when input.value is set in the same tick as the append.
|
|
20794
|
+
if (typeof this.input.checkDisplayValueSlotChange === 'function') {
|
|
20795
|
+
this.input.checkDisplayValueSlotChange();
|
|
20796
|
+
}
|
|
20797
|
+
} else if (this.value) {
|
|
20798
|
+
// No optionSelected yet (e.g. setMenuValue was called but the menu's
|
|
20799
|
+
// auroMenu-selectedOption event hasn't fired yet, or we're on remount
|
|
20800
|
+
// with no options loaded). Synthesize a displayValue from the value so
|
|
20801
|
+
// the overlay isn't blank.
|
|
20802
|
+
//
|
|
20803
|
+
// NOTE: This renders the raw machine value (e.g. "SEA"), not the
|
|
20804
|
+
// human-readable label (e.g. "Seattle, WA"). For consumers where
|
|
20805
|
+
// value ≠ label, this produces a brief flash of the raw value until
|
|
20806
|
+
// the option elements load and updateTriggerTextDisplay re-runs with
|
|
20807
|
+
// the correct label. This is intentionally preferred over a blank
|
|
20808
|
+
// state — the displayValueInTrigger.remove() cleanup above ensures
|
|
20809
|
+
// this placeholder is replaced once the real option is available.
|
|
20810
|
+
const syntheticDV = document.createElement('span');
|
|
20811
|
+
syntheticDV.setAttribute('slot', 'displayValue');
|
|
20812
|
+
syntheticDV.textContent = this.value;
|
|
20813
|
+
this.input.appendChild(syntheticDV);
|
|
20814
|
+
if (typeof this.input.checkDisplayValueSlotChange === 'function') {
|
|
20815
|
+
this.input.checkDisplayValueSlotChange();
|
|
20816
|
+
}
|
|
20410
20817
|
}
|
|
20411
20818
|
|
|
20412
20819
|
this.requestUpdate();
|
|
20413
20820
|
}
|
|
20414
20821
|
|
|
20822
|
+
/**
|
|
20823
|
+
* Writes nextValue to the trigger input and the bib input when their current
|
|
20824
|
+
* value differs, then re-asserts imask after Lit's update flushes.
|
|
20825
|
+
* @param {string} nextValue - The value to write to both inputs.
|
|
20826
|
+
* @returns {Promise<void>} Resolves after both inputs flush and imask
|
|
20827
|
+
* re-asserts; resolves immediately when no sync is needed.
|
|
20828
|
+
* @private
|
|
20829
|
+
*/
|
|
20830
|
+
async syncInputValuesAcrossTriggerAndBib(nextValue) {
|
|
20831
|
+
// Only set the flag when there's an actual write to suppress —
|
|
20832
|
+
// syncValuesAndStates re-enters here during typing when both inputs
|
|
20833
|
+
// already match, and a no-op flag flip would make the bib branch's
|
|
20834
|
+
// bail eat legitimate user-input events.
|
|
20835
|
+
const triggerNeedsSync = this.input.value !== nextValue;
|
|
20836
|
+
const bibNeedsSync = Boolean(this.inputInBib) && this.inputInBib.value !== nextValue;
|
|
20837
|
+
if (!triggerNeedsSync && !bibNeedsSync) {
|
|
20838
|
+
return;
|
|
20839
|
+
}
|
|
20840
|
+
|
|
20841
|
+
this._syncingDisplayValue = true;
|
|
20842
|
+
|
|
20843
|
+
const pending = [];
|
|
20844
|
+
if (triggerNeedsSync) {
|
|
20845
|
+
this.input.value = nextValue;
|
|
20846
|
+
pending.push(this.input.updateComplete);
|
|
20847
|
+
}
|
|
20848
|
+
if (bibNeedsSync) {
|
|
20849
|
+
this.inputInBib.value = nextValue;
|
|
20850
|
+
pending.push(this.inputInBib.updateComplete);
|
|
20851
|
+
}
|
|
20852
|
+
// finally — not a bare .then — so that an imask throw (see commit
|
|
20853
|
+
// d1857401c: imask can throw on credit-card format change) doesn't strand
|
|
20854
|
+
// _syncingDisplayValue=true and silently swallow every subsequent input.
|
|
20855
|
+
try {
|
|
20856
|
+
await Promise.all(pending);
|
|
20857
|
+
// imask reasserts otherwise, and handleBlur reverts to its stale value.
|
|
20858
|
+
if (triggerNeedsSync && this.input.maskInstance && typeof this.input.maskInstance.updateValue === 'function') {
|
|
20859
|
+
this.input.maskInstance.updateValue();
|
|
20860
|
+
}
|
|
20861
|
+
if (bibNeedsSync && this.inputInBib.maskInstance && typeof this.inputInBib.maskInstance.updateValue === 'function') {
|
|
20862
|
+
this.inputInBib.maskInstance.updateValue();
|
|
20863
|
+
}
|
|
20864
|
+
} finally {
|
|
20865
|
+
this._syncingDisplayValue = false;
|
|
20866
|
+
}
|
|
20867
|
+
}
|
|
20868
|
+
|
|
20415
20869
|
/**
|
|
20416
20870
|
* Processes hidden state of all menu options and determines if there are any available options not hidden.
|
|
20417
20871
|
* @private
|
|
20872
|
+
* @param {object} [options={}] - Optional flag bag.
|
|
20873
|
+
* @param {boolean} [options.preferComboboxValue=false] - When true,
|
|
20874
|
+
* handleMenuOptions matches the selected option against `this.value`
|
|
20875
|
+
* first instead of `this.input.value`. Needed on mount and re-mount
|
|
20876
|
+
* because under `persistInput` the consumer's typedValue prop can drift
|
|
20877
|
+
* from the framework value (Svelte `{#key}` re-mount after a swap, or
|
|
20878
|
+
* SPA preselect after route change) and the old input-first match would
|
|
20879
|
+
* then pick the stale text. Only handleSlotChange passes this; typing
|
|
20880
|
+
* and clearing paths keep the input-first match so user clears aren't
|
|
20881
|
+
* undone.
|
|
20418
20882
|
* @returns {void}
|
|
20419
20883
|
*/
|
|
20420
|
-
handleMenuOptions() {
|
|
20884
|
+
handleMenuOptions({ preferComboboxValue = false } = {}) {
|
|
20421
20885
|
this.generateOptionsArray();
|
|
20422
20886
|
this.availableOptions = [];
|
|
20887
|
+
// Single source of truth for the menu's filter/highlight token per call.
|
|
20888
|
+
// syncValuesAndStates re-writes the same value on exact-match keystrokes —
|
|
20889
|
+
// Lit's hasChanged makes that a no-op — and the prior duplicate set inside
|
|
20890
|
+
// handleTriggerInputValueChange is gone.
|
|
20891
|
+
if (this.menu) {
|
|
20892
|
+
this.menu.matchWord = normalizeFilterValue(this.input.value);
|
|
20893
|
+
}
|
|
20423
20894
|
this.updateFilter();
|
|
20424
20895
|
|
|
20425
20896
|
// Set aria-setsize/aria-posinset on each visible option so screen readers
|
|
@@ -20431,15 +20902,28 @@ class AuroCombobox extends AuroElement {
|
|
|
20431
20902
|
option.setAttribute('aria-posinset', index + 1);
|
|
20432
20903
|
});
|
|
20433
20904
|
|
|
20434
|
-
|
|
20435
|
-
|
|
20436
|
-
|
|
20437
|
-
|
|
20438
|
-
|
|
20905
|
+
// On mount/re-mount (via handleSlotChange), prefer the framework-set
|
|
20906
|
+
// `this.value` when it matches a menu option. Covers SPA preselect and
|
|
20907
|
+
// consumer swap patterns (e.g. Svelte `{#key}` re-mount) where
|
|
20908
|
+
// `this.value` is authoritative but `this.input.value` may be empty or
|
|
20909
|
+
// carry stale typed text from another field. Event-driven callers do
|
|
20910
|
+
// not pass the flag, otherwise user clears would be undone by
|
|
20911
|
+
// re-syncing to the previous combobox.value.
|
|
20912
|
+
if (preferComboboxValue &&
|
|
20913
|
+
this.value &&
|
|
20914
|
+
this.menu.options?.some((opt) => opt.value === this.value)) {
|
|
20915
|
+
this.setMenuValue(this.value);
|
|
20916
|
+
this.syncValuesAndStates();
|
|
20917
|
+
} else if (this.input.value &&
|
|
20918
|
+
this.menu.options?.some((opt) => opt.value === this.input.value)) {
|
|
20919
|
+
this.setMenuValue(this.input.value);
|
|
20439
20920
|
this.syncValuesAndStates();
|
|
20440
20921
|
}
|
|
20441
20922
|
|
|
20442
|
-
|
|
20923
|
+
// Re-activate when optionActive is not in the current scrollable viewport,
|
|
20924
|
+
// or when _index has been reset (e.g. by clearSelection in an async update)
|
|
20925
|
+
// so that makeSelection() can find the correct option.
|
|
20926
|
+
if (!this.availableOptions.includes(this.menu.optionActive) || this.menu._index < 0) {
|
|
20443
20927
|
this.activateFirstEnabledAvailableOption();
|
|
20444
20928
|
}
|
|
20445
20929
|
}
|
|
@@ -20501,6 +20985,10 @@ class AuroCombobox extends AuroElement {
|
|
|
20501
20985
|
// from combobox's light DOM and won't be detected by dropdown's contains() check.
|
|
20502
20986
|
this.dropdown.noHideOnThisFocusLoss = true;
|
|
20503
20987
|
|
|
20988
|
+
// Suppress the dropdown's generic focus restoration on close — the combobox
|
|
20989
|
+
// manages its own focus via setClearBtnFocus / setInputFocus / keyboard strategy.
|
|
20990
|
+
this.dropdown.noFocusRestoreOnClose = true;
|
|
20991
|
+
|
|
20504
20992
|
// Listen for the ID to be added to the dropdown so we can capture it and use it for accessibility.
|
|
20505
20993
|
this.dropdown.addEventListener('auroDropdown-idAdded', (event) => {
|
|
20506
20994
|
this.dropdownId = event.detail.id;
|
|
@@ -20511,18 +20999,6 @@ class AuroCombobox extends AuroElement {
|
|
|
20511
20999
|
this.dropdownOpen = ev.detail.expanded;
|
|
20512
21000
|
this.updateMenuShapeSize();
|
|
20513
21001
|
|
|
20514
|
-
// Defer aria-expanded "true" so VoiceOver finishes character echo
|
|
20515
|
-
// before announcing "expanded". Set "false" immediately on close.
|
|
20516
|
-
clearTimeout(this._expandedTimeout);
|
|
20517
|
-
if (this.dropdownOpen) {
|
|
20518
|
-
const expandedDelay = 150;
|
|
20519
|
-
this._expandedTimeout = setTimeout(() => {
|
|
20520
|
-
this.triggerExpandedState = true;
|
|
20521
|
-
}, expandedDelay);
|
|
20522
|
-
} else {
|
|
20523
|
-
this.triggerExpandedState = false;
|
|
20524
|
-
}
|
|
20525
|
-
|
|
20526
21002
|
// Clear aria-activedescendant when dropdown closes
|
|
20527
21003
|
if (!this.dropdownOpen && this.input) {
|
|
20528
21004
|
this.input.setActiveDescendant(null);
|
|
@@ -20535,6 +21011,14 @@ class AuroCombobox extends AuroElement {
|
|
|
20535
21011
|
// keyboard navigation continues from the correct place in the page
|
|
20536
21012
|
if (this.dropdown.isBibFullscreen) {
|
|
20537
21013
|
restoreTriggerAfterClose(this.dropdown, this.input);
|
|
21014
|
+
|
|
21015
|
+
// After the rAF inside restoreTriggerAfterClose() refocuses the
|
|
21016
|
+
// trigger, park the caret at end-of-text. Without this, the trigger
|
|
21017
|
+
// shows the new value (e.g. "Peaches") but its caret sits at [0, 0]
|
|
21018
|
+
// because nothing wrote to the native input between close and focus.
|
|
21019
|
+
doubleRaf(() => {
|
|
21020
|
+
this.setInputFocus();
|
|
21021
|
+
});
|
|
20538
21022
|
}
|
|
20539
21023
|
}
|
|
20540
21024
|
|
|
@@ -20564,13 +21048,29 @@ class AuroCombobox extends AuroElement {
|
|
|
20564
21048
|
|
|
20565
21049
|
guardTouchPassthrough(this.menu);
|
|
20566
21050
|
|
|
20567
|
-
//
|
|
20568
|
-
//
|
|
20569
|
-
|
|
21051
|
+
// showModal() takes focus away from the trigger. Early focus once
|
|
21052
|
+
// the dialog has painted; the shared doubleRaf below is the fallback
|
|
21053
|
+
// for when the dialog needs an extra frame and also clears the
|
|
21054
|
+
// validation guard.
|
|
21055
|
+
requestAnimationFrame(() => {
|
|
20570
21056
|
this.setInputFocus();
|
|
20571
|
-
this._inFullscreenTransition = false;
|
|
20572
21057
|
});
|
|
20573
21058
|
}
|
|
21059
|
+
// else (desktop popover-open): Chrome resets the trigger caret to
|
|
21060
|
+
// [0, 0] when its floating <label for="…"> overlay receives focus.
|
|
21061
|
+
// The shared doubleRaf below parks the caret back at end-of-text
|
|
21062
|
+
// after the dropdown layout settles.
|
|
21063
|
+
|
|
21064
|
+
doubleRaf(() => {
|
|
21065
|
+
// Guard: skip if the dropdown closed before this rAF fired
|
|
21066
|
+
// (e.g. user selected an option immediately after the bib opened).
|
|
21067
|
+
if (this.dropdownOpen) {
|
|
21068
|
+
this.setInputFocus();
|
|
21069
|
+
}
|
|
21070
|
+
if (this._inFullscreenTransition) {
|
|
21071
|
+
this._inFullscreenTransition = false;
|
|
21072
|
+
}
|
|
21073
|
+
});
|
|
20574
21074
|
}
|
|
20575
21075
|
});
|
|
20576
21076
|
|
|
@@ -20588,7 +21088,12 @@ class AuroCombobox extends AuroElement {
|
|
|
20588
21088
|
this.dropdown.bibDialogLabel = labelElement.textContent.trim() || undefined;
|
|
20589
21089
|
}
|
|
20590
21090
|
|
|
20591
|
-
|
|
21091
|
+
if (this.customBibWidth) {
|
|
21092
|
+
this.dropdown.dropdownWidth = this.customBibWidth;
|
|
21093
|
+
}
|
|
21094
|
+
|
|
21095
|
+
// Exposes the CSS parts from the dropdown and bibtemplate for styling
|
|
21096
|
+
this.dropdown.exposeCssParts();
|
|
20592
21097
|
this.bibtemplate.exposeCssParts();
|
|
20593
21098
|
|
|
20594
21099
|
this.hideBib = this.hideBib.bind(this);
|
|
@@ -20607,8 +21112,10 @@ class AuroCombobox extends AuroElement {
|
|
|
20607
21112
|
this.dropdown.trigger.inert = false;
|
|
20608
21113
|
}
|
|
20609
21114
|
|
|
20610
|
-
|
|
20611
|
-
this.
|
|
21115
|
+
this._scheduleTimer(() => {
|
|
21116
|
+
if (this.dropdown.isPopoverVisible) {
|
|
21117
|
+
this.setInputFocus();
|
|
21118
|
+
}
|
|
20612
21119
|
}, 0);
|
|
20613
21120
|
});
|
|
20614
21121
|
}
|
|
@@ -20617,14 +21124,19 @@ class AuroCombobox extends AuroElement {
|
|
|
20617
21124
|
* @private
|
|
20618
21125
|
*/
|
|
20619
21126
|
setClearBtnFocus() {
|
|
20620
|
-
|
|
20621
|
-
|
|
20622
|
-
//
|
|
20623
|
-
//
|
|
20624
|
-
|
|
21127
|
+
doubleRaf(() => {
|
|
21128
|
+
// First establish focus inside the input's shadow root.
|
|
21129
|
+
// Without this, clearBtn.focus() silently fails when focus is on
|
|
21130
|
+
// document.body (e.g. after a click selection closes the bib dialog).
|
|
21131
|
+
// delegatesFocus on BaseInput routes this to the native <input>.
|
|
21132
|
+
this.input.focus();
|
|
21133
|
+
|
|
21134
|
+
// Now move focus to the clear button within the same shadow root.
|
|
21135
|
+
const clearBtn = this.input.shadowRoot.querySelector('.clearBtn');
|
|
21136
|
+
if (clearBtn) {
|
|
20625
21137
|
clearBtn.focus();
|
|
20626
|
-
}
|
|
20627
|
-
}
|
|
21138
|
+
}
|
|
21139
|
+
});
|
|
20628
21140
|
}
|
|
20629
21141
|
|
|
20630
21142
|
/**
|
|
@@ -20646,10 +21158,30 @@ class AuroCombobox extends AuroElement {
|
|
|
20646
21158
|
*/
|
|
20647
21159
|
setInputFocus() {
|
|
20648
21160
|
if (this.dropdown.isBibFullscreen && this.dropdown.isPopoverVisible) {
|
|
20649
|
-
|
|
21161
|
+
// Sync the native input value synchronously before focusing.
|
|
21162
|
+
// Lit's property-to-attribute sync is async (microtask), so the
|
|
21163
|
+
// native <input> inside inputInBib may still hold a stale value
|
|
21164
|
+
// when focus moves here during the fullscreen transition. Without
|
|
21165
|
+
// this, keystrokes (e.g. Backspace) operate on the wrong content.
|
|
21166
|
+
const nativeInput = this.inputInBib.inputElement;
|
|
21167
|
+
const triggerNativeInput = this.input.inputElement;
|
|
21168
|
+
if (nativeInput && triggerNativeInput && nativeInput.value !== triggerNativeInput.value) {
|
|
21169
|
+
this.inputInBib.skipNextProgrammaticInputEvent = true;
|
|
21170
|
+
nativeInput.value = triggerNativeInput.value || '';
|
|
21171
|
+
}
|
|
21172
|
+
|
|
21173
|
+
// Focus the native input directly to ensure it receives keystrokes
|
|
21174
|
+
// after the fullscreen dialog opens. The dialog's showModal() may
|
|
21175
|
+
// have moved focus to the dialog element itself; focusing the
|
|
21176
|
+
// auro-input custom element doesn't always reach the native input
|
|
21177
|
+
// when the dialog DOM isn't fully painted.
|
|
21178
|
+
if (nativeInput) {
|
|
21179
|
+
nativeInput.focus();
|
|
21180
|
+
} else {
|
|
21181
|
+
this.inputInBib.focus();
|
|
21182
|
+
}
|
|
20650
21183
|
|
|
20651
21184
|
// Place cursor at end of existing text so the user can continue editing
|
|
20652
|
-
const nativeInput = this.inputInBib.inputElement;
|
|
20653
21185
|
if (nativeInput && nativeInput.value) {
|
|
20654
21186
|
const len = nativeInput.value.length;
|
|
20655
21187
|
nativeInput.setSelectionRange(len, len);
|
|
@@ -20731,7 +21263,7 @@ class AuroCombobox extends AuroElement {
|
|
|
20731
21263
|
|
|
20732
21264
|
// racing condition on custom-combobox with custom-menu
|
|
20733
21265
|
if (!this.menu) {
|
|
20734
|
-
|
|
21266
|
+
this._scheduleTimer(() => {
|
|
20735
21267
|
this.configureMenu();
|
|
20736
21268
|
}, 0);
|
|
20737
21269
|
return;
|
|
@@ -20751,46 +21283,73 @@ class AuroCombobox extends AuroElement {
|
|
|
20751
21283
|
this.menu.setAttribute('nocheckmark', '');
|
|
20752
21284
|
}
|
|
20753
21285
|
|
|
20754
|
-
|
|
20755
|
-
|
|
20756
|
-
|
|
21286
|
+
// Handle menu option selection
|
|
21287
|
+
this.menu.addEventListener('auroMenu-selectedOption', (evt) => {
|
|
21288
|
+
// Capture before the consumption below — true means this event is the
|
|
21289
|
+
// echo of our own setMenuValue (programmatic value sync), false means
|
|
21290
|
+
// a fresh user selection.
|
|
21291
|
+
const isEcho = this._pendingMenuValueSync === true;
|
|
21292
|
+
|
|
21293
|
+
if (this.menu.optionSelected) {
|
|
21294
|
+
const selected = this.menu.optionSelected;
|
|
20757
21295
|
|
|
20758
|
-
|
|
20759
|
-
|
|
20760
|
-
|
|
20761
|
-
[this.optionSelected] = event.detail.options;
|
|
21296
|
+
if (this.optionSelected !== selected) {
|
|
21297
|
+
this.optionSelected = selected;
|
|
21298
|
+
}
|
|
20762
21299
|
|
|
20763
|
-
|
|
20764
|
-
|
|
21300
|
+
// Skip writeback when this event is the echo of our own setMenuValue —
|
|
21301
|
+
// otherwise it cascades against handleInputValueChange in suggestion mode.
|
|
21302
|
+
if (this._pendingMenuValueSync) {
|
|
21303
|
+
this._pendingMenuValueSync = false;
|
|
21304
|
+
} else if (!this.value || this.value !== this.optionSelected.value) {
|
|
21305
|
+
this.value = this.optionSelected.value;
|
|
21306
|
+
}
|
|
20765
21307
|
|
|
20766
|
-
|
|
20767
|
-
|
|
21308
|
+
// Update display
|
|
21309
|
+
this.updateTriggerTextDisplay(getOptionLabel(this.optionSelected));
|
|
20768
21310
|
|
|
20769
|
-
|
|
20770
|
-
|
|
20771
|
-
|
|
20772
|
-
|
|
21311
|
+
// Update match word for filtering
|
|
21312
|
+
const trimmedInput = normalizeFilterValue(this.input.value);
|
|
21313
|
+
if (this.menu.matchWord !== trimmedInput) {
|
|
21314
|
+
this.menu.matchWord = trimmedInput;
|
|
21315
|
+
}
|
|
20773
21316
|
}
|
|
20774
21317
|
|
|
20775
|
-
// Update available options based on selection
|
|
20776
|
-
this.handleMenuOptions();
|
|
20777
|
-
|
|
20778
21318
|
// Hide dropdown on selection (except during slot changes)
|
|
20779
|
-
if (
|
|
20780
|
-
|
|
20781
|
-
|
|
20782
|
-
|
|
20783
|
-
|
|
20784
|
-
|
|
20785
|
-
|
|
21319
|
+
if (evt.detail && evt.detail.source !== 'slotchange') {
|
|
21320
|
+
// do not close while typing in suggestion mode with no value selected, to allow freeform input
|
|
21321
|
+
this.hideBib();
|
|
21322
|
+
|
|
21323
|
+
// Move focus to the clear button when the user makes a selection,
|
|
21324
|
+
// unless the Shift+Tab handler opted this selection out.
|
|
21325
|
+
if (this._suppressClearBtnFocusOnSelection) {
|
|
21326
|
+
this._suppressClearBtnFocusOnSelection = false;
|
|
21327
|
+
} else if (!isEcho && this.menu.value !== undefined) {
|
|
21328
|
+
this.setClearBtnFocus();
|
|
21329
|
+
}
|
|
20786
21330
|
|
|
20787
21331
|
// Announce the selection after the dropdown closes so it isn't
|
|
20788
21332
|
// overridden by VoiceOver's "collapsed" announcement from aria-expanded.
|
|
20789
|
-
|
|
20790
|
-
|
|
20791
|
-
|
|
20792
|
-
|
|
20793
|
-
|
|
21333
|
+
// Skip when there's no selected value (e.g. menu.clearSelection() from
|
|
21334
|
+
// the unmatched-value path), otherwise VoiceOver reads "undefined".
|
|
21335
|
+
const selectedValue = this.menu.value;
|
|
21336
|
+
if (selectedValue) {
|
|
21337
|
+
const announcementDelay = 300;
|
|
21338
|
+
this._scheduleTimer(() => {
|
|
21339
|
+
announceToScreenReader(this._getAnnouncementRoot(), `${selectedValue}, selected`);
|
|
21340
|
+
}, announcementDelay);
|
|
21341
|
+
}
|
|
21342
|
+
}
|
|
21343
|
+
|
|
21344
|
+
// Programmatic value syncs leave availableOptions stale because
|
|
21345
|
+
// updateTriggerTextDisplay sets input.value with _syncingDisplayValue
|
|
21346
|
+
// and handleInputValueChange bails. Refresh the filter on echo events
|
|
21347
|
+
// only — fresh user selections take the existing hideBib path.
|
|
21348
|
+
if (isEcho && this.menu.optionSelected) {
|
|
21349
|
+
this._programmaticFilterRefresh = true;
|
|
21350
|
+
this.updateComplete.then(() => {
|
|
21351
|
+
this._programmaticFilterRefresh = false;
|
|
21352
|
+
});
|
|
20794
21353
|
}
|
|
20795
21354
|
});
|
|
20796
21355
|
|
|
@@ -20798,17 +21357,55 @@ class AuroCombobox extends AuroElement {
|
|
|
20798
21357
|
this.hideBib();
|
|
20799
21358
|
});
|
|
20800
21359
|
|
|
21360
|
+
// When the menu cannot match a programmatic value to any option,
|
|
21361
|
+
// clear the combobox selection state so it doesn't reference a
|
|
21362
|
+
// stale option. Safe from re-entrancy because any resulting
|
|
21363
|
+
// input.value changes dispatch isProgrammatic events.
|
|
21364
|
+
this.menu.addEventListener('auroMenu-selectValueFailure', () => {
|
|
21365
|
+
// Announce the rejection BEFORE we clear `this.value` so the live
|
|
21366
|
+
// region carries the attempted value — without this the bib closes
|
|
21367
|
+
// silently and screen-reader users get no signal that their request
|
|
21368
|
+
// (e.g. a direct setMenuValue() call) was dropped.
|
|
21369
|
+
const attemptedValue = this.value;
|
|
21370
|
+
if (attemptedValue) {
|
|
21371
|
+
announceToScreenReader(this._getAnnouncementRoot(), `No matching option for ${attemptedValue}`);
|
|
21372
|
+
}
|
|
21373
|
+
this.value = undefined;
|
|
21374
|
+
this.optionSelected = undefined;
|
|
21375
|
+
});
|
|
21376
|
+
|
|
20801
21377
|
this.menu.addEventListener('auroMenu-activatedOption', (evt) => {
|
|
20802
21378
|
this.optionActive = evt.detail;
|
|
20803
21379
|
|
|
20804
21380
|
if (this.input) {
|
|
20805
|
-
|
|
21381
|
+
// setActiveDescendant runs after Lit's update finishes because the
|
|
21382
|
+
// template's `.a11yActivedescendant` binding calls setAttribute on
|
|
21383
|
+
// the internal <input> in auro-input.updated(), which clears the
|
|
21384
|
+
// reflected ariaActiveDescendantElement property. Setting the ref
|
|
21385
|
+
// synchronously here would get overwritten by that attribute write.
|
|
21386
|
+
// Awaiting updateComplete lets the attribute write finish first,
|
|
21387
|
+
// then the ref sticks and screen readers can cross the shadow-DOM
|
|
21388
|
+
// boundary to the auro-menuoption in light DOM.
|
|
21389
|
+
//
|
|
21390
|
+
// The equality check covers the async gap: this.optionActive can
|
|
21391
|
+
// change before the callback runs (user arrowed elsewhere, or the
|
|
21392
|
+
// menu closed and cleared it to null), so we bail if the target
|
|
21393
|
+
// no longer matches to avoid reinstating a stale ref.
|
|
21394
|
+
const targetOption = this.optionActive;
|
|
21395
|
+
this.updateComplete.then(() => {
|
|
21396
|
+
if (this.input && this.optionActive === targetOption) {
|
|
21397
|
+
this.input.setActiveDescendant(targetOption);
|
|
21398
|
+
}
|
|
21399
|
+
});
|
|
20806
21400
|
}
|
|
20807
21401
|
|
|
20808
|
-
//
|
|
20809
|
-
//
|
|
20810
|
-
//
|
|
20811
|
-
|
|
21402
|
+
// In fullscreen mode the menu sits inside a nested <dialog> shadow root,
|
|
21403
|
+
// and aria-activedescendant references across that boundary are lost —
|
|
21404
|
+
// VoiceOver/NVDA don't read the active option natively, so we mirror it
|
|
21405
|
+
// into the polite live region. In popover mode aria-activedescendant on
|
|
21406
|
+
// the trigger input is read natively; double-announcing would flood the
|
|
21407
|
+
// queue on arrow-key repeat.
|
|
21408
|
+
if (this.optionActive && this.dropdown.isBibFullscreen) {
|
|
20812
21409
|
const optionText = this.optionActive.textContent.trim();
|
|
20813
21410
|
const selectedState = this.optionActive.hasAttribute('selected') ? ', selected' : ', not selected';
|
|
20814
21411
|
const optionIndex = this.availableOptions.indexOf(this.optionActive) + 1;
|
|
@@ -20841,7 +21438,12 @@ class AuroCombobox extends AuroElement {
|
|
|
20841
21438
|
* Validate every time we remove focus from the combo box.
|
|
20842
21439
|
*/
|
|
20843
21440
|
this.addEventListener('focusout', () => {
|
|
20844
|
-
|
|
21441
|
+
// Skip while the dropdown is open — focus transits out briefly on
|
|
21442
|
+
// mousedown of a menu option (popover top-layer breaks :focus-within),
|
|
21443
|
+
// and validating against the pre-selection value flashes a stale error
|
|
21444
|
+
// between mousedown and mouseup. The next focusout fires after the
|
|
21445
|
+
// dropdown closes and validates against the post-selection value.
|
|
21446
|
+
if (!this.componentHasFocus && !this._inFullscreenTransition && !this.dropdownOpen) {
|
|
20845
21447
|
this.validate();
|
|
20846
21448
|
}
|
|
20847
21449
|
});
|
|
@@ -20898,43 +21500,65 @@ class AuroCombobox extends AuroElement {
|
|
|
20898
21500
|
// event from the trigger. The _syncingBibValue guard persists across the
|
|
20899
21501
|
// async boundary and prevents that re-entrant event from running the
|
|
20900
21502
|
// non-fullscreen path (which would call clear() → hideBib()).
|
|
20901
|
-
// When the event comes from the fullscreen bib input, sync the value to
|
|
20902
|
-
// the trigger and run filtering, but suppress the re-entrant input event
|
|
20903
|
-
// that the trigger fires (via Lit updated() → notifyValueChanged()) so
|
|
20904
|
-
// the non-fullscreen hide/clear logic doesn't close the dialog.
|
|
20905
21503
|
if (event.target === this.inputInBib) {
|
|
20906
|
-
|
|
20907
|
-
this
|
|
20908
|
-
this.
|
|
20909
|
-
|
|
20910
|
-
}
|
|
21504
|
+
// Mirror the trigger-branch bail below — programmatic inputInBib writes
|
|
21505
|
+
// notify back into this branch via Lit's notifyValueChanged.
|
|
21506
|
+
if (this._syncingDisplayValue) {
|
|
21507
|
+
return;
|
|
21508
|
+
}
|
|
21509
|
+
|
|
21510
|
+
// Filtering runs via re-entrance: writing this.input.value below
|
|
21511
|
+
// dispatches an 'input' event that the trigger's listener routes to
|
|
21512
|
+
// handleTriggerInputValueChange, which refreshes the menu filter.
|
|
21513
|
+
if (this.input.value !== this.inputInBib.value) {
|
|
21514
|
+
this._syncingBibValue = true;
|
|
21515
|
+
this.input.value = this.inputInBib.value;
|
|
21516
|
+
this.input.updateComplete.then(() => {
|
|
21517
|
+
this._syncingBibValue = false;
|
|
21518
|
+
});
|
|
21519
|
+
}
|
|
20911
21520
|
|
|
20912
|
-
// Run filtering inline — the re-entrant event won't reach this code.
|
|
20913
|
-
this.menu.matchWord = normalizeFilterValue(this.inputInBib.value);
|
|
20914
|
-
this.optionActive = null;
|
|
20915
|
-
this.handleMenuOptions();
|
|
20916
21521
|
this.dispatchEvent(new CustomEvent('inputValue', { detail: { value: this.inputValue } }));
|
|
20917
|
-
|
|
21522
|
+
} else if (event.target === this.input) {
|
|
21523
|
+
|
|
21524
|
+
// Also sync the native input immediately so keystrokes arriving
|
|
21525
|
+
// before Lit's async update cycle (e.g. rapid Backspaces during a
|
|
21526
|
+
// fullscreen transition) operate on the correct content.
|
|
21527
|
+
// Skip the next programmatic input event to prevent the patched setter
|
|
21528
|
+
// from re-entering handleInputValueChange via the bib path.
|
|
21529
|
+
const bibNativeInput = this.inputInBib.inputElement;
|
|
21530
|
+
if (bibNativeInput && bibNativeInput.value !== this.input.value) {
|
|
21531
|
+
this.inputInBib.skipNextProgrammaticInputEvent = true;
|
|
21532
|
+
bibNativeInput.value = this.input.value || '';
|
|
21533
|
+
}
|
|
20918
21534
|
}
|
|
20919
21535
|
|
|
20920
|
-
//
|
|
20921
|
-
|
|
21536
|
+
// SPA preselect guard: on init render, auro-input's notifyValueChanged
|
|
21537
|
+
// echoes an empty value through as an isProgrammatic input event before
|
|
21538
|
+
// the framework-set combobox.value has propagated down to the input.
|
|
21539
|
+
// Without this bail, the `this.value = this.input.value` below clobbers
|
|
21540
|
+
// the framework value with '' and clear() wipes optionSelected. Scoped
|
|
21541
|
+
// to the exact shape of that echo (isProgrammatic + non-empty combobox
|
|
21542
|
+
// value + empty input.value) so it doesn't affect the swap/typed paths
|
|
21543
|
+
// where value/input already track each other through the sync helpers.
|
|
21544
|
+
if (event && event.isProgrammatic && this.value && !this.input.value) {
|
|
20922
21545
|
return;
|
|
20923
21546
|
}
|
|
20924
21547
|
|
|
20925
|
-
this.
|
|
21548
|
+
this.value = this.input.value;
|
|
20926
21549
|
|
|
20927
|
-
|
|
20928
|
-
this.
|
|
21550
|
+
// Ignore re-entrant input events caused by programmatic value sets.
|
|
21551
|
+
if (this._syncingBibValue || this._syncingDisplayValue) {
|
|
21552
|
+
return;
|
|
21553
|
+
}
|
|
20929
21554
|
|
|
20930
21555
|
if (this.behavior === 'suggestion') {
|
|
20931
21556
|
this.value = this.input.value;
|
|
20932
21557
|
}
|
|
20933
21558
|
|
|
20934
|
-
if (!this.input.value) {
|
|
21559
|
+
if (!this.input.value && !this._clearing) {
|
|
20935
21560
|
this.clear();
|
|
20936
21561
|
}
|
|
20937
|
-
this.handleMenuOptions();
|
|
20938
21562
|
|
|
20939
21563
|
// Validate only if the value was set programmatically (not during user
|
|
20940
21564
|
// interaction). In fullscreen dialog mode, componentHasFocus returns false
|
|
@@ -20944,34 +21568,40 @@ class AuroCombobox extends AuroElement {
|
|
|
20944
21568
|
this.validate();
|
|
20945
21569
|
}
|
|
20946
21570
|
|
|
20947
|
-
|
|
20948
|
-
|
|
20949
|
-
|
|
20950
|
-
|
|
20951
|
-
|
|
20952
|
-
|
|
20953
|
-
|
|
20954
|
-
|
|
20955
|
-
|
|
21571
|
+
this.dispatchEvent(new CustomEvent('inputValue', { detail: { value: this.inputValue } }));
|
|
21572
|
+
}
|
|
21573
|
+
|
|
21574
|
+
/**
|
|
21575
|
+
* Handles input value changes originating from the trigger input.
|
|
21576
|
+
* Refreshes menu options and filtering, delegates to handleInputValueChange
|
|
21577
|
+
* for value synchronization, and manages fullscreen bib focus.
|
|
21578
|
+
* @private
|
|
21579
|
+
* @param {Event} event - The input event from the trigger input element.
|
|
21580
|
+
* @returns {void}
|
|
21581
|
+
*/
|
|
21582
|
+
handleTriggerInputValueChange(event) {
|
|
21583
|
+
// 'input' fires for every user-initiated value change — typing, paste,
|
|
21584
|
+
// IME composition end, dead-key composition, drag-drop. Flip _userTyped
|
|
21585
|
+
// here so updated('availableOptions') auto-opens the bib for sources
|
|
21586
|
+
// that keydown alone misses: paste fires no keydown, IME uses
|
|
21587
|
+
// key='Process', and dead keys produce multi-char keys (all bypass the
|
|
21588
|
+
// prior keydown.key.length===1 gate). Skip programmatic syncs.
|
|
21589
|
+
if (!this._syncingDisplayValue && !this._syncingBibValue && !this._programmaticFilterRefresh) {
|
|
21590
|
+
this._userTyped = true;
|
|
20956
21591
|
}
|
|
20957
21592
|
|
|
20958
|
-
|
|
20959
|
-
|
|
20960
|
-
|
|
20961
|
-
|
|
20962
|
-
|
|
20963
|
-
// dialog opens — the user then has to tap the input again to resume
|
|
20964
|
-
// typing.
|
|
20965
|
-
if (this.dropdown.isBibFullscreen && this.input.value && this.input.value.length > 0) {
|
|
20966
|
-
if (!this.dropdown.isPopoverVisible) {
|
|
20967
|
-
this.showBib();
|
|
20968
|
-
}
|
|
20969
|
-
if (this.dropdown.isPopoverVisible) {
|
|
20970
|
-
this.setInputFocus();
|
|
20971
|
-
}
|
|
21593
|
+
this.handleMenuOptions();
|
|
21594
|
+
this.optionActive = null;
|
|
21595
|
+
|
|
21596
|
+
if (this.value === this.input.value) {
|
|
21597
|
+
return;
|
|
20972
21598
|
}
|
|
20973
21599
|
|
|
20974
|
-
this.
|
|
21600
|
+
this.handleInputValueChange(event);
|
|
21601
|
+
|
|
21602
|
+
if (this.dropdown.isBibFullscreen && this.input.value && this.input.value.length > 0 && this.dropdown.isPopoverVisible) {
|
|
21603
|
+
this.setInputFocus();
|
|
21604
|
+
}
|
|
20975
21605
|
}
|
|
20976
21606
|
|
|
20977
21607
|
/**
|
|
@@ -20985,10 +21615,12 @@ class AuroCombobox extends AuroElement {
|
|
|
20985
21615
|
inputResolver: (comp, ctx) => (ctx.isModal && comp.inputInBib ? comp.inputInBib : comp.input),
|
|
20986
21616
|
});
|
|
20987
21617
|
|
|
20988
|
-
this.addEventListener('focusin', () => {
|
|
21618
|
+
this.addEventListener('focusin', (event) => {
|
|
20989
21619
|
this.touched = true;
|
|
20990
21620
|
|
|
20991
|
-
|
|
21621
|
+
if (event.composedPath()[0] === this) {
|
|
21622
|
+
this.focus();
|
|
21623
|
+
}
|
|
20992
21624
|
});
|
|
20993
21625
|
|
|
20994
21626
|
this.addEventListener('auroFormElement-validated', (evt) => {
|
|
@@ -21000,6 +21632,16 @@ class AuroCombobox extends AuroElement {
|
|
|
21000
21632
|
return;
|
|
21001
21633
|
}
|
|
21002
21634
|
|
|
21635
|
+
// Ignore dispatches from the bib (fullscreen) input. It's re-validated
|
|
21636
|
+
// inside this.validate()'s auroInputElements loop with its own
|
|
21637
|
+
// (often undefined) validity, and the event is composed/bubbles up to
|
|
21638
|
+
// this listener with `target` retargeted to the combobox. Letting it
|
|
21639
|
+
// through would overwrite the trigger input's correct validity with
|
|
21640
|
+
// the bib input's stale one (e.g. wiping `tooShort` during typing).
|
|
21641
|
+
if (this.inputInBib && evt.composedPath()[0] === this.inputInBib && this.inputInBib !== this.input) {
|
|
21642
|
+
return;
|
|
21643
|
+
}
|
|
21644
|
+
|
|
21003
21645
|
this.input.validity = evt.detail.validity;
|
|
21004
21646
|
this.input.errorMessage = evt.detail.message;
|
|
21005
21647
|
this.validity = evt.detail.validity;
|
|
@@ -21029,6 +21671,11 @@ class AuroCombobox extends AuroElement {
|
|
|
21029
21671
|
disconnectedCallback() {
|
|
21030
21672
|
super.disconnectedCallback();
|
|
21031
21673
|
this._inFullscreenTransition = false;
|
|
21674
|
+
// Cancel any outstanding timers so detached callbacks don't fire on
|
|
21675
|
+
// disposed DOM — most are no-ops, but configureMenu's racing-condition
|
|
21676
|
+
// retry would otherwise keep rescheduling itself indefinitely.
|
|
21677
|
+
this._pendingTimers.forEach((id) => clearTimeout(id));
|
|
21678
|
+
this._pendingTimers.clear();
|
|
21032
21679
|
}
|
|
21033
21680
|
|
|
21034
21681
|
firstUpdated() {
|
|
@@ -21061,10 +21708,18 @@ class AuroCombobox extends AuroElement {
|
|
|
21061
21708
|
* @returns {void}
|
|
21062
21709
|
*/
|
|
21063
21710
|
setMenuValue(value) {
|
|
21064
|
-
if (!this.menu) {
|
|
21711
|
+
if (!this.menu || this.menu.value === value) {
|
|
21065
21712
|
return;
|
|
21066
21713
|
}
|
|
21714
|
+
// One-shot flag consumed by the auroMenu-selectedOption listener so the
|
|
21715
|
+
// echo of this sync doesn't propagate back to this.value.
|
|
21716
|
+
this._pendingMenuValueSync = true;
|
|
21067
21717
|
this.menu.value = value;
|
|
21718
|
+
// Backup clear: if menu.value === menu.optionSelected.value already, the
|
|
21719
|
+
// listener won't fire and the flag would swallow the next user click.
|
|
21720
|
+
this._scheduleTimer(() => {
|
|
21721
|
+
this._pendingMenuValueSync = false;
|
|
21722
|
+
}, 0);
|
|
21068
21723
|
}
|
|
21069
21724
|
|
|
21070
21725
|
/**
|
|
@@ -21076,9 +21731,16 @@ class AuroCombobox extends AuroElement {
|
|
|
21076
21731
|
this.value = undefined;
|
|
21077
21732
|
this.typedValue = undefined;
|
|
21078
21733
|
this.input.value = undefined;
|
|
21734
|
+
// Fullscreen bib mounts a second auro-input that holds the user-facing
|
|
21735
|
+
// native <input> on mobile; clearing only the trigger leaves stale text
|
|
21736
|
+
// there when the bib is reopened after reset.
|
|
21737
|
+
if (this.inputInBib) {
|
|
21738
|
+
this.inputInBib.value = undefined;
|
|
21739
|
+
}
|
|
21079
21740
|
this.menu.value = undefined;
|
|
21080
21741
|
this.validation.reset(this);
|
|
21081
21742
|
this.touched = false;
|
|
21743
|
+
this.validity = undefined;
|
|
21082
21744
|
}
|
|
21083
21745
|
|
|
21084
21746
|
/**
|
|
@@ -21086,16 +21748,35 @@ class AuroCombobox extends AuroElement {
|
|
|
21086
21748
|
* @returns {void}
|
|
21087
21749
|
*/
|
|
21088
21750
|
clear() {
|
|
21089
|
-
//
|
|
21090
|
-
|
|
21091
|
-
this.
|
|
21092
|
-
|
|
21093
|
-
// Then clear input and menu
|
|
21094
|
-
if (this.input.value) {
|
|
21095
|
-
this.input.clear();
|
|
21751
|
+
// input.clear() fires an input event that re-enters handleInputValueChange
|
|
21752
|
+
// → which calls clear() again on empty input. Guard against that loop.
|
|
21753
|
+
if (this._clearing) {
|
|
21754
|
+
return;
|
|
21096
21755
|
}
|
|
21097
|
-
|
|
21098
|
-
|
|
21756
|
+
this._clearing = true;
|
|
21757
|
+
try {
|
|
21758
|
+
this.optionSelected = undefined;
|
|
21759
|
+
this.value = undefined;
|
|
21760
|
+
|
|
21761
|
+
// Clear the appended displayValue clone in the trigger if present.
|
|
21762
|
+
// :not(slot) excludes the template's <slot name="displayValue"
|
|
21763
|
+
// slot="displayValue"> forwarder (line 1816), which also has
|
|
21764
|
+
// slot="displayValue" and would otherwise be matched first and removed,
|
|
21765
|
+
// permanently breaking the consumer-provided displayValue slot.
|
|
21766
|
+
const displayValueInTrigger = this.input.querySelector('[slot="displayValue"]:not(slot)');
|
|
21767
|
+
|
|
21768
|
+
if (displayValueInTrigger) {
|
|
21769
|
+
displayValueInTrigger.remove();
|
|
21770
|
+
}
|
|
21771
|
+
|
|
21772
|
+
if (this.input.value) {
|
|
21773
|
+
this.input.clear();
|
|
21774
|
+
}
|
|
21775
|
+
if (this.menu.value || this.menu.optionSelected) {
|
|
21776
|
+
this.menu.reset();
|
|
21777
|
+
}
|
|
21778
|
+
} finally {
|
|
21779
|
+
this._clearing = false;
|
|
21099
21780
|
}
|
|
21100
21781
|
}
|
|
21101
21782
|
|
|
@@ -21111,45 +21792,55 @@ class AuroCombobox extends AuroElement {
|
|
|
21111
21792
|
}
|
|
21112
21793
|
|
|
21113
21794
|
updated(changedProperties) {
|
|
21114
|
-
// After the component is ready,
|
|
21795
|
+
// After the component is ready, propagate direct changes down to child components.
|
|
21115
21796
|
if (changedProperties.has('value')) {
|
|
21116
|
-
|
|
21117
|
-
|
|
21118
|
-
|
|
21119
|
-
|
|
21120
|
-
|
|
21121
|
-
|
|
21122
|
-
|
|
21123
|
-
|
|
21124
|
-
|
|
21125
|
-
|
|
21126
|
-
|
|
21127
|
-
this.menu.options.forEach((opt) => {
|
|
21128
|
-
if (!opt.hasAttribute('static')) {
|
|
21129
|
-
opt.removeAttribute('hidden');
|
|
21130
|
-
}
|
|
21797
|
+
// Only flag programmatic refreshes — user-typed value changes must not
|
|
21798
|
+
// suppress the availableOptions branch's showBib(). Firefox batches
|
|
21799
|
+
// 'value' and 'availableOptions' into the same updated() call, so
|
|
21800
|
+
// setting the flag unconditionally here masks the user-typed open path.
|
|
21801
|
+
if (!this._userTyped) {
|
|
21802
|
+
this._programmaticFilterRefresh = true;
|
|
21803
|
+
// Self-clear after this update cycle completes. This collapses
|
|
21804
|
+
// the previous scattered clear-points into one and prevents the
|
|
21805
|
+
// flag from surviving into the next user interaction.
|
|
21806
|
+
this.updateComplete.then(() => {
|
|
21807
|
+
this._programmaticFilterRefresh = false;
|
|
21131
21808
|
});
|
|
21132
21809
|
}
|
|
21133
21810
|
|
|
21134
|
-
if (this.
|
|
21135
|
-
|
|
21136
|
-
|
|
21137
|
-
|
|
21138
|
-
|
|
21139
|
-
|
|
21140
|
-
|
|
21811
|
+
if (this.input.value !== this.value) {
|
|
21812
|
+
// Clear menu.value AND menu.optionSelected together. Clearing only
|
|
21813
|
+
// menu.value leaves the previously-selected option element pinned
|
|
21814
|
+
// as menu.optionSelected; a later auroMenu-selectedOption event
|
|
21815
|
+
// would then write its stale .value back into combobox.value
|
|
21816
|
+
// (e.g. Tab-after-Backspace re-selecting the prior option).
|
|
21817
|
+
if (this.menu.value || this.menu.optionSelected) {
|
|
21818
|
+
this.menu.clearSelection();
|
|
21141
21819
|
}
|
|
21142
|
-
|
|
21143
|
-
|
|
21144
|
-
|
|
21145
|
-
|
|
21146
|
-
|
|
21820
|
+
|
|
21821
|
+
if (!this.persistInput) {
|
|
21822
|
+
this.syncInputValuesAcrossTriggerAndBib(this.value || '');
|
|
21823
|
+
}
|
|
21824
|
+
|
|
21825
|
+
// Programmatic value with no matching option: updateFilter will close
|
|
21826
|
+
// the bib silently (see line 648 — no noMatchOption + 0 results
|
|
21827
|
+
// hides). Announce so screen-reader users hear the request was
|
|
21828
|
+
// dropped. Gated on `input.value !== this.value` so this never fires
|
|
21829
|
+
// for user typing — that path always reconciles input.value to
|
|
21830
|
+
// this.value before updated() runs.
|
|
21831
|
+
if (
|
|
21832
|
+
this.value &&
|
|
21833
|
+
this.menu &&
|
|
21834
|
+
this.menu.options &&
|
|
21835
|
+
this.menu.options.length > 0 &&
|
|
21836
|
+
!this.menu.options.some((opt) => opt.value === this.value)
|
|
21837
|
+
) {
|
|
21838
|
+
announceToScreenReader(this._getAnnouncementRoot(), `No matching option for ${this.value}`);
|
|
21147
21839
|
}
|
|
21148
21840
|
}
|
|
21149
|
-
|
|
21150
|
-
|
|
21151
|
-
|
|
21152
|
-
this.hideBib();
|
|
21841
|
+
|
|
21842
|
+
if (!this.value) {
|
|
21843
|
+
this.clear();
|
|
21153
21844
|
}
|
|
21154
21845
|
|
|
21155
21846
|
// Sync the input and match word, but don't directly set menu.value again
|
|
@@ -21163,7 +21854,7 @@ class AuroCombobox extends AuroElement {
|
|
|
21163
21854
|
composed: true,
|
|
21164
21855
|
detail: {
|
|
21165
21856
|
optionSelected: this.menu.optionSelected,
|
|
21166
|
-
value: this.
|
|
21857
|
+
value: this.value
|
|
21167
21858
|
}
|
|
21168
21859
|
}));
|
|
21169
21860
|
|
|
@@ -21182,12 +21873,26 @@ class AuroCombobox extends AuroElement {
|
|
|
21182
21873
|
// branch from calling hideBib() when the dropdown was just opened but
|
|
21183
21874
|
// :focus-within hasn't propagated through the top-layer dialog's nested
|
|
21184
21875
|
// shadow DOM boundaries.
|
|
21185
|
-
|
|
21186
|
-
|
|
21876
|
+
// Skip the show/hide side effects when the availableOptions change came
|
|
21877
|
+
// from a programmatic filter refresh after a value swap — the user
|
|
21878
|
+
// didn't interact, so we shouldn't auto-open the bib (especially for
|
|
21879
|
+
// the no-match path where the existing condition unconditionally fires).
|
|
21880
|
+
if ((this.menu && !this._programmaticFilterRefresh)) {
|
|
21881
|
+
if (
|
|
21882
|
+
this.availableOptions.length > 0 ||
|
|
21883
|
+
this.menu.loading ||
|
|
21884
|
+
this.noMatchOption
|
|
21885
|
+
) {
|
|
21886
|
+
if (this._userTyped && !this.dropdownOpen) {
|
|
21887
|
+
this.showBib();
|
|
21888
|
+
}
|
|
21889
|
+
this._userTyped = false;
|
|
21890
|
+
}
|
|
21891
|
+
|
|
21187
21892
|
if (!this.availableOptions.includes(this.menu.optionActive)) {
|
|
21188
21893
|
this.activateFirstEnabledAvailableOption();
|
|
21189
21894
|
}
|
|
21190
|
-
} else {
|
|
21895
|
+
} else if (!this.dropdown.isBibFullscreen) {
|
|
21191
21896
|
this.hideBib();
|
|
21192
21897
|
}
|
|
21193
21898
|
}
|
|
@@ -21278,7 +21983,11 @@ class AuroCombobox extends AuroElement {
|
|
|
21278
21983
|
}
|
|
21279
21984
|
});
|
|
21280
21985
|
|
|
21281
|
-
|
|
21986
|
+
// Slot change (mount/re-mount): pass `preferComboboxValue` so that a
|
|
21987
|
+
// framework-set `this.value` wins over any stale `input.value` when
|
|
21988
|
+
// matching against the newly-available options. Fixes the display
|
|
21989
|
+
// for SPA preselect and Svelte `{#key}` re-mount swap patterns.
|
|
21990
|
+
this.handleMenuOptions({ preferComboboxValue: true });
|
|
21282
21991
|
|
|
21283
21992
|
break;
|
|
21284
21993
|
|
|
@@ -21331,10 +22040,10 @@ class AuroCombobox extends AuroElement {
|
|
|
21331
22040
|
shape="${this.shape}"
|
|
21332
22041
|
size="${this.size}">
|
|
21333
22042
|
<${this.inputTag}
|
|
21334
|
-
@input="${this.
|
|
22043
|
+
@input="${this.handleTriggerInputValueChange}"
|
|
21335
22044
|
appearance="${this.onDark ? 'inverse' : this.appearance}"
|
|
21336
22045
|
.a11yActivedescendant="${this.dropdownOpen && this.optionActive ? this.optionActive.id : undefined}"
|
|
21337
|
-
.a11yExpanded="${this.
|
|
22046
|
+
.a11yExpanded="${this.dropdownOpen}"
|
|
21338
22047
|
.a11yControls="${this.dropdownId}"
|
|
21339
22048
|
.autocomplete="${this.autocomplete}"
|
|
21340
22049
|
.inputmode="${this.inputmode}"
|
|
@@ -21367,7 +22076,7 @@ class AuroCombobox extends AuroElement {
|
|
|
21367
22076
|
<slot @slotchange="${this.handleSlotChange}"></slot>
|
|
21368
22077
|
<${this.inputTag}
|
|
21369
22078
|
id="inputInBib"
|
|
21370
|
-
autofocus
|
|
22079
|
+
?autofocus="${this.dropdownOpen && this.dropdown?.isBibFullscreen}"
|
|
21371
22080
|
@input="${this.handleInputValueChange}"
|
|
21372
22081
|
.a11yActivedescendant="${this.dropdownOpen && this.optionActive ? this.optionActive.id : undefined}"
|
|
21373
22082
|
.a11yControls=${`${this.dropdownId}-floater-bib`}
|