@aurodesignsystem-dev/auro-formkit 0.0.0-pr1408.16 → 0.0.0-pr1408.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/checkbox/demo/api.min.js +1 -1
- package/components/checkbox/demo/index.min.js +1 -1
- package/components/checkbox/dist/index.js +1 -1
- package/components/checkbox/dist/registered.js +1 -1
- package/components/combobox/demo/api.min.js +187 -141
- package/components/combobox/demo/index.min.js +187 -141
- package/components/combobox/demo/keyboardBehavior.md +9 -36
- package/components/combobox/dist/auro-combobox.d.ts +17 -0
- package/components/combobox/dist/comboboxKeyboardStrategy.d.ts +6 -3
- package/components/combobox/dist/index.js +187 -141
- package/components/combobox/dist/registered.js +187 -141
- package/components/counter/demo/api.min.js +2 -2
- package/components/counter/demo/index.min.js +2 -2
- package/components/counter/dist/index.js +2 -2
- package/components/counter/dist/registered.js +2 -2
- package/components/datepicker/demo/api.md +1 -1
- package/components/datepicker/demo/api.min.js +77 -157
- package/components/datepicker/demo/index.min.js +77 -157
- package/components/datepicker/demo/keyboardBehavior.md +1 -6
- package/components/datepicker/dist/auro-datepicker.d.ts +8 -7
- package/components/datepicker/dist/datepickerKeyboardStrategy.d.ts +1 -4
- package/components/datepicker/dist/index.js +77 -157
- package/components/datepicker/dist/registered.js +77 -157
- package/components/dropdown/demo/api.min.js +1 -1
- package/components/dropdown/demo/index.min.js +1 -1
- package/components/dropdown/dist/index.js +1 -1
- package/components/dropdown/dist/registered.js +1 -1
- package/components/form/demo/api.min.js +382 -390
- package/components/form/demo/index.min.js +382 -390
- package/components/input/demo/api.min.js +106 -77
- package/components/input/demo/index.min.js +106 -77
- package/components/input/dist/auro-input.d.ts +11 -0
- package/components/input/dist/base-input.d.ts +1 -0
- package/components/input/dist/index.js +36 -18
- package/components/input/dist/registered.js +36 -18
- package/components/menu/demo/keyboardBehavior.md +0 -0
- package/components/radio/demo/api.min.js +1 -1
- package/components/radio/demo/index.min.js +1 -1
- package/components/radio/demo/keyboardBehavior.md +0 -0
- package/components/radio/dist/index.js +1 -1
- package/components/radio/dist/registered.js +1 -1
- package/components/select/demo/api.min.js +13 -4
- package/components/select/demo/index.min.js +13 -4
- package/components/select/dist/index.js +13 -4
- package/components/select/dist/registered.js +13 -4
- package/custom-elements.json +1449 -1401
- package/package.json +3 -3
- /package/components/datepicker/demo/{keyboardBehavior.html → keyboard-behavior.html} +0 -0
|
@@ -1125,7 +1125,13 @@ function guardTouchPassthrough(element) {
|
|
|
1125
1125
|
}
|
|
1126
1126
|
|
|
1127
1127
|
/**
|
|
1128
|
-
* Restores the dropdown trigger after a fullscreen dialog closes
|
|
1128
|
+
* Restores the dropdown trigger after a fullscreen dialog closes
|
|
1129
|
+
* when focus doesn't leave the component (e.g. using Esc or Enter keys).
|
|
1130
|
+
* When leaving the component (e.g., tabbing out of the combobox after closing
|
|
1131
|
+
* the fullscreen dialog), focus restoration is handled by the browser's native
|
|
1132
|
+
* dialog focus restoration behavior, so this function only restores focus
|
|
1133
|
+
* when focus remains inside the component after the dialog closes.
|
|
1134
|
+
|
|
1129
1135
|
*
|
|
1130
1136
|
* Removes the `inert` attribute from the trigger so it is accessible again,
|
|
1131
1137
|
* and restores focus to the given target after one animation frame. The rAF
|
|
@@ -1141,8 +1147,11 @@ function guardTouchPassthrough(element) {
|
|
|
1141
1147
|
function restoreTriggerAfterClose(dropdown, focusTarget) {
|
|
1142
1148
|
dropdown.trigger.inert = false;
|
|
1143
1149
|
|
|
1150
|
+
// Wait a frame so that dialog.close() has completed and the browser's
|
|
1151
|
+
// native focus restoration has run before we attempt to focus the
|
|
1152
|
+
// trigger / input programmatically.
|
|
1144
1153
|
requestAnimationFrame(() => {
|
|
1145
|
-
if (!dropdown.isPopoverVisible) {
|
|
1154
|
+
if (!dropdown.isPopoverVisible && dropdown.trigger.contains(document.activeElement)) {
|
|
1146
1155
|
focusTarget.focus();
|
|
1147
1156
|
}
|
|
1148
1157
|
});
|
|
@@ -1249,102 +1258,33 @@ function isClearBtnFocused(ctx, clearBtn = getClearBtn(ctx)) {
|
|
|
1249
1258
|
if (!clearBtn) {
|
|
1250
1259
|
return false;
|
|
1251
1260
|
}
|
|
1252
|
-
|
|
1261
|
+
const isFocused = Boolean(clearBtn.shadowRoot && clearBtn.shadowRoot.activeElement !== null);
|
|
1262
|
+
return isFocused;
|
|
1253
1263
|
}
|
|
1254
1264
|
|
|
1255
1265
|
const comboboxKeyboardStrategy = {
|
|
1256
|
-
|
|
1257
|
-
// If the clear button has focus, let the browser
|
|
1258
|
-
// stopPropagation prevents parent containers (e.g., forms) from treating
|
|
1259
|
-
// Enter as a submit, but we must NOT call preventDefault — that would
|
|
1260
|
-
// block the browser's built-in "Enter activates focused button" behavior.
|
|
1266
|
+
ArrowDown(component, evt, ctx) {
|
|
1267
|
+
// If the clear button has focus, let the browser handle ArrowDown normally.
|
|
1261
1268
|
if (isClearBtnFocused(ctx)) {
|
|
1262
|
-
evt.stopPropagation();
|
|
1263
1269
|
return;
|
|
1264
1270
|
}
|
|
1265
1271
|
|
|
1266
|
-
if
|
|
1267
|
-
|
|
1268
|
-
await component.updateComplete;
|
|
1269
|
-
evt.preventDefault();
|
|
1270
|
-
evt.stopPropagation();
|
|
1271
|
-
component.setClearBtnFocus();
|
|
1272
|
-
} else {
|
|
1273
|
-
// Prevent the keypress from bubbling to parent containers (e.g., forms)
|
|
1274
|
-
// which could interpret Enter as a submit or trigger other unintended behavior.
|
|
1275
|
-
// This is safe because showBib() opens the dialog programmatically,
|
|
1276
|
-
// not via event propagation.
|
|
1277
|
-
evt.preventDefault();
|
|
1278
|
-
evt.stopPropagation();
|
|
1279
|
-
component.showBib();
|
|
1280
|
-
}
|
|
1281
|
-
},
|
|
1282
|
-
|
|
1283
|
-
Tab(component, evt, ctx) {
|
|
1284
|
-
if (!ctx.isExpanded) {
|
|
1285
|
-
return;
|
|
1286
|
-
}
|
|
1287
|
-
|
|
1288
|
-
// Shift+Tab moves the highlight to the first non-disabled option
|
|
1289
|
-
// without making a selection or closing the bib.
|
|
1290
|
-
if (evt.shiftKey) {
|
|
1272
|
+
// option display and navigation are prevented if there are no available options
|
|
1273
|
+
if (component.availableOptions.length > 0) {
|
|
1291
1274
|
evt.preventDefault();
|
|
1292
|
-
const firstActive = component.menu.menuService.menuOptions.find((option) => option.isActive);
|
|
1293
|
-
if (firstActive) {
|
|
1294
|
-
component.menu.updateActiveOption(firstActive);
|
|
1295
|
-
}
|
|
1296
|
-
return;
|
|
1297
|
-
}
|
|
1298
1275
|
|
|
1299
|
-
|
|
1300
|
-
if (
|
|
1301
|
-
return;
|
|
1302
|
-
}
|
|
1303
|
-
const clearBtn = getClearBtn(ctx);
|
|
1304
|
-
const clearBtnHasFocus = isClearBtnFocused(ctx, clearBtn);
|
|
1305
|
-
|
|
1306
|
-
// Tab from input: if clear button exists and doesn't have focus, focus it
|
|
1307
|
-
if (clearBtn && !clearBtnHasFocus && ctx.activeInput.value) {
|
|
1308
|
-
// Force clear button container visible to work around Safari not
|
|
1309
|
-
// propagating :focus-within through shadow DOM boundaries, which
|
|
1310
|
-
// causes .wrapper:not(:focus-within) to hide .notification.clear.
|
|
1311
|
-
const clearContainer = clearBtn.closest('.clear');
|
|
1312
|
-
if (clearContainer) {
|
|
1313
|
-
clearContainer.style.display = 'flex';
|
|
1314
|
-
clearBtn.addEventListener('focusout', () => {
|
|
1315
|
-
// Delay cleanup so :focus-within settles when focus moves
|
|
1316
|
-
// to a sibling (e.g., Shift+Tab back to the input).
|
|
1317
|
-
requestAnimationFrame(() => {
|
|
1318
|
-
clearContainer.style.display = '';
|
|
1319
|
-
});
|
|
1320
|
-
}, { once: true });
|
|
1321
|
-
}
|
|
1276
|
+
// navigate if bib is open otherwise open it
|
|
1277
|
+
if (component.dropdown.isPopoverVisible) {
|
|
1322
1278
|
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
const nativeBtn = clearBtn.shadowRoot && clearBtn.shadowRoot.querySelector('button');
|
|
1326
|
-
if (nativeBtn) {
|
|
1327
|
-
nativeBtn.focus();
|
|
1279
|
+
if (evt.altKey || evt.metaKey) {
|
|
1280
|
+
component.activateLastEnabledAvailableOption();
|
|
1328
1281
|
} else {
|
|
1329
|
-
|
|
1282
|
+
navigateArrow(component, 'down');
|
|
1330
1283
|
}
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
// Tab from clear button (or no clear button / no value) →
|
|
1335
|
-
// select the highlighted option if any, then close
|
|
1336
|
-
if (component.optionActive) {
|
|
1337
|
-
component.menu.makeSelection();
|
|
1284
|
+
} else {
|
|
1285
|
+
component.showBib();
|
|
1338
1286
|
}
|
|
1339
|
-
component.hideBib();
|
|
1340
|
-
return;
|
|
1341
|
-
}
|
|
1342
|
-
|
|
1343
|
-
// Non-fullscreen: select + close
|
|
1344
|
-
if (component.menu.optionActive && component.menu.optionActive.value) {
|
|
1345
|
-
component.menu.value = component.menu.optionActive.value;
|
|
1346
1287
|
}
|
|
1347
|
-
component.hideBib();
|
|
1348
1288
|
},
|
|
1349
1289
|
|
|
1350
1290
|
ArrowUp(component, evt, ctx) {
|
|
@@ -1353,31 +1293,85 @@ const comboboxKeyboardStrategy = {
|
|
|
1353
1293
|
return;
|
|
1354
1294
|
}
|
|
1355
1295
|
|
|
1296
|
+
// option display and navigation are prevented if there are no available options
|
|
1356
1297
|
if (component.availableOptions.length > 0) {
|
|
1357
|
-
|
|
1298
|
+
evt.preventDefault();
|
|
1299
|
+
|
|
1300
|
+
// navigate if bib is open otherwise open it
|
|
1301
|
+
if (component.dropdown.isPopoverVisible) {
|
|
1302
|
+
if (evt.altKey || evt.metaKey) {
|
|
1303
|
+
component.activateFirstEnabledAvailableOption();
|
|
1304
|
+
} else {
|
|
1305
|
+
navigateArrow(component, 'up');
|
|
1306
|
+
}
|
|
1307
|
+
} else {
|
|
1308
|
+
component.showBib();
|
|
1309
|
+
}
|
|
1358
1310
|
}
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1311
|
+
},
|
|
1312
|
+
|
|
1313
|
+
End(component, evt, ctx) {
|
|
1314
|
+
if (ctx.isExpanded) {
|
|
1362
1315
|
evt.preventDefault();
|
|
1363
|
-
|
|
1316
|
+
evt.stopPropagation();
|
|
1317
|
+
component.activateLastEnabledAvailableOption();
|
|
1364
1318
|
}
|
|
1365
1319
|
},
|
|
1366
1320
|
|
|
1367
|
-
|
|
1368
|
-
// If the clear button has focus, let the browser handle ArrowDown normally.
|
|
1321
|
+
Enter(component, evt, ctx) {
|
|
1369
1322
|
if (isClearBtnFocused(ctx)) {
|
|
1370
|
-
|
|
1371
|
-
|
|
1323
|
+
// If the clear button has focus, let the browser activate it normally.
|
|
1324
|
+
// stopPropagation prevents parent containers (e.g., forms) from treating
|
|
1325
|
+
// Enter as a submit, but we must NOT call preventDefault — that would
|
|
1326
|
+
// block the browser's built-in "Enter activates focused button" behavior.
|
|
1327
|
+
evt.stopPropagation();
|
|
1328
|
+
} else if (ctx.isExpanded && component.menu.optionActive) {
|
|
1329
|
+
component.menu.makeSelection();
|
|
1372
1330
|
|
|
1373
|
-
|
|
1331
|
+
if (ctx.isModal) {
|
|
1332
|
+
component.setTriggerInputFocus();
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
evt.preventDefault();
|
|
1336
|
+
evt.stopPropagation();
|
|
1337
|
+
} else {
|
|
1338
|
+
// Prevent the keypress from bubbling to parent containers (e.g., forms)
|
|
1339
|
+
// which could interpret Enter as a submit or trigger other unintended behavior.
|
|
1340
|
+
// This is safe because showBib() opens the dialog programmatically,
|
|
1341
|
+
// not via event propagation.
|
|
1342
|
+
evt.preventDefault();
|
|
1343
|
+
evt.stopPropagation();
|
|
1374
1344
|
component.showBib();
|
|
1375
1345
|
}
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1346
|
+
},
|
|
1347
|
+
|
|
1348
|
+
Escape(component, _evt, ctx) {
|
|
1349
|
+
if (ctx.isExpanded && ctx.isModal) {
|
|
1350
|
+
component.setTriggerInputFocus();
|
|
1351
|
+
}
|
|
1352
|
+
},
|
|
1353
|
+
|
|
1354
|
+
Home(component, evt, ctx) {
|
|
1355
|
+
if (ctx.isExpanded) {
|
|
1379
1356
|
evt.preventDefault();
|
|
1380
|
-
|
|
1357
|
+
evt.stopPropagation();
|
|
1358
|
+
component.activateFirstEnabledAvailableOption();
|
|
1359
|
+
}
|
|
1360
|
+
},
|
|
1361
|
+
|
|
1362
|
+
Tab(component, evt, ctx) {
|
|
1363
|
+
if (ctx.isExpanded && !isClearBtnFocused(ctx)) {
|
|
1364
|
+
// ClearBtn will not bubble up tab key events when it's focused, so need to manage it here when focused
|
|
1365
|
+
component.menu.makeSelection();
|
|
1366
|
+
component.hideBib();
|
|
1367
|
+
|
|
1368
|
+
// In fullscreen modal mode, closing the dialog does not
|
|
1369
|
+
// automatically restores focus to the input. In the tab case,
|
|
1370
|
+
// Explicitly move focus to the trigger's clear button so the
|
|
1371
|
+
// user can continues tabbing through the page normally.
|
|
1372
|
+
if (ctx.isModal && !evt.shiftKey) {
|
|
1373
|
+
component.setClearBtnFocus();
|
|
1374
|
+
}
|
|
1381
1375
|
}
|
|
1382
1376
|
},
|
|
1383
1377
|
};
|
|
@@ -4983,7 +4977,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$4 {
|
|
|
4983
4977
|
}
|
|
4984
4978
|
};
|
|
4985
4979
|
|
|
4986
|
-
var formkitVersion$2 = '
|
|
4980
|
+
var formkitVersion$2 = '202604032311';
|
|
4987
4981
|
|
|
4988
4982
|
let AuroElement$2 = class AuroElement extends i$4 {
|
|
4989
4983
|
static get properties() {
|
|
@@ -11724,6 +11718,16 @@ class BaseInput extends AuroElement$1 {
|
|
|
11724
11718
|
this.wrapperElement = this.shadowRoot.querySelector('.wrapper');
|
|
11725
11719
|
this.inputElement = this.renderRoot.querySelector('input');
|
|
11726
11720
|
this.labelElement = this.shadowRoot.querySelector('label');
|
|
11721
|
+
this.clearBtn = this.clearButtonRef.value;
|
|
11722
|
+
|
|
11723
|
+
// This must get moved into inputKeyboardStrategy when implemented
|
|
11724
|
+
this.clearBtn.addEventListener('keydown', (evt) => {
|
|
11725
|
+
evt.stopPropagation();
|
|
11726
|
+
});
|
|
11727
|
+
|
|
11728
|
+
this.clearBtn.addEventListener('click', (evt) => {
|
|
11729
|
+
evt.stopPropagation();
|
|
11730
|
+
});
|
|
11727
11731
|
|
|
11728
11732
|
this.patchInputEvent(this.inputElement);
|
|
11729
11733
|
|
|
@@ -12747,7 +12751,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$4 {
|
|
|
12747
12751
|
}
|
|
12748
12752
|
};
|
|
12749
12753
|
|
|
12750
|
-
var formkitVersion$1 = '
|
|
12754
|
+
var formkitVersion$1 = '202604032311';
|
|
12751
12755
|
|
|
12752
12756
|
// Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
|
|
12753
12757
|
// See LICENSE in the project root for license information.
|
|
@@ -12804,6 +12808,11 @@ class AuroInput extends BaseInput {
|
|
|
12804
12808
|
* @private
|
|
12805
12809
|
*/
|
|
12806
12810
|
this.iconTag = versioning.generateTag('auro-formkit-input-icon', iconVersion$2, _$2);
|
|
12811
|
+
|
|
12812
|
+
/**
|
|
12813
|
+
* @private
|
|
12814
|
+
*/
|
|
12815
|
+
this.clearButtonRef = e$1();
|
|
12807
12816
|
}
|
|
12808
12817
|
|
|
12809
12818
|
static get styles() {
|
|
@@ -12821,6 +12830,19 @@ class AuroInput extends BaseInput {
|
|
|
12821
12830
|
];
|
|
12822
12831
|
}
|
|
12823
12832
|
|
|
12833
|
+
/**
|
|
12834
|
+
* Returns classmap configuration for the clear button visibility.
|
|
12835
|
+
* The button is hidden when the input has no value, is read-only, or is disabled.
|
|
12836
|
+
* @private
|
|
12837
|
+
* @returns {Record<string, boolean>} - Classmap object controlling clear button display state.
|
|
12838
|
+
*/
|
|
12839
|
+
get clearBtnClassMap() {
|
|
12840
|
+
return {
|
|
12841
|
+
'util_displayHidden': !this.hasValue || this.readyOnly || this.disabled
|
|
12842
|
+
};
|
|
12843
|
+
}
|
|
12844
|
+
|
|
12845
|
+
|
|
12824
12846
|
/**
|
|
12825
12847
|
* Determines if the HTML input element should be visually hidden.
|
|
12826
12848
|
* Returns true when display value content exists without focus and has a value,
|
|
@@ -13140,10 +13162,11 @@ class AuroInput extends BaseInput {
|
|
|
13140
13162
|
<${this.buttonTag}
|
|
13141
13163
|
@click="${this.handleClickClear}"
|
|
13142
13164
|
appearance="${this.onDark ? 'inverse' : this.appearance}"
|
|
13143
|
-
class="notificationBtn clearBtn"
|
|
13165
|
+
class="notificationBtn clearBtn ${e$3(this.clearBtnClassMap)}"
|
|
13144
13166
|
shape="circle"
|
|
13145
13167
|
size="sm"
|
|
13146
|
-
variant="ghost"
|
|
13168
|
+
variant="ghost"
|
|
13169
|
+
${n$2(this.clearButtonRef)}>
|
|
13147
13170
|
<span><slot name="ariaLabel.clear">Clear Input</slot></span>
|
|
13148
13171
|
<${this.iconTag}
|
|
13149
13172
|
aria-hidden="true"
|
|
@@ -13288,11 +13311,7 @@ class AuroInput extends BaseInput {
|
|
|
13288
13311
|
<div part="accent-right" class="accents right">
|
|
13289
13312
|
${this.renderValidationErrorIconHtml()}
|
|
13290
13313
|
${this.hasValue && this.type === 'password' ? this.renderHtmlNotificationPassword() : undefined}
|
|
13291
|
-
${this.
|
|
13292
|
-
${!this.disabled && !this.readonly ? u$7`
|
|
13293
|
-
${this.renderHtmlActionClear()}
|
|
13294
|
-
` : undefined}
|
|
13295
|
-
` : undefined}
|
|
13314
|
+
${this.renderHtmlActionClear()}
|
|
13296
13315
|
</div>
|
|
13297
13316
|
</div>
|
|
13298
13317
|
<div class="helpTextWrapper leftIndent rightIndent" part="inputHelpText">
|
|
@@ -13324,11 +13343,7 @@ class AuroInput extends BaseInput {
|
|
|
13324
13343
|
${this.layout.includes('right') || this.layout === "emphasized" ? u$7`
|
|
13325
13344
|
${this.renderValidationErrorIconHtml()}
|
|
13326
13345
|
` : undefined}
|
|
13327
|
-
${this.
|
|
13328
|
-
${!this.disabled && !this.readonly ? u$7`
|
|
13329
|
-
${this.renderHtmlActionClear()}
|
|
13330
|
-
` : undefined}
|
|
13331
|
-
` : undefined}
|
|
13346
|
+
${this.renderHtmlActionClear()}
|
|
13332
13347
|
</div>
|
|
13333
13348
|
</div>
|
|
13334
13349
|
<div class="${e$3(this.helpTextClasses)}" part="inputHelpText">
|
|
@@ -13356,11 +13371,7 @@ class AuroInput extends BaseInput {
|
|
|
13356
13371
|
</div>
|
|
13357
13372
|
<div class="accents right">
|
|
13358
13373
|
${this.renderValidationErrorIconHtml()}
|
|
13359
|
-
${this.
|
|
13360
|
-
${!this.disabled && !this.readonly ? u$7`
|
|
13361
|
-
${this.renderHtmlActionClear()}
|
|
13362
|
-
` : undefined}
|
|
13363
|
-
` : undefined}
|
|
13374
|
+
${this.renderHtmlActionClear()}
|
|
13364
13375
|
</div>
|
|
13365
13376
|
</div>
|
|
13366
13377
|
<div class="helpTextWrapper leftIndent rightIndent" part="inputHelpText">
|
|
@@ -13786,7 +13797,7 @@ class AuroBibtemplate extends i$4 {
|
|
|
13786
13797
|
}
|
|
13787
13798
|
}
|
|
13788
13799
|
|
|
13789
|
-
var formkitVersion = '
|
|
13800
|
+
var formkitVersion = '202604032311';
|
|
13790
13801
|
|
|
13791
13802
|
var styleCss$3 = i$7`.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock{display:block}.util_displayFlex{display:flex}.util_displayHidden{display:none}.util_displayHiddenVisually{position:absolute;overflow:hidden;clip:rect(1px, 1px, 1px, 1px);width:1px;height:1px;padding:0;border:0}:host{display:block;text-align:left}:host [auro-dropdown]{--ds-auro-dropdown-trigger-background-color: transparent}:host #inputInBib::part(wrapper){box-shadow:none}:host #inputInBib::part(accent-left){display:none}:host([layout*=classic]) [auro-input]{width:100%}:host([layout*=classic]) [auro-input]::part(helpText){display:none}:host([layout*=classic]) #slotHolder{display:none}`;
|
|
13792
13803
|
|
|
@@ -14265,6 +14276,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14265
14276
|
|
|
14266
14277
|
/**
|
|
14267
14278
|
* Array of available options to display in the dropdown.
|
|
14279
|
+
* This array contains all non-hidden options (e.g., hidden by filtering on input value).
|
|
14268
14280
|
* @private
|
|
14269
14281
|
*/
|
|
14270
14282
|
availableOptions: {
|
|
@@ -14642,12 +14654,40 @@ class AuroCombobox extends AuroElement {
|
|
|
14642
14654
|
AuroLibraryRuntimeUtils$4.prototype.registerComponent(name, AuroCombobox);
|
|
14643
14655
|
}
|
|
14644
14656
|
|
|
14657
|
+
/**
|
|
14658
|
+
* Mark the first available (non-hidden), enabled option as `active`.
|
|
14659
|
+
* @private
|
|
14660
|
+
* @returns {void}
|
|
14661
|
+
*/
|
|
14662
|
+
activateFirstEnabledAvailableOption() {
|
|
14663
|
+
const firstEnabledOptionIndex = this.availableOptions.findIndex((opt) => !opt.disabled);
|
|
14664
|
+
this.updateActiveOption(firstEnabledOptionIndex);
|
|
14665
|
+
}
|
|
14666
|
+
|
|
14667
|
+
/**
|
|
14668
|
+
* Mark the last available (non-hidden), enabled option as `active`.
|
|
14669
|
+
* @private
|
|
14670
|
+
* @returns {void}
|
|
14671
|
+
*/
|
|
14672
|
+
activateLastEnabledAvailableOption() {
|
|
14673
|
+
let lastEnabledOptionIndex = -1;
|
|
14674
|
+
|
|
14675
|
+
// Work backwards through the available options array to find the last enabled option
|
|
14676
|
+
for (let index = this.availableOptions.length - 1; index >= 0; index -= 1) {
|
|
14677
|
+
if (!this.availableOptions[index].disabled) {
|
|
14678
|
+
lastEnabledOptionIndex = index;
|
|
14679
|
+
break;
|
|
14680
|
+
}
|
|
14681
|
+
}
|
|
14682
|
+
|
|
14683
|
+
this.updateActiveOption(lastEnabledOptionIndex);
|
|
14684
|
+
}
|
|
14685
|
+
|
|
14645
14686
|
/**
|
|
14646
14687
|
* Updates the filter for the available options based on the input value.
|
|
14647
14688
|
* @private
|
|
14648
14689
|
*/
|
|
14649
14690
|
updateFilter() {
|
|
14650
|
-
|
|
14651
14691
|
// Reset available options if noFilter is set to false after being true.
|
|
14652
14692
|
if (this.noFilter) {
|
|
14653
14693
|
this.availableOptions = [...this.options];
|
|
@@ -14766,6 +14806,10 @@ class AuroCombobox extends AuroElement {
|
|
|
14766
14806
|
if (this.value && this.input.value && !this.menu.value) {
|
|
14767
14807
|
this.syncValuesAndStates();
|
|
14768
14808
|
}
|
|
14809
|
+
|
|
14810
|
+
if (!this.availableOptions.includes(this.menu.optionActive)) {
|
|
14811
|
+
this.activateFirstEnabledAvailableOption();
|
|
14812
|
+
}
|
|
14769
14813
|
}
|
|
14770
14814
|
|
|
14771
14815
|
/**
|
|
@@ -14839,9 +14883,6 @@ class AuroCombobox extends AuroElement {
|
|
|
14839
14883
|
if (this.dropdownOpen) {
|
|
14840
14884
|
const expandedDelay = 150;
|
|
14841
14885
|
this._expandedTimeout = setTimeout(() => {
|
|
14842
|
-
if (!this.value) {
|
|
14843
|
-
this.updateActiveOption(0);
|
|
14844
|
-
}
|
|
14845
14886
|
this.triggerExpandedState = true;
|
|
14846
14887
|
}, expandedDelay);
|
|
14847
14888
|
} else {
|
|
@@ -14851,22 +14892,16 @@ class AuroCombobox extends AuroElement {
|
|
|
14851
14892
|
// Clear aria-activedescendant when dropdown closes
|
|
14852
14893
|
if (!this.dropdownOpen && this.input) {
|
|
14853
14894
|
this.input.setActiveDescendant(null);
|
|
14854
|
-
this.optionActive = null;
|
|
14855
|
-
|
|
14856
|
-
// Remove the highlighted state from all menu options so re-opening
|
|
14857
|
-
// the dropdown doesn't show a stale highlight.
|
|
14858
|
-
if (this.options) {
|
|
14859
|
-
this.options.forEach((opt) => {
|
|
14860
|
-
opt.active = false;
|
|
14861
|
-
opt.classList.remove('active');
|
|
14862
|
-
});
|
|
14863
|
-
}
|
|
14864
14895
|
|
|
14865
14896
|
// Restore pointer events on the menu in case they were disabled
|
|
14866
14897
|
// during fullscreen open to prevent touch pass-through.
|
|
14867
14898
|
this.menu.style.pointerEvents = '';
|
|
14868
14899
|
|
|
14869
|
-
|
|
14900
|
+
// When closing a fullscreen bib, restore focus to the trigger so that
|
|
14901
|
+
// keyboard navigation continues from the correct place in the page
|
|
14902
|
+
if (this.dropdown.isBibFullscreen) {
|
|
14903
|
+
restoreTriggerAfterClose(this.dropdown, this.input);
|
|
14904
|
+
}
|
|
14870
14905
|
}
|
|
14871
14906
|
|
|
14872
14907
|
if (this.dropdownOpen) {
|
|
@@ -14901,13 +14936,6 @@ class AuroCombobox extends AuroElement {
|
|
|
14901
14936
|
this.setInputFocus();
|
|
14902
14937
|
this._inFullscreenTransition = false;
|
|
14903
14938
|
});
|
|
14904
|
-
} else {
|
|
14905
|
-
// wait a frame in case the bib gets hidden immediately after showing because there is no value
|
|
14906
|
-
setTimeout(() => {
|
|
14907
|
-
if (this.componentHasFocus) {
|
|
14908
|
-
this.setInputFocus();
|
|
14909
|
-
}
|
|
14910
|
-
}, 0);
|
|
14911
14939
|
}
|
|
14912
14940
|
}
|
|
14913
14941
|
});
|
|
@@ -14957,7 +14985,25 @@ class AuroCombobox extends AuroElement {
|
|
|
14957
14985
|
setClearBtnFocus() {
|
|
14958
14986
|
const clearBtn = this.input.shadowRoot.querySelector('.clearBtn');
|
|
14959
14987
|
if (clearBtn) {
|
|
14960
|
-
|
|
14988
|
+
// Wait for the element to fully render across
|
|
14989
|
+
// multiple Lit update cycles before moving focus
|
|
14990
|
+
doubleRaf(() => {
|
|
14991
|
+
clearBtn.focus();
|
|
14992
|
+
});
|
|
14993
|
+
}
|
|
14994
|
+
}
|
|
14995
|
+
|
|
14996
|
+
/**
|
|
14997
|
+
* @private
|
|
14998
|
+
*/
|
|
14999
|
+
setTriggerInputFocus() {
|
|
15000
|
+
const input = this.input.shadowRoot.querySelector('input');
|
|
15001
|
+
if (input) {
|
|
15002
|
+
// Wait for the element to fully render across
|
|
15003
|
+
// multiple Lit update cycles before moving focus
|
|
15004
|
+
doubleRaf(() => {
|
|
15005
|
+
input.focus();
|
|
15006
|
+
});
|
|
14961
15007
|
}
|
|
14962
15008
|
}
|
|
14963
15009
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<div class="mainContent">
|
|
4
4
|
<div class="scrollWrapper">
|
|
5
5
|
<auro-header level="2" id="tabBehavior">Tab Behavior</auro-header>
|
|
6
|
-
<p>The component trigger contains an <code><auro-input></code> which has two
|
|
6
|
+
<p>The component trigger contains an <code><auro-input></code> which has two elements:</p>
|
|
7
7
|
<ol>
|
|
8
8
|
<li><strong>Input</strong></li>
|
|
9
9
|
<li><strong>Clear button:</strong> only shown when the input has a value.</li>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<p>Each focusable element <em>(when shown)</em> participates in the browser window's default <code>tabindex</code> sequence.</p>
|
|
12
12
|
<p>When the component is <code>disabled</code> it is removed from the <code>tabindex</code> sequence. VoiceOver's virtual cursor <em>(swipe navigation)</em> can still encounter the component, but standard keyboard <code>Tab</code> navigation skips it.</p>
|
|
13
13
|
<p>On <strong>large viewport devices</strong> (e.g., desktop browser, tablet) there is no focusable content inside the component bib.</p>
|
|
14
|
-
<p>On <strong>small viewport devices</strong> (e.g., phone) the bib opens a modal dialog with a focusable <strong>input</strong> and <strong>clear button</strong> which
|
|
14
|
+
<p>On <strong>small viewport devices</strong> (e.g., phone) the bib opens a modal dialog with a focusable <strong>input</strong> and <strong>clear button</strong> which can receive <strong>Click</strong> and <strong>Tap</strong> events.</p>
|
|
15
15
|
<auro-header level="2" id="keyEvents">Key Events</auro-header>
|
|
16
16
|
<!-- AURO-GENERATED-CONTENT:START (FILE:src=./../docs/partials/keyEvents.md) -->
|
|
17
17
|
<!-- The below content is automatically added from ./../docs/partials/keyEvents.md -->
|
|
@@ -166,8 +166,8 @@
|
|
|
166
166
|
</td>
|
|
167
167
|
</tr>
|
|
168
168
|
<tr>
|
|
169
|
-
<td rowspan="
|
|
170
|
-
<td rowspan="
|
|
169
|
+
<td rowspan="4">Enter</td>
|
|
170
|
+
<td rowspan="4">-</td>
|
|
171
171
|
<td>Collapsed, list options have been populated</td>
|
|
172
172
|
<td>
|
|
173
173
|
Trigger input, <strong>NOT</strong> the input clear button
|
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
</td>
|
|
187
187
|
</tr>
|
|
188
188
|
<tr>
|
|
189
|
-
<td
|
|
189
|
+
<td>Expanded, large viewport device</td>
|
|
190
190
|
<td>
|
|
191
191
|
Trigger input element, <strong>NOT</strong> the trigger input clear button
|
|
192
192
|
</td>
|
|
@@ -195,15 +195,7 @@
|
|
|
195
195
|
</td>
|
|
196
196
|
</tr>
|
|
197
197
|
<tr>
|
|
198
|
-
<td>
|
|
199
|
-
Trigger input close button, <strong>NOT</strong> the trigger input
|
|
200
|
-
</td>
|
|
201
|
-
<td>
|
|
202
|
-
The input value is cleared and <strong>focus</strong> is moved to the trigger input element.
|
|
203
|
-
</td>
|
|
204
|
-
</tr>
|
|
205
|
-
<tr>
|
|
206
|
-
<td rowspan="2">Expanded, small viewport device</td>
|
|
198
|
+
<td>Expanded, small viewport device</td>
|
|
207
199
|
<td>
|
|
208
200
|
Dialog input element, <strong>NOT</strong> the dialog input clear button
|
|
209
201
|
</td>
|
|
@@ -211,14 +203,6 @@
|
|
|
211
203
|
The current <code>focused</code> option is selected, closes the bib and <strong>focus</strong> is returned to the trigger input element.
|
|
212
204
|
</td>
|
|
213
205
|
</tr>
|
|
214
|
-
<tr>
|
|
215
|
-
<td>
|
|
216
|
-
Dialog input clear button, <strong>NOT</strong> the dialog input element
|
|
217
|
-
</td>
|
|
218
|
-
<td>
|
|
219
|
-
The <strong>input</strong> value is cleared, <strong>focus</strong> moves to the dialog input element.
|
|
220
|
-
</td>
|
|
221
|
-
</tr>
|
|
222
206
|
<tr>
|
|
223
207
|
<td>Escape</td>
|
|
224
208
|
<td>-</td>
|
|
@@ -248,9 +232,9 @@
|
|
|
248
232
|
</td>
|
|
249
233
|
</tr>
|
|
250
234
|
<tr>
|
|
251
|
-
<td rowspan="
|
|
252
|
-
<td
|
|
253
|
-
<td
|
|
235
|
+
<td rowspan="2">Tab</td>
|
|
236
|
+
<td>-</td>
|
|
237
|
+
<td>Expanded</td>
|
|
254
238
|
<td>
|
|
255
239
|
Input element, <strong>NOT</strong> the input clear button
|
|
256
240
|
<div class="note">
|
|
@@ -261,17 +245,6 @@
|
|
|
261
245
|
The current <code>focused</code> option is selected, the bib is closed and <strong>focus</strong> is moved to the <strong>clear button</strong> in the component trigger.
|
|
262
246
|
</td>
|
|
263
247
|
</tr>
|
|
264
|
-
<tr>
|
|
265
|
-
<td>
|
|
266
|
-
Input clear button, <strong>NOT</strong> the input element
|
|
267
|
-
<div class="note">
|
|
268
|
-
<strong>Note:</strong> Includes both trigger and bib content input clear buttons.
|
|
269
|
-
</div>
|
|
270
|
-
</td>
|
|
271
|
-
<td>
|
|
272
|
-
<span style="background-color: pink; color: red;"> What do we do here? </span>
|
|
273
|
-
</td>
|
|
274
|
-
</tr>
|
|
275
248
|
<tr>
|
|
276
249
|
<td>Shift</td>
|
|
277
250
|
<td>Expanded</td>
|
|
@@ -42,6 +42,7 @@ export class AuroCombobox extends AuroElement {
|
|
|
42
42
|
};
|
|
43
43
|
/**
|
|
44
44
|
* Array of available options to display in the dropdown.
|
|
45
|
+
* This array contains all non-hidden options (e.g., hidden by filtering on input value).
|
|
45
46
|
* @private
|
|
46
47
|
*/
|
|
47
48
|
availableOptions: {
|
|
@@ -381,6 +382,18 @@ export class AuroCombobox extends AuroElement {
|
|
|
381
382
|
* @returns {boolean} - Returns true if the element is valid, false otherwise.
|
|
382
383
|
*/
|
|
383
384
|
isValid(): boolean;
|
|
385
|
+
/**
|
|
386
|
+
* Mark the first available (non-hidden), enabled option as `active`.
|
|
387
|
+
* @private
|
|
388
|
+
* @returns {void}
|
|
389
|
+
*/
|
|
390
|
+
private activateFirstEnabledAvailableOption;
|
|
391
|
+
/**
|
|
392
|
+
* Mark the last available (non-hidden), enabled option as `active`.
|
|
393
|
+
* @private
|
|
394
|
+
* @returns {void}
|
|
395
|
+
*/
|
|
396
|
+
private activateLastEnabledAvailableOption;
|
|
384
397
|
/**
|
|
385
398
|
* Updates the filter for the available options based on the input value.
|
|
386
399
|
* @private
|
|
@@ -438,6 +451,10 @@ export class AuroCombobox extends AuroElement {
|
|
|
438
451
|
* @private
|
|
439
452
|
*/
|
|
440
453
|
private setClearBtnFocus;
|
|
454
|
+
/**
|
|
455
|
+
* @private
|
|
456
|
+
*/
|
|
457
|
+
private setTriggerInputFocus;
|
|
441
458
|
/**
|
|
442
459
|
* Suppresses or restores dialog semantics on the bib's dialog element.
|
|
443
460
|
* On desktop (non-fullscreen), VoiceOver verbosely announces "listbox inside
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export namespace comboboxKeyboardStrategy {
|
|
2
|
-
function Enter(component: any, evt: any, ctx: any): Promise<void>;
|
|
3
|
-
function Tab(component: any, evt: any, ctx: any): void;
|
|
4
|
-
function ArrowUp(component: any, evt: any, ctx: any): void;
|
|
5
2
|
function ArrowDown(component: any, evt: any, ctx: any): void;
|
|
3
|
+
function ArrowUp(component: any, evt: any, ctx: any): void;
|
|
4
|
+
function End(component: any, evt: any, ctx: any): void;
|
|
5
|
+
function Enter(component: any, evt: any, ctx: any): void;
|
|
6
|
+
function Escape(component: any, _evt: any, ctx: any): void;
|
|
7
|
+
function Home(component: any, evt: any, ctx: any): void;
|
|
8
|
+
function Tab(component: any, evt: any, ctx: any): void;
|
|
6
9
|
}
|