@y14e/tabs 2.0.0 → 2.0.2
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/README.md +4 -4
- package/dist/index.cjs +106 -152
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +106 -152
- package/package.json +3 -4
package/README.md
CHANGED
|
@@ -10,14 +10,14 @@ npm i @y14e/tabs
|
|
|
10
10
|
|
|
11
11
|
```ts
|
|
12
12
|
// npm
|
|
13
|
-
import Tabs from '@y14e/tabs@2.0.
|
|
13
|
+
import Tabs from '@y14e/tabs@2.0.2';
|
|
14
14
|
|
|
15
15
|
// CDNs
|
|
16
|
-
import Tabs from 'https://esm.sh/@y14e/tabs@2.0.
|
|
16
|
+
import Tabs from 'https://esm.sh/@y14e/tabs@2.0.2';
|
|
17
17
|
// or
|
|
18
|
-
import Tabs from 'https://cdn.jsdelivr.net/npm/@y14e/tabs@2.0.
|
|
18
|
+
import Tabs from 'https://cdn.jsdelivr.net/npm/@y14e/tabs@2.0.2/+esm';
|
|
19
19
|
// or
|
|
20
|
-
import Tabs from 'https://esm.unpkg.com/@y14e/tabs@2.0.
|
|
20
|
+
import Tabs from 'https://esm.unpkg.com/@y14e/tabs@2.0.2';
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
## Usage
|
package/dist/index.cjs
CHANGED
|
@@ -1,55 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
// node_modules/@y14e/
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
caseInsensitive = false,
|
|
9
|
-
parse = DEFAULT_PARSER,
|
|
10
|
-
serialize = DEFAULT_SERIALIZER
|
|
11
|
-
} = options;
|
|
12
|
-
const value = element.getAttribute(attribute)?.trim();
|
|
13
|
-
const tokens = value ? parse(value).filter(Boolean) : [];
|
|
14
|
-
if (caseInsensitive) {
|
|
15
|
-
const lower = token.toLowerCase();
|
|
16
|
-
if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
|
|
17
|
-
tokens.push(token);
|
|
18
|
-
element.setAttribute(attribute, serialize(tokens));
|
|
19
|
-
}
|
|
20
|
-
} else {
|
|
21
|
-
const set = new Set(tokens);
|
|
22
|
-
set.add(token);
|
|
23
|
-
element.setAttribute(attribute, serialize([...set]));
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
var snapshots = /* @__PURE__ */ new WeakMap();
|
|
27
|
-
function restoreAttributes(elements) {
|
|
28
|
-
for (const element of elements) {
|
|
29
|
-
const snapshot = snapshots.get(element);
|
|
30
|
-
if (!snapshot) {
|
|
31
|
-
continue;
|
|
32
|
-
}
|
|
33
|
-
for (const [attribute, value] of snapshot.entries()) {
|
|
34
|
-
value === null ? element.removeAttribute(attribute) : element.setAttribute(attribute, value);
|
|
35
|
-
}
|
|
36
|
-
snapshots.delete(element);
|
|
3
|
+
// node_modules/@y14e/button/dist/index.js
|
|
4
|
+
function getActiveElement() {
|
|
5
|
+
let current = document.activeElement;
|
|
6
|
+
while (current?.shadowRoot?.activeElement) {
|
|
7
|
+
current = current.shadowRoot.activeElement;
|
|
37
8
|
}
|
|
9
|
+
return current;
|
|
38
10
|
}
|
|
39
|
-
function saveAttributes(elements, attributes) {
|
|
40
|
-
elements.forEach((element) => {
|
|
41
|
-
let snapshot = snapshots.get(element);
|
|
42
|
-
if (!snapshot) {
|
|
43
|
-
snapshot = /* @__PURE__ */ new Map();
|
|
44
|
-
snapshots.set(element, snapshot);
|
|
45
|
-
}
|
|
46
|
-
attributes.forEach((attribute) => {
|
|
47
|
-
snapshot.set(attribute, element.getAttribute(attribute));
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// node_modules/@y14e/button/dist/index.js
|
|
53
11
|
var Button = class {
|
|
54
12
|
#element;
|
|
55
13
|
#controller = null;
|
|
@@ -97,22 +55,15 @@ var Button = class {
|
|
|
97
55
|
active.click();
|
|
98
56
|
};
|
|
99
57
|
};
|
|
100
|
-
function getActiveElement() {
|
|
101
|
-
let current = document.activeElement;
|
|
102
|
-
while (current?.shadowRoot?.activeElement) {
|
|
103
|
-
current = current.shadowRoot.activeElement;
|
|
104
|
-
}
|
|
105
|
-
return current;
|
|
106
|
-
}
|
|
107
58
|
|
|
108
59
|
// node_modules/@y14e/roving-tabindex/dist/index.js
|
|
109
|
-
var
|
|
110
|
-
var
|
|
111
|
-
function
|
|
60
|
+
var DEFAULT_PARSER = (value) => value.split(/\s+/);
|
|
61
|
+
var DEFAULT_SERIALIZER = (tokens) => tokens.join(" ");
|
|
62
|
+
function addTokenToAttribute(element, attribute, token, options = {}) {
|
|
112
63
|
const {
|
|
113
64
|
caseInsensitive = false,
|
|
114
|
-
parse =
|
|
115
|
-
serialize =
|
|
65
|
+
parse = DEFAULT_PARSER,
|
|
66
|
+
serialize = DEFAULT_SERIALIZER
|
|
116
67
|
} = options;
|
|
117
68
|
const value = element.getAttribute(attribute)?.trim();
|
|
118
69
|
const tokens = value ? parse(value).filter(Boolean) : [];
|
|
@@ -128,25 +79,25 @@ function addTokenToAttribute2(element, attribute, token, options = {}) {
|
|
|
128
79
|
element.setAttribute(attribute, serialize([...set]));
|
|
129
80
|
}
|
|
130
81
|
}
|
|
131
|
-
var
|
|
132
|
-
function
|
|
82
|
+
var snapshots = /* @__PURE__ */ new WeakMap();
|
|
83
|
+
function restoreAttributes(elements) {
|
|
133
84
|
for (const element of elements) {
|
|
134
|
-
const snapshot =
|
|
85
|
+
const snapshot = snapshots.get(element);
|
|
135
86
|
if (!snapshot) {
|
|
136
87
|
continue;
|
|
137
88
|
}
|
|
138
89
|
for (const [attribute, value] of snapshot.entries()) {
|
|
139
90
|
value === null ? element.removeAttribute(attribute) : element.setAttribute(attribute, value);
|
|
140
91
|
}
|
|
141
|
-
|
|
92
|
+
snapshots.delete(element);
|
|
142
93
|
}
|
|
143
94
|
}
|
|
144
|
-
function
|
|
95
|
+
function saveAttributes(elements, attributes) {
|
|
145
96
|
elements.forEach((element) => {
|
|
146
|
-
let snapshot =
|
|
97
|
+
let snapshot = snapshots.get(element);
|
|
147
98
|
if (!snapshot) {
|
|
148
99
|
snapshot = /* @__PURE__ */ new Map();
|
|
149
|
-
|
|
100
|
+
snapshots.set(element, snapshot);
|
|
150
101
|
}
|
|
151
102
|
attributes.forEach((attribute) => {
|
|
152
103
|
snapshot.set(attribute, element.getAttribute(attribute));
|
|
@@ -356,6 +307,16 @@ function getComposedChildren(node) {
|
|
|
356
307
|
}
|
|
357
308
|
return getChildren(node);
|
|
358
309
|
}
|
|
310
|
+
function focusElement(element) {
|
|
311
|
+
"focus" in element && typeof element.focus === "function" && element.focus();
|
|
312
|
+
}
|
|
313
|
+
function getActiveElement2() {
|
|
314
|
+
let current = document.activeElement;
|
|
315
|
+
while (current?.shadowRoot?.activeElement) {
|
|
316
|
+
current = current.shadowRoot.activeElement;
|
|
317
|
+
}
|
|
318
|
+
return current;
|
|
319
|
+
}
|
|
359
320
|
function getChildren(node) {
|
|
360
321
|
const elements = [];
|
|
361
322
|
for (let child = node.firstElementChild; child; child = child.nextElementSibling) {
|
|
@@ -385,60 +346,12 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
385
346
|
return () => {
|
|
386
347
|
};
|
|
387
348
|
}
|
|
388
|
-
|
|
389
|
-
direction,
|
|
390
|
-
navigationOnly = false,
|
|
391
|
-
noMemory = false,
|
|
392
|
-
noStart = false,
|
|
393
|
-
selector,
|
|
394
|
-
typeahead = false,
|
|
395
|
-
wrap = false
|
|
396
|
-
} = options;
|
|
397
|
-
if (typeof direction !== "undefined" && !["horizontal", "vertical"].includes(direction)) {
|
|
398
|
-
console.warn("Invalid direction option. Fallback: both (undefined).");
|
|
399
|
-
direction = void 0;
|
|
400
|
-
}
|
|
401
|
-
if (typeof navigationOnly !== "boolean") {
|
|
402
|
-
console.warn("Invalid navigationOnly option. Fallback: false.");
|
|
403
|
-
navigationOnly = false;
|
|
404
|
-
}
|
|
405
|
-
if (typeof noMemory !== "boolean") {
|
|
406
|
-
console.warn("Invalid noMemory option. Fallback: false.");
|
|
407
|
-
noMemory = false;
|
|
408
|
-
}
|
|
409
|
-
if (typeof noStart !== "boolean") {
|
|
410
|
-
console.warn("Invalid noStart option. Fallback: false.");
|
|
411
|
-
noStart = false;
|
|
412
|
-
}
|
|
413
|
-
if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
|
|
414
|
-
console.warn(
|
|
415
|
-
"Invalid selector. Fallback: all focusable elements (undefined)."
|
|
416
|
-
);
|
|
417
|
-
selector = void 0;
|
|
418
|
-
}
|
|
419
|
-
if (typeof typeahead !== "boolean") {
|
|
420
|
-
console.warn("Invalid typeahead option. Fallback: false.");
|
|
421
|
-
typeahead = false;
|
|
422
|
-
}
|
|
423
|
-
if (typeof wrap !== "boolean") {
|
|
424
|
-
console.warn("Invalid wrap option. Fallback: false.");
|
|
425
|
-
wrap = false;
|
|
426
|
-
}
|
|
427
|
-
const settings = {
|
|
428
|
-
navigationOnly,
|
|
429
|
-
noMemory,
|
|
430
|
-
noStart,
|
|
431
|
-
typeahead,
|
|
432
|
-
wrap
|
|
433
|
-
};
|
|
434
|
-
direction && Object.assign(settings, { direction });
|
|
435
|
-
selector && Object.assign(settings, { selector });
|
|
436
|
-
const roving = new RovingTabIndex(container, settings);
|
|
349
|
+
const roving = new RovingTabIndex(container, options);
|
|
437
350
|
return () => roving.destroy();
|
|
438
351
|
}
|
|
439
352
|
var RovingTabIndex = class {
|
|
440
353
|
#container;
|
|
441
|
-
#
|
|
354
|
+
#settings;
|
|
442
355
|
#focusables = /* @__PURE__ */ new Set();
|
|
443
356
|
#focusablesByFirstChar = /* @__PURE__ */ new Map();
|
|
444
357
|
#selectorFilter;
|
|
@@ -446,7 +359,54 @@ var RovingTabIndex = class {
|
|
|
446
359
|
#isDestroyed = false;
|
|
447
360
|
constructor(container, options = {}) {
|
|
448
361
|
this.#container = container;
|
|
449
|
-
|
|
362
|
+
let {
|
|
363
|
+
direction,
|
|
364
|
+
navigationOnly = false,
|
|
365
|
+
noMemory = false,
|
|
366
|
+
noStart = false,
|
|
367
|
+
selector,
|
|
368
|
+
typeahead = false,
|
|
369
|
+
wrap = false
|
|
370
|
+
} = options;
|
|
371
|
+
if (typeof direction !== "undefined" && !["horizontal", "vertical"].includes(direction)) {
|
|
372
|
+
console.warn("Invalid direction option. Fallback: both (undefined).");
|
|
373
|
+
direction = void 0;
|
|
374
|
+
}
|
|
375
|
+
if (typeof navigationOnly !== "boolean") {
|
|
376
|
+
console.warn("Invalid navigationOnly option. Fallback: false.");
|
|
377
|
+
navigationOnly = false;
|
|
378
|
+
}
|
|
379
|
+
if (typeof noMemory !== "boolean") {
|
|
380
|
+
console.warn("Invalid noMemory option. Fallback: false.");
|
|
381
|
+
noMemory = false;
|
|
382
|
+
}
|
|
383
|
+
if (typeof noStart !== "boolean") {
|
|
384
|
+
console.warn("Invalid noStart option. Fallback: false.");
|
|
385
|
+
noStart = false;
|
|
386
|
+
}
|
|
387
|
+
if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
|
|
388
|
+
console.warn(
|
|
389
|
+
"Invalid selector. Fallback: all focusable elements (undefined)."
|
|
390
|
+
);
|
|
391
|
+
selector = void 0;
|
|
392
|
+
}
|
|
393
|
+
if (typeof typeahead !== "boolean") {
|
|
394
|
+
console.warn("Invalid typeahead option. Fallback: false.");
|
|
395
|
+
typeahead = false;
|
|
396
|
+
}
|
|
397
|
+
if (typeof wrap !== "boolean") {
|
|
398
|
+
console.warn("Invalid wrap option. Fallback: false.");
|
|
399
|
+
wrap = false;
|
|
400
|
+
}
|
|
401
|
+
this.#settings = {
|
|
402
|
+
navigationOnly,
|
|
403
|
+
noMemory,
|
|
404
|
+
noStart,
|
|
405
|
+
typeahead,
|
|
406
|
+
wrap
|
|
407
|
+
};
|
|
408
|
+
direction && Object.assign(this.#settings, { direction });
|
|
409
|
+
selector && Object.assign(this.#settings, { selector });
|
|
450
410
|
this.#selectorFilter = this.#createSelectorFilter();
|
|
451
411
|
this.#initialize();
|
|
452
412
|
}
|
|
@@ -457,7 +417,7 @@ var RovingTabIndex = class {
|
|
|
457
417
|
this.#isDestroyed = true;
|
|
458
418
|
this.#controller?.abort();
|
|
459
419
|
this.#controller = null;
|
|
460
|
-
|
|
420
|
+
restoreAttributes([...this.#focusables]);
|
|
461
421
|
this.#focusables.clear();
|
|
462
422
|
this.#focusablesByFirstChar.clear();
|
|
463
423
|
this.#container.removeAttribute("data-roving-tabindex-initialized");
|
|
@@ -482,7 +442,7 @@ var RovingTabIndex = class {
|
|
|
482
442
|
return;
|
|
483
443
|
}
|
|
484
444
|
const isFocusable22 = this.#focusables.has(target);
|
|
485
|
-
this.#
|
|
445
|
+
this.#settings.noMemory && !isFocusable22 ? this.#update(null) : isFocusable22 && this.#update(target);
|
|
486
446
|
};
|
|
487
447
|
#onKeyDown = (event) => {
|
|
488
448
|
if (!event.composedPath().includes(this.#container)) {
|
|
@@ -492,7 +452,7 @@ var RovingTabIndex = class {
|
|
|
492
452
|
if (altKey || ctrlKey || metaKey || shiftKey) {
|
|
493
453
|
return;
|
|
494
454
|
}
|
|
495
|
-
const { direction, typeahead, wrap } = this.#
|
|
455
|
+
const { direction, typeahead, wrap } = this.#settings;
|
|
496
456
|
const isBoth = !direction;
|
|
497
457
|
const isHorizontal = direction === "horizontal";
|
|
498
458
|
if (![
|
|
@@ -551,7 +511,7 @@ var RovingTabIndex = class {
|
|
|
551
511
|
const current = new Set(this.#getFocusables());
|
|
552
512
|
for (const focusable of this.#focusables) {
|
|
553
513
|
if (!current.has(focusable)) {
|
|
554
|
-
focusable.isConnected &&
|
|
514
|
+
focusable.isConnected && restoreAttributes([focusable]);
|
|
555
515
|
this.#focusables.delete(focusable);
|
|
556
516
|
this.#focusablesByFirstChar.forEach((focusables) => {
|
|
557
517
|
const index = focusables.indexOf(focusable);
|
|
@@ -559,14 +519,14 @@ var RovingTabIndex = class {
|
|
|
559
519
|
});
|
|
560
520
|
}
|
|
561
521
|
}
|
|
562
|
-
const { navigationOnly, noStart, typeahead } = this.#
|
|
522
|
+
const { navigationOnly, noStart, typeahead } = this.#settings;
|
|
563
523
|
for (const focusable of current) {
|
|
564
524
|
if (this.#focusables.has(focusable)) {
|
|
565
525
|
continue;
|
|
566
526
|
}
|
|
567
527
|
this.#focusables.add(focusable);
|
|
568
528
|
if (!navigationOnly) {
|
|
569
|
-
|
|
529
|
+
saveAttributes([focusable], ["tabindex"]);
|
|
570
530
|
focusable.setAttribute("tabindex", "-1");
|
|
571
531
|
}
|
|
572
532
|
if (!typeahead) {
|
|
@@ -579,8 +539,8 @@ var RovingTabIndex = class {
|
|
|
579
539
|
);
|
|
580
540
|
if (char) {
|
|
581
541
|
keys.add(char);
|
|
582
|
-
|
|
583
|
-
|
|
542
|
+
saveAttributes([focusable], ["aria-keyshortcuts"]);
|
|
543
|
+
addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
|
|
584
544
|
caseInsensitive: true
|
|
585
545
|
});
|
|
586
546
|
}
|
|
@@ -603,28 +563,18 @@ var RovingTabIndex = class {
|
|
|
603
563
|
}
|
|
604
564
|
}
|
|
605
565
|
#createSelectorFilter() {
|
|
606
|
-
const { selector } = this.#
|
|
566
|
+
const { selector } = this.#settings;
|
|
607
567
|
return (element) => !selector || [...this.#container.querySelectorAll(selector)].includes(element);
|
|
608
568
|
}
|
|
609
569
|
#getFocusables() {
|
|
610
570
|
return getFocusables(this.#container, {
|
|
611
571
|
composed: true,
|
|
612
572
|
filter: this.#selectorFilter,
|
|
613
|
-
skipNegativeTabIndexCheck: !this.#
|
|
573
|
+
skipNegativeTabIndexCheck: !this.#settings.navigationOnly,
|
|
614
574
|
skipVisibilityCheck: true
|
|
615
575
|
});
|
|
616
576
|
}
|
|
617
577
|
};
|
|
618
|
-
function focusElement(element) {
|
|
619
|
-
"focus" in element && typeof element.focus === "function" && element.focus();
|
|
620
|
-
}
|
|
621
|
-
function getActiveElement2() {
|
|
622
|
-
let current = document.activeElement;
|
|
623
|
-
while (current?.shadowRoot?.activeElement) {
|
|
624
|
-
current = current.shadowRoot.activeElement;
|
|
625
|
-
}
|
|
626
|
-
return current;
|
|
627
|
-
}
|
|
628
578
|
|
|
629
579
|
// src/index.ts
|
|
630
580
|
var Tabs = class _Tabs {
|
|
@@ -1145,7 +1095,7 @@ function isFocusable2(element) {
|
|
|
1145
1095
|
* Tabs
|
|
1146
1096
|
* WAI-ARIA compliant tabs pattern implementation in TypeScript.
|
|
1147
1097
|
*
|
|
1148
|
-
* @version 2.0.
|
|
1098
|
+
* @version 2.0.2
|
|
1149
1099
|
* @author Yusuke Kamiyamane
|
|
1150
1100
|
* @license MIT
|
|
1151
1101
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -1153,27 +1103,31 @@ function isFocusable2(element) {
|
|
|
1153
1103
|
*/
|
|
1154
1104
|
/*! Bundled license information:
|
|
1155
1105
|
|
|
1156
|
-
@y14e/attributes-utils/dist/index.js:
|
|
1157
|
-
(**
|
|
1158
|
-
* Attributes Utils
|
|
1159
|
-
*
|
|
1160
|
-
* @version 1.1.2
|
|
1161
|
-
* @author Yusuke Kamiyamane
|
|
1162
|
-
* @license MIT
|
|
1163
|
-
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
1164
|
-
* @see {@link https://github.com/y14e/attributes-utils}
|
|
1165
|
-
*)
|
|
1166
|
-
|
|
1167
1106
|
@y14e/button/dist/index.js:
|
|
1168
1107
|
(**
|
|
1169
1108
|
* Button
|
|
1170
1109
|
*
|
|
1171
|
-
* @version 1.0.
|
|
1110
|
+
* @version 1.0.3
|
|
1172
1111
|
* @author Yusuke Kamiyamane
|
|
1173
1112
|
* @license MIT
|
|
1174
1113
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
1175
1114
|
* @see {@link https://github.com/y14e/button}
|
|
1176
1115
|
*)
|
|
1116
|
+
(*! Bundled license information:
|
|
1117
|
+
|
|
1118
|
+
power-focusable/dist/index.js:
|
|
1119
|
+
(**
|
|
1120
|
+
* Power Focusable
|
|
1121
|
+
* High-precision focus management utility with full composed tree support.
|
|
1122
|
+
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
1123
|
+
*
|
|
1124
|
+
* @version 4.3.3
|
|
1125
|
+
* @author Yusuke Kamiyamane
|
|
1126
|
+
* @license MIT
|
|
1127
|
+
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
1128
|
+
* @see {@link https://github.com/y14e/power-focusable}
|
|
1129
|
+
*)
|
|
1130
|
+
*)
|
|
1177
1131
|
|
|
1178
1132
|
@y14e/roving-tabindex/dist/index.js:
|
|
1179
1133
|
(**
|
|
@@ -1181,7 +1135,7 @@ function isFocusable2(element) {
|
|
|
1181
1135
|
* Lightweight roving tabindex utility with fully focus management.
|
|
1182
1136
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
1183
1137
|
*
|
|
1184
|
-
* @version 3.0.
|
|
1138
|
+
* @version 3.0.8
|
|
1185
1139
|
* @author Yusuke Kamiyamane
|
|
1186
1140
|
* @license MIT
|
|
1187
1141
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,53 +1,11 @@
|
|
|
1
|
-
// node_modules/@y14e/
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
caseInsensitive = false,
|
|
7
|
-
parse = DEFAULT_PARSER,
|
|
8
|
-
serialize = DEFAULT_SERIALIZER
|
|
9
|
-
} = options;
|
|
10
|
-
const value = element.getAttribute(attribute)?.trim();
|
|
11
|
-
const tokens = value ? parse(value).filter(Boolean) : [];
|
|
12
|
-
if (caseInsensitive) {
|
|
13
|
-
const lower = token.toLowerCase();
|
|
14
|
-
if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
|
|
15
|
-
tokens.push(token);
|
|
16
|
-
element.setAttribute(attribute, serialize(tokens));
|
|
17
|
-
}
|
|
18
|
-
} else {
|
|
19
|
-
const set = new Set(tokens);
|
|
20
|
-
set.add(token);
|
|
21
|
-
element.setAttribute(attribute, serialize([...set]));
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
var snapshots = /* @__PURE__ */ new WeakMap();
|
|
25
|
-
function restoreAttributes(elements) {
|
|
26
|
-
for (const element of elements) {
|
|
27
|
-
const snapshot = snapshots.get(element);
|
|
28
|
-
if (!snapshot) {
|
|
29
|
-
continue;
|
|
30
|
-
}
|
|
31
|
-
for (const [attribute, value] of snapshot.entries()) {
|
|
32
|
-
value === null ? element.removeAttribute(attribute) : element.setAttribute(attribute, value);
|
|
33
|
-
}
|
|
34
|
-
snapshots.delete(element);
|
|
1
|
+
// node_modules/@y14e/button/dist/index.js
|
|
2
|
+
function getActiveElement() {
|
|
3
|
+
let current = document.activeElement;
|
|
4
|
+
while (current?.shadowRoot?.activeElement) {
|
|
5
|
+
current = current.shadowRoot.activeElement;
|
|
35
6
|
}
|
|
7
|
+
return current;
|
|
36
8
|
}
|
|
37
|
-
function saveAttributes(elements, attributes) {
|
|
38
|
-
elements.forEach((element) => {
|
|
39
|
-
let snapshot = snapshots.get(element);
|
|
40
|
-
if (!snapshot) {
|
|
41
|
-
snapshot = /* @__PURE__ */ new Map();
|
|
42
|
-
snapshots.set(element, snapshot);
|
|
43
|
-
}
|
|
44
|
-
attributes.forEach((attribute) => {
|
|
45
|
-
snapshot.set(attribute, element.getAttribute(attribute));
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// node_modules/@y14e/button/dist/index.js
|
|
51
9
|
var Button = class {
|
|
52
10
|
#element;
|
|
53
11
|
#controller = null;
|
|
@@ -95,22 +53,15 @@ var Button = class {
|
|
|
95
53
|
active.click();
|
|
96
54
|
};
|
|
97
55
|
};
|
|
98
|
-
function getActiveElement() {
|
|
99
|
-
let current = document.activeElement;
|
|
100
|
-
while (current?.shadowRoot?.activeElement) {
|
|
101
|
-
current = current.shadowRoot.activeElement;
|
|
102
|
-
}
|
|
103
|
-
return current;
|
|
104
|
-
}
|
|
105
56
|
|
|
106
57
|
// node_modules/@y14e/roving-tabindex/dist/index.js
|
|
107
|
-
var
|
|
108
|
-
var
|
|
109
|
-
function
|
|
58
|
+
var DEFAULT_PARSER = (value) => value.split(/\s+/);
|
|
59
|
+
var DEFAULT_SERIALIZER = (tokens) => tokens.join(" ");
|
|
60
|
+
function addTokenToAttribute(element, attribute, token, options = {}) {
|
|
110
61
|
const {
|
|
111
62
|
caseInsensitive = false,
|
|
112
|
-
parse =
|
|
113
|
-
serialize =
|
|
63
|
+
parse = DEFAULT_PARSER,
|
|
64
|
+
serialize = DEFAULT_SERIALIZER
|
|
114
65
|
} = options;
|
|
115
66
|
const value = element.getAttribute(attribute)?.trim();
|
|
116
67
|
const tokens = value ? parse(value).filter(Boolean) : [];
|
|
@@ -126,25 +77,25 @@ function addTokenToAttribute2(element, attribute, token, options = {}) {
|
|
|
126
77
|
element.setAttribute(attribute, serialize([...set]));
|
|
127
78
|
}
|
|
128
79
|
}
|
|
129
|
-
var
|
|
130
|
-
function
|
|
80
|
+
var snapshots = /* @__PURE__ */ new WeakMap();
|
|
81
|
+
function restoreAttributes(elements) {
|
|
131
82
|
for (const element of elements) {
|
|
132
|
-
const snapshot =
|
|
83
|
+
const snapshot = snapshots.get(element);
|
|
133
84
|
if (!snapshot) {
|
|
134
85
|
continue;
|
|
135
86
|
}
|
|
136
87
|
for (const [attribute, value] of snapshot.entries()) {
|
|
137
88
|
value === null ? element.removeAttribute(attribute) : element.setAttribute(attribute, value);
|
|
138
89
|
}
|
|
139
|
-
|
|
90
|
+
snapshots.delete(element);
|
|
140
91
|
}
|
|
141
92
|
}
|
|
142
|
-
function
|
|
93
|
+
function saveAttributes(elements, attributes) {
|
|
143
94
|
elements.forEach((element) => {
|
|
144
|
-
let snapshot =
|
|
95
|
+
let snapshot = snapshots.get(element);
|
|
145
96
|
if (!snapshot) {
|
|
146
97
|
snapshot = /* @__PURE__ */ new Map();
|
|
147
|
-
|
|
98
|
+
snapshots.set(element, snapshot);
|
|
148
99
|
}
|
|
149
100
|
attributes.forEach((attribute) => {
|
|
150
101
|
snapshot.set(attribute, element.getAttribute(attribute));
|
|
@@ -354,6 +305,16 @@ function getComposedChildren(node) {
|
|
|
354
305
|
}
|
|
355
306
|
return getChildren(node);
|
|
356
307
|
}
|
|
308
|
+
function focusElement(element) {
|
|
309
|
+
"focus" in element && typeof element.focus === "function" && element.focus();
|
|
310
|
+
}
|
|
311
|
+
function getActiveElement2() {
|
|
312
|
+
let current = document.activeElement;
|
|
313
|
+
while (current?.shadowRoot?.activeElement) {
|
|
314
|
+
current = current.shadowRoot.activeElement;
|
|
315
|
+
}
|
|
316
|
+
return current;
|
|
317
|
+
}
|
|
357
318
|
function getChildren(node) {
|
|
358
319
|
const elements = [];
|
|
359
320
|
for (let child = node.firstElementChild; child; child = child.nextElementSibling) {
|
|
@@ -383,60 +344,12 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
383
344
|
return () => {
|
|
384
345
|
};
|
|
385
346
|
}
|
|
386
|
-
|
|
387
|
-
direction,
|
|
388
|
-
navigationOnly = false,
|
|
389
|
-
noMemory = false,
|
|
390
|
-
noStart = false,
|
|
391
|
-
selector,
|
|
392
|
-
typeahead = false,
|
|
393
|
-
wrap = false
|
|
394
|
-
} = options;
|
|
395
|
-
if (typeof direction !== "undefined" && !["horizontal", "vertical"].includes(direction)) {
|
|
396
|
-
console.warn("Invalid direction option. Fallback: both (undefined).");
|
|
397
|
-
direction = void 0;
|
|
398
|
-
}
|
|
399
|
-
if (typeof navigationOnly !== "boolean") {
|
|
400
|
-
console.warn("Invalid navigationOnly option. Fallback: false.");
|
|
401
|
-
navigationOnly = false;
|
|
402
|
-
}
|
|
403
|
-
if (typeof noMemory !== "boolean") {
|
|
404
|
-
console.warn("Invalid noMemory option. Fallback: false.");
|
|
405
|
-
noMemory = false;
|
|
406
|
-
}
|
|
407
|
-
if (typeof noStart !== "boolean") {
|
|
408
|
-
console.warn("Invalid noStart option. Fallback: false.");
|
|
409
|
-
noStart = false;
|
|
410
|
-
}
|
|
411
|
-
if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
|
|
412
|
-
console.warn(
|
|
413
|
-
"Invalid selector. Fallback: all focusable elements (undefined)."
|
|
414
|
-
);
|
|
415
|
-
selector = void 0;
|
|
416
|
-
}
|
|
417
|
-
if (typeof typeahead !== "boolean") {
|
|
418
|
-
console.warn("Invalid typeahead option. Fallback: false.");
|
|
419
|
-
typeahead = false;
|
|
420
|
-
}
|
|
421
|
-
if (typeof wrap !== "boolean") {
|
|
422
|
-
console.warn("Invalid wrap option. Fallback: false.");
|
|
423
|
-
wrap = false;
|
|
424
|
-
}
|
|
425
|
-
const settings = {
|
|
426
|
-
navigationOnly,
|
|
427
|
-
noMemory,
|
|
428
|
-
noStart,
|
|
429
|
-
typeahead,
|
|
430
|
-
wrap
|
|
431
|
-
};
|
|
432
|
-
direction && Object.assign(settings, { direction });
|
|
433
|
-
selector && Object.assign(settings, { selector });
|
|
434
|
-
const roving = new RovingTabIndex(container, settings);
|
|
347
|
+
const roving = new RovingTabIndex(container, options);
|
|
435
348
|
return () => roving.destroy();
|
|
436
349
|
}
|
|
437
350
|
var RovingTabIndex = class {
|
|
438
351
|
#container;
|
|
439
|
-
#
|
|
352
|
+
#settings;
|
|
440
353
|
#focusables = /* @__PURE__ */ new Set();
|
|
441
354
|
#focusablesByFirstChar = /* @__PURE__ */ new Map();
|
|
442
355
|
#selectorFilter;
|
|
@@ -444,7 +357,54 @@ var RovingTabIndex = class {
|
|
|
444
357
|
#isDestroyed = false;
|
|
445
358
|
constructor(container, options = {}) {
|
|
446
359
|
this.#container = container;
|
|
447
|
-
|
|
360
|
+
let {
|
|
361
|
+
direction,
|
|
362
|
+
navigationOnly = false,
|
|
363
|
+
noMemory = false,
|
|
364
|
+
noStart = false,
|
|
365
|
+
selector,
|
|
366
|
+
typeahead = false,
|
|
367
|
+
wrap = false
|
|
368
|
+
} = options;
|
|
369
|
+
if (typeof direction !== "undefined" && !["horizontal", "vertical"].includes(direction)) {
|
|
370
|
+
console.warn("Invalid direction option. Fallback: both (undefined).");
|
|
371
|
+
direction = void 0;
|
|
372
|
+
}
|
|
373
|
+
if (typeof navigationOnly !== "boolean") {
|
|
374
|
+
console.warn("Invalid navigationOnly option. Fallback: false.");
|
|
375
|
+
navigationOnly = false;
|
|
376
|
+
}
|
|
377
|
+
if (typeof noMemory !== "boolean") {
|
|
378
|
+
console.warn("Invalid noMemory option. Fallback: false.");
|
|
379
|
+
noMemory = false;
|
|
380
|
+
}
|
|
381
|
+
if (typeof noStart !== "boolean") {
|
|
382
|
+
console.warn("Invalid noStart option. Fallback: false.");
|
|
383
|
+
noStart = false;
|
|
384
|
+
}
|
|
385
|
+
if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
|
|
386
|
+
console.warn(
|
|
387
|
+
"Invalid selector. Fallback: all focusable elements (undefined)."
|
|
388
|
+
);
|
|
389
|
+
selector = void 0;
|
|
390
|
+
}
|
|
391
|
+
if (typeof typeahead !== "boolean") {
|
|
392
|
+
console.warn("Invalid typeahead option. Fallback: false.");
|
|
393
|
+
typeahead = false;
|
|
394
|
+
}
|
|
395
|
+
if (typeof wrap !== "boolean") {
|
|
396
|
+
console.warn("Invalid wrap option. Fallback: false.");
|
|
397
|
+
wrap = false;
|
|
398
|
+
}
|
|
399
|
+
this.#settings = {
|
|
400
|
+
navigationOnly,
|
|
401
|
+
noMemory,
|
|
402
|
+
noStart,
|
|
403
|
+
typeahead,
|
|
404
|
+
wrap
|
|
405
|
+
};
|
|
406
|
+
direction && Object.assign(this.#settings, { direction });
|
|
407
|
+
selector && Object.assign(this.#settings, { selector });
|
|
448
408
|
this.#selectorFilter = this.#createSelectorFilter();
|
|
449
409
|
this.#initialize();
|
|
450
410
|
}
|
|
@@ -455,7 +415,7 @@ var RovingTabIndex = class {
|
|
|
455
415
|
this.#isDestroyed = true;
|
|
456
416
|
this.#controller?.abort();
|
|
457
417
|
this.#controller = null;
|
|
458
|
-
|
|
418
|
+
restoreAttributes([...this.#focusables]);
|
|
459
419
|
this.#focusables.clear();
|
|
460
420
|
this.#focusablesByFirstChar.clear();
|
|
461
421
|
this.#container.removeAttribute("data-roving-tabindex-initialized");
|
|
@@ -480,7 +440,7 @@ var RovingTabIndex = class {
|
|
|
480
440
|
return;
|
|
481
441
|
}
|
|
482
442
|
const isFocusable22 = this.#focusables.has(target);
|
|
483
|
-
this.#
|
|
443
|
+
this.#settings.noMemory && !isFocusable22 ? this.#update(null) : isFocusable22 && this.#update(target);
|
|
484
444
|
};
|
|
485
445
|
#onKeyDown = (event) => {
|
|
486
446
|
if (!event.composedPath().includes(this.#container)) {
|
|
@@ -490,7 +450,7 @@ var RovingTabIndex = class {
|
|
|
490
450
|
if (altKey || ctrlKey || metaKey || shiftKey) {
|
|
491
451
|
return;
|
|
492
452
|
}
|
|
493
|
-
const { direction, typeahead, wrap } = this.#
|
|
453
|
+
const { direction, typeahead, wrap } = this.#settings;
|
|
494
454
|
const isBoth = !direction;
|
|
495
455
|
const isHorizontal = direction === "horizontal";
|
|
496
456
|
if (![
|
|
@@ -549,7 +509,7 @@ var RovingTabIndex = class {
|
|
|
549
509
|
const current = new Set(this.#getFocusables());
|
|
550
510
|
for (const focusable of this.#focusables) {
|
|
551
511
|
if (!current.has(focusable)) {
|
|
552
|
-
focusable.isConnected &&
|
|
512
|
+
focusable.isConnected && restoreAttributes([focusable]);
|
|
553
513
|
this.#focusables.delete(focusable);
|
|
554
514
|
this.#focusablesByFirstChar.forEach((focusables) => {
|
|
555
515
|
const index = focusables.indexOf(focusable);
|
|
@@ -557,14 +517,14 @@ var RovingTabIndex = class {
|
|
|
557
517
|
});
|
|
558
518
|
}
|
|
559
519
|
}
|
|
560
|
-
const { navigationOnly, noStart, typeahead } = this.#
|
|
520
|
+
const { navigationOnly, noStart, typeahead } = this.#settings;
|
|
561
521
|
for (const focusable of current) {
|
|
562
522
|
if (this.#focusables.has(focusable)) {
|
|
563
523
|
continue;
|
|
564
524
|
}
|
|
565
525
|
this.#focusables.add(focusable);
|
|
566
526
|
if (!navigationOnly) {
|
|
567
|
-
|
|
527
|
+
saveAttributes([focusable], ["tabindex"]);
|
|
568
528
|
focusable.setAttribute("tabindex", "-1");
|
|
569
529
|
}
|
|
570
530
|
if (!typeahead) {
|
|
@@ -577,8 +537,8 @@ var RovingTabIndex = class {
|
|
|
577
537
|
);
|
|
578
538
|
if (char) {
|
|
579
539
|
keys.add(char);
|
|
580
|
-
|
|
581
|
-
|
|
540
|
+
saveAttributes([focusable], ["aria-keyshortcuts"]);
|
|
541
|
+
addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
|
|
582
542
|
caseInsensitive: true
|
|
583
543
|
});
|
|
584
544
|
}
|
|
@@ -601,28 +561,18 @@ var RovingTabIndex = class {
|
|
|
601
561
|
}
|
|
602
562
|
}
|
|
603
563
|
#createSelectorFilter() {
|
|
604
|
-
const { selector } = this.#
|
|
564
|
+
const { selector } = this.#settings;
|
|
605
565
|
return (element) => !selector || [...this.#container.querySelectorAll(selector)].includes(element);
|
|
606
566
|
}
|
|
607
567
|
#getFocusables() {
|
|
608
568
|
return getFocusables(this.#container, {
|
|
609
569
|
composed: true,
|
|
610
570
|
filter: this.#selectorFilter,
|
|
611
|
-
skipNegativeTabIndexCheck: !this.#
|
|
571
|
+
skipNegativeTabIndexCheck: !this.#settings.navigationOnly,
|
|
612
572
|
skipVisibilityCheck: true
|
|
613
573
|
});
|
|
614
574
|
}
|
|
615
575
|
};
|
|
616
|
-
function focusElement(element) {
|
|
617
|
-
"focus" in element && typeof element.focus === "function" && element.focus();
|
|
618
|
-
}
|
|
619
|
-
function getActiveElement2() {
|
|
620
|
-
let current = document.activeElement;
|
|
621
|
-
while (current?.shadowRoot?.activeElement) {
|
|
622
|
-
current = current.shadowRoot.activeElement;
|
|
623
|
-
}
|
|
624
|
-
return current;
|
|
625
|
-
}
|
|
626
576
|
|
|
627
577
|
// src/index.ts
|
|
628
578
|
var Tabs = class _Tabs {
|
|
@@ -1143,7 +1093,7 @@ function isFocusable2(element) {
|
|
|
1143
1093
|
* Tabs
|
|
1144
1094
|
* WAI-ARIA compliant tabs pattern implementation in TypeScript.
|
|
1145
1095
|
*
|
|
1146
|
-
* @version 2.0.
|
|
1096
|
+
* @version 2.0.2
|
|
1147
1097
|
* @author Yusuke Kamiyamane
|
|
1148
1098
|
* @license MIT
|
|
1149
1099
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -1151,27 +1101,31 @@ function isFocusable2(element) {
|
|
|
1151
1101
|
*/
|
|
1152
1102
|
/*! Bundled license information:
|
|
1153
1103
|
|
|
1154
|
-
@y14e/attributes-utils/dist/index.js:
|
|
1155
|
-
(**
|
|
1156
|
-
* Attributes Utils
|
|
1157
|
-
*
|
|
1158
|
-
* @version 1.1.2
|
|
1159
|
-
* @author Yusuke Kamiyamane
|
|
1160
|
-
* @license MIT
|
|
1161
|
-
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
1162
|
-
* @see {@link https://github.com/y14e/attributes-utils}
|
|
1163
|
-
*)
|
|
1164
|
-
|
|
1165
1104
|
@y14e/button/dist/index.js:
|
|
1166
1105
|
(**
|
|
1167
1106
|
* Button
|
|
1168
1107
|
*
|
|
1169
|
-
* @version 1.0.
|
|
1108
|
+
* @version 1.0.3
|
|
1170
1109
|
* @author Yusuke Kamiyamane
|
|
1171
1110
|
* @license MIT
|
|
1172
1111
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
1173
1112
|
* @see {@link https://github.com/y14e/button}
|
|
1174
1113
|
*)
|
|
1114
|
+
(*! Bundled license information:
|
|
1115
|
+
|
|
1116
|
+
power-focusable/dist/index.js:
|
|
1117
|
+
(**
|
|
1118
|
+
* Power Focusable
|
|
1119
|
+
* High-precision focus management utility with full composed tree support.
|
|
1120
|
+
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
1121
|
+
*
|
|
1122
|
+
* @version 4.3.3
|
|
1123
|
+
* @author Yusuke Kamiyamane
|
|
1124
|
+
* @license MIT
|
|
1125
|
+
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
1126
|
+
* @see {@link https://github.com/y14e/power-focusable}
|
|
1127
|
+
*)
|
|
1128
|
+
*)
|
|
1175
1129
|
|
|
1176
1130
|
@y14e/roving-tabindex/dist/index.js:
|
|
1177
1131
|
(**
|
|
@@ -1179,7 +1133,7 @@ function isFocusable2(element) {
|
|
|
1179
1133
|
* Lightweight roving tabindex utility with fully focus management.
|
|
1180
1134
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
1181
1135
|
*
|
|
1182
|
-
* @version 3.0.
|
|
1136
|
+
* @version 3.0.8
|
|
1183
1137
|
* @author Yusuke Kamiyamane
|
|
1184
1138
|
* @license MIT
|
|
1185
1139
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@y14e/tabs",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "WAI-ARIA compliant tabs pattern implementation in TypeScript",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -42,9 +42,8 @@
|
|
|
42
42
|
},
|
|
43
43
|
"homepage": "https://github.com/y14e/tabs#readme",
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@y14e/
|
|
46
|
-
"@y14e/
|
|
47
|
-
"@y14e/roving-tabindex": "^3.0.5",
|
|
45
|
+
"@y14e/button": "^1.0.3",
|
|
46
|
+
"@y14e/roving-tabindex": "^3.0.8",
|
|
48
47
|
"bun-types": "latest",
|
|
49
48
|
"tsup": "^8.0.0",
|
|
50
49
|
"typescript": "^5.6.0",
|