@aurodesignsystem-dev/auro-formkit 0.0.0-pr1408.16 → 0.0.0-pr1408.17
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 +184 -143
- package/components/combobox/demo/index.min.js +184 -143
- 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 +184 -143
- package/components/combobox/dist/registered.js +184 -143
- 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.min.js +44 -22
- package/components/datepicker/demo/index.min.js +44 -22
- package/components/datepicker/dist/index.js +44 -22
- package/components/datepicker/dist/registered.js +44 -22
- 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 +342 -257
- package/components/form/demo/index.min.js +342 -257
- package/components/input/demo/api.min.js +102 -77
- package/components/input/demo/index.min.js +102 -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 +32 -18
- package/components/input/dist/registered.js +32 -18
- package/components/radio/demo/api.min.js +1 -1
- package/components/radio/demo/index.min.js +1 -1
- package/components/radio/dist/index.js +1 -1
- package/components/radio/dist/registered.js +1 -1
- package/components/select/demo/api.min.js +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 +1435 -1391
- package/package.json +1 -1
|
@@ -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,32 @@ 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
|
-
return;
|
|
1264
|
-
}
|
|
1265
|
-
|
|
1266
|
-
if (ctx.isExpanded && component.optionActive) {
|
|
1267
|
-
component.menu.makeSelection();
|
|
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
1269
|
return;
|
|
1286
1270
|
}
|
|
1287
1271
|
|
|
1288
|
-
//
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
if (firstActive) {
|
|
1294
|
-
component.menu.updateActiveOption(firstActive);
|
|
1295
|
-
}
|
|
1296
|
-
return;
|
|
1297
|
-
}
|
|
1298
|
-
|
|
1299
|
-
if (ctx.isModal) {
|
|
1300
|
-
if (!ctx.activeInput) {
|
|
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
|
-
}
|
|
1272
|
+
// option display and navigation are prevented if there are no available options
|
|
1273
|
+
if (component.availableOptions.length > 0) {
|
|
1274
|
+
// navigate if bib is open otherwise open it
|
|
1275
|
+
if (component.dropdown.isPopoverVisible) {
|
|
1276
|
+
evt.preventDefault();
|
|
1322
1277
|
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
const nativeBtn = clearBtn.shadowRoot && clearBtn.shadowRoot.querySelector('button');
|
|
1326
|
-
if (nativeBtn) {
|
|
1327
|
-
nativeBtn.focus();
|
|
1278
|
+
if (evt.altKey || evt.metaKey) {
|
|
1279
|
+
component.activateLastEnabledAvailableOption();
|
|
1328
1280
|
} else {
|
|
1329
|
-
|
|
1281
|
+
navigateArrow(component, 'down');
|
|
1330
1282
|
}
|
|
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();
|
|
1283
|
+
} else {
|
|
1284
|
+
component.showBib();
|
|
1338
1285
|
}
|
|
1339
|
-
component.hideBib();
|
|
1340
|
-
return;
|
|
1341
1286
|
}
|
|
1342
|
-
|
|
1343
|
-
// Non-fullscreen: select + close
|
|
1344
|
-
if (component.menu.optionActive && component.menu.optionActive.value) {
|
|
1345
|
-
component.menu.value = component.menu.optionActive.value;
|
|
1346
|
-
}
|
|
1347
|
-
component.hideBib();
|
|
1348
1287
|
},
|
|
1349
1288
|
|
|
1350
1289
|
ArrowUp(component, evt, ctx) {
|
|
@@ -1353,31 +1292,85 @@ const comboboxKeyboardStrategy = {
|
|
|
1353
1292
|
return;
|
|
1354
1293
|
}
|
|
1355
1294
|
|
|
1295
|
+
// option display and navigation are prevented if there are no available options
|
|
1356
1296
|
if (component.availableOptions.length > 0) {
|
|
1357
|
-
|
|
1297
|
+
// navigate if bib is open otherwise open it
|
|
1298
|
+
if (component.dropdown.isPopoverVisible) {
|
|
1299
|
+
evt.preventDefault();
|
|
1300
|
+
|
|
1301
|
+
if (evt.altKey || evt.metaKey) {
|
|
1302
|
+
component.activateFirstEnabledAvailableOption();
|
|
1303
|
+
} else {
|
|
1304
|
+
navigateArrow(component, 'up');
|
|
1305
|
+
}
|
|
1306
|
+
} else {
|
|
1307
|
+
component.showBib();
|
|
1308
|
+
}
|
|
1358
1309
|
}
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1310
|
+
},
|
|
1311
|
+
|
|
1312
|
+
End(component, evt, ctx) {
|
|
1313
|
+
if (ctx.isExpanded) {
|
|
1362
1314
|
evt.preventDefault();
|
|
1363
|
-
|
|
1315
|
+
evt.stopPropagation();
|
|
1316
|
+
component.activateLastEnabledAvailableOption();
|
|
1364
1317
|
}
|
|
1365
1318
|
},
|
|
1366
1319
|
|
|
1367
|
-
|
|
1368
|
-
// If the clear button has focus, let the browser handle ArrowDown normally.
|
|
1320
|
+
Enter(component, evt, ctx) {
|
|
1369
1321
|
if (isClearBtnFocused(ctx)) {
|
|
1370
|
-
|
|
1371
|
-
|
|
1322
|
+
// If the clear button has focus, let the browser activate it normally.
|
|
1323
|
+
// stopPropagation prevents parent containers (e.g., forms) from treating
|
|
1324
|
+
// Enter as a submit, but we must NOT call preventDefault — that would
|
|
1325
|
+
// block the browser's built-in "Enter activates focused button" behavior.
|
|
1326
|
+
evt.stopPropagation();
|
|
1327
|
+
} else if (ctx.isExpanded && component.menu.optionActive) {
|
|
1328
|
+
component.menu.makeSelection();
|
|
1372
1329
|
|
|
1373
|
-
|
|
1330
|
+
if (ctx.isModal) {
|
|
1331
|
+
component.setTriggerInputFocus();
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
evt.preventDefault();
|
|
1335
|
+
evt.stopPropagation();
|
|
1336
|
+
} else {
|
|
1337
|
+
// Prevent the keypress from bubbling to parent containers (e.g., forms)
|
|
1338
|
+
// which could interpret Enter as a submit or trigger other unintended behavior.
|
|
1339
|
+
// This is safe because showBib() opens the dialog programmatically,
|
|
1340
|
+
// not via event propagation.
|
|
1341
|
+
evt.preventDefault();
|
|
1342
|
+
evt.stopPropagation();
|
|
1374
1343
|
component.showBib();
|
|
1375
1344
|
}
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1345
|
+
},
|
|
1346
|
+
|
|
1347
|
+
Escape(component, _evt, ctx) {
|
|
1348
|
+
if (ctx.isExpanded && ctx.isModal) {
|
|
1349
|
+
component.setTriggerInputFocus();
|
|
1350
|
+
}
|
|
1351
|
+
},
|
|
1352
|
+
|
|
1353
|
+
Home(component, evt, ctx) {
|
|
1354
|
+
if (ctx.isExpanded) {
|
|
1379
1355
|
evt.preventDefault();
|
|
1380
|
-
|
|
1356
|
+
evt.stopPropagation();
|
|
1357
|
+
component.activateFirstEnabledAvailableOption();
|
|
1358
|
+
}
|
|
1359
|
+
},
|
|
1360
|
+
|
|
1361
|
+
Tab(component, evt, ctx) {
|
|
1362
|
+
if (ctx.isExpanded && !isClearBtnFocused(ctx)) {
|
|
1363
|
+
// ClearBtn will not bubble up tab key events when it's focused, so need to manage it here when focused
|
|
1364
|
+
component.menu.makeSelection();
|
|
1365
|
+
component.hideBib();
|
|
1366
|
+
|
|
1367
|
+
// In fullscreen modal mode, closing the dialog does not
|
|
1368
|
+
// automatically restores focus to the input. In the tab case,
|
|
1369
|
+
// Explicitly move focus to the trigger's clear button so the
|
|
1370
|
+
// user can continues tabbing through the page normally.
|
|
1371
|
+
if (ctx.isModal && !evt.shiftKey) {
|
|
1372
|
+
component.setClearBtnFocus();
|
|
1373
|
+
}
|
|
1381
1374
|
}
|
|
1382
1375
|
},
|
|
1383
1376
|
};
|
|
@@ -4983,7 +4976,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$4 {
|
|
|
4983
4976
|
}
|
|
4984
4977
|
};
|
|
4985
4978
|
|
|
4986
|
-
var formkitVersion$2 = '
|
|
4979
|
+
var formkitVersion$2 = '202604031704';
|
|
4987
4980
|
|
|
4988
4981
|
let AuroElement$2 = class AuroElement extends i$4 {
|
|
4989
4982
|
static get properties() {
|
|
@@ -11724,6 +11717,12 @@ class BaseInput extends AuroElement$1 {
|
|
|
11724
11717
|
this.wrapperElement = this.shadowRoot.querySelector('.wrapper');
|
|
11725
11718
|
this.inputElement = this.renderRoot.querySelector('input');
|
|
11726
11719
|
this.labelElement = this.shadowRoot.querySelector('label');
|
|
11720
|
+
this.clearBtn = this.clearButtonRef.value;
|
|
11721
|
+
|
|
11722
|
+
// This must get moved into inputKeyboardStrategy when implemented
|
|
11723
|
+
this.clearBtn.addEventListener('keydown', (evt) => {
|
|
11724
|
+
evt.stopPropagation();
|
|
11725
|
+
});
|
|
11727
11726
|
|
|
11728
11727
|
this.patchInputEvent(this.inputElement);
|
|
11729
11728
|
|
|
@@ -12747,7 +12746,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$4 {
|
|
|
12747
12746
|
}
|
|
12748
12747
|
};
|
|
12749
12748
|
|
|
12750
|
-
var formkitVersion$1 = '
|
|
12749
|
+
var formkitVersion$1 = '202604031704';
|
|
12751
12750
|
|
|
12752
12751
|
// Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
|
|
12753
12752
|
// See LICENSE in the project root for license information.
|
|
@@ -12804,6 +12803,11 @@ class AuroInput extends BaseInput {
|
|
|
12804
12803
|
* @private
|
|
12805
12804
|
*/
|
|
12806
12805
|
this.iconTag = versioning.generateTag('auro-formkit-input-icon', iconVersion$2, _$2);
|
|
12806
|
+
|
|
12807
|
+
/**
|
|
12808
|
+
* @private
|
|
12809
|
+
*/
|
|
12810
|
+
this.clearButtonRef = e$1();
|
|
12807
12811
|
}
|
|
12808
12812
|
|
|
12809
12813
|
static get styles() {
|
|
@@ -12821,6 +12825,19 @@ class AuroInput extends BaseInput {
|
|
|
12821
12825
|
];
|
|
12822
12826
|
}
|
|
12823
12827
|
|
|
12828
|
+
/**
|
|
12829
|
+
* Returns classmap configuration for the clear button visibility.
|
|
12830
|
+
* The button is hidden when the input has no value, is read-only, or is disabled.
|
|
12831
|
+
* @private
|
|
12832
|
+
* @returns {Record<string, boolean>} - Classmap object controlling clear button display state.
|
|
12833
|
+
*/
|
|
12834
|
+
get clearBtnClassMap() {
|
|
12835
|
+
return {
|
|
12836
|
+
'util_displayHidden': !this.hasValue || this.readyOnly || this.disabled
|
|
12837
|
+
};
|
|
12838
|
+
}
|
|
12839
|
+
|
|
12840
|
+
|
|
12824
12841
|
/**
|
|
12825
12842
|
* Determines if the HTML input element should be visually hidden.
|
|
12826
12843
|
* Returns true when display value content exists without focus and has a value,
|
|
@@ -13140,10 +13157,11 @@ class AuroInput extends BaseInput {
|
|
|
13140
13157
|
<${this.buttonTag}
|
|
13141
13158
|
@click="${this.handleClickClear}"
|
|
13142
13159
|
appearance="${this.onDark ? 'inverse' : this.appearance}"
|
|
13143
|
-
class="notificationBtn clearBtn"
|
|
13160
|
+
class="notificationBtn clearBtn ${e$3(this.clearBtnClassMap)}"
|
|
13144
13161
|
shape="circle"
|
|
13145
13162
|
size="sm"
|
|
13146
|
-
variant="ghost"
|
|
13163
|
+
variant="ghost"
|
|
13164
|
+
${n$2(this.clearButtonRef)}>
|
|
13147
13165
|
<span><slot name="ariaLabel.clear">Clear Input</slot></span>
|
|
13148
13166
|
<${this.iconTag}
|
|
13149
13167
|
aria-hidden="true"
|
|
@@ -13288,11 +13306,7 @@ class AuroInput extends BaseInput {
|
|
|
13288
13306
|
<div part="accent-right" class="accents right">
|
|
13289
13307
|
${this.renderValidationErrorIconHtml()}
|
|
13290
13308
|
${this.hasValue && this.type === 'password' ? this.renderHtmlNotificationPassword() : undefined}
|
|
13291
|
-
${this.
|
|
13292
|
-
${!this.disabled && !this.readonly ? u$7`
|
|
13293
|
-
${this.renderHtmlActionClear()}
|
|
13294
|
-
` : undefined}
|
|
13295
|
-
` : undefined}
|
|
13309
|
+
${this.renderHtmlActionClear()}
|
|
13296
13310
|
</div>
|
|
13297
13311
|
</div>
|
|
13298
13312
|
<div class="helpTextWrapper leftIndent rightIndent" part="inputHelpText">
|
|
@@ -13324,11 +13338,7 @@ class AuroInput extends BaseInput {
|
|
|
13324
13338
|
${this.layout.includes('right') || this.layout === "emphasized" ? u$7`
|
|
13325
13339
|
${this.renderValidationErrorIconHtml()}
|
|
13326
13340
|
` : undefined}
|
|
13327
|
-
${this.
|
|
13328
|
-
${!this.disabled && !this.readonly ? u$7`
|
|
13329
|
-
${this.renderHtmlActionClear()}
|
|
13330
|
-
` : undefined}
|
|
13331
|
-
` : undefined}
|
|
13341
|
+
${this.renderHtmlActionClear()}
|
|
13332
13342
|
</div>
|
|
13333
13343
|
</div>
|
|
13334
13344
|
<div class="${e$3(this.helpTextClasses)}" part="inputHelpText">
|
|
@@ -13356,11 +13366,7 @@ class AuroInput extends BaseInput {
|
|
|
13356
13366
|
</div>
|
|
13357
13367
|
<div class="accents right">
|
|
13358
13368
|
${this.renderValidationErrorIconHtml()}
|
|
13359
|
-
${this.
|
|
13360
|
-
${!this.disabled && !this.readonly ? u$7`
|
|
13361
|
-
${this.renderHtmlActionClear()}
|
|
13362
|
-
` : undefined}
|
|
13363
|
-
` : undefined}
|
|
13369
|
+
${this.renderHtmlActionClear()}
|
|
13364
13370
|
</div>
|
|
13365
13371
|
</div>
|
|
13366
13372
|
<div class="helpTextWrapper leftIndent rightIndent" part="inputHelpText">
|
|
@@ -13786,7 +13792,7 @@ class AuroBibtemplate extends i$4 {
|
|
|
13786
13792
|
}
|
|
13787
13793
|
}
|
|
13788
13794
|
|
|
13789
|
-
var formkitVersion = '
|
|
13795
|
+
var formkitVersion = '202604031704';
|
|
13790
13796
|
|
|
13791
13797
|
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
13798
|
|
|
@@ -14265,6 +14271,7 @@ class AuroCombobox extends AuroElement {
|
|
|
14265
14271
|
|
|
14266
14272
|
/**
|
|
14267
14273
|
* Array of available options to display in the dropdown.
|
|
14274
|
+
* This array contains all non-hidden options (e.g., hidden by filtering on input value).
|
|
14268
14275
|
* @private
|
|
14269
14276
|
*/
|
|
14270
14277
|
availableOptions: {
|
|
@@ -14642,12 +14649,40 @@ class AuroCombobox extends AuroElement {
|
|
|
14642
14649
|
AuroLibraryRuntimeUtils$4.prototype.registerComponent(name, AuroCombobox);
|
|
14643
14650
|
}
|
|
14644
14651
|
|
|
14652
|
+
/**
|
|
14653
|
+
* Mark the first available (non-hidden), enabled option as `active`.
|
|
14654
|
+
* @private
|
|
14655
|
+
* @returns {void}
|
|
14656
|
+
*/
|
|
14657
|
+
activateFirstEnabledAvailableOption() {
|
|
14658
|
+
const firstEnabledOptionIndex = this.availableOptions.findIndex((opt) => !opt.disabled);
|
|
14659
|
+
this.updateActiveOption(firstEnabledOptionIndex);
|
|
14660
|
+
}
|
|
14661
|
+
|
|
14662
|
+
/**
|
|
14663
|
+
* Mark the last available (non-hidden), enabled option as `active`.
|
|
14664
|
+
* @private
|
|
14665
|
+
* @returns {void}
|
|
14666
|
+
*/
|
|
14667
|
+
activateLastEnabledAvailableOption() {
|
|
14668
|
+
let lastEnabledOptionIndex = -1;
|
|
14669
|
+
|
|
14670
|
+
// Work backwards through the available options array to find the last enabled option
|
|
14671
|
+
for (let index = this.availableOptions.length - 1; index >= 0; index -= 1) {
|
|
14672
|
+
if (!this.availableOptions[index].disabled) {
|
|
14673
|
+
lastEnabledOptionIndex = index;
|
|
14674
|
+
break;
|
|
14675
|
+
}
|
|
14676
|
+
}
|
|
14677
|
+
|
|
14678
|
+
this.updateActiveOption(lastEnabledOptionIndex);
|
|
14679
|
+
}
|
|
14680
|
+
|
|
14645
14681
|
/**
|
|
14646
14682
|
* Updates the filter for the available options based on the input value.
|
|
14647
14683
|
* @private
|
|
14648
14684
|
*/
|
|
14649
14685
|
updateFilter() {
|
|
14650
|
-
|
|
14651
14686
|
// Reset available options if noFilter is set to false after being true.
|
|
14652
14687
|
if (this.noFilter) {
|
|
14653
14688
|
this.availableOptions = [...this.options];
|
|
@@ -14766,6 +14801,10 @@ class AuroCombobox extends AuroElement {
|
|
|
14766
14801
|
if (this.value && this.input.value && !this.menu.value) {
|
|
14767
14802
|
this.syncValuesAndStates();
|
|
14768
14803
|
}
|
|
14804
|
+
|
|
14805
|
+
if (!this.availableOptions.includes(this.menu.optionActive)) {
|
|
14806
|
+
this.activateFirstEnabledAvailableOption();
|
|
14807
|
+
}
|
|
14769
14808
|
}
|
|
14770
14809
|
|
|
14771
14810
|
/**
|
|
@@ -14839,9 +14878,6 @@ class AuroCombobox extends AuroElement {
|
|
|
14839
14878
|
if (this.dropdownOpen) {
|
|
14840
14879
|
const expandedDelay = 150;
|
|
14841
14880
|
this._expandedTimeout = setTimeout(() => {
|
|
14842
|
-
if (!this.value) {
|
|
14843
|
-
this.updateActiveOption(0);
|
|
14844
|
-
}
|
|
14845
14881
|
this.triggerExpandedState = true;
|
|
14846
14882
|
}, expandedDelay);
|
|
14847
14883
|
} else {
|
|
@@ -14851,22 +14887,16 @@ class AuroCombobox extends AuroElement {
|
|
|
14851
14887
|
// Clear aria-activedescendant when dropdown closes
|
|
14852
14888
|
if (!this.dropdownOpen && this.input) {
|
|
14853
14889
|
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
14890
|
|
|
14865
14891
|
// Restore pointer events on the menu in case they were disabled
|
|
14866
14892
|
// during fullscreen open to prevent touch pass-through.
|
|
14867
14893
|
this.menu.style.pointerEvents = '';
|
|
14868
14894
|
|
|
14869
|
-
|
|
14895
|
+
// When closing a fullscreen bib, restore focus to the trigger so that
|
|
14896
|
+
// keyboard navigation continues from the correct place in the page
|
|
14897
|
+
if (this.dropdown.isBibFullscreen) {
|
|
14898
|
+
restoreTriggerAfterClose(this.dropdown, this.input);
|
|
14899
|
+
}
|
|
14870
14900
|
}
|
|
14871
14901
|
|
|
14872
14902
|
if (this.dropdownOpen) {
|
|
@@ -14901,13 +14931,6 @@ class AuroCombobox extends AuroElement {
|
|
|
14901
14931
|
this.setInputFocus();
|
|
14902
14932
|
this._inFullscreenTransition = false;
|
|
14903
14933
|
});
|
|
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
14934
|
}
|
|
14912
14935
|
}
|
|
14913
14936
|
});
|
|
@@ -14957,7 +14980,25 @@ class AuroCombobox extends AuroElement {
|
|
|
14957
14980
|
setClearBtnFocus() {
|
|
14958
14981
|
const clearBtn = this.input.shadowRoot.querySelector('.clearBtn');
|
|
14959
14982
|
if (clearBtn) {
|
|
14960
|
-
|
|
14983
|
+
// Wait for the element to fully render across
|
|
14984
|
+
// multiple Lit update cycles before moving focus
|
|
14985
|
+
doubleRaf(() => {
|
|
14986
|
+
clearBtn.focus();
|
|
14987
|
+
});
|
|
14988
|
+
}
|
|
14989
|
+
}
|
|
14990
|
+
|
|
14991
|
+
/**
|
|
14992
|
+
* @private
|
|
14993
|
+
*/
|
|
14994
|
+
setTriggerInputFocus() {
|
|
14995
|
+
const input = this.input.shadowRoot.querySelector('input');
|
|
14996
|
+
if (input) {
|
|
14997
|
+
// Wait for the element to fully render across
|
|
14998
|
+
// multiple Lit update cycles before moving focus
|
|
14999
|
+
doubleRaf(() => {
|
|
15000
|
+
input.focus();
|
|
15001
|
+
});
|
|
14961
15002
|
}
|
|
14962
15003
|
}
|
|
14963
15004
|
|
|
@@ -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
|
}
|