@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 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.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.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.0/+esm';
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.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/attributes-utils/dist/index.js
4
- var DEFAULT_PARSER = (value) => value.split(/\s+/);
5
- var DEFAULT_SERIALIZER = (tokens) => tokens.join(" ");
6
- function addTokenToAttribute(element, attribute, token, options = {}) {
7
- const {
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 DEFAULT_PARSER2 = (value) => value.split(/\s+/);
110
- var DEFAULT_SERIALIZER2 = (tokens) => tokens.join(" ");
111
- function addTokenToAttribute2(element, attribute, token, options = {}) {
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 = DEFAULT_PARSER2,
115
- serialize = DEFAULT_SERIALIZER2
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 snapshots2 = /* @__PURE__ */ new WeakMap();
132
- function restoreAttributes2(elements) {
82
+ var snapshots = /* @__PURE__ */ new WeakMap();
83
+ function restoreAttributes(elements) {
133
84
  for (const element of elements) {
134
- const snapshot = snapshots2.get(element);
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
- snapshots2.delete(element);
92
+ snapshots.delete(element);
142
93
  }
143
94
  }
144
- function saveAttributes2(elements, attributes) {
95
+ function saveAttributes(elements, attributes) {
145
96
  elements.forEach((element) => {
146
- let snapshot = snapshots2.get(element);
97
+ let snapshot = snapshots.get(element);
147
98
  if (!snapshot) {
148
99
  snapshot = /* @__PURE__ */ new Map();
149
- snapshots2.set(element, snapshot);
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
- let {
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
- #options;
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
- this.#options = options;
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
- restoreAttributes2([...this.#focusables]);
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.#options.noMemory && !isFocusable22 ? this.#update(null) : isFocusable22 && this.#update(target);
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.#options;
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 && restoreAttributes2([focusable]);
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.#options;
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
- saveAttributes2([focusable], ["tabindex"]);
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
- saveAttributes2([focusable], ["aria-keyshortcuts"]);
583
- addTokenToAttribute2(focusable, "aria-keyshortcuts", char, {
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.#options;
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.#options.navigationOnly,
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.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.2
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.5
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
@@ -2,7 +2,7 @@
2
2
  * Tabs
3
3
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
4
4
  *
5
- * @version 2.0.0
5
+ * @version 2.0.2
6
6
  * @author Yusuke Kamiyamane
7
7
  * @license MIT
8
8
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Tabs
3
3
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
4
4
  *
5
- * @version 2.0.0
5
+ * @version 2.0.2
6
6
  * @author Yusuke Kamiyamane
7
7
  * @license MIT
8
8
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.js CHANGED
@@ -1,53 +1,11 @@
1
- // node_modules/@y14e/attributes-utils/dist/index.js
2
- var DEFAULT_PARSER = (value) => value.split(/\s+/);
3
- var DEFAULT_SERIALIZER = (tokens) => tokens.join(" ");
4
- function addTokenToAttribute(element, attribute, token, options = {}) {
5
- const {
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 DEFAULT_PARSER2 = (value) => value.split(/\s+/);
108
- var DEFAULT_SERIALIZER2 = (tokens) => tokens.join(" ");
109
- function addTokenToAttribute2(element, attribute, token, options = {}) {
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 = DEFAULT_PARSER2,
113
- serialize = DEFAULT_SERIALIZER2
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 snapshots2 = /* @__PURE__ */ new WeakMap();
130
- function restoreAttributes2(elements) {
80
+ var snapshots = /* @__PURE__ */ new WeakMap();
81
+ function restoreAttributes(elements) {
131
82
  for (const element of elements) {
132
- const snapshot = snapshots2.get(element);
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
- snapshots2.delete(element);
90
+ snapshots.delete(element);
140
91
  }
141
92
  }
142
- function saveAttributes2(elements, attributes) {
93
+ function saveAttributes(elements, attributes) {
143
94
  elements.forEach((element) => {
144
- let snapshot = snapshots2.get(element);
95
+ let snapshot = snapshots.get(element);
145
96
  if (!snapshot) {
146
97
  snapshot = /* @__PURE__ */ new Map();
147
- snapshots2.set(element, snapshot);
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
- let {
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
- #options;
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
- this.#options = options;
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
- restoreAttributes2([...this.#focusables]);
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.#options.noMemory && !isFocusable22 ? this.#update(null) : isFocusable22 && this.#update(target);
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.#options;
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 && restoreAttributes2([focusable]);
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.#options;
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
- saveAttributes2([focusable], ["tabindex"]);
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
- saveAttributes2([focusable], ["aria-keyshortcuts"]);
581
- addTokenToAttribute2(focusable, "aria-keyshortcuts", char, {
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.#options;
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.#options.navigationOnly,
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.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.2
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.5
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.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/attributes-utils": "^1.1.2",
46
- "@y14e/button": "^1.0.2",
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",