@y14e/tabs 2.0.9 → 2.0.11

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';
13
+ import Tabs from "@y14e/tabs";
14
14
 
15
15
  // CDNs
16
- import Tabs from 'https://esm.sh/@y14e/tabs@2.0.9';
16
+ import Tabs from "https://esm.sh/@y14e/tabs@2.0.11";
17
17
  // or
18
- import Tabs from 'https://cdn.jsdelivr.net/npm/@y14e/tabs@2.0.9/+esm';
18
+ import Tabs from "https://cdn.jsdelivr.net/npm/@y14e/tabs@2.0.11/+esm";
19
19
  // or
20
- import Tabs from 'https://esm.unpkg.com/@y14e/tabs@2.0.9';
20
+ import Tabs from "https://esm.unpkg.com/@y14e/tabs@2.0.11";
21
21
  ```
22
22
 
23
23
  ## Usage
@@ -68,7 +68,7 @@ If `true`, only the first tab list remains interactive; subsequent duplicates ar
68
68
  Override the global default settings applied to all accordion instances.
69
69
 
70
70
  ```ts
71
- import Tabs from '@y14e/tabs';
71
+ import Tabs from "@y14e/tabs";
72
72
 
73
73
  Tabs.defaults = {
74
74
  animation: {
@@ -76,7 +76,7 @@ Tabs.defaults = {
76
76
  crossFade: false,
77
77
  duration: 1000,
78
78
  fade: true,
79
- }
79
+ },
80
80
  },
81
81
  manual: true,
82
82
  };
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
- // node_modules/@y14e/attributes-utils/dist/index.js
3
+ // node_modules/@y14e/attribute-util/dist/index.js
4
4
  var DEFAULT_PARSER = (value) => value.split(/\s+/);
5
5
  var DEFAULT_SERIALIZER = (tokens) => tokens.join(" ");
6
- function addTokenToAttribute(element, attribute, token, options = {}) {
7
- const value = element.getAttribute(attribute)?.trim();
6
+ function addAttributeToken(element, name, token, options = {}) {
7
+ const value = element.getAttribute(name)?.trim();
8
8
  const {
9
9
  caseInsensitive = false,
10
10
  parse = DEFAULT_PARSER,
@@ -15,12 +15,12 @@ function addTokenToAttribute(element, attribute, token, options = {}) {
15
15
  const lower = token.toLowerCase();
16
16
  if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
17
17
  tokens.push(token);
18
- element.setAttribute(attribute, serialize(tokens));
18
+ element.setAttribute(name, serialize(tokens));
19
19
  }
20
20
  } else {
21
21
  const set = new Set(tokens);
22
22
  set.add(token);
23
- element.setAttribute(attribute, serialize([...set]));
23
+ element.setAttribute(name, serialize([...set]));
24
24
  }
25
25
  }
26
26
  var snapshots = /* @__PURE__ */ new WeakMap();
@@ -30,22 +30,22 @@ function restoreAttributes(element_or_elements) {
30
30
  if (!snapshot) {
31
31
  continue;
32
32
  }
33
- for (const [attribute, value] of snapshot.entries()) {
34
- value === null ? element.removeAttribute(attribute) : element.setAttribute(attribute, value);
33
+ for (const [name, value] of snapshot.entries()) {
34
+ value === null ? element.removeAttribute(name) : element.setAttribute(name, value);
35
35
  }
36
36
  snapshots.delete(element);
37
37
  }
38
38
  }
39
- function saveAttributes(element_or_elements, attribute_or_attributes) {
40
- const attributes = Array.isArray(attribute_or_attributes) ? attribute_or_attributes : [attribute_or_attributes];
39
+ function saveAttributes(element_or_elements, name_or_names) {
40
+ const names = Array.isArray(name_or_names) ? name_or_names : [name_or_names];
41
41
  (Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
42
42
  let snapshot = snapshots.get(element);
43
43
  if (!snapshot) {
44
44
  snapshot = /* @__PURE__ */ new Map();
45
45
  snapshots.set(element, snapshot);
46
46
  }
47
- attributes.forEach((attribute) => {
48
- snapshot.set(attribute, element.getAttribute(attribute));
47
+ names.forEach((name) => {
48
+ snapshot.set(name, element.getAttribute(name));
49
49
  });
50
50
  });
51
51
  }
@@ -368,6 +368,56 @@ var Button = class {
368
368
  };
369
369
  };
370
370
 
371
+ // node_modules/@y14e/attributes-utils/dist/index.js
372
+ var DEFAULT_PARSER2 = (value) => value.split(/\s+/);
373
+ var DEFAULT_SERIALIZER2 = (tokens) => tokens.join(" ");
374
+ function addTokenToAttribute(element, name, token, options = {}) {
375
+ const value = element.getAttribute(name)?.trim();
376
+ const {
377
+ caseInsensitive = false,
378
+ parse = DEFAULT_PARSER2,
379
+ serialize = DEFAULT_SERIALIZER2
380
+ } = options;
381
+ const tokens = value ? parse(value).filter(Boolean) : [];
382
+ if (caseInsensitive) {
383
+ const lower = token.toLowerCase();
384
+ if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
385
+ tokens.push(token);
386
+ element.setAttribute(name, serialize(tokens));
387
+ }
388
+ } else {
389
+ const set = new Set(tokens);
390
+ set.add(token);
391
+ element.setAttribute(name, serialize([...set]));
392
+ }
393
+ }
394
+ var snapshots2 = /* @__PURE__ */ new WeakMap();
395
+ function restoreAttributes2(element_or_elements) {
396
+ for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
397
+ const snapshot = snapshots2.get(element);
398
+ if (!snapshot) {
399
+ continue;
400
+ }
401
+ for (const [name, value] of snapshot.entries()) {
402
+ value === null ? element.removeAttribute(name) : element.setAttribute(name, value);
403
+ }
404
+ snapshots2.delete(element);
405
+ }
406
+ }
407
+ function saveAttributes2(element_or_elements, name_or_names) {
408
+ const names = Array.isArray(name_or_names) ? name_or_names : [name_or_names];
409
+ (Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
410
+ let snapshot = snapshots2.get(element);
411
+ if (!snapshot) {
412
+ snapshot = /* @__PURE__ */ new Map();
413
+ snapshots2.set(element, snapshot);
414
+ }
415
+ names.forEach((name) => {
416
+ snapshot.set(name, element.getAttribute(name));
417
+ });
418
+ });
419
+ }
420
+
371
421
  // node_modules/@y14e/roving-tabindex/dist/index.js
