@aurodesignsystem-dev/auro-formkit 0.0.0-pr1507.0 → 0.0.0-pr1508.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/checkbox/demo/customize.html +1 -2
- package/components/checkbox/demo/customize.min.js +1 -1
- package/components/checkbox/demo/getting-started.min.js +1 -1
- package/components/checkbox/demo/index.min.js +1 -1
- package/components/checkbox/dist/index.js +1 -1
- package/components/checkbox/dist/registered.js +1 -1
- package/components/combobox/demo/customize.html +1 -2
- package/components/combobox/demo/customize.md +108 -132
- package/components/combobox/demo/customize.min.js +150 -293
- package/components/combobox/demo/getting-started.min.js +150 -293
- package/components/combobox/demo/index.min.js +150 -293
- package/components/combobox/dist/auro-combobox.d.ts +9 -0
- package/components/combobox/dist/index.js +150 -293
- package/components/combobox/dist/registered.js +150 -293
- package/components/counter/demo/customize.min.js +10 -2
- package/components/counter/demo/index.min.js +10 -2
- package/components/counter/dist/index.js +10 -2
- package/components/counter/dist/registered.js +10 -2
- package/components/datepicker/demo/api.md +2 -0
- package/components/datepicker/demo/customize.js +0 -2
- package/components/datepicker/demo/customize.md +138 -38
- package/components/datepicker/demo/customize.min.js +59 -168
- package/components/datepicker/demo/index.min.js +59 -150
- package/components/datepicker/dist/index.js +59 -150
- package/components/datepicker/dist/registered.js +59 -150
- package/components/datepicker/dist/src/auro-datepicker.d.ts +2 -0
- package/components/dropdown/demo/customize.min.js +9 -1
- package/components/dropdown/demo/getting-started.min.js +9 -1
- package/components/dropdown/demo/index.min.js +9 -1
- package/components/dropdown/dist/auro-dropdown.d.ts +1 -0
- package/components/dropdown/dist/index.js +9 -1
- package/components/dropdown/dist/registered.js +9 -1
- package/components/form/demo/customize.html +6 -6
- package/components/form/demo/customize.js +19 -0
- package/components/form/demo/customize.md +203 -51
- package/components/form/demo/customize.min.js +707 -633
- package/components/form/demo/getting-started.min.js +635 -633
- package/components/form/demo/index.min.js +635 -633
- package/components/form/demo/registerDemoDeps.min.js +272 -596
- package/components/form/dist/auro-form.d.ts +122 -4
- package/components/form/dist/index.js +363 -37
- package/components/form/dist/registered.js +363 -37
- package/components/input/demo/customize.html +1 -2
- package/components/input/demo/customize.md +54 -53
- package/components/input/demo/customize.min.js +41 -147
- package/components/input/demo/getting-started.min.js +41 -147
- package/components/input/demo/index.min.js +41 -147
- package/components/input/dist/base-input.d.ts +1 -49
- package/components/input/dist/index.js +41 -147
- package/components/input/dist/registered.js +41 -147
- package/components/radio/demo/customize.min.js +1 -1
- package/components/radio/demo/getting-started.min.js +1 -1
- package/components/radio/demo/index.min.js +1 -1
- package/components/radio/dist/index.js +1 -1
- package/components/radio/dist/registered.js +1 -1
- package/components/select/demo/customize.html +1 -2
- package/components/select/demo/customize.min.js +10 -2
- package/components/select/demo/getting-started.min.js +10 -2
- package/components/select/demo/index.min.js +10 -2
- package/components/select/dist/index.js +10 -2
- package/components/select/dist/registered.js +10 -2
- package/custom-elements.json +1592 -1707
- package/package.json +1 -1
|
@@ -825,6 +825,8 @@ function navigateArrow(component, direction, options = {}) {
|
|
|
825
825
|
}
|
|
826
826
|
}
|
|
827
827
|
|
|
828
|
+
/* eslint-disable no-underscore-dangle */
|
|
829
|
+
|
|
828
830
|
/**
|
|
829
831
|
* Returns the clear button element from the active input's shadow
|
|
830
832
|
* DOM, if available.
|
|
@@ -860,11 +862,9 @@ function isClearBtnFocused(ctx, clearBtn = getClearBtn(ctx)) {
|
|
|
860
862
|
* @param {Object} menu - The menu component.
|
|
861
863
|
*/
|
|
862
864
|
function reconcileMenuIndex(menu) {
|
|
863
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
864
865
|
if (menu._index < 0 && menu.optionActive && menu.items) {
|
|
865
866
|
const idx = menu.items.indexOf(menu.optionActive);
|
|
866
867
|
if (idx >= 0) {
|
|
867
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
868
868
|
menu._index = idx;
|
|
869
869
|
}
|
|
870
870
|
}
|
|
@@ -4888,7 +4888,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$3 {
|
|
|
4888
4888
|
}
|
|
4889
4889
|
};
|
|
4890
4890
|
|
|
4891
|
-
var formkitVersion$2 = '
|
|
4891
|
+
var formkitVersion$2 = '202606231948';
|
|
4892
4892
|
|
|
4893
4893
|
let AuroElement$2 = class AuroElement extends i$3 {
|
|
4894
4894
|
static get properties() {
|
|
@@ -5839,6 +5839,14 @@ class AuroDropdown extends AuroElement$2 {
|
|
|
5839
5839
|
};
|
|
5840
5840
|
this.addEventListener('keydown', this._bibTabHandler);
|
|
5841
5841
|
|
|
5842
|
+
// Suppress AuroFloatingUI's auto-hide-on-focus-loss while the
|
|
5843
|
+
// desktopModal trap owns focus management. Without this, the very
|
|
5844
|
+
// first focus move into the bib (from the RAF below) triggers
|
|
5845
|
+
// handleFocusLoss → hideBib, tearing down the trap before the
|
|
5846
|
+
// user can press Tab.
|
|
5847
|
+
this._priorNoHideOnFocusLoss = this.noHideOnThisFocusLoss;
|
|
5848
|
+
this.noHideOnThisFocusLoss = true;
|
|
5849
|
+
|
|
5842
5850
|
// Move initial focus into the bib content, matching FocusTrap behavior
|
|
5843
5851
|
requestAnimationFrame(() => {
|
|
5844
5852
|
const focusables = getFocusableElements(this.bibContent);
|
|
@@ -16609,6 +16617,7 @@ class AuroInputUtilities {
|
|
|
16609
16617
|
const maskOptions = this.getMaskOptions('date', normalizedFormat);
|
|
16610
16618
|
|
|
16611
16619
|
if (!(valueObject instanceof Date) || Number.isNaN(valueObject.getTime()) || !maskOptions || typeof maskOptions.format !== 'function') {
|
|
16620
|
+
console.debug('Invalid date object or mask options for formatting', { valueObject, maskOptions }); // eslint-disable-line no-console
|
|
16612
16621
|
return undefined;
|
|
16613
16622
|
}
|
|
16614
16623
|
|
|
@@ -16760,10 +16769,8 @@ class BaseInput extends AuroElement$1 {
|
|
|
16760
16769
|
this.layout = 'classic';
|
|
16761
16770
|
this.locale = 'en-US';
|
|
16762
16771
|
this.max = undefined;
|
|
16763
|
-
this._maxObject = undefined;
|
|
16764
16772
|
this.maxLength = undefined;
|
|
16765
16773
|
this.min = undefined;
|
|
16766
|
-
this._minObject = undefined;
|
|
16767
16774
|
this.minLength = undefined;
|
|
16768
16775
|
this.required = false;
|
|
16769
16776
|
this.onDark = false;
|
|
@@ -16771,7 +16778,6 @@ class BaseInput extends AuroElement$1 {
|
|
|
16771
16778
|
this.size = 'lg';
|
|
16772
16779
|
this.shape = 'classic';
|
|
16773
16780
|
this.value = undefined;
|
|
16774
|
-
this._valueObject = undefined;
|
|
16775
16781
|
|
|
16776
16782
|
this._initializePrivateDefaults();
|
|
16777
16783
|
}
|
|
@@ -17311,7 +17317,7 @@ class BaseInput extends AuroElement$1 {
|
|
|
17311
17317
|
* @returns {Date|undefined}
|
|
17312
17318
|
*/
|
|
17313
17319
|
get valueObject() {
|
|
17314
|
-
return this.
|
|
17320
|
+
return this.value && dateFormatter.isValidDate(this.value) ? dateFormatter.stringToDateInstance(this.value) : undefined;
|
|
17315
17321
|
}
|
|
17316
17322
|
|
|
17317
17323
|
/**
|
|
@@ -17319,7 +17325,7 @@ class BaseInput extends AuroElement$1 {
|
|
|
17319
17325
|
* @returns {Date|undefined}
|
|
17320
17326
|
*/
|
|
17321
17327
|
get minObject() {
|
|
17322
|
-
return this.
|
|
17328
|
+
return this.min && dateFormatter.isValidDate(this.min) ? dateFormatter.stringToDateInstance(this.min) : undefined;
|
|
17323
17329
|
}
|
|
17324
17330
|
|
|
17325
17331
|
/**
|
|
@@ -17327,50 +17333,7 @@ class BaseInput extends AuroElement$1 {
|
|
|
17327
17333
|
* @returns {Date|undefined}
|
|
17328
17334
|
*/
|
|
17329
17335
|
get maxObject() {
|
|
17330
|
-
return this.
|
|
17331
|
-
}
|
|
17332
|
-
|
|
17333
|
-
/**
|
|
17334
|
-
* Parses a date string into a Date object when the corresponding `_*Object`
|
|
17335
|
-
* field hasn't been synced yet by `updated()`. Returns undefined when the
|
|
17336
|
-
* input type/format isn't a full date or the string is not a valid date.
|
|
17337
|
-
*
|
|
17338
|
-
* Why this exists: a parent (datepicker) can call `inputN.validate()` from
|
|
17339
|
-
* inside its own `updated()` before this input's `updated()` has run
|
|
17340
|
-
* `syncDateValues()` — so `_valueObject`/`_maxObject` are still `undefined`
|
|
17341
|
-
* and range checks would otherwise silently no-op (flipping the result to
|
|
17342
|
-
* `valid` or `patternMismatch`).
|
|
17343
|
-
* @private
|
|
17344
|
-
* @param {string|undefined} dateStr - ISO date string from `value`/`min`/`max`.
|
|
17345
|
-
* @returns {Date|undefined}
|
|
17346
|
-
*/
|
|
17347
|
-
_computeDateObjectFallback(dateStr) {
|
|
17348
|
-
if (!dateStr || !this.util || !this.util.isFullDateFormat(this.type, this.format)) {
|
|
17349
|
-
return undefined;
|
|
17350
|
-
}
|
|
17351
|
-
if (!dateFormatter.isValidDate(dateStr)) {
|
|
17352
|
-
return undefined;
|
|
17353
|
-
}
|
|
17354
|
-
return dateFormatter.stringToDateInstance(dateStr);
|
|
17355
|
-
}
|
|
17356
|
-
|
|
17357
|
-
/**
|
|
17358
|
-
* Internal setter for readonly date object properties.
|
|
17359
|
-
* @private
|
|
17360
|
-
* @param {'valueObject'|'minObject'|'maxObject'} propertyName - Public object property name.
|
|
17361
|
-
* @param {Date|undefined} propertyValue - Value to assign.
|
|
17362
|
-
* @returns {void}
|
|
17363
|
-
*/
|
|
17364
|
-
setDateObjectProperty(propertyName, propertyValue) {
|
|
17365
|
-
const internalPropertyName = `_${propertyName}`;
|
|
17366
|
-
const previousValue = this[internalPropertyName];
|
|
17367
|
-
|
|
17368
|
-
if (previousValue === propertyValue) {
|
|
17369
|
-
return;
|
|
17370
|
-
}
|
|
17371
|
-
|
|
17372
|
-
this[internalPropertyName] = propertyValue;
|
|
17373
|
-
this.requestUpdate(propertyName, previousValue);
|
|
17336
|
+
return this.max && dateFormatter.isValidDate(this.max) ? dateFormatter.stringToDateInstance(this.max) : undefined;
|
|
17374
17337
|
}
|
|
17375
17338
|
|
|
17376
17339
|
connectedCallback() {
|
|
@@ -17399,7 +17362,6 @@ class BaseInput extends AuroElement$1 {
|
|
|
17399
17362
|
format: this.format
|
|
17400
17363
|
});
|
|
17401
17364
|
this.configureDataForType();
|
|
17402
|
-
this.syncDateValues();
|
|
17403
17365
|
}
|
|
17404
17366
|
|
|
17405
17367
|
disconnectedCallback() {
|
|
@@ -17419,10 +17381,6 @@ class BaseInput extends AuroElement$1 {
|
|
|
17419
17381
|
this.wrapperElement.addEventListener('click', this.handleClick);
|
|
17420
17382
|
}
|
|
17421
17383
|
|
|
17422
|
-
// add attribute for query selectors when auro-input is registered under a custom name
|
|
17423
|
-
if (this.tagName.toLowerCase() !== 'auro-input' && !this.hasAttribute('auro-input')) {
|
|
17424
|
-
this.setAttribute('auro-input', '');
|
|
17425
|
-
}
|
|
17426
17384
|
this.inputId = this.id ? `${this.id}-input` : window.crypto.randomUUID();
|
|
17427
17385
|
|
|
17428
17386
|
// use validity message override if declared when initializing the component
|
|
@@ -17433,7 +17391,6 @@ class BaseInput extends AuroElement$1 {
|
|
|
17433
17391
|
this.setCustomHelpTextMessage();
|
|
17434
17392
|
this.configureAutoFormatting();
|
|
17435
17393
|
this.configureDataForType();
|
|
17436
|
-
this.syncDateValues();
|
|
17437
17394
|
}
|
|
17438
17395
|
|
|
17439
17396
|
/**
|
|
@@ -17570,8 +17527,6 @@ class BaseInput extends AuroElement$1 {
|
|
|
17570
17527
|
this.configureDataForType();
|
|
17571
17528
|
}
|
|
17572
17529
|
|
|
17573
|
-
this.syncDateValues(changedProperties);
|
|
17574
|
-
|
|
17575
17530
|
if (changedProperties.has('value')) {
|
|
17576
17531
|
if (this.value && this.value.length > 0) {
|
|
17577
17532
|
this.hasValue = true;
|
|
@@ -17593,14 +17548,14 @@ class BaseInput extends AuroElement$1 {
|
|
|
17593
17548
|
|
|
17594
17549
|
if (formattedValue !== this.inputElement.value) {
|
|
17595
17550
|
this.skipNextProgrammaticInputEvent = true;
|
|
17596
|
-
if (this.maskInstance && this.type
|
|
17551
|
+
if (this.maskInstance && this.type !== 'date') {
|
|
17597
17552
|
// Route through the mask so its _value and el.value stay in lock-step
|
|
17598
17553
|
// (set value calls updateControl which writes el.value = displayValue).
|
|
17599
17554
|
// Writing el.value directly leaves the mask thinking displayValue is
|
|
17600
|
-
// stale; _saveSelection on the next focus/click then warns.
|
|
17601
|
-
//
|
|
17602
|
-
//
|
|
17603
|
-
//
|
|
17555
|
+
// stale; _saveSelection on the next focus/click then warns. Date is
|
|
17556
|
+
// excluded because its formattedValue can be raw ISO when the calendar
|
|
17557
|
+
// is invalid, and re-masking through mm/dd/yyyy would truncate it and
|
|
17558
|
+
// flip validity from patternMismatch to tooShort.
|
|
17604
17559
|
this.maskInstance.value = formattedValue || '';
|
|
17605
17560
|
} else if (formattedValue) {
|
|
17606
17561
|
this.inputElement.value = formattedValue;
|
|
@@ -17642,120 +17597,65 @@ class BaseInput extends AuroElement$1 {
|
|
|
17642
17597
|
}));
|
|
17643
17598
|
}
|
|
17644
17599
|
|
|
17645
|
-
|
|
17646
|
-
/**
|
|
17647
|
-
* Synchronizes the ISO string values and Date object representations for date-related properties.
|
|
17648
|
-
* This keeps the model and display values aligned when either side changes.
|
|
17649
|
-
*
|
|
17650
|
-
* When a full date format is in use, this method updates `value`, `min`, and `max` from their corresponding
|
|
17651
|
-
* Date objects or vice versa, based on which properties have changed. It only runs when the current configuration
|
|
17652
|
-
* represents a full year/month/day date format.
|
|
17653
|
-
*
|
|
17654
|
-
* @param {Map<string, unknown>|undefined} [changedProperties=undefined] - Optional map of changed properties used to limit which values are synchronized.
|
|
17655
|
-
* @returns {void}
|
|
17656
|
-
* @private
|
|
17657
|
-
*/
|
|
17658
|
-
syncDateValues(changedProperties = undefined) {
|
|
17659
|
-
if (!this.util.isFullDateFormat(this.type, this.format)) {
|
|
17660
|
-
return;
|
|
17661
|
-
}
|
|
17662
|
-
|
|
17663
|
-
this.syncSingleDateValue(changedProperties, 'valueObject', 'value');
|
|
17664
|
-
this.syncSingleDateValue(changedProperties, 'minObject', 'min');
|
|
17665
|
-
this.syncSingleDateValue(changedProperties, 'maxObject', 'max');
|
|
17666
|
-
}
|
|
17667
|
-
|
|
17668
|
-
/**
|
|
17669
|
-
* Synchronizes one date object/string property pair.
|
|
17670
|
-
* @private
|
|
17671
|
-
* @param {Map<string, unknown>|undefined} changedProperties - Map of changed properties from Lit.
|
|
17672
|
-
* @param {string} objectProperty - Date object property name.
|
|
17673
|
-
* @param {string} valueProperty - ISO string property name.
|
|
17674
|
-
* @returns {void}
|
|
17675
|
-
*/
|
|
17676
|
-
syncSingleDateValue(changedProperties, objectProperty, valueProperty) {
|
|
17677
|
-
const objectPropertyChanged = !changedProperties || changedProperties.has(objectProperty);
|
|
17678
|
-
|
|
17679
|
-
// objectProperty wins over valueProperty when both changed
|
|
17680
|
-
if (objectPropertyChanged && this[objectProperty]) {
|
|
17681
|
-
this[valueProperty] = dateFormatter.toISOFormatString(this[objectProperty]);
|
|
17682
|
-
return;
|
|
17683
|
-
}
|
|
17684
|
-
|
|
17685
|
-
const valuePropertyChanged = !changedProperties || changedProperties.has(valueProperty);
|
|
17686
|
-
if (!valuePropertyChanged) {
|
|
17687
|
-
return;
|
|
17688
|
-
}
|
|
17689
|
-
|
|
17690
|
-
// when value is newly set to the same ISO string that corresponds to the existing Date object, do not clear the Date object (avoid unnecessary updates)
|
|
17691
|
-
if (
|
|
17692
|
-
changedProperties &&
|
|
17693
|
-
valueProperty === 'value' &&
|
|
17694
|
-
changedProperties.get('value') === undefined &&
|
|
17695
|
-
this[objectProperty] instanceof Date &&
|
|
17696
|
-
this[valueProperty] === dateFormatter.toISOFormatString(this[objectProperty])
|
|
17697
|
-
) {
|
|
17698
|
-
return;
|
|
17699
|
-
}
|
|
17700
|
-
|
|
17701
|
-
if (dateFormatter.isValidDate(this[valueProperty])) {
|
|
17702
|
-
this.setDateObjectProperty(objectProperty, dateFormatter.stringToDateInstance(this[valueProperty]));
|
|
17703
|
-
} else {
|
|
17704
|
-
this.setDateObjectProperty(objectProperty, undefined);
|
|
17705
|
-
}
|
|
17706
|
-
}
|
|
17707
|
-
|
|
17708
17600
|
/**
|
|
17709
17601
|
* Sets up IMasks and logic based on auto-formatting requirements.
|
|
17710
17602
|
* @private
|
|
17711
17603
|
* @returns {void}
|
|
17712
17604
|
*/
|
|
17713
17605
|
configureAutoFormatting() {
|
|
17714
|
-
//
|
|
17715
|
-
//
|
|
17716
|
-
//
|
|
17717
|
-
//
|
|
17606
|
+
// _configuringMask gates two things: external re-entry into this method
|
|
17607
|
+
// while setup is mid-flight (from property changes that call back here),
|
|
17608
|
+
// and the accept/complete listeners below — both need to ignore the mask
|
|
17609
|
+
// events fired by our own value-restore step.
|
|
17718
17610
|
if (this._configuringMask) return;
|
|
17719
17611
|
this._configuringMask = true;
|
|
17720
17612
|
try {
|
|
17613
|
+
// Destroy any prior mask so IMask can attach fresh under the new format.
|
|
17614
|
+
// Null the reference too — if the new maskOptions.mask is falsy (e.g.
|
|
17615
|
+
// type switched from credit-card to text) the IMask() reassignment
|
|
17616
|
+
// below is skipped, and downstream writes at line ~823 would otherwise
|
|
17617
|
+
// route through the destroyed instance.
|
|
17721
17618
|
if (this.maskInstance) {
|
|
17722
17619
|
this.maskInstance.destroy();
|
|
17620
|
+
this.maskInstance = null;
|
|
17723
17621
|
}
|
|
17724
17622
|
|
|
17725
|
-
// Pass new format to util
|
|
17726
17623
|
this.util.updateFormat(this.format);
|
|
17727
17624
|
|
|
17728
17625
|
const maskOptions = this.util.getMaskOptions(this.type, this.format);
|
|
17729
17626
|
|
|
17730
17627
|
if (this.inputElement && maskOptions.mask) {
|
|
17731
|
-
|
|
17732
|
-
//
|
|
17733
|
-
//
|
|
17734
|
-
//
|
|
17735
|
-
// When the format changes (e.g. locale switch) and we have a valid ISO
|
|
17736
|
-
// model value, compute the display string for the NEW format instead of
|
|
17737
|
-
// re-using the old display string, which may be invalid in the new mask.
|
|
17628
|
+
// Capture the current display so it can be re-applied after IMask
|
|
17629
|
+
// attaches. The restore at the bottom goes through maskInstance.value
|
|
17630
|
+
// (not inputElement.value directly) so the mask's internal state and
|
|
17631
|
+
// the input's displayed text stay in lock-step.
|
|
17738
17632
|
let existingValue = this.inputElement.value;
|
|
17633
|
+
|
|
17634
|
+
// Format-change case (e.g. locale switch): existingValue is the OLD
|
|
17635
|
+
// mask's display string and may not parse under the new mask. When
|
|
17636
|
+
// we have a valid date model, rebuild the display from valueObject
|
|
17637
|
+
// (the canonical source) using the new mask's format function.
|
|
17739
17638
|
if (
|
|
17740
17639
|
this.util.isFullDateFormat(this.type, this.format) &&
|
|
17741
17640
|
this.value &&
|
|
17742
|
-
|
|
17743
|
-
this.valueObject instanceof Date &&
|
|
17744
|
-
!Number.isNaN(this.valueObject.getTime()) &&
|
|
17641
|
+
this.valueObject &&
|
|
17745
17642
|
typeof maskOptions.format === 'function'
|
|
17746
17643
|
) {
|
|
17747
17644
|
existingValue = maskOptions.format(this.valueObject);
|
|
17748
17645
|
}
|
|
17749
17646
|
|
|
17647
|
+
// Clear before IMask attaches so the constructor seeds an empty
|
|
17648
|
+
// internal value. Otherwise IMask reads the stale unmasked string
|
|
17649
|
+
// and emits a spurious 'accept' before the restore below runs.
|
|
17750
17650
|
this.skipNextProgrammaticInputEvent = true;
|
|
17751
17651
|
this.inputElement.value = '';
|
|
17752
17652
|
|
|
17753
17653
|
this.maskInstance = IMask(this.inputElement, maskOptions);
|
|
17754
17654
|
|
|
17655
|
+
// Mask fires 'accept' on every value change, including the restore
|
|
17656
|
+
// step below. Skip events fired during configureAutoFormatting so
|
|
17657
|
+
// we don't overwrite a value the parent just pushed.
|
|
17755
17658
|
this.maskInstance.on('accept', () => {
|
|
17756
|
-
// Suppress propagation during configureAutoFormatting's own value-restoration
|
|
17757
|
-
// (line below) — the mask emits 'accept' on every value-set, including ours,
|
|
17758
|
-
// and we don't want to overwrite a value the parent just pushed.
|
|
17759
17659
|
if (this._configuringMask) return;
|
|
17760
17660
|
this.value = this.util.toModelValue(this.maskInstance.value, this.format);
|
|
17761
17661
|
if (this.type === "date") {
|
|
@@ -17763,6 +17663,8 @@ class BaseInput extends AuroElement$1 {
|
|
|
17763
17663
|
}
|
|
17764
17664
|
});
|
|
17765
17665
|
|
|
17666
|
+
// Mask fires 'complete' on the restore step below for any value that
|
|
17667
|
+
// happens to be a complete match. Same setup-suppression as 'accept'.
|
|
17766
17668
|
this.maskInstance.on('complete', () => {
|
|
17767
17669
|
if (this._configuringMask) return;
|
|
17768
17670
|
this.value = this.util.toModelValue(this.maskInstance.value, this.format);
|
|
@@ -17771,7 +17673,9 @@ class BaseInput extends AuroElement$1 {
|
|
|
17771
17673
|
}
|
|
17772
17674
|
});
|
|
17773
17675
|
|
|
17774
|
-
//
|
|
17676
|
+
// Write existingValue through the mask (not the input directly) so
|
|
17677
|
+
// the mask reformats it under the new rules and keeps its internal
|
|
17678
|
+
// _value aligned with the input's displayed text.
|
|
17775
17679
|
if (existingValue) {
|
|
17776
17680
|
this.maskInstance.value = existingValue;
|
|
17777
17681
|
}
|
|
@@ -17939,7 +17843,6 @@ class BaseInput extends AuroElement$1 {
|
|
|
17939
17843
|
*/
|
|
17940
17844
|
reset() {
|
|
17941
17845
|
this.value = undefined;
|
|
17942
|
-
this.setDateObjectProperty('valueObject', undefined);
|
|
17943
17846
|
this.validation.reset(this);
|
|
17944
17847
|
}
|
|
17945
17848
|
|
|
@@ -17948,7 +17851,6 @@ class BaseInput extends AuroElement$1 {
|
|
|
17948
17851
|
*/
|
|
17949
17852
|
clear() {
|
|
17950
17853
|
this.value = undefined;
|
|
17951
|
-
this.setDateObjectProperty('valueObject', undefined);
|
|
17952
17854
|
}
|
|
17953
17855
|
|
|
17954
17856
|
/**
|
|
@@ -18477,7 +18379,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$3 {
|
|
|
18477
18379
|
}
|
|
18478
18380
|
};
|
|
18479
18381
|
|
|
18480
|
-
var formkitVersion$1 = '
|
|
18382
|
+
var formkitVersion$1 = '202606231948';
|
|
18481
18383
|
|
|
18482
18384
|
// Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
|
|
18483
18385
|
// See LICENSE in the project root for license information.
|
|
@@ -19598,7 +19500,7 @@ class AuroBibtemplate extends i$3 {
|
|
|
19598
19500
|
}
|
|
19599
19501
|
}
|
|
19600
19502
|
|
|
19601
|
-
var formkitVersion = '
|
|
19503
|
+
var formkitVersion = '202606231948';
|
|
19602
19504
|
|
|
19603
19505
|
var styleCss$3 = i$6`.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}`;
|
|
19604
19506
|
|
|
@@ -20585,7 +20487,7 @@ class AuroCombobox extends AuroElement {
|
|
|
20585
20487
|
if (this.menu) {
|
|
20586
20488
|
this.menu.matchWord = normalizeFilterValue(this.input.value);
|
|
20587
20489
|
}
|
|
20588
|
-
const label = getOptionLabel(this.menu.optionSelected)
|
|
20490
|
+
const label = getOptionLabel(this.menu.optionSelected);
|
|
20589
20491
|
this.updateTriggerTextDisplay(label || this.value);
|
|
20590
20492
|
}
|
|
20591
20493
|
|
|
@@ -20599,40 +20501,9 @@ class AuroCombobox extends AuroElement {
|
|
|
20599
20501
|
// in suggestion mode, do not override input value if no selection has been made and the input currently has focus
|
|
20600
20502
|
const isInputFocusedWithNoSelection = !this.menu.value && (this.input.matches(':focus-within') || (this.inputInBib && this.inputInBib.matches(':focus-within')));
|
|
20601
20503
|
|
|
20602
|
-
|
|
20603
|
-
|
|
20604
|
-
|
|
20605
|
-
// syncValuesAndStates re-enters here during typing when both inputs
|
|
20606
|
-
// already match, and a no-op flag flip would make the bib branch's
|
|
20607
|
-
// bail eat legitimate user-input events.
|
|
20608
|
-
const triggerNeedsSync = this.input.value !== nextValue;
|
|
20609
|
-
const bibNeedsSync = Boolean(this.inputInBib && this.inputInBib !== this.input && this.inputInBib.value !== nextValue);
|
|
20610
|
-
if (triggerNeedsSync || bibNeedsSync) {
|
|
20611
|
-
this._syncingDisplayValue = true;
|
|
20612
|
-
if (triggerNeedsSync) {
|
|
20613
|
-
this.input.value = nextValue;
|
|
20614
|
-
}
|
|
20615
|
-
if (bibNeedsSync) {
|
|
20616
|
-
this.inputInBib.value = nextValue;
|
|
20617
|
-
}
|
|
20618
|
-
const pending = [];
|
|
20619
|
-
if (triggerNeedsSync) {
|
|
20620
|
-
pending.push(this.input.updateComplete);
|
|
20621
|
-
}
|
|
20622
|
-
if (bibNeedsSync) {
|
|
20623
|
-
pending.push(this.inputInBib.updateComplete);
|
|
20624
|
-
}
|
|
20625
|
-
Promise.all(pending).then(() => {
|
|
20626
|
-
// imask reasserts otherwise, and handleBlur reverts to its stale value.
|
|
20627
|
-
if (triggerNeedsSync && this.input.maskInstance && typeof this.input.maskInstance.updateValue === 'function') {
|
|
20628
|
-
this.input.maskInstance.updateValue();
|
|
20629
|
-
}
|
|
20630
|
-
if (bibNeedsSync && this.inputInBib && this.inputInBib.maskInstance && typeof this.inputInBib.maskInstance.updateValue === 'function') {
|
|
20631
|
-
this.inputInBib.maskInstance.updateValue();
|
|
20632
|
-
}
|
|
20633
|
-
this._syncingDisplayValue = false;
|
|
20634
|
-
});
|
|
20635
|
-
}
|
|
20504
|
+
const suppressed = this.persistInput || (this.behavior === 'suggestion' && isInputFocusedWithNoSelection);
|
|
20505
|
+
if (!suppressed) {
|
|
20506
|
+
this.syncInputValuesAcrossTriggerAndBib(label || this.value);
|
|
20636
20507
|
}
|
|
20637
20508
|
|
|
20638
20509
|
// update the displayValue in the trigger if displayValue slot content is present
|
|
@@ -20660,6 +20531,48 @@ class AuroCombobox extends AuroElement {
|
|
|
20660
20531
|
this.requestUpdate();
|
|
20661
20532
|
}
|
|
20662
20533
|
|
|
20534
|
+
/**
|
|
20535
|
+
* Writes nextValue to the trigger input and the bib input when their current
|
|
20536
|
+
* value differs, then re-asserts imask after Lit's update flushes.
|
|
20537
|
+
* @param {string} nextValue - The value to write to both inputs.
|
|
20538
|
+
* @returns {Promise<void> | null} Promise that resolves after the inputs flush,
|
|
20539
|
+
* or null when no sync was needed (so callers can skip post-flush work).
|
|
20540
|
+
* @private
|
|
20541
|
+
*/
|
|
20542
|
+
syncInputValuesAcrossTriggerAndBib(nextValue) {
|
|
20543
|
+
// Only set the flag when there's an actual write to suppress —
|
|
20544
|
+
// syncValuesAndStates re-enters here during typing when both inputs
|
|
20545
|
+
// already match, and a no-op flag flip would make the bib branch's
|
|
20546
|
+
// bail eat legitimate user-input events.
|
|
20547
|
+
const triggerNeedsSync = this.input.value !== nextValue;
|
|
20548
|
+
const bibNeedsSync = this.inputInBib.value !== nextValue;
|
|
20549
|
+
if (!triggerNeedsSync && !bibNeedsSync) {
|
|
20550
|
+
return null;
|
|
20551
|
+
}
|
|
20552
|
+
|
|
20553
|
+
this._syncingDisplayValue = true;
|
|
20554
|
+
|
|
20555
|
+
const pending = [];
|
|
20556
|
+
if (triggerNeedsSync) {
|
|
20557
|
+
this.input.value = nextValue;
|
|
20558
|
+
pending.push(this.input.updateComplete);
|
|
20559
|
+
}
|
|
20560
|
+
if (bibNeedsSync) {
|
|
20561
|
+
this.inputInBib.value = nextValue;
|
|
20562
|
+
pending.push(this.inputInBib.updateComplete);
|
|
20563
|
+
}
|
|
20564
|
+
return Promise.all(pending).then(() => {
|
|
20565
|
+
// imask reasserts otherwise, and handleBlur reverts to its stale value.
|
|
20566
|
+
if (triggerNeedsSync && this.input.maskInstance && typeof this.input.maskInstance.updateValue === 'function') {
|
|
20567
|
+
this.input.maskInstance.updateValue();
|
|
20568
|
+
}
|
|
20569
|
+
if (bibNeedsSync && this.inputInBib && this.inputInBib.maskInstance && typeof this.inputInBib.maskInstance.updateValue === 'function') {
|
|
20570
|
+
this.inputInBib.maskInstance.updateValue();
|
|
20571
|
+
}
|
|
20572
|
+
this._syncingDisplayValue = false;
|
|
20573
|
+
});
|
|
20574
|
+
}
|
|
20575
|
+
|
|
20663
20576
|
/**
|
|
20664
20577
|
* Processes hidden state of all menu options and determines if there are any available options not hidden.
|
|
20665
20578
|
* @private
|
|
@@ -20687,9 +20600,9 @@ class AuroCombobox extends AuroElement {
|
|
|
20687
20600
|
this.syncValuesAndStates();
|
|
20688
20601
|
}
|
|
20689
20602
|
|
|
20690
|
-
// Re-activate when optionActive is
|
|
20691
|
-
// been reset (e.g. by clearSelection in an async update)
|
|
20692
|
-
// makeSelection() can find the correct option.
|
|
20603
|
+
// Re-activate when optionActive is not in the current scrollable viewport,
|
|
20604
|
+
// or when _index has been reset (e.g. by clearSelection in an async update)
|
|
20605
|
+
// so that makeSelection() can find the correct option.
|
|
20693
20606
|
if (!this.availableOptions.includes(this.menu.optionActive) || this.menu._index < 0) {
|
|
20694
20607
|
this.activateFirstEnabledAvailableOption();
|
|
20695
20608
|
}
|
|
@@ -20823,28 +20736,25 @@ class AuroCombobox extends AuroElement {
|
|
|
20823
20736
|
|
|
20824
20737
|
guardTouchPassthrough(this.menu);
|
|
20825
20738
|
|
|
20826
|
-
//
|
|
20827
|
-
//
|
|
20828
|
-
//
|
|
20739
|
+
// showModal() takes focus away from the trigger. Early focus once
|
|
20740
|
+
// the dialog has painted; the shared doubleRaf below is the fallback
|
|
20741
|
+
// for when the dialog needs an extra frame and also clears the
|
|
20742
|
+
// validation guard.
|
|
20829
20743
|
requestAnimationFrame(() => {
|
|
20830
20744
|
this.setInputFocus();
|
|
20831
20745
|
});
|
|
20832
|
-
|
|
20833
|
-
doubleRaf(() => {
|
|
20834
|
-
this.setInputFocus();
|
|
20835
|
-
this._inFullscreenTransition = false;
|
|
20836
|
-
});
|
|
20837
|
-
} else {
|
|
20838
|
-
// Desktop popover-open: restore the trigger caret to end-of-text.
|
|
20839
|
-
// Clicking the trigger lands on auro-input's floating <label for="…">
|
|
20840
|
-
// overlay; Chrome resets the native input's selection to [0, 0] on
|
|
20841
|
-
// label-focus before any JS runs. setInputFocus()'s non-fullscreen
|
|
20842
|
-
// branch parks the caret at end. doubleRaf lets the dropdown layout
|
|
20843
|
-
// settle first, matching the fullscreen branch timing.
|
|
20844
|
-
doubleRaf(() => {
|
|
20845
|
-
this.setInputFocus();
|
|
20846
|
-
});
|
|
20847
20746
|
}
|
|
20747
|
+
// else (desktop popover-open): Chrome resets the trigger caret to
|
|
20748
|
+
// [0, 0] when its floating <label for="…"> overlay receives focus.
|
|
20749
|
+
// The shared doubleRaf below parks the caret back at end-of-text
|
|
20750
|
+
// after the dropdown layout settles.
|
|
20751
|
+
|
|
20752
|
+
doubleRaf(() => {
|
|
20753
|
+
this.setInputFocus();
|
|
20754
|
+
if (this._inFullscreenTransition) {
|
|
20755
|
+
this._inFullscreenTransition = false;
|
|
20756
|
+
}
|
|
20757
|
+
});
|
|
20848
20758
|
}
|
|
20849
20759
|
});
|
|
20850
20760
|
|
|
@@ -20949,24 +20859,7 @@ class AuroCombobox extends AuroElement {
|
|
|
20949
20859
|
nativeInput.setSelectionRange(len, len);
|
|
20950
20860
|
}
|
|
20951
20861
|
} else {
|
|
20952
|
-
|
|
20953
|
-
// fullscreen→floating switch can close the dialog and leave focus on
|
|
20954
|
-
// body. Every other Branch 2 callsite already has focus on the input
|
|
20955
|
-
// via the focusin → this.focus() redirect (L1448-1452), so this is a
|
|
20956
|
-
// no-op in the common case.
|
|
20957
|
-
if (!this.input.componentHasFocus) {
|
|
20958
|
-
this.input.focus();
|
|
20959
|
-
}
|
|
20960
|
-
|
|
20961
|
-
// Park the trigger native input's caret at end-of-text every time the
|
|
20962
|
-
// popover opens. Chrome focuses the native via the floating <label for="…">
|
|
20963
|
-
// overlay on click and resets selection to [0, 0]; no JS fires between
|
|
20964
|
-
// mousedown and selectionchange, so we restore the caret here.
|
|
20965
|
-
const triggerNativeInput = this.input.inputElement;
|
|
20966
|
-
if (triggerNativeInput && triggerNativeInput.value) {
|
|
20967
|
-
const len = triggerNativeInput.value.length;
|
|
20968
|
-
triggerNativeInput.setSelectionRange(len, len);
|
|
20969
|
-
}
|
|
20862
|
+
this.input.focus();
|
|
20970
20863
|
}
|
|
20971
20864
|
}
|
|
20972
20865
|
|
|
@@ -21072,7 +20965,7 @@ class AuroCombobox extends AuroElement {
|
|
|
21072
20965
|
if (this.menu.optionSelected) {
|
|
21073
20966
|
const selected = this.menu.optionSelected;
|
|
21074
20967
|
|
|
21075
|
-
if (
|
|
20968
|
+
if (this.optionSelected !== selected) {
|
|
21076
20969
|
this.optionSelected = selected;
|
|
21077
20970
|
}
|
|
21078
20971
|
|
|
@@ -21085,7 +20978,7 @@ class AuroCombobox extends AuroElement {
|
|
|
21085
20978
|
}
|
|
21086
20979
|
|
|
21087
20980
|
// Update display
|
|
21088
|
-
this.updateTriggerTextDisplay(getOptionLabel(this.optionSelected)
|
|
20981
|
+
this.updateTriggerTextDisplay(getOptionLabel(this.optionSelected));
|
|
21089
20982
|
|
|
21090
20983
|
// Update match word for filtering
|
|
21091
20984
|
const trimmedInput = normalizeFilterValue(this.input.value);
|
|
@@ -21101,13 +20994,22 @@ class AuroCombobox extends AuroElement {
|
|
|
21101
20994
|
this.hideBib();
|
|
21102
20995
|
}
|
|
21103
20996
|
|
|
20997
|
+
// Move focus to the clear button when the user makes a selection.
|
|
20998
|
+
if (!isEcho && this.menu.value !== undefined) {
|
|
20999
|
+
this.setClearBtnFocus();
|
|
21000
|
+
}
|
|
21001
|
+
|
|
21104
21002
|
// Announce the selection after the dropdown closes so it isn't
|
|
21105
21003
|
// overridden by VoiceOver's "collapsed" announcement from aria-expanded.
|
|
21004
|
+
// Skip when there's no selected value (e.g. menu.clearSelection() from
|
|
21005
|
+
// the unmatched-value path), otherwise VoiceOver reads "undefined".
|
|
21106
21006
|
const selectedValue = this.menu.value;
|
|
21107
|
-
|
|
21108
|
-
|
|
21109
|
-
|
|
21110
|
-
|
|
21007
|
+
if (selectedValue) {
|
|
21008
|
+
const announcementDelay = 300;
|
|
21009
|
+
setTimeout(() => {
|
|
21010
|
+
announceToScreenReader(this._getAnnouncementRoot(), `${selectedValue}, selected`);
|
|
21011
|
+
}, announcementDelay);
|
|
21012
|
+
}
|
|
21111
21013
|
}
|
|
21112
21014
|
|
|
21113
21015
|
// Programmatic value syncs leave availableOptions stale because
|
|
@@ -21121,18 +21023,6 @@ class AuroCombobox extends AuroElement {
|
|
|
21121
21023
|
this._programmaticFilterRefresh = false;
|
|
21122
21024
|
}, 0);
|
|
21123
21025
|
}
|
|
21124
|
-
|
|
21125
|
-
// base-input skips auto-validate when focus is inside its own shadow,
|
|
21126
|
-
// which it is after setTriggerInputFocus — re-run so prior tooShort
|
|
21127
|
-
// clears. processCreditCard reasserts errorMessage on every render.
|
|
21128
|
-
if (!isEcho && this.menu.optionSelected && this.input.validate) {
|
|
21129
|
-
this.input.updateComplete.then(() => {
|
|
21130
|
-
this.input.validate(true);
|
|
21131
|
-
if (this.input.validity === 'valid') {
|
|
21132
|
-
this.input.errorMessage = '';
|
|
21133
|
-
}
|
|
21134
|
-
});
|
|
21135
|
-
}
|
|
21136
21026
|
});
|
|
21137
21027
|
|
|
21138
21028
|
this.menu.addEventListener('auroMenu-customEventFired', () => {
|
|
@@ -21467,15 +21357,7 @@ class AuroCombobox extends AuroElement {
|
|
|
21467
21357
|
this.menu.value = undefined;
|
|
21468
21358
|
this.validation.reset(this);
|
|
21469
21359
|
this.touched = false;
|
|
21470
|
-
// Force validity back to the cleared state. validation.reset() calls
|
|
21471
|
-
// validate() at the end, and (post-credit-card-fix) the trigger input's
|
|
21472
|
-
// residual validity may still be copied into the combobox by the
|
|
21473
|
-
// auroInputElements loop. Explicitly clear here so reset() actually
|
|
21474
|
-
// leaves the component in a "no validity" state.
|
|
21475
21360
|
this.validity = undefined;
|
|
21476
|
-
this.errorMessage = '';
|
|
21477
|
-
this.input.validity = undefined;
|
|
21478
|
-
this.input.errorMessage = '';
|
|
21479
21361
|
}
|
|
21480
21362
|
|
|
21481
21363
|
/**
|
|
@@ -21528,52 +21410,27 @@ class AuroCombobox extends AuroElement {
|
|
|
21528
21410
|
this.input.value = this.value;
|
|
21529
21411
|
}
|
|
21530
21412
|
|
|
21531
|
-
// Sync menu.value only when an option actually matches
|
|
21413
|
+
// Sync menu.value only when an option actually matches, or when filter
|
|
21414
|
+
// mode needs setMenuValue to dispatch auroMenu-selectValueFailure (the
|
|
21415
|
+
// listener at line 1206 clears combobox.value, mirroring select's
|
|
21416
|
+
// pattern). Otherwise sync the input display for freeform values.
|
|
21532
21417
|
if (this.menu.options && this.menu.options.length > 0) {
|
|
21533
|
-
if (this.menu.options.some((opt) => opt.value === this.value)) {
|
|
21534
|
-
this.setMenuValue(this.value);
|
|
21535
|
-
} else if (this.behavior === 'filter') {
|
|
21536
|
-
// In filter mode, freeform values aren't allowed. Push the unmatched
|
|
21537
|
-
// value through setMenuValue so menu dispatches auroMenu-selectValueFailure
|
|
21538
|
-
// and the listener at line 1206 clears combobox.value (mirrors select's
|
|
21539
|
-
// pattern). Bypassing setMenuValue here would skip the failure cascade.
|
|
21418
|
+
if (this.menu.options.some((opt) => opt.value === this.value) || this.behavior === 'filter') {
|
|
21540
21419
|
this.setMenuValue(this.value);
|
|
21541
21420
|
} else {
|
|
21542
|
-
|
|
21543
|
-
|
|
21421
|
+
// Clear menu.value AND menu.optionSelected together. Clearing only
|
|
21422
|
+
// menu.value leaves the previously-selected option element pinned
|
|
21423
|
+
// as menu.optionSelected; a later auroMenu-selectedOption event
|
|
21424
|
+
// would then write its stale .value back into combobox.value.
|
|
21425
|
+
if (this.menu.value || this.menu.optionSelected) {
|
|
21426
|
+
this.menu.clearSelection();
|
|
21544
21427
|
}
|
|
21545
|
-
//
|
|
21546
|
-
//
|
|
21547
|
-
//
|
|
21548
|
-
|
|
21549
|
-
|
|
21550
|
-
|
|
21551
|
-
const triggerNeedsSync = this.input.value !== nextValue;
|
|
21552
|
-
const bibNeedsSync = Boolean(this.inputInBib && this.inputInBib !== this.input && this.inputInBib.value !== nextValue);
|
|
21553
|
-
if (triggerNeedsSync || bibNeedsSync) {
|
|
21554
|
-
this._syncingDisplayValue = true;
|
|
21555
|
-
if (triggerNeedsSync) {
|
|
21556
|
-
this.input.value = nextValue;
|
|
21557
|
-
}
|
|
21558
|
-
if (bibNeedsSync) {
|
|
21559
|
-
this.inputInBib.value = nextValue;
|
|
21560
|
-
}
|
|
21561
|
-
const pending = [];
|
|
21562
|
-
if (triggerNeedsSync) {
|
|
21563
|
-
pending.push(this.input.updateComplete);
|
|
21564
|
-
}
|
|
21565
|
-
if (bibNeedsSync) {
|
|
21566
|
-
pending.push(this.inputInBib.updateComplete);
|
|
21567
|
-
}
|
|
21568
|
-
Promise.all(pending).then(() => {
|
|
21569
|
-
if (triggerNeedsSync && this.input.maskInstance && typeof this.input.maskInstance.updateValue === 'function') {
|
|
21570
|
-
this.input.maskInstance.updateValue();
|
|
21571
|
-
}
|
|
21572
|
-
if (bibNeedsSync && this.inputInBib && this.inputInBib.maskInstance && typeof this.inputInBib.maskInstance.updateValue === 'function') {
|
|
21573
|
-
this.inputInBib.maskInstance.updateValue();
|
|
21574
|
-
}
|
|
21575
|
-
this._syncingDisplayValue = false;
|
|
21576
|
-
// handleInputValueChange bailed on the flag — refresh the filter.
|
|
21428
|
+
// Suggestion-mode freeform value: sync the trigger + bib to show it,
|
|
21429
|
+
// then refresh the filter once the inputs flush (handleInputValueChange
|
|
21430
|
+
// bailed on _syncingDisplayValue).
|
|
21431
|
+
const syncPromise = this.syncInputValuesAcrossTriggerAndBib(this.value || '');
|
|
21432
|
+
if (syncPromise) {
|
|
21433
|
+
syncPromise.then(() => {
|
|
21577
21434
|
this._programmaticFilterRefresh = true;
|
|
21578
21435
|
this.handleMenuOptions();
|
|
21579
21436
|
setTimeout(() => {
|