@jsenv/dom 0.12.0 → 0.12.1
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/dist/jsenv_dom.js +26 -6
- package/package.json +1 -1
package/dist/jsenv_dom.js
CHANGED
|
@@ -4375,21 +4375,30 @@ const findFocusDelegateTarget = (el) => {
|
|
|
4375
4375
|
return null;
|
|
4376
4376
|
};
|
|
4377
4377
|
|
|
4378
|
-
const findFocusable = (element) => {
|
|
4378
|
+
const findFocusable = (element, { exclude } = {}) => {
|
|
4379
4379
|
const associatedElements = getAssociatedElements(element);
|
|
4380
4380
|
if (associatedElements) {
|
|
4381
4381
|
for (const associatedElement of associatedElements) {
|
|
4382
|
-
const focusable = findFocusable(associatedElement);
|
|
4382
|
+
const focusable = findFocusable(associatedElement, { exclude });
|
|
4383
4383
|
if (focusable) {
|
|
4384
4384
|
return focusable;
|
|
4385
4385
|
}
|
|
4386
4386
|
}
|
|
4387
4387
|
return null;
|
|
4388
4388
|
}
|
|
4389
|
-
|
|
4389
|
+
const isFocusable = (node) => {
|
|
4390
|
+
if (!elementIsFocusable(node)) {
|
|
4391
|
+
return false;
|
|
4392
|
+
}
|
|
4393
|
+
if (exclude && exclude(node)) {
|
|
4394
|
+
return false;
|
|
4395
|
+
}
|
|
4396
|
+
return true;
|
|
4397
|
+
};
|
|
4398
|
+
if (isFocusable(element)) {
|
|
4390
4399
|
return element;
|
|
4391
4400
|
}
|
|
4392
|
-
const focusableDescendant = findDescendant(element,
|
|
4401
|
+
const focusableDescendant = findDescendant(element, isFocusable);
|
|
4393
4402
|
if (focusableDescendant) {
|
|
4394
4403
|
// If the first focusable is an unchecked radio/checkbox, prefer the checked
|
|
4395
4404
|
// sibling in the same group (mirrors native browser radio focus behavior
|
|
@@ -4496,10 +4505,15 @@ const DEFAULT_BEHAVIORS = [
|
|
|
4496
4505
|
keys: {
|
|
4497
4506
|
// Tab moves focus on any element
|
|
4498
4507
|
tab: "focus_nav",
|
|
4499
|
-
|
|
4508
|
+
},
|
|
4509
|
+
// no fallback: only claims Tab, other keys continue to next entries
|
|
4510
|
+
},
|
|
4511
|
+
{
|
|
4512
|
+
// Escape natively dismisses only <dialog> elements
|
|
4513
|
+
test: (el) => el.tagName === "DIALOG" || Boolean(el.closest("dialog")),
|
|
4514
|
+
keys: {
|
|
4500
4515
|
escape: "dismiss",
|
|
4501
4516
|
},
|
|
4502
|
-
// no fallback: only claims Tab/Escape, other keys continue to next entries
|
|
4503
4517
|
},
|
|
4504
4518
|
{
|
|
4505
4519
|
test: (el) => el.matches("input[type='radio'], input[type='checkbox']"),
|
|
@@ -4518,6 +4532,12 @@ const DEFAULT_BEHAVIORS = [
|
|
|
4518
4532
|
"input:not([type]), input[type='text'], input[type='search'], input[type='url'], input[type='email'], input[type='password'], input[type='tel']",
|
|
4519
4533
|
),
|
|
4520
4534
|
keys: {
|
|
4535
|
+
escape: (e) => {
|
|
4536
|
+
if (e.target.type === "search") {
|
|
4537
|
+
return e.target.value ? "clear" : "";
|
|
4538
|
+
}
|
|
4539
|
+
return "";
|
|
4540
|
+
},
|
|
4521
4541
|
enter: (e) => (e.target.form ? "form_submit" : ""),
|
|
4522
4542
|
arrowleft: "cursor_move",
|
|
4523
4543
|
arrowright: "cursor_move",
|