372
422
  function createRovingTabIndex(container, options = {}) {
373
423
  if (!(container instanceof Element)) {
@@ -415,17 +465,20 @@ var RovingTabIndex = class _RovingTabIndex {
415
465
  noStart = false;
416
466
  }
417
467
  if (selector !== "") {
468
+ let hasError = false;
418
469
  if (typeof selector !== "string" || !selector.trim()) {
419
- console.warn("Invalid selector. Fallback: no selector string.");
420
- selector = "";
470
+ hasError = true;
421
471
  } else {
422
472
  try {
423
- container.querySelector(selector);
473
+ this.#container.querySelector(selector);
424
474
  } catch {
425
- console.warn("Invalid selector. Fallback: no selector string.");
426
- selector = "";
475
+ hasError = true;
427
476
  }
428
477
  }
478
+ if (hasError) {
479
+ console.warn("Invalid selector. Fallback: no selector string.");
480
+ selector = "";
481
+ }
429
482
  }
430
483
  if (typeof typeahead !== "boolean") {
431
484
  console.warn("Invalid typeahead option. Fallback: false.");
@@ -456,7 +509,7 @@ var RovingTabIndex = class _RovingTabIndex {
456
509
  this.#controller = null;
457
510
  this.#focusables.forEach((focusable) => {
458
511
  _RovingTabIndex.#initialized.delete(focusable);
459
- restoreAttributes(focusable);
512
+ restoreAttributes2(focusable);
460
513
  });
461
514
  this.#focusables.clear();
462
515
  this.#focusablesByFirstChar.clear();
@@ -506,20 +559,20 @@ var RovingTabIndex = class _RovingTabIndex {
506
559
  return;
507
560
  }
508
561
  }
562
+ const candidates = this.#getFocusables().filter(
563
+ (focusable2) => this.#focusables.has(focusable2)
564
+ );
509
565
  const active = getActiveElement();
510
566
  if (!(active instanceof Element)) {
511
567
  return;
512
568
  }
513
- const candidates = this.#getFocusables().filter(
514
- (focusable2) => this.#focusables.has(focusable2)
515
- );
516
569
  if (!candidates.includes(active)) {
517
570
  return;
518
571
  }
519
572
  event.preventDefault();
520
- const activeIndex = candidates.indexOf(active);
521
573
  let newIndex;
