@y14e/accordion 2.0.13 → 2.0.15

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/accordion
10
10
 
11
11
  ```ts
12
12
  // npm
13
- import { Accordion } from "@y14e/accordion";
13
+ import { Accordion } from '@y14e/accordion';
14
14
 
15
15
  // CDNs
16
- import { Accordion } from "https://esm.sh/@y14e/accordion@2.0.13";
16
+ import { Accordion } from 'https://esm.sh/@y14e/accordion@2.0.15';
17
17
  // or
18
- import { Accordion } from "https://cdn.jsdelivr.net/npm/@y14e/accordion@2.0.13/+esm";
18
+ import { Accordion } from 'https://cdn.jsdelivr.net/npm/@y14e/accordion@2.0.15/+esm';
19
19
  // or
20
- import { Accordion } from "https://esm.unpkg.com/@y14e/accordion@2.0.13";
20
+ import { Accordion } from 'https://esm.unpkg.com/@y14e/accordion@2.0.15';
21
21
  ```
22
22
 
23
23
  ## Usage
@@ -51,15 +51,15 @@ interface AccordionOptions {
51
51
  Override the global default settings applied to all accordion instances.
52
52
 
53
53
  ```ts
54
- import { Accordion } from "@y14e/accordion";
54
+ import { Accordion } from '@y14e/accordion';
55
55
 
56
56
  Accordion.defaults = {
57
57
  animation: {
58
58
  duration: 1000,
59
59
  },
60
60
  selector: {
61
- content: ".content",
62
- trigger: ".trigger",
61
+ content: '.content',
62
+ trigger: '.trigger',
63
63
  },
64
64
  };
65
65
 
@@ -4,12 +4,11 @@
4
4
  var DEFAULT_PARSER = (value) => value.split(/\s+/);
5
5
  var DEFAULT_SERIALIZER = (tokens) => tokens.join(" ");
6
6
  function addAttributeToken(element, name, token, options = {}) {
7
+ if (!isValid(element, name, token)) {
8
+ return;
9
+ }
7
10
  const value = element.getAttribute(name)?.trim();
8
- const {
9
- caseInsensitive = false,
10
- parse = DEFAULT_PARSER,
11
- serialize = DEFAULT_SERIALIZER
12
- } = options;
11
+ const { caseInsensitive, parse, serialize } = resolveOptions(options);
13
12
  const tokens = value ? parse(value).filter(Boolean) : [];
14
13
  if (caseInsensitive) {
15
14
  const lower = token.toLowerCase();
@@ -38,20 +37,61 @@ function restoreAttributes(element_or_elements) {
38
37
  }
39
38
  function saveAttributes(element_or_elements, name_or_names) {
40
39
  const names = Array.isArray(name_or_names) ? name_or_names : [name_or_names];
41
- (Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
40
+ for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
42
41
  let snapshot = snapshots.get(element);
43
42
  if (!snapshot) {
44
43
  snapshot = /* @__PURE__ */ new Map();
45
44
  snapshots.set(element, snapshot);
46
45
  }
47
- names.forEach((name) => {
46
+ for (const name of names) {
48
47
  snapshot.set(name, element.getAttribute(name));
49
- });
50
- });
48
+ }
49
+ }
50
+ }
51
+ function isValid(element, name, token) {
52
+ if (!(element instanceof Element)) {
53
+ console.warn("Invalid element");
54
+ return false;
55
+ }
56
+ try {
57
+ document.createElement("div").setAttribute(name, "");
58
+ } catch {
59
+ console.warn(`Invalid attribute name: '${name}'`);
60
+ return false;
61
+ }
62
+ if (typeof token !== "string" || !token.trim()) {
63
+ console.warn("Invalid token");
64
+ return false;
65
+ }
66
+ return true;
67
+ }
68
+ function resolveOptions(options) {
69
+ let {
70
+ caseInsensitive = false,
71
+ parse = DEFAULT_PARSER,
72
+ serialize = DEFAULT_SERIALIZER
73
+ } = options;
74
+ if (typeof caseInsensitive !== "boolean") {
75
+ console.warn("Invalid caseInsensitive option. Fallback: false.");
76
+ caseInsensitive = false;
77
+ }
78
+ if (typeof parse !== "function") {
79
+ console.warn(
80
+ "Invalid parser. Fallback: default parser (splits by whitespace)."
81
+ );
82
+ parse = DEFAULT_PARSER;
83
+ }
84
+ if (typeof serialize !== "function") {
85
+ console.warn(
86
+ "Invalid serializer. Fallback: default serializer (joins by whitespace)."
87
+ );
88
+ serialize = DEFAULT_SERIALIZER;
89
+ }
90
+ return { caseInsensitive, parse, serialize };
51
91
  }
52
92
 
53
93
  // node_modules/power-focusable/dist/index.js
54
- var FOCUSABLE_SELECTOR = `:is(a[href], area[href], button, embed, iframe, input:not([type="hidden" i]), object, select, details > summary:first-of-type, textarea, [contenteditable]:not([contenteditable="false" i]), [controls], [tabindex]):not(:disabled, [hidden], [inert], [tabindex="-1"])`;
94
+ var FOCUSABLE_SELECTOR = ':is(a[href], area[href], button, embed, iframe, input:not([type="hidden" i]), object, select, details > summary:first-of-type, textarea, [contenteditable]:not([contenteditable="false" i]), [controls], [tabindex]):not(:disabled, [hidden], [inert], [tabindex="-1"])';
55
95
  var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX = FOCUSABLE_SELECTOR.replace(
56
96
  /(,\s*)?\[tabindex="-1"\]/g,
57
97
  ""
@@ -61,37 +101,13 @@ function getFocusables(container = document.body, options = {}) {
61
101
  console.warn("Invalid container element. Fallback: <body> element.");
62
102
  container = document.body;
63
103
  }
64
- let {
65
- composed = false,
104
+ const {
105
+ composed,
66
106
  filter,
67
107
  include,
68
- skipNegativeTabIndexCheck = false,
69
- skipVisibilityCheck = false
70
- } = options;
71
- if (typeof composed !== "boolean") {
72
- console.warn("Invalid composed option. Fallback: false.");
73
- composed = false;
74
- }
75
- if (typeof filter !== "undefined" && typeof filter !== "function") {
76
- console.warn(
77
- "Invalid filter function. Fallback: no filter function (undefined)."
78
- );
79
- filter = void 0;
80
- }
81
- if (typeof include !== "undefined" && typeof include !== "function") {
82
- console.warn(
83
- "Invalid include function. Fallback: no include function (undefined)."
84
- );
85
- include = void 0;
86
- }
87
- if (typeof skipNegativeTabIndexCheck !== "boolean") {
88
- console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
89
- skipNegativeTabIndexCheck = false;
90
- }
91
- if (typeof skipVisibilityCheck !== "boolean") {
92
- console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
93
- skipVisibilityCheck = false;
94
- }
108
+ skipNegativeTabIndexCheck,
109
+ skipVisibilityCheck
110
+ } = resolveOptions2(options);
95
111
  const candidates = [];
96
112
  if (composed || include) {
97
113
  let traverse2 = function(node) {
@@ -101,29 +117,19 @@ function getFocusables(container = document.body, options = {}) {
101
117
  }) || include?.(node)) {
102
118
  candidates[candidates.length] = node;
103
119
  }
104
- const children2 = composed ? getComposedChildren(node) : getChildren(node);
105
- for (let i = 0, l = children2.length; i < l; i++) {
106
- const child = children2[i];
107
- child && traverse2(child);
108
- }
120
+ (composed ? getComposedChildren(node) : getChildren(node)).map(traverse2);
109
121
  };
110
- const children = composed ? getComposedChildren(container) : getChildren(container);
111
- for (let i = 0, l = children.length; i < l; i++) {
112
- const child = children[i];
113
- child && traverse2(child);
114
- }
122
+ (composed ? getComposedChildren(container) : getChildren(container)).map(
123
+ traverse2
124
+ );
115
125
  } else {
116
- const matches = container.querySelectorAll(
126
+ for (const match of container.querySelectorAll(
117
127
  skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
118
- );
119
- for (let i = 0, l = matches.length; i < l; i++) {
120
- const matched = matches[i];
121
- if (matched && isFocusable(matched, {
128
+ )) {
129
+ match && isFocusable(match, {
122
130
  skipNegativeTabIndexCheck,
123
131
  skipVisibilityCheck
124
- })) {
125
- candidates[candidates.length] = matched;
126
- }
132
+ }) && candidates.push(match);
127
133
  }
128
134
  }
129
135
  return normalizeRadioGroup(
@@ -135,15 +141,7 @@ function isFocusable(element, options = {}) {
135
141
  console.warn("Invalid element");
136
142
  return false;
137
143
  }
138
- let { skipNegativeTabIndexCheck = false, skipVisibilityCheck = false } = options;
139
- if (typeof skipNegativeTabIndexCheck !== "boolean") {
140
- console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
141
- skipNegativeTabIndexCheck = false;
142
- }
143
- if (typeof skipVisibilityCheck !== "boolean") {
144
- console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
145
- skipVisibilityCheck = false;
146
- }
144
+ const { skipNegativeTabIndexCheck, skipVisibilityCheck } = resolveOptions2(options);
147
145
  if (element.hasAttribute("hidden") || isInert(element)) {
148
146
  return false;
149
147
  }
@@ -198,8 +196,7 @@ function isDisabledDeep(element) {
198
196
  }
199
197
  function normalizeRadioGroup(elements) {
200
198
  let map = null;
201
- for (let i = 0, l = elements.length; i < l; i++) {
202
- const element = elements[i];
199
+ for (const element of elements) {
203
200
  if (!(element instanceof HTMLInputElement)) {
204
201
  continue;
205
202
  }
@@ -249,23 +246,10 @@ function normalizeRadioGroup(elements) {
249
246
  function sortByTabIndex(elements) {
250
247
  const ordered = [];
251
248
  const natural = [];
252
- for (let i = 0, l = elements.length; i < l; i++) {
253
- const element = elements[i];
254
- if (element) {
255
- const target = getTabIndex(element) > 0 ? ordered : natural;
256
- target[target.length] = element;
257
- }
258
- }
259
- ordered.sort((a, b) => getTabIndex(a) - getTabIndex(b));
260
- let count = 0;
261
- const sorted = new Array(ordered.length + natural.length);
262
- for (let i = 0, l = ordered.length; i < l; i++) {
263
- sorted[count++] = ordered[i];
249
+ for (const element of elements) {
250
+ (getTabIndex(element) > 0 ? ordered : natural).push(element);
264
251
  }
265
- for (let i = 0, l = natural.length; i < l; i++) {
266
- sorted[count++] = natural[i];
267
- }
268
- return sorted;
252
+ return ordered.sort((a, b) => getTabIndex(a) - getTabIndex(b)).concat(natural);
269
253
  }
270
254
  function getComposedChildren(node) {
271
255
  if (node instanceof ShadowRoot) {
@@ -318,6 +302,61 @@ function isInert(element) {
318
302
  function isUngroupedRadio(element) {
319
303
  return element.type === "radio" && !!element.name;
320
304
  }
305
+ function resolveOptions2(options) {
306
+ let {
307
+ anchor = getActiveElement(),
308
+ composed = false,
309
+ filter,
310
+ include,
311
+ skipNegativeTabIndexCheck = false,
312
+ skipVisibilityCheck = false,
313
+ wrap = false
314
+ } = options;
315
+ if (!(anchor instanceof Element)) {
316
+ const active = getActiveElement();
317
+ if (active instanceof Element) {
318
+ console.warn("Invalid anchor element. Fallback: active element.");
319
+ anchor = active;
320
+ }
321
+ }
322
+ if (typeof composed !== "boolean") {
323
+ console.warn("Invalid composed option. Fallback: false.");
324
+ composed = false;
325
+ }
326
+ if (filter !== void 0 && typeof filter !== "function") {
327
+ console.warn(
328
+ "Invalid filter function. Fallback: no filter function (undefined)."
329
+ );
330
+ filter = void 0;
331
+ }
332
+ if (include !== void 0 && typeof include !== "function") {
333
+ console.warn(
334
+ "Invalid include function. Fallback: no include function (undefined)."
335
+ );
336
+ include = void 0;
337
+ }
338
+ if (typeof skipNegativeTabIndexCheck !== "boolean") {
339
+ console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
340
+ skipNegativeTabIndexCheck = false;
341
+ }
342
+ if (typeof skipVisibilityCheck !== "boolean") {
343
+ console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
344
+ skipVisibilityCheck = false;
345
+ }
346
+ if (typeof wrap !== "boolean") {
347
+ console.warn("Invalid wrap option. Fallback: false.");
348
+ wrap = false;
349
+ }
350
+ return {
351
+ anchor,
352
+ composed,
353
+ filter,
354
+ include,
355
+ skipNegativeTabIndexCheck,
356
+ skipVisibilityCheck,
357
+ wrap
358
+ };
359
+ }
321
360
 
322
361
  // node_modules/@y14e/button/dist/index.js
323
362
  var Button = class {
@@ -389,56 +428,7 @@ var RovingTabIndex = class _RovingTabIndex {
389
428
  #isDestroyed = false;
390
429
  constructor(container, options = {}) {
391
430
  this.#container = container;
392
- let {
393
- direction = "both",
394
- navigationOnly = false,
395
- noMemory = false,
396
- noStart = false,
397
- selector = "",
398
- typeahead = false,
399
- wrap = false
400
- } = options;
401
- if (!["both", "horizontal", "vertical"].includes(direction)) {
402
- console.warn("Invalid direction option. Fallback: 'both'.");
403
- direction = "both";
404
- }
405
- if (typeof navigationOnly !== "boolean") {
406
- console.warn("Invalid navigationOnly option. Fallback: false.");
407
- navigationOnly = false;
408
- }
409
- if (typeof noMemory !== "boolean") {
410
- console.warn("Invalid noMemory option. Fallback: false.");
411
- noMemory = false;
412
- }
413
- if (typeof noStart !== "boolean") {
414
- console.warn("Invalid noStart option. Fallback: false.");
415
- noStart = false;
416
- }
417
- if (selector !== "") {
418
- try {
419
- document.querySelector(selector);
420
- } catch {
421
- console.warn("Invalid selector. Fallback: no selector string.");
422
- selector = "";
423
- }
424
- }
425
- if (typeof typeahead !== "boolean") {
426
- console.warn("Invalid typeahead option. Fallback: false.");
427
- typeahead = false;
428
- }
429
- if (typeof wrap !== "boolean") {
430
- console.warn("Invalid wrap option. Fallback: false.");
431
- wrap = false;
432
- }
433
- this.#settings = {
434
- direction,
435
- navigationOnly,
436
- noMemory,
437
- noStart,
438
- selector,
439
- typeahead,
440
- wrap
441
- };
431
+ this.#settings = this.#resolveOptions(options);
442
432
  this.#selectorFilter = this.#createSelectorFilter();
443
433
  this.#initialize();
444
434
  }
@@ -449,10 +439,10 @@ var RovingTabIndex = class _RovingTabIndex {
449
439
  this.#isDestroyed = true;
450
440
  this.#controller?.abort();
451
441
  this.#controller = null;
452
- this.#focusables.forEach((focusable) => {
442
+ for (const focusable of this.#focusables) {
453
443
  _RovingTabIndex.#initialized.delete(focusable);
454
444
  restoreAttributes(focusable);
455
- });
445
+ }
456
446
  this.#focusables.clear();
457
447
  this.#focusablesByFirstChar.clear();
458
448
  }
@@ -596,17 +586,17 @@ var RovingTabIndex = class _RovingTabIndex {
596
586
  caseInsensitive: true
597
587
  });
598
588
  }
599
- keys.forEach((key) => {
589
+ for (const key of keys) {
600
590
  const focusables = this.#focusablesByFirstChar.get(key) ?? [];
601
591
  focusables.push(focusable);
602
592
  this.#focusablesByFirstChar.set(key, focusables);
603
- });
593
+ }
604
594
  }
605
595
  if (!navigationOnly) {
606
596
  if (active && this.#focusables.has(active)) {
607
- this.#focusables.forEach((focusable) => {
597
+ for (const focusable of this.#focusables) {
608
598
  focusable.setAttribute("tabindex", focusable === active ? "0" : "-1");
609
- });
599
+ }
610
600
  } else {
611
601
  [...this.#focusables].forEach((focusable, i) => {
612
602
  focusable.setAttribute("tabindex", i || noStart ? "-1" : "0");
@@ -626,6 +616,59 @@ var RovingTabIndex = class _RovingTabIndex {
626
616
  skipVisibilityCheck: true
627
617
  });
628
618
  }
619
+ #resolveOptions(options) {
620
+ let {
621
+ direction = "both",
622
+ navigationOnly = false,
623
+ noMemory = false,
624
+ noStart = false,
625
+ selector = "",
626
+ typeahead = false,
627
+ wrap = false
628
+ } = options;
629
+ direction = direction.toLowerCase();
630
+ if (!["both", "horizontal", "vertical"].includes(direction)) {
631
+ console.warn("Invalid direction option. Fallback: 'both'.");
632
+ direction = "both";
633
+ }
634
+ if (typeof navigationOnly !== "boolean") {
635
+ console.warn("Invalid navigationOnly option. Fallback: false.");
636
+ navigationOnly = false;
637
+ }
638
+ if (typeof noMemory !== "boolean") {
639
+ console.warn("Invalid noMemory option. Fallback: false.");
640
+ noMemory = false;
641
+ }
642
+ if (typeof noStart !== "boolean") {
643
+ console.warn("Invalid noStart option. Fallback: false.");
644
+ noStart = false;
645
+ }
646
+ if (selector !== "") {
647
+ try {
648
+ document.querySelector(selector);
649
+ } catch {
650
+ console.warn("Invalid selector. Fallback: no selector string.");
651
+ selector = "";
652
+ }
653
+ }
654
+ if (typeof typeahead !== "boolean") {
655
+ console.warn("Invalid typeahead option. Fallback: false.");
656
+ typeahead = false;
657
+ }
658
+ if (typeof wrap !== "boolean") {
659
+ console.warn("Invalid wrap option. Fallback: false.");
660
+ wrap = false;
661
+ }
662
+ return {
663
+ direction,
664
+ navigationOnly,
665
+ noMemory,
666
+ noStart,
667
+ selector,
668
+ typeahead,
669
+ wrap
670
+ };
671
+ }
629
672
  };
630
673
 
631
674
  // src/index.ts
@@ -714,15 +757,15 @@ var Accordion = class _Accordion {
714
757
  this.#eventController = null;
715
758
  this.#cleanupRovingTabIndex?.();
716
759
  this.#cleanupRovingTabIndex = null;
717
- this.#buttons.forEach((button) => {
760
+ for (const button of this.#buttons) {
718
761
  button.destroy();
719
- });
762
+ }
720
763
  this.#buttons.length = 0;
721
764
  !force && await this.#waitAnimationsFinish();
722
- this.#contentElements.forEach((content) => {
765
+ for (const content of this.#contentElements) {
723
766
  force && this.#bindings.get(content)?.animation?.finish();
724
767
  this.#onContentAnimationFinish(content);
725
- });
768
+ }
726
769
  this.#animationController?.abort();
727
770
  this.#animationController = null;
728
771
  restoreAttributes([
@@ -807,9 +850,9 @@ var Accordion = class _Accordion {
807
850
  return;
808
851
  }
809
852
  trigger.ariaExpanded === "false" && content.setAttribute("hidden", "until-found");
810
- ["block-size", "overflow"].forEach((name) => {
853
+ for (const name of ["block-size", "overflow"]) {
811
854
  content.style.removeProperty(name);
812
- });
855
+ }
813
856
  }
814
857
  #onContentBeforeMatch = (event) => {
815
858
  const content = event.currentTarget;
@@ -936,10 +979,10 @@ var Accordion = class _Accordion {
936
979
  }
937
980
  async #waitAnimationsFinish() {
938
981
  const promises = [];
939
- this.#contentElements.forEach((content) => {
982
+ for (const content of this.#contentElements) {
940
983
  const animation = this.#bindings.get(content)?.animation;
941
984
  animation && promises.push(waitAnimationFinish(animation));
942
- });
985
+ }
943
986
  await Promise.allSettled(promises);
944
987
  }
945
988
  };
@@ -952,7 +995,7 @@ function waitAnimationFinish(animation) {
952
995
  * Accordion
953
996
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
954
997
  *
955
- * @version 2.0.13
998
+ * @version 2.0.15
956
999
  * @author Yusuke Kamiyamane
957
1000
  * @license MIT
958
1001
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -964,7 +1007,7 @@ function waitAnimationFinish(animation) {
964
1007
  (**
965
1008
  * Attribute Utils
966
1009
  *
967
- * @version 2.0.5
1010
+ * @version 2.0.10
968
1011
  * @author Yusuke Kamiyamane
969
1012
  * @license MIT
970
1013
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -977,7 +1020,7 @@ power-focusable/dist/index.js:
977
1020
  * High-precision focus management utility with full composed tree support.
978
1021
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
979
1022
  *
980
- * @version 4.3.28
1023
+ * @version 4.3.30
981
1024
  * @author Yusuke Kamiyamane
982
1025
  * @license MIT
983
1026
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1001,7 +1044,7 @@ power-focusable/dist/index.js:
1001
1044
  * Lightweight roving tabindex utility with fully focus management.
1002
1045
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
1003
1046
  *
1004
- * @version 3.1.25
1047
+ * @version 3.1.28
1005
1048
  * @author Yusuke Kamiyamane
1006
1049
  * @license MIT
1007
1050
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -2,12 +2,11 @@
2
2
  var DEFAULT_PARSER = (value) => value.split(/\s+/);
3
3
  var DEFAULT_SERIALIZER = (tokens) => tokens.join(" ");
4
4
  function addAttributeToken(element, name, token, options = {}) {
5
+ if (!isValid(element, name, token)) {
6
+ return;
7
+ }
5
8
  const value = element.getAttribute(name)?.trim();
6
- const {
7
- caseInsensitive = false,
8
- parse = DEFAULT_PARSER,
9
- serialize = DEFAULT_SERIALIZER
10
- } = options;
9
+ const { caseInsensitive, parse, serialize } = resolveOptions(options);
11
10
  const tokens = value ? parse(value).filter(Boolean) : [];
12
11
  if (caseInsensitive) {
13
12
  const lower = token.toLowerCase();
@@ -36,20 +35,61 @@ function restoreAttributes(element_or_elements) {
36
35
  }
37
36
  function saveAttributes(element_or_elements, name_or_names) {
38
37
  const names = Array.isArray(name_or_names) ? name_or_names : [name_or_names];
39
- (Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
38
+ for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
40
39
  let snapshot = snapshots.get(element);
41
40
  if (!snapshot) {
42
41
  snapshot = /* @__PURE__ */ new Map();
43
42
  snapshots.set(element, snapshot);
44
43
  }
45
- names.forEach((name) => {
44
+ for (const name of names) {
46
45
  snapshot.set(name, element.getAttribute(name));
47
- });
48
- });
46
+ }
47
+ }
48
+ }
49
+ function isValid(element, name, token) {
50
+ if (!(element instanceof Element)) {
51
+ console.warn("Invalid element");
52
+ return false;
53
+ }
54
+ try {
55
+ document.createElement("div").setAttribute(name, "");
56
+ } catch {
57
+ console.warn(`Invalid attribute name: '${name}'`);
58
+ return false;
59
+ }
60
+ if (typeof token !== "string" || !token.trim()) {
61
+ console.warn("Invalid token");
62
+ return false;
63
+ }
64
+ return true;
65
+ }
66
+ function resolveOptions(options) {
67
+ let {
68
+ caseInsensitive = false,
69
+ parse = DEFAULT_PARSER,
70
+ serialize = DEFAULT_SERIALIZER
71
+ } = options;
72
+ if (typeof caseInsensitive !== "boolean") {
73
+ console.warn("Invalid caseInsensitive option. Fallback: false.");
74
+ caseInsensitive = false;
75
+ }
76
+ if (typeof parse !== "function") {
77
+ console.warn(
78
+ "Invalid parser. Fallback: default parser (splits by whitespace)."
79
+ );
80
+ parse = DEFAULT_PARSER;
81
+ }
82
+ if (typeof serialize !== "function") {
83
+ console.warn(
84
+ "Invalid serializer. Fallback: default serializer (joins by whitespace)."
85
+ );
86
+ serialize = DEFAULT_SERIALIZER;
87
+ }
88
+ return { caseInsensitive, parse, serialize };
49
89
  }
50
90
 
51
91
  // node_modules/power-focusable/dist/index.js
52
- var FOCUSABLE_SELECTOR = `:is(a[href], area[href], button, embed, iframe, input:not([type="hidden" i]), object, select, details > summary:first-of-type, textarea, [contenteditable]:not([contenteditable="false" i]), [controls], [tabindex]):not(:disabled, [hidden], [inert], [tabindex="-1"])`;
92
+ var FOCUSABLE_SELECTOR = ':is(a[href], area[href], button, embed, iframe, input:not([type="hidden" i]), object, select, details > summary:first-of-type, textarea, [contenteditable]:not([contenteditable="false" i]), [controls], [tabindex]):not(:disabled, [hidden], [inert], [tabindex="-1"])';
53
93
  var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX = FOCUSABLE_SELECTOR.replace(
54
94
  /(,\s*)?\[tabindex="-1"\]/g,
55
95
  ""
@@ -59,37 +99,13 @@ function getFocusables(container = document.body, options = {}) {
59
99
  console.warn("Invalid container element. Fallback: <body> element.");
60
100
  container = document.body;
61
101
  }
62
- let {
63
- composed = false,
102
+ const {
103
+ composed,
64
104
  filter,
65
105
  include,
66
- skipNegativeTabIndexCheck = false,
67
- skipVisibilityCheck = false
68
- } = options;
69
- if (typeof composed !== "boolean") {
70
- console.warn("Invalid composed option. Fallback: false.");
71
- composed = false;
72
- }
73
- if (typeof filter !== "undefined" && typeof filter !== "function") {
74
- console.warn(
75
- "Invalid filter function. Fallback: no filter function (undefined)."
76
- );
77
- filter = void 0;
78
- }
79
- if (typeof include !== "undefined" && typeof include !== "function") {
80
- console.warn(
81
- "Invalid include function. Fallback: no include function (undefined)."
82
- );
83
- include = void 0;
84
- }
85
- if (typeof skipNegativeTabIndexCheck !== "boolean") {
86
- console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
87
- skipNegativeTabIndexCheck = false;
88
- }
89
- if (typeof skipVisibilityCheck !== "boolean") {
90
- console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
91
- skipVisibilityCheck = false;
92
- }
106
+ skipNegativeTabIndexCheck,
107
+ skipVisibilityCheck
108
+ } = resolveOptions2(options);
93
109
  const candidates = [];
94
110
  if (composed || include) {
95
111
  let traverse2 = function(node) {
@@ -99,29 +115,19 @@ function getFocusables(container = document.body, options = {}) {
99
115
  }) || include?.(node)) {
100
116
  candidates[candidates.length] = node;
101
117
  }
102
- const children2 = composed ? getComposedChildren(node) : getChildren(node);
103
- for (let i = 0, l = children2.length; i < l; i++) {
104
- const child = children2[i];
105
- child && traverse2(child);
106
- }
118
+ (composed ? getComposedChildren(node) : getChildren(node)).map(traverse2);
107
119
  };
108
- const children = composed ? getComposedChildren(container) : getChildren(container);
109
- for (let i = 0, l = children.length; i < l; i++) {
110
- const child = children[i];
111
- child && traverse2(child);
112
- }
120
+ (composed ? getComposedChildren(container) : getChildren(container)).map(
121
+ traverse2
122
+ );
113
123
  } else {
114
- const matches = container.querySelectorAll(
124
+ for (const match of container.querySelectorAll(
115
125
  skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
116
- );
117
- for (let i = 0, l = matches.length; i < l; i++) {
118
- const matched = matches[i];
119
- if (matched && isFocusable(matched, {
126
+ )) {
127
+ match && isFocusable(match, {
120
128
  skipNegativeTabIndexCheck,
121
129
  skipVisibilityCheck
122
- })) {
123
- candidates[candidates.length] = matched;
124
- }
130
+ }) && candidates.push(match);
125
131
  }
126
132
  }
127
133
  return normalizeRadioGroup(
@@ -133,15 +139,7 @@ function isFocusable(element, options = {}) {
133
139
  console.warn("Invalid element");
134
140
  return false;
135
141
  }
136
- let { skipNegativeTabIndexCheck = false, skipVisibilityCheck = false } = options;
137
- if (typeof skipNegativeTabIndexCheck !== "boolean") {
138
- console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
139
- skipNegativeTabIndexCheck = false;
140
- }
141
- if (typeof skipVisibilityCheck !== "boolean") {
142
- console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
143
- skipVisibilityCheck = false;
144
- }
142
+ const { skipNegativeTabIndexCheck, skipVisibilityCheck } = resolveOptions2(options);
145
143
  if (element.hasAttribute("hidden") || isInert(element)) {
146
144
  return false;
147
145
  }
@@ -196,8 +194,7 @@ function isDisabledDeep(element) {
196
194
  }
197
195
  function normalizeRadioGroup(elements) {
198
196
  let map = null;
199
- for (let i = 0, l = elements.length; i < l; i++) {
200
- const element = elements[i];
197
+ for (const element of elements) {
201
198
  if (!(element instanceof HTMLInputElement)) {
202
199
  continue;
203
200
  }
@@ -247,23 +244,10 @@ function normalizeRadioGroup(elements) {
247
244
  function sortByTabIndex(elements) {
248
245
  const ordered = [];
249
246
  const natural = [];
250
- for (let i = 0, l = elements.length; i < l; i++) {
251
- const element = elements[i];
252
- if (element) {
253
- const target = getTabIndex(element) > 0 ? ordered : natural;
254
- target[target.length] = element;
255
- }
256
- }
257
- ordered.sort((a, b) => getTabIndex(a) - getTabIndex(b));
258
- let count = 0;
259
- const sorted = new Array(ordered.length + natural.length);
260
- for (let i = 0, l = ordered.length; i < l; i++) {
261
- sorted[count++] = ordered[i];
247
+ for (const element of elements) {
248
+ (getTabIndex(element) > 0 ? ordered : natural).push(element);
262
249
  }
263
- for (let i = 0, l = natural.length; i < l; i++) {
264
- sorted[count++] = natural[i];
265
- }
266
- return sorted;
250
+ return ordered.sort((a, b) => getTabIndex(a) - getTabIndex(b)).concat(natural);
267
251
  }
268
252
  function getComposedChildren(node) {
269
253
  if (node instanceof ShadowRoot) {
@@ -316,6 +300,61 @@ function isInert(element) {
316
300
  function isUngroupedRadio(element) {
317
301
  return element.type === "radio" && !!element.name;
318
302
  }
303
+ function resolveOptions2(options) {
304
+ let {
305
+ anchor = getActiveElement(),
306
+ composed = false,
307
+ filter,
308
+ include,
309
+ skipNegativeTabIndexCheck = false,
310
+ skipVisibilityCheck = false,
311
+ wrap = false
312
+ } = options;
313
+ if (!(anchor instanceof Element)) {
314
+ const active = getActiveElement();
315
+ if (active instanceof Element) {
316
+ console.warn("Invalid anchor element. Fallback: active element.");
317
+ anchor = active;
318
+ }
319
+ }
320
+ if (typeof composed !== "boolean") {
321
+ console.warn("Invalid composed option. Fallback: false.");
322
+ composed = false;
323
+ }
324
+ if (filter !== void 0 && typeof filter !== "function") {
325
+ console.warn(
326
+ "Invalid filter function. Fallback: no filter function (undefined)."
327
+ );
328
+ filter = void 0;
329
+ }
330
+ if (include !== void 0 && typeof include !== "function") {
331
+ console.warn(
332
+ "Invalid include function. Fallback: no include function (undefined)."
333
+ );
334
+ include = void 0;
335
+ }
336
+ if (typeof skipNegativeTabIndexCheck !== "boolean") {
337
+ console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
338
+ skipNegativeTabIndexCheck = false;
339
+ }
340
+ if (typeof skipVisibilityCheck !== "boolean") {
341
+ console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
342
+ skipVisibilityCheck = false;
343
+ }
344
+ if (typeof wrap !== "boolean") {
345
+ console.warn("Invalid wrap option. Fallback: false.");
346
+ wrap = false;
347
+ }
348
+ return {
349
+ anchor,
350
+ composed,
351
+ filter,
352
+ include,
353
+ skipNegativeTabIndexCheck,
354
+ skipVisibilityCheck,
355
+ wrap
356
+ };
357
+ }
319
358
 
320
359
  // node_modules/@y14e/button/dist/index.js
321
360
  var Button = class {
@@ -387,56 +426,7 @@ var RovingTabIndex = class _RovingTabIndex {
387
426
  #isDestroyed = false;
388
427
  constructor(container, options = {}) {
389
428
  this.#container = container;
390
- let {
391
- direction = "both",
392
- navigationOnly = false,
393
- noMemory = false,
394
- noStart = false,
395
- selector = "",
396
- typeahead = false,
397
- wrap = false
398
- } = options;
399
- if (!["both", "horizontal", "vertical"].includes(direction)) {
400
- console.warn("Invalid direction option. Fallback: 'both'.");
401
- direction = "both";
402
- }
403
- if (typeof navigationOnly !== "boolean") {
404
- console.warn("Invalid navigationOnly option. Fallback: false.");
405
- navigationOnly = false;
406
- }
407
- if (typeof noMemory !== "boolean") {
408
- console.warn("Invalid noMemory option. Fallback: false.");
409
- noMemory = false;
410
- }
411
- if (typeof noStart !== "boolean") {
412
- console.warn("Invalid noStart option. Fallback: false.");
413
- noStart = false;
414
- }
415
- if (selector !== "") {
416
- try {
417
- document.querySelector(selector);
418
- } catch {
419
- console.warn("Invalid selector. Fallback: no selector string.");
420
- selector = "";
421
- }
422
- }
423
- if (typeof typeahead !== "boolean") {
424
- console.warn("Invalid typeahead option. Fallback: false.");
425
- typeahead = false;
426
- }
427
- if (typeof wrap !== "boolean") {
428
- console.warn("Invalid wrap option. Fallback: false.");
429
- wrap = false;
430
- }
431
- this.#settings = {
432
- direction,
433
- navigationOnly,
434
- noMemory,
435
- noStart,
436
- selector,
437
- typeahead,
438
- wrap
439
- };
429
+ this.#settings = this.#resolveOptions(options);
440
430
  this.#selectorFilter = this.#createSelectorFilter();
441
431
  this.#initialize();
442
432
  }
@@ -447,10 +437,10 @@ var RovingTabIndex = class _RovingTabIndex {
447
437
  this.#isDestroyed = true;
448
438
  this.#controller?.abort();
449
439
  this.#controller = null;
450
- this.#focusables.forEach((focusable) => {
440
+ for (const focusable of this.#focusables) {
451
441
  _RovingTabIndex.#initialized.delete(focusable);
452
442
  restoreAttributes(focusable);
453
- });
443
+ }
454
444
  this.#focusables.clear();
455
445
  this.#focusablesByFirstChar.clear();
456
446
  }
@@ -594,17 +584,17 @@ var RovingTabIndex = class _RovingTabIndex {
594
584
  caseInsensitive: true
595
585
  });
596
586
  }
597
- keys.forEach((key) => {
587
+ for (const key of keys) {
598
588
  const focusables = this.#focusablesByFirstChar.get(key) ?? [];
599
589
  focusables.push(focusable);
600
590
  this.#focusablesByFirstChar.set(key, focusables);
601
- });
591
+ }
602
592
  }
603
593
  if (!navigationOnly) {
604
594
  if (active && this.#focusables.has(active)) {
605
- this.#focusables.forEach((focusable) => {
595
+ for (const focusable of this.#focusables) {
606
596
  focusable.setAttribute("tabindex", focusable === active ? "0" : "-1");
607
- });
597
+ }
608
598
  } else {
609
599
  [...this.#focusables].forEach((focusable, i) => {
610
600
  focusable.setAttribute("tabindex", i || noStart ? "-1" : "0");
@@ -624,6 +614,59 @@ var RovingTabIndex = class _RovingTabIndex {
624
614
  skipVisibilityCheck: true
625
615
  });
626
616
  }
617
+ #resolveOptions(options) {
618
+ let {
619
+ direction = "both",
620
+ navigationOnly = false,
621
+ noMemory = false,
622
+ noStart = false,
623
+ selector = "",
624
+ typeahead = false,
625
+ wrap = false
626
+ } = options;
627
+ direction = direction.toLowerCase();
628
+ if (!["both", "horizontal", "vertical"].includes(direction)) {
629
+ console.warn("Invalid direction option. Fallback: 'both'.");
630
+ direction = "both";
631
+ }
632
+ if (typeof navigationOnly !== "boolean") {
633
+ console.warn("Invalid navigationOnly option. Fallback: false.");
634
+ navigationOnly = false;
635
+ }
636
+ if (typeof noMemory !== "boolean") {
637
+ console.warn("Invalid noMemory option. Fallback: false.");
638
+ noMemory = false;
639
+ }
640
+ if (typeof noStart !== "boolean") {
641
+ console.warn("Invalid noStart option. Fallback: false.");
642
+ noStart = false;
643
+ }
644
+ if (selector !== "") {
645
+ try {
646
+ document.querySelector(selector);
647
+ } catch {
648
+ console.warn("Invalid selector. Fallback: no selector string.");
649
+ selector = "";
650
+ }
651
+ }
652
+ if (typeof typeahead !== "boolean") {
653
+ console.warn("Invalid typeahead option. Fallback: false.");
654
+ typeahead = false;
655
+ }
656
+ if (typeof wrap !== "boolean") {
657
+ console.warn("Invalid wrap option. Fallback: false.");
658
+ wrap = false;
659
+ }
660
+ return {
661
+ direction,
662
+ navigationOnly,
663
+ noMemory,
664
+ noStart,
665
+ selector,
666
+ typeahead,
667
+ wrap
668
+ };
669
+ }
627
670
  };
628
671
 
629
672
  // src/index.ts
@@ -712,15 +755,15 @@ var Accordion = class _Accordion {
712
755
  this.#eventController = null;
713
756
  this.#cleanupRovingTabIndex?.();
714
757
  this.#cleanupRovingTabIndex = null;
715
- this.#buttons.forEach((button) => {
758
+ for (const button of this.#buttons) {
716
759
  button.destroy();
717
- });
760
+ }
718
761
  this.#buttons.length = 0;
719
762
  !force && await this.#waitAnimationsFinish();
720
- this.#contentElements.forEach((content) => {
763
+ for (const content of this.#contentElements) {
721
764
  force && this.#bindings.get(content)?.animation?.finish();
722
765
  this.#onContentAnimationFinish(content);
723
- });
766
+ }
724
767
  this.#animationController?.abort();
725
768
  this.#animationController = null;
726
769
  restoreAttributes([
@@ -805,9 +848,9 @@ var Accordion = class _Accordion {
805
848
  return;
806
849
  }
807
850
  trigger.ariaExpanded === "false" && content.setAttribute("hidden", "until-found");
808
- ["block-size", "overflow"].forEach((name) => {
851
+ for (const name of ["block-size", "overflow"]) {
809
852
  content.style.removeProperty(name);
810
- });
853
+ }
811
854
  }
812
855
  #onContentBeforeMatch = (event) => {
813
856
  const content = event.currentTarget;
@@ -934,10 +977,10 @@ var Accordion = class _Accordion {
934
977
  }
935
978
  async #waitAnimationsFinish() {
936
979
  const promises = [];
937
- this.#contentElements.forEach((content) => {
980
+ for (const content of this.#contentElements) {
938
981
  const animation = this.#bindings.get(content)?.animation;
939
982
  animation && promises.push(waitAnimationFinish(animation));
940
- });
983
+ }
941
984
  await Promise.allSettled(promises);
942
985
  }
943
986
  };
@@ -950,7 +993,7 @@ function waitAnimationFinish(animation) {
950
993
  * Accordion
951
994
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
952
995
  *
953
- * @version 2.0.13
996
+ * @version 2.0.15
954
997
  * @author Yusuke Kamiyamane
955
998
  * @license MIT
956
999
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -962,7 +1005,7 @@ function waitAnimationFinish(animation) {
962
1005
  (**
963
1006
  * Attribute Utils
964
1007
  *
965
- * @version 2.0.5
1008
+ * @version 2.0.10
966
1009
  * @author Yusuke Kamiyamane
967
1010
  * @license MIT
968
1011
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -975,7 +1018,7 @@ power-focusable/dist/index.js:
975
1018
  * High-precision focus management utility with full composed tree support.
976
1019
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
977
1020
  *
978
- * @version 4.3.28
1021
+ * @version 4.3.30
979
1022
  * @author Yusuke Kamiyamane
980
1023
  * @license MIT
981
1024
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -999,7 +1042,7 @@ power-focusable/dist/index.js:
999
1042
  * Lightweight roving tabindex utility with fully focus management.
1000
1043
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
1001
1044
  *
1002
- * @version 3.1.25
1045
+ * @version 3.1.28
1003
1046
  * @author Yusuke Kamiyamane
1004
1047
  * @license MIT
1005
1048
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.cjs CHANGED
@@ -110,15 +110,15 @@ var Accordion = class _Accordion {
110
110
  this.#eventController = null;
111
111
  this.#cleanupRovingTabIndex?.();
112
112
  this.#cleanupRovingTabIndex = null;
113
- this.#buttons.forEach((button) => {
113
+ for (const button of this.#buttons) {
114
114
  button.destroy();
115
- });
115
+ }
116
116
  this.#buttons.length = 0;
117
117
  !force && await this.#waitAnimationsFinish();
118
- this.#contentElements.forEach((content) => {
118
+ for (const content of this.#contentElements) {
119
119
  force && this.#bindings.get(content)?.animation?.finish();
120
120
  this.#onContentAnimationFinish(content);
121
- });
121
+ }
122
122
  this.#animationController?.abort();
123
123
  this.#animationController = null;
124
124
  utils__namespace.restoreAttributes([
@@ -203,9 +203,9 @@ var Accordion = class _Accordion {
203
203
  return;
204
204
  }
205
205
  trigger.ariaExpanded === "false" && content.setAttribute("hidden", "until-found");
206
- ["block-size", "overflow"].forEach((name) => {
206
+ for (const name of ["block-size", "overflow"]) {
207
207
  content.style.removeProperty(name);
208
- });
208
+ }
209
209
  }
210
210
  #onContentBeforeMatch = (event) => {
211
211
  const content = event.currentTarget;
@@ -332,10 +332,10 @@ var Accordion = class _Accordion {
332
332
  }
333
333
  async #waitAnimationsFinish() {
334
334
  const promises = [];
335
- this.#contentElements.forEach((content) => {
335
+ for (const content of this.#contentElements) {
336
336
  const animation = this.#bindings.get(content)?.animation;
337
337
  animation && promises.push(waitAnimationFinish(animation));
338
- });
338
+ }
339
339
  await Promise.allSettled(promises);
340
340
  }
341
341
  };
@@ -348,7 +348,7 @@ function waitAnimationFinish(animation) {
348
348
  * Accordion
349
349
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
350
350
  *
351
- * @version 2.0.13
351
+ * @version 2.0.15
352
352
  * @author Yusuke Kamiyamane
353
353
  * @license MIT
354
354
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.d.cts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Accordion
3
3
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
4
4
  *
5
- * @version 2.0.13
5
+ * @version 2.0.15
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
  * Accordion
3
3
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
4
4
  *
5
- * @version 2.0.13
5
+ * @version 2.0.15
6
6
  * @author Yusuke Kamiyamane
7
7
  * @license MIT
8
8
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.js CHANGED
@@ -88,15 +88,15 @@ var Accordion = class _Accordion {
88
88
  this.#eventController = null;
89
89
  this.#cleanupRovingTabIndex?.();
90
90
  this.#cleanupRovingTabIndex = null;
91
- this.#buttons.forEach((button) => {
91
+ for (const button of this.#buttons) {
92
92
  button.destroy();
93
- });
93
+ }
94
94
  this.#buttons.length = 0;
95
95
  !force && await this.#waitAnimationsFinish();
96
- this.#contentElements.forEach((content) => {
96
+ for (const content of this.#contentElements) {
97
97
  force && this.#bindings.get(content)?.animation?.finish();
98
98
  this.#onContentAnimationFinish(content);
99
- });
99
+ }
100
100
  this.#animationController?.abort();
101
101
  this.#animationController = null;
102
102
  utils.restoreAttributes([
@@ -181,9 +181,9 @@ var Accordion = class _Accordion {
181
181
  return;
182
182
  }
183
183
  trigger.ariaExpanded === "false" && content.setAttribute("hidden", "until-found");
184
- ["block-size", "overflow"].forEach((name) => {
184
+ for (const name of ["block-size", "overflow"]) {
185
185
  content.style.removeProperty(name);
186
- });
186
+ }
187
187
  }
188
188
  #onContentBeforeMatch = (event) => {
189
189
  const content = event.currentTarget;
@@ -310,10 +310,10 @@ var Accordion = class _Accordion {
310
310
  }
311
311
  async #waitAnimationsFinish() {
312
312
  const promises = [];
313
- this.#contentElements.forEach((content) => {
313
+ for (const content of this.#contentElements) {
314
314
  const animation = this.#bindings.get(content)?.animation;
315
315
  animation && promises.push(waitAnimationFinish(animation));
316
- });
316
+ }
317
317
  await Promise.allSettled(promises);
318
318
  }
319
319
  };
@@ -326,7 +326,7 @@ function waitAnimationFinish(animation) {
326
326
  * Accordion
327
327
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
328
328
  *
329
- * @version 2.0.13
329
+ * @version 2.0.15
330
330
  * @author Yusuke Kamiyamane
331
331
  * @license MIT
332
332
  * @copyright Copyright (c) Yusuke Kamiyamane
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@y14e/accordion",
3
- "version": "2.0.13",
3
+ "version": "2.0.15",
4
4
  "description": "WAI-ARIA compliant accordion pattern implementation in TypeScript",
5
5
  "keywords": [
6
6
  "a11y",
@@ -54,8 +54,8 @@
54
54
  "esbuild": true
55
55
  },
56
56
  "dependencies": {
57
- "@y14e/attribute-utils": "^2.0.5",
57
+ "@y14e/attribute-utils": "^2.0.10",
58
58
  "@y14e/button": "^1.0.8",
59
- "@y14e/roving-tabindex": "^3.1.25"
59
+ "@y14e/roving-tabindex": "^3.1.28"
60
60
  }
61
61
  }