522
- let target = candidates;
574
+ const activeIndex = candidates.indexOf(active);
575
+ let focusables = candidates;
523
576
  switch (key) {
524
577
  case "End":
525
578
  newIndex = -1;
@@ -536,22 +589,24 @@ var RovingTabIndex = class _RovingTabIndex {
536
589
  case "ArrowRight":
537
590
  case "ArrowDown": {
538
591
  const rawIndex = activeIndex + 1;
539
- const length = target.length;
592
+ const length = focusables.length;
540
593
  newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
541
594
  break;
542
595
  }
543
596
  default: {
544
- const focusables = new Set(
597
+ const focusablesByFirstChar = new Set(
545
598
  this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
546
599
  );
547
- target = candidates.filter((focusable2) => focusables.has(focusable2));
548
- const afterIndex = target.findIndex(
600
+ focusables = candidates.filter(
601
+ (candidate) => focusablesByFirstChar.has(candidate)
602
+ );
603
+ const afterIndex = focusables.findIndex(
549
604
  (focusable2) => candidates.indexOf(focusable2) > activeIndex
550
605
  );
551
606
  newIndex = afterIndex >= 0 ? afterIndex : 0;
552
607
  }
553
608
  }
554
- const focusable = target.at(newIndex);
609
+ const focusable = focusables.at(newIndex);
555
610
  focusable && focusElement(focusable);
556
611
  };
557
612
  #update(active) {
@@ -559,7 +614,7 @@ var RovingTabIndex = class _RovingTabIndex {
559
614
  for (const focusable of this.#focusables) {
560
615
  if (!current.has(focusable)) {
561
616
  _RovingTabIndex.#initialized.delete(focusable);
562
- restoreAttributes(focusable);
617
+ restoreAttributes2(focusable);
563
618
  this.#focusables.delete(focusable);
564
619
  for (const [key, focusables] of this.#focusablesByFirstChar) {
565
620
  const index = focusables.indexOf(focusable);
@@ -581,7 +636,7 @@ var RovingTabIndex = class _RovingTabIndex {
581
636
  this.#focusables.add(focusable);
582
637
  _RovingTabIndex.#initialized.add(focusable);
583
638
  if (!navigationOnly) {
584
- saveAttributes(focusable, "tabindex");
639
+ saveAttributes2(focusable, "tabindex");
585
640
  focusable.setAttribute("tabindex", "-1");
586
641
  }
587
642
  if (!typeahead) {
@@ -594,7 +649,7 @@ var RovingTabIndex = class _RovingTabIndex {
594
649
  );
595
650
  if (char) {
596
651
  keys.add(char);
597
- saveAttributes(focusable, "aria-keyshortcuts");
652
+ saveAttributes2(focusable, "aria-keyshortcuts");
598
653
  addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
599
654
  caseInsensitive: true
600
655
  });
@@ -953,7 +1008,7 @@ var Tabs = class _Tabs {
953
1008
  return;
954
1009
  }
955
1010
  panel.id ||= `tabs-panel-${id}`;
956
- addTokenToAttribute(tab, "aria-controls", panel.id);
1011
+ addAttributeToken(tab, "aria-controls", panel.id);
957
1012
  !tab.hasAttribute("aria-selected") && tab.setAttribute("aria-selected", "false");
958
1013
  const isAvoided = this.#isAvoidedTab(tab);
959
1014
  if (!isAvoided) {
@@ -961,7 +1016,7 @@ var Tabs = class _Tabs {
961
1016
  }
962
1017
  tab.setAttribute("role", "tab");
963
1018
  !this.#isFocusable(tab) && tab.style.setProperty("pointer-events", "none");
964
- addTokenToAttribute(panel, "aria-labelledby", tab.id);
1019
+ addAttributeToken(panel, "aria-labelledby", tab.id);
965
1020
  tab.addEventListener("click", this.#onTabClick, { signal });
966
1021
  tab.addEventListener("focus", this.#onTabFocus, { signal });
967
1022
  this.#buttons.push(new Button(tab));
@@ -1038,7 +1093,7 @@ var Tabs = class _Tabs {
1038
1093
  tab && this.activate(tab, true);
1039
1094
  };
1040
1095
  #createBinding(tabs, panel) {
1041
- return { tabs, panel, animation: null };
1096
+ return { animation: null, panel, tabs };
1042
1097
  }
1043
1098
  #hasFocusable(container) {
1044
1099
  return !![
@@ -1150,7 +1205,7 @@ var TabsIndicator = class {
1150
1205
  * Tabs
1151
1206
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
1152
1207
  *
1153
- * @version 2.0.9
1208
+ * @version 2.0.11
1154
1209
  * @author Yusuke Kamiyamane
1155
1210
  * @license MIT
1156
1211
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1158,15 +1213,15 @@ var TabsIndicator = class {
1158
1213
  */
1159
1214
  /*! Bundled license information:
1160
1215
 
1161
- @y14e/attributes-utils/dist/index.js:
1216
+ @y14e/attribute-util/dist/index.js:
1162
1217
  (**
1163
- * Attributes Utils
1218
+ * Attribute Util
1164
1219
  *
1165
- * @version 1.1.4
1220
+ * @version 2.0.0
1166
1221
  * @author Yusuke Kamiyamane
1167
1222
  * @license MIT
1168
1223
  * @copyright Copyright (c) Yusuke Kamiyamane
1169
- * @see {@link https://github.com/y14e/attributes-utils}
1224
+ * @see {@link https://github.com/y14e/attribute-util}
1170
1225
  *)
1171
1226
 
1172
1227
  power-focusable/dist/index.js:
@@ -1175,7 +1230,7 @@ power-focusable/dist/index.js:
1175
1230
  * High-precision focus management utility with full composed tree support.
1176
1231
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
1177
1232
  *
1178
- * @version 4.3.21
1233
+ * @version 4.3.23
1179
1234
  * @author Yusuke Kamiyamane
1180
1235
  * @license MIT
1181
1236
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1193,13 +1248,24 @@ power-focusable/dist/index.js:
1193
1248
  * @see {@link https://github.com/y14e/button}
1194
1249
  *)
1195
1250
 
1251
+ @y14e/attributes-utils/dist/index.js:
1252
+ (**
1253
+ * Attributes Utils
1254
+ *
1255
+ * @version 1.1.7
1256
+ * @author Yusuke Kamiyamane
1257
+ * @license MIT
1258
+ * @copyright Copyright (c) Yusuke Kamiyamane
1259
+ * @see {@link https://github.com/y14e/attributes-utils}
1260
+ *)
1261
+
1196
1262
  @y14e/roving-tabindex/dist/index.js:
1197
1263
  (**
1198
1264
  * Roving Tabindex
1199
1265
  * Lightweight roving tabindex utility with fully focus management.
1200
1266
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
1201
1267
  *
1202
- * @version 3.1.18
1268
+ * @version 3.1.20
1203
1269
  * @author Yusuke Kamiyamane
1204
1270
  * @license MIT
1205
1271
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1,8 +1,8 @@
1
- // node_modules/@y14e/attributes-utils/dist/index.js
1
+ // node_modules/@y14e/attribute-util/dist/index.js
2
2
  var DEFAULT_PARSER = (value) => value.split(/\s+/);
3
3
  var DEFAULT_SERIALIZER = (tokens) => tokens.join(" ");
4
- function addTokenToAttribute(element, attribute, token, options = {}) {
5
- const value = element.getAttribute(attribute)?.trim();
4
+ function addAttributeToken(element, name, token, options = {}) {
5
+ const value = element.getAttribute(name)?.trim();
6
6
  const {
7
7
  caseInsensitive = false,
8
8
  parse = DEFAULT_PARSER,
@@ -13,12 +13,12 @@ function addTokenToAttribute(element, attribute, token, options = {}) {
13
13
  const lower = token.toLowerCase();
14
14
  if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
15
15
  tokens.push(token);
16
- element.setAttribute(attribute, serialize(tokens));
16
+ element.setAttribute(name, serialize(tokens));
17
17
  }
18
18
  } else {
19
19
  const set = new Set(tokens);
20
20
  set.add(token);
21
- element.setAttribute(attribute, serialize([...set]));
21
+ element.setAttribute(name, serialize([...set]));
22
22
  }
23
23
  }
24
24
  var snapshots = /* @__PURE__ */ new WeakMap();
@@ -28,22 +28,22 @@ function restoreAttributes(element_or_elements) {
28
28
  if (!snapshot) {
29
29
  continue;
30
30
  }
31
- for (const [attribute, value] of snapshot.entries()) {
32
- value === null ? element.removeAttribute(attribute) : element.setAttribute(attribute, value);
31
+ for (const [name, value] of snapshot.entries()) {
32
+ value === null ? element.removeAttribute(name) : element.setAttribute(name, value);
33
33
  }
34
34
  snapshots.delete(element);
35
35
  }
36
36
  }
37
- function saveAttributes(element_or_elements, attribute_or_attributes) {
38
- const attributes = Array.isArray(attribute_or_attributes) ? attribute_or_attributes : [attribute_or_attributes];
37
+ function saveAttributes(element_or_elements, name_or_names) {
38
+ const names = Array.isArray(name_or_names) ? name_or_names : [name_or_names];
39
39
  (Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
40
40
  let snapshot = snapshots.get(element);
41
41
  if (!snapshot) {
42
42
  snapshot = /* @__PURE__ */ new Map();
43
43
  snapshots.set(element, snapshot);
44
44
  }
45
- attributes.forEach((attribute) => {
46
- snapshot.set(attribute, element.getAttribute(attribute));
45
+ names.forEach((name) => {
46
+ snapshot.set(name, element.getAttribute(name));
47
47
  });
48
48
  });
49
49
  }
@@ -366,6 +366,56 @@ var Button = class {
366
366
  };
367
367
  };
368
368
 
369
+ // node_modules/@y14e/attributes-utils/dist/index.js
370
+ var DEFAULT_PARSER2 = (value) => value.split(/\s+/);
371
+ var DEFAULT_SERIALIZER2 = (tokens) => tokens.join(" ");
372
+ function addTokenToAttribute(element, name, token, options = {}) {
373
+ const value = element.getAttribute(name)?.trim();
374
+ const {
375
+ caseInsensitive = false,
376
+ parse = DEFAULT_PARSER2,
377
+ serialize = DEFAULT_SERIALIZER2
378
+ } = options;
379
+ const tokens = value ? parse(value).filter(Boolean) : [];
380
+ if (caseInsensitive) {
381
+ const lower = token.toLowerCase();
382
+ if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
383
+ tokens.push(token);
384
+ element.setAttribute(name, serialize(tokens));
385
+ }
386
+ } else {
387
+ const set = new Set(tokens);
388
+ set.add(token);
389
+ element.setAttribute(name, serialize([...set]));
390
+ }
391
+ }
392
+ var snapshots2 = /* @__PURE__ */ new WeakMap();
393
+ function restoreAttributes2(element_or_elements) {
394
+ for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
395
+ const snapshot = snapshots2.get(element);
396
+ if (!snapshot) {
397
+ continue;
398
+ }
399
+ for (const [name, value] of snapshot.entries()) {
400
+ value === null ? element.removeAttribute(name) : element.setAttribute(name, value);
401
+ }
402
+ snapshots2.delete(element);
403
+ }
404
+ }
405
+ function saveAttributes2(element_or_elements, name_or_names) {
406
+ const names = Array.isArray(name_or_names) ? name_or_names : [name_or_names];
407
+ (Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
408
+ let snapshot = snapshots2.get(element);
409
+ if (!snapshot) {
410
+ snapshot = /* @__PURE__ */ new Map();
411
+ snapshots2.set(element, snapshot);
412
+ }
413
+ names.forEach((name) => {
414
+ snapshot.set(name, element.getAttribute(name));
415
+ });
416
+ });
417
+ }
418
+
369
419
  // node_modules/@y14e/roving-tabindex/dist/index.js
370
420
  function createRovingTabIndex(container, options = {}) {
371
421
  if (!(container instanceof Element)) {
@@ -413,17 +463,20 @@ var RovingTabIndex = class _RovingTabIndex {
413
463
  noStart = false;
414
464
  }
415
465
  if (selector !== "") {
466
+ let hasError = false;
416
467
  if (typeof selector !== "string" || !selector.trim()) {
417
- console.warn("Invalid selector. Fallback: no selector string.");
418
- selector = "";
468
+ hasError = true;
419
469
  } else {
420
470
  try {
421
- container.querySelector(selector);
471
+ this.#container.querySelector(selector);
422
472
  } catch {
423
- console.warn("Invalid selector. Fallback: no selector string.");
424
- selector = "";
473
+ hasError = true;
425
474
  }
426
475
  }
476
+ if (hasError) {
477
+ console.warn("Invalid selector. Fallback: no selector string.");
478
+ selector = "";
479
+ }
427
480
  }
428
481
  if (typeof typeahead !== "boolean") {
429
482
  console.warn("Invalid typeahead option. Fallback: false.");
@@ -454,7 +507,7 @@ var RovingTabIndex = class _RovingTabIndex {
454
507
  this.#controller = null;
455
508
  this.#focusables.forEach((focusable) => {
456
509
  _RovingTabIndex.#initialized.delete(focusable);
457
- restoreAttributes(focusable);
510
+ restoreAttributes2(focusable);
458
511
  });
459
512
  this.#focusables.clear();
460
513
  this.#focusablesByFirstChar.clear();
@@ -504,20 +557,20 @@ var RovingTabIndex = class _RovingTabIndex {
504
557
  return;
505
558
  }
506
559
  }
560
+ const candidates = this.#getFocusables().filter(
561
+ (focusable2) => this.#focusables.has(focusable2)
562
+ );
507
563
  const active = getActiveElement();
508
564
  if (!(active instanceof Element)) {
509
565
  return;
510
566
  }
511
- const candidates = this.#getFocusables().filter(
512
- (focusable2) => this.#focusables.has(focusable2)
513
- );
514
567
  if (!candidates.includes(active)) {
515
568
  return;
516
569
  }
517
570
  event.preventDefault();
518
- const activeIndex = candidates.indexOf(active);
519
571
  let newIndex;
520
- let target = candidates;
572
+ const activeIndex = candidates.indexOf(active);
573
+ let focusables = candidates;
521
574
  switch (key) {
522
575
  case "End":
523
576
  newIndex = -1;
@@ -534,22 +587,24 @@ var RovingTabIndex = class _RovingTabIndex {
534
587
  case "ArrowRight":
535
588
  case "ArrowDown": {
536
589
  const rawIndex = activeIndex + 1;
537
- const length = target.length;
590
+ const length = focusables.length;
538
591
  newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
539
592
  break;
540
593
  }
541
594
  default: {
542
- const focusables = new Set(
595
+ const focusablesByFirstChar = new Set(
543
596
  this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
544
597
  );
545
- target = candidates.filter((focusable2) => focusables.has(focusable2));
546
- const afterIndex = target.findIndex(
598
+ focusables = candidates.filter(
599
+ (candidate) => focusablesByFirstChar.has(candidate)
600
+ );
601
+ const afterIndex = focusables.findIndex(
547
602
  (focusable2) => candidates.indexOf(focusable2) > activeIndex
548
603
  );
549
604
  newIndex = afterIndex >= 0 ? afterIndex : 0;
550
605
  }
551
606
  }
552
- const focusable = target.at(newIndex);
607
+ const focusable = focusables.at(newIndex);
553
608
  focusable && focusElement(focusable);
554
609
  };
555
610
  #update(active) {
@@ -557,7 +612,7 @@ var RovingTabIndex = class _RovingTabIndex {
557
612
  for (const focusable of this.#focusables) {
558
613
  if (!current.has(focusable)) {
559
614
  _RovingTabIndex.#initialized.delete(focusable);
560
- restoreAttributes(focusable);
615
+ restoreAttributes2(focusable);
561
616
  this.#focusables.delete(focusable);
562
617
  for (const [key, focusables] of this.#focusablesByFirstChar) {
563
618
  const index = focusables.indexOf(focusable);
@@ -579,7 +634,7 @@ var RovingTabIndex = class _RovingTabIndex {
579
634
  this.#focusables.add(focusable);
580
635
  _RovingTabIndex.#initialized.add(focusable);
581
636
  if (!navigationOnly) {
582
- saveAttributes(focusable, "tabindex");
637
+ saveAttributes2(focusable, "tabindex");
583
638
  focusable.setAttribute("tabindex", "-1");
584
639
  }
585
640
  if (!typeahead) {
@@ -592,7 +647,7 @@ var RovingTabIndex = class _RovingTabIndex {
592
647
  );
593
648
  if (char) {
594
649
  keys.add(char);
595
- saveAttributes(focusable, "aria-keyshortcuts");
650
+ saveAttributes2(focusable, "aria-keyshortcuts");
596
651
  addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
597
652
  caseInsensitive: true
598
653
  });
@@ -951,7 +1006,7 @@ var Tabs = class _Tabs {
951
1006
  return;
952
1007
  }
953
1008
  panel.id ||= `tabs-panel-${id}`;
954
- addTokenToAttribute(tab, "aria-controls", panel.id);
1009
+ addAttributeToken(tab, "aria-controls", panel.id);
955
1010
  !tab.hasAttribute("aria-selected") && tab.setAttribute("aria-selected", "false");
956
1011
  const isAvoided = this.#isAvoidedTab(tab);
957
1012
  if (!isAvoided) {
@@ -959,7 +1014,7 @@ var Tabs = class _Tabs {
959
1014
  }
960
1015
  tab.setAttribute("role", "tab");
961
1016
  !this.#isFocusable(tab) && tab.style.setProperty("pointer-events", "none");
962
- addTokenToAttribute(panel, "aria-labelledby", tab.id);
1017
+ addAttributeToken(panel, "aria-labelledby", tab.id);
963
1018
  tab.addEventListener("click", this.#onTabClick, { signal });
964
1019
  tab.addEventListener("focus", this.#onTabFocus, { signal });
965
1020
  this.#buttons.push(new Button(tab));
@@ -1036,7 +1091,7 @@ var Tabs = class _Tabs {
1036
1091
  tab && this.activate(tab, true);
1037
1092
  };
1038
1093
  #createBinding(tabs, panel) {
1039
- return { tabs, panel, animation: null };
1094
+ return { animation: null, panel, tabs };
1040
1095
  }
1041
1096
  #hasFocusable(container) {
1042
1097
  return !![
@@ -1148,7 +1203,7 @@ var TabsIndicator = class {
1148
1203
  * Tabs
1149
1204
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
1150
1205
  *
1151
- * @version 2.0.9
1206
+ * @version 2.0.11
1152
1207
  * @author Yusuke Kamiyamane
1153
1208
  * @license MIT
1154
1209
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1156,15 +1211,15 @@ var TabsIndicator = class {
1156
1211
  */
1157
1212
  /*! Bundled license information:
1158
1213
 
1159
- @y14e/attributes-utils/dist/index.js:
1214
+ @y14e/attribute-util/dist/index.js:
1160
1215
  (**
1161
- * Attributes Utils
1216
+ * Attribute Util
1162
1217
  *
1163
- * @version 1.1.4
1218
+ * @version 2.0.0
1164
1219
  * @author Yusuke Kamiyamane
1165
1220
  * @license MIT
1166
1221
  * @copyright Copyright (c) Yusuke Kamiyamane
1167
- * @see {@link https://github.com/y14e/attributes-utils}
1222
+ * @see {@link https://github.com/y14e/attribute-util}
1168
1223
  *)
1169
1224
 
1170
1225
  power-focusable/dist/index.js:
@@ -1173,7 +1228,7 @@ power-focusable/dist/index.js:
1173
1228
  * High-precision focus management utility with full composed tree support.
1174
1229
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
1175
1230
  *
1176
- * @version 4.3.21
1231
+ * @version 4.3.23
1177
1232
  * @author Yusuke Kamiyamane
1178
1233
  * @license MIT
1179
1234
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1191,13 +1246,24 @@ power-focusable/dist/index.js:
1191
1246
  * @see {@link https://github.com/y14e/button}
1192
1247
  *)
1193
1248
 
1249
+ @y14e/attributes-utils/dist/index.js:
1250
+ (**
1251
+ * Attributes Utils
1252
+ *
1253
+ * @version 1.1.7
1254
+ * @author Yusuke Kamiyamane
1255
+ * @license MIT
1256
+ * @copyright Copyright (c) Yusuke Kamiyamane
1257
+ * @see {@link https://github.com/y14e/attributes-utils}
1258
+ *)
1259
+
1194
1260
  @y14e/roving-tabindex/dist/index.js:
1195
1261
  (**
1196
1262
  * Roving Tabindex
1197
1263
  * Lightweight roving tabindex utility with fully focus management.
1198
1264
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
1199
1265
  *
1200
- * @version 3.1.18
1266
+ * @version 3.1.20
1201
1267
  * @author Yusuke Kamiyamane
1202
1268
  * @license MIT
1203
1269
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.cjs CHANGED
@@ -1,11 +1,30 @@
1
1
  'use strict';
2
2
 
3
- var attributesUtils = require('@y14e/attributes-utils');
3
+ var util = require('@y14e/attribute-util');
4
4
  var Button = require('@y14e/button');
5
5
  var rovingTabindex = require('@y14e/roving-tabindex');
6
6
 
7
7
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
8
 
9
+ function _interopNamespace(e) {
10
+ if (e && e.__esModule) return e;
11
+ var n = Object.create(null);
12
+ if (e) {
13
+ Object.keys(e).forEach(function (k) {
14
+ if (k !== 'default') {
15
+ var d = Object.getOwnPropertyDescriptor(e, k);
16
+ Object.defineProperty(n, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: function () { return e[k]; }
19
+ });
20
+ }
21
+ });
22
+ }
23
+ n.default = e;
24
+ return Object.freeze(n);
25
+ }
26
+
27
+ var util__namespace = /*#__PURE__*/_interopNamespace(util);
9
28
  var Button__default = /*#__PURE__*/_interopDefault(Button);
10
29
 
11
30
  // src/index.ts
@@ -279,13 +298,13 @@ var Tabs = class _Tabs {
279
298
  this.#onContentAnimationFinish();
280
299
  this.#animationController?.abort();
281
300
  this.#animationController = null;
282
- attributesUtils.restoreAttributes([
301
+ util__namespace.restoreAttributes([
283
302
  ...this.#listElements,
284
303
  ...this.#tabElements,
285
304
  ...this.#indicatorElements,
286
305
  ...this.#panelElements
287
306
  ]);
288
- this.#contentElement && attributesUtils.restoreAttributes(this.#contentElement);
307
+ this.#contentElement && util__namespace.restoreAttributes(this.#contentElement);
289
308
  this.#listElements.length = 0;
290
309
  this.#tabElements.length = 0;
291
310
  this.#contentElement = null;
@@ -293,22 +312,22 @@ var Tabs = class _Tabs {
293
312
  this.#rootElement.removeAttribute("data-tabs-initialized");
294
313
  }
295
314
  #initialize() {
296
- attributesUtils.saveAttributes(this.#listElements, [
315
+ util__namespace.saveAttributes(this.#listElements, [
297
316
  "aria-hidden",
298
317
  "aria-orientation",
299
318
  "role",
300
319
  "style"
301
320
  ]);
302
- attributesUtils.saveAttributes(this.#tabElements, [
321
+ util__namespace.saveAttributes(this.#tabElements, [
303
322
  "aria-controls",
304
323
  "id",
305
324
  "role",
306
325
  "style",
307
326
  "tabindex"
308
327
  ]);
309
- attributesUtils.saveAttributes(this.#indicatorElements, "style");
310
- this.#contentElement && attributesUtils.saveAttributes(this.#contentElement, "style");
311
- attributesUtils.saveAttributes(this.#panelElements, [
328
+ util__namespace.saveAttributes(this.#indicatorElements, "style");
329
+ this.#contentElement && util__namespace.saveAttributes(this.#contentElement, "style");
330
+ util__namespace.saveAttributes(this.#panelElements, [
312
331
  "aria-controls",
313
332
  "aria-labelledby",
314
333
  "id",
@@ -330,7 +349,7 @@ var Tabs = class _Tabs {
330
349
  return;
331
350
  }
332
351
  panel.id ||= `tabs-panel-${id}`;
333
- attributesUtils.addTokenToAttribute(tab, "aria-controls", panel.id);
352
+ util__namespace.addAttributeToken(tab, "aria-controls", panel.id);
334
353
  !tab.hasAttribute("aria-selected") && tab.setAttribute("aria-selected", "false");
335
354
  const isAvoided = this.#isAvoidedTab(tab);
336
355
  if (!isAvoided) {
@@ -338,7 +357,7 @@ var Tabs = class _Tabs {
338
357
  }
339
358
  tab.setAttribute("role", "tab");
340
359
  !this.#isFocusable(tab) && tab.style.setProperty("pointer-events", "none");
341
- attributesUtils.addTokenToAttribute(panel, "aria-labelledby", tab.id);
360
+ util__namespace.addAttributeToken(panel, "aria-labelledby", tab.id);
342
361
  tab.addEventListener("click", this.#onTabClick, { signal });
343
362
  tab.addEventListener("focus", this.#onTabFocus, { signal });
344
363
  this.#buttons.push(new Button__default.default(tab));
@@ -415,7 +434,7 @@ var Tabs = class _Tabs {
415
434
  tab && this.activate(tab, true);
416
435
  };
417
436
  #createBinding(tabs, panel) {
418
- return { tabs, panel, animation: null };
437
+ return { animation: null, panel, tabs };
419
438
  }
420
439
  #hasFocusable(container) {
421
440
  return !![
@@ -527,7 +546,7 @@ var TabsIndicator = class {
527
546
  * Tabs
528
547
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
529
548
  *
530
- * @version 2.0.9
549
+ * @version 2.0.11
531
550
  * @author Yusuke Kamiyamane
532
551
  * @license MIT
533
552
  * @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.9
5
+ * @version 2.0.11
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.9
5
+ * @version 2.0.11
6
6
  * @author Yusuke Kamiyamane
7
7
  * @license MIT
8
8
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { restoreAttributes, saveAttributes, addTokenToAttribute } from '@y14e/attributes-utils';
1
+ import * as util from '@y14e/attribute-util';
2
2
  import Button from '@y14e/button';
3
3
  import { createRovingTabIndex } from '@y14e/roving-tabindex';
4
4
 
@@ -273,13 +273,13 @@ var Tabs = class _Tabs {
273
273
  this.#onContentAnimationFinish();
274
274
  this.#animationController?.abort();
275
275
  this.#animationController = null;
276
- restoreAttributes([
276
+ util.restoreAttributes([
277
277
  ...this.#listElements,
278
278
  ...this.#tabElements,
279
279
  ...this.#indicatorElements,
280
280
  ...this.#panelElements
281
281
  ]);
282
- this.#contentElement && restoreAttributes(this.#contentElement);
282
+ this.#contentElement && util.restoreAttributes(this.#contentElement);
283
283
  this.#listElements.length = 0;
284
284
  this.#tabElements.length = 0;
285
285
  this.#contentElement = null;
@@ -287,22 +287,22 @@ var Tabs = class _Tabs {
287
287
  this.#rootElement.removeAttribute("data-tabs-initialized");
288
288
  }
289
289
  #initialize() {
290
- saveAttributes(this.#listElements, [
290
+ util.saveAttributes(this.#listElements, [
291
291
  "aria-hidden",
292
292
  "aria-orientation",
293
293
  "role",
294
294
  "style"
295
295
  ]);
296
- saveAttributes(this.#tabElements, [
296
+ util.saveAttributes(this.#tabElements, [
297
297
  "aria-controls",
298
298
  "id",
299
299
  "role",
300
300
  "style",
301
301
  "tabindex"
302
302
  ]);
303
- saveAttributes(this.#indicatorElements, "style");
304
- this.#contentElement && saveAttributes(this.#contentElement, "style");
305
- saveAttributes(this.#panelElements, [
303
+ util.saveAttributes(this.#indicatorElements, "style");
304
+ this.#contentElement && util.saveAttributes(this.#contentElement, "style");
305
+ util.saveAttributes(this.#panelElements, [
306
306
  "aria-controls",
307
307
  "aria-labelledby",
308
308
  "id",
@@ -324,7 +324,7 @@ var Tabs = class _Tabs {
324
324
  return;
325
325
  }
326
326
  panel.id ||= `tabs-panel-${id}`;
327
- addTokenToAttribute(tab, "aria-controls", panel.id);
327
+ util.addAttributeToken(tab, "aria-controls", panel.id);
328
328
  !tab.hasAttribute("aria-selected") && tab.setAttribute("aria-selected", "false");
329
329
  const isAvoided = this.#isAvoidedTab(tab);
330
330
  if (!isAvoided) {
@@ -332,7 +332,7 @@ var Tabs = class _Tabs {
332
332
  }
333
333
  tab.setAttribute("role", "tab");
334
334
  !this.#isFocusable(tab) && tab.style.setProperty("pointer-events", "none");
335
- addTokenToAttribute(panel, "aria-labelledby", tab.id);
335
+ util.addAttributeToken(panel, "aria-labelledby", tab.id);
336
336
  tab.addEventListener("click", this.#onTabClick, { signal });
337
337
  tab.addEventListener("focus", this.#onTabFocus, { signal });
338
338
  this.#buttons.push(new Button(tab));
@@ -409,7 +409,7 @@ var Tabs = class _Tabs {
409
409
  tab && this.activate(tab, true);
410
410
  };
411
411
  #createBinding(tabs, panel) {
412
- return { tabs, panel, animation: null };
412
+ return { animation: null, panel, tabs };
413
413
  }
414
414
  #hasFocusable(container) {
415
415
  return !![
@@ -521,7 +521,7 @@ var TabsIndicator = class {
521
521
  * Tabs
522
522
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
523
523
  *
524
- * @version 2.0.9
524
+ * @version 2.0.11
525
525
  * @author Yusuke Kamiyamane
526
526
  * @license MIT
527
527
  * @copyright Copyright (c) Yusuke Kamiyamane
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@y14e/tabs",
3
- "version": "2.0.9",
3
+ "version": "2.0.11",
4
4
  "description": "WAI-ARIA compliant tabs pattern implementation in TypeScript",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -50,8 +50,8 @@
50
50
  "node": ">=18"
51
51
  },
52
52
  "dependencies": {
53
- "@y14e/attributes-utils": "^1.1.4",
53
+ "@y14e/attribute-util": "^2.0.0",
54
54
  "@y14e/button": "^1.0.6",
55
- "@y14e/roving-tabindex": "^3.1.18"
55
+ "@y14e/roving-tabindex": "^3.1.20"
56
56
  }
57
57
  }