@y14e/accordion 2.0.2 → 2.0.4

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.2';
16
+ import Accordion from "https://esm.sh/@y14e/accordion@2.0.4";
17
17
  // or
18
- import Accordion from 'https://cdn.jsdelivr.net/npm/@y14e/accordion@2.0.2/+esm';
18
+ import Accordion from "https://cdn.jsdelivr.net/npm/@y14e/accordion@2.0.4/+esm";
19
19
  // or
20
- import Accordion from 'https://esm.unpkg.com/@y14e/accordion@2.0.2';
20
+ import Accordion from "https://esm.unpkg.com/@y14e/accordion@2.0.4";
21
21
  ```
22
22
 
23
23
  ## Usage
@@ -28,21 +28,20 @@ new Accordion(root, options);
28
28
  //
29
29
  // root: HTMLElement
30
30
  // options (optional): AccordionOptions
31
-
32
31
  ```
33
32
 
34
33
  ## 🪄 Options
35
34
 
36
35
  ```ts
37
36
  interface AccordionOptions {
38
- animation?: {
39
- duration?: number; // ms (default: 300)
40
- easing?: string; // <easing-function> (default: 'ease')
37
+ animation: {
38
+ duration: number; // ms (default: 300)
39
+ easing: string; // <easing-function> (default: 'ease')
41
40
  };
42
- collapsible?: boolean; // default: true
43
- selector?: {
44
- content?: string; // default: '[data-accordion-content]'
45
- trigger?: string; // default: '[data-accordion-trigger]'
41
+ collapsible: boolean; // default: true
42
+ selector: {
43
+ content: string; // default: '[data-accordion-content]'
44
+ trigger: string; // default: '[data-accordion-trigger]'
46
45
  };
47
46
  }
48
47
  ```
@@ -52,15 +51,15 @@ interface AccordionOptions {
52
51
  Override the global default settings applied to all accordion instances.
53
52
 
54
53
  ```ts
55
- import Accordion from '@y14e/accordion';
54
+ import Accordion from "@y14e/accordion";
56
55
 
57
56
  Accordion.defaults = {
58
57
  animation: {
59
58
  duration: 1000,
60
59
  },
61
60
  selector: {
62
- content: '.content',
63
- trigger: '.trigger',
61
+ content: ".content",
62
+ trigger: ".trigger",
64
63
  },
65
64
  };
66
65
 
@@ -3,8 +3,8 @@
3
3
  // node_modules/@y14e/attributes-utils/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,42 +15,48 @@ 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();
27
- function restoreAttributes(elements) {
28
- for (const element of elements) {
27
+ function restoreAttributes(element_or_elements) {
28
+ for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
29
29
  const snapshot = snapshots.get(element);
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(elements, attributes) {
40
- elements.forEach((element) => {
39
+ function saveAttributes(element_or_elements, name_or_names) {
40
+ 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) => {
41
42
  let snapshot = snapshots.get(element);
42
43
  if (!snapshot) {
43
44
  snapshot = /* @__PURE__ */ new Map();
44
45
  snapshots.set(element, snapshot);
45
46
  }
46
- attributes.forEach((attribute) => {
47
- snapshot.set(attribute, element.getAttribute(attribute));
47
+ names.forEach((name) => {
48
+ snapshot.set(name, element.getAttribute(name));
48
49
  });
49
50
  });
50
51
  }
52
+ var addTokenToAttribute = addAttributeToken;
51
53
 
52
54
  // node_modules/power-focusable/dist/index.js
53
55
  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"])`;
56
+ var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX = FOCUSABLE_SELECTOR.replace(
57
+ /(,\s*)?\[tabindex="-1"\]/g,
58
+ ""
59
+ );
54
60
  function getFocusables(container = document.body, options = {}) {
55
61
  if (!(container instanceof Element)) {
56
62
  console.warn("Invalid container element. Fallback: <body> element.");
@@ -87,36 +93,43 @@ function getFocusables(container = document.body, options = {}) {
87
93
  console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
88
94
  skipVisibilityCheck = false;
89
95
  }
90
- const elements = [];
96
+ const candidates = [];
91
97
  if (composed || include) {
92
98
  let traverse2 = function(node) {
93
- if (!(node instanceof Element)) {
94
- return;
95
- }
96
- if (isFocusable(node, { skipNegativeTabIndexCheck, skipVisibilityCheck }) || include?.(node)) {
97
- elements[elements.length] = node;
99
+ if (isFocusable(node, {
100
+ skipNegativeTabIndexCheck,
101
+ skipVisibilityCheck
102
+ }) || include?.(node)) {
103
+ candidates[candidates.length] = node;
98
104
  }
99
- const children = getComposedChildren(node);
100
- for (let i = 0, l = children.length; i < l; i++) {
101
- const child = children[i];
105
+ const children2 = composed ? getComposedChildren(node) : getChildren(node);
106
+ for (let i = 0, l = children2.length; i < l; i++) {
107
+ const child = children2[i];
102
108
  child && traverse2(child);
103
109
  }
104
110
  };
105
- traverse2(container);
111
+ const children = composed ? getComposedChildren(container) : getChildren(container);
112
+ for (let i = 0, l = children.length; i < l; i++) {
113
+ const child = children[i];
114
+ child && traverse2(child);
115
+ }
106
116
  } else {
107
- const candidates = container.querySelectorAll(FOCUSABLE_SELECTOR);
108
- for (let i = 0, l = candidates.length; i < l; i++) {
109
- const candidate = candidates[i];
110
- if (candidate && isFocusable(candidate, {
117
+ const matches = container.querySelectorAll(
118
+ skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
119
+ );
120
+ for (let i = 0, l = matches.length; i < l; i++) {
121
+ const matched = matches[i];
122
+ if (matched && isFocusable(matched, {
111
123
  skipNegativeTabIndexCheck,
112
124
  skipVisibilityCheck
113
125
  })) {
114
- elements[elements.length] = candidate;
126
+ candidates[candidates.length] = matched;
115
127
  }
116
128
  }
117
129
  }
118
- const unfiltered = normalizeRadioGroup(sortByTabIndex(elements));
119
- return filter ? unfiltered.filter(filter) : unfiltered;
130
+ return normalizeRadioGroup(
131
+ sortByTabIndex(filter ? candidates.filter(filter) : candidates)
132
+ );
120
133
  }
121
134
  function isFocusable(element, options = {}) {
122
135
  if (!(element instanceof Element)) {
@@ -139,7 +152,7 @@ function isFocusable(element, options = {}) {
139
152
  return false;
140
153
  }
141
154
  if (!element.matches(
142
- skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR.replace(/(,\s*)?\[tabindex="-1"\]/g, "") : FOCUSABLE_SELECTOR
155
+ skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
143
156
  )) {
144
157
  return false;
145
158
  }
@@ -197,22 +210,42 @@ function normalizeRadioGroup(elements) {
197
210
  if (!map) {
198
211
  map = /* @__PURE__ */ new Map();
199
212
  }
200
- const key = `${element.form?.id ?? "no-form"}::${element.name}`;
201
- const group = map.get(key) ?? map.set(key, []).get(key);
202
- if (group) {
203
- group[group.length] = element;
213
+ const root = element.getRootNode();
214
+ let value = map.get(root);
215
+ if (!value) {
216
+ value = /* @__PURE__ */ new Map();
217
+ map.set(root, value);
218
+ }
219
+ let v = value.get(element.form);
220
+ if (!v) {
221
+ v = /* @__PURE__ */ new Map();
222
+ value.set(element.form, v);
223
+ }
224
+ let vv = v.get(element.name);
225
+ if (!vv) {
226
+ vv = [];
227
+ v.set(element.name, vv);
204
228
  }
229
+ vv[vv.length] = element;
205
230
  }
206
231
  if (!map) {
207
232
  return elements;
208
233
  }
209
234
  const placeholder = /* @__PURE__ */ new Set();
210
- for (const group of map.values()) {
211
- placeholder.add(group.find((radio) => radio.checked) ?? group[0]);
235
+ for (const value of map.values()) {
236
+ for (const v of value.values()) {
237
+ for (const vv of v.values()) {
238
+ const radio = vv.find((element) => element.checked) ?? vv[0];
239
+ radio && placeholder.add(radio);
240
+ }
241
+ }
212
242
  }
213
- return elements.filter(
214
- (element) => isUngroupedRadio(element) ? placeholder.has(element) : true
215
- );
243
+ return elements.filter((element) => {
244
+ if (!(element instanceof HTMLInputElement)) {
245
+ return true;
246
+ }
247
+ return !isUngroupedRadio(element) || placeholder.has(element);
248
+ });
216
249
  }
217
250
  function sortByTabIndex(elements) {
218
251
  const ordered = [];
@@ -284,7 +317,7 @@ function isInert(element) {
284
317
  return "inert" in element && !!element.inert;
285
318
  }
286
319
  function isUngroupedRadio(element) {
287
- return element instanceof HTMLInputElement && element.type === "radio" && !!element.name;
320
+ return element.type === "radio" && !!element.name;
288
321
  }
289
322
 
290
323
  // node_modules/@y14e/button/dist/index.js
@@ -336,6 +369,56 @@ var Button = class {
336
369
  };
337
370
  };
338
371
 
372
+ // node_modules/@y14e/roving-tabindex/node_modules/@y14e/attributes-utils/dist/index.js
373
+ var DEFAULT_PARSER2 = (value) => value.split(/\s+/);
374
+ var DEFAULT_SERIALIZER2 = (tokens) => tokens.join(" ");
375
+ function addTokenToAttribute2(element, name, token, options = {}) {
376
+ const value = element.getAttribute(name)?.trim();
377
+ const {
378
+ caseInsensitive = false,
379
+ parse = DEFAULT_PARSER2,
380
+ serialize = DEFAULT_SERIALIZER2
381
+ } = options;
382
+ const tokens = value ? parse(value).filter(Boolean) : [];
383
+ if (caseInsensitive) {
384
+ const lower = token.toLowerCase();
385
+ if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
386
+ tokens.push(token);
387
+ element.setAttribute(name, serialize(tokens));
388
+ }
389
+ } else {
390
+ const set = new Set(tokens);
391
+ set.add(token);
392
+ element.setAttribute(name, serialize([...set]));
393
+ }
394
+ }
395
+ var snapshots2 = /* @__PURE__ */ new WeakMap();
396
+ function restoreAttributes2(element_or_elements) {
397
+ for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
398
+ const snapshot = snapshots2.get(element);
399
+ if (!snapshot) {
400
+ continue;
401
+ }
402
+ for (const [name, value] of snapshot.entries()) {
403
+ value === null ? element.removeAttribute(name) : element.setAttribute(name, value);
404
+ }
405
+ snapshots2.delete(element);
406
+ }
407
+ }
408
+ function saveAttributes2(element_or_elements, name_or_names) {
409
+ const names = Array.isArray(name_or_names) ? name_or_names : [name_or_names];
410
+ (Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
411
+ let snapshot = snapshots2.get(element);
412
+ if (!snapshot) {
413
+ snapshot = /* @__PURE__ */ new Map();
414
+ snapshots2.set(element, snapshot);
415
+ }
416
+ names.forEach((name) => {
417
+ snapshot.set(name, element.getAttribute(name));
418
+ });
419
+ });
420
+ }
421
+
339
422
  // node_modules/@y14e/roving-tabindex/dist/index.js
340
423
  function createRovingTabIndex(container, options = {}) {
341
424
  if (!(container instanceof Element)) {
@@ -343,14 +426,8 @@ function createRovingTabIndex(container, options = {}) {
343
426
  return () => {
344
427
  };
345
428
  }
346
- try {
347
- const roving = new RovingTabIndex(container, options);
348
- return () => roving.destroy();
349
- } catch (error) {
350
- error instanceof Error && console.warn(error.message || error);
351
- return () => {
352
- };
353
- }
429
+ const roving = new RovingTabIndex(container, options);
430
+ return () => roving.destroy();
354
431
  }
355
432
  var RovingTabIndex = class _RovingTabIndex {
356
433
  static #initialized = /* @__PURE__ */ new Set();
@@ -364,17 +441,17 @@ var RovingTabIndex = class _RovingTabIndex {
364
441
  constructor(container, options = {}) {
365
442
  this.#container = container;
366
443
  let {
367
- direction,
444
+ direction = "both",
368
445
  navigationOnly = false,
369
446
  noMemory = false,
370
447
  noStart = false,
371
- selector,
448
+ selector = "",
372
449
  typeahead = false,
373
450
  wrap = false
374
451
  } = options;
375
- if (typeof direction !== "undefined" && !["horizontal", "vertical"].includes(direction)) {
376
- console.warn("Invalid direction option. Fallback: both (undefined).");
377
- direction = void 0;
452
+ if (!["both", "horizontal", "vertical"].includes(direction)) {
453
+ console.warn("Invalid direction option. Fallback: 'both'.");
454
+ direction = "both";
378
455
  }
379
456
  if (typeof navigationOnly !== "boolean") {
380
457
  console.warn("Invalid navigationOnly option. Fallback: false.");
@@ -388,11 +465,21 @@ var RovingTabIndex = class _RovingTabIndex {
388
465
  console.warn("Invalid noStart option. Fallback: false.");
389
466
  noStart = false;
390
467
  }
391
- if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
392
- console.warn(
393
- "Invalid selector. Fallback: all focusable elements (undefined)."
394
- );
395
- selector = void 0;
468
+ if (selector !== "") {
469
+ let hasError = false;
470
+ if (typeof selector !== "string" || !selector.trim()) {
471
+ hasError = true;
472
+ } else {
473
+ try {
474
+ this.#container.querySelector(selector);
475
+ } catch {
476
+ hasError = true;
477
+ }
478
+ }
479
+ if (hasError) {
480
+ console.warn("Invalid selector. Fallback: no selector string.");
481
+ selector = "";
482
+ }
396
483
  }
397
484
  if (typeof typeahead !== "boolean") {
398
485
  console.warn("Invalid typeahead option. Fallback: false.");
@@ -402,9 +489,15 @@ var RovingTabIndex = class _RovingTabIndex {
402
489
  console.warn("Invalid wrap option. Fallback: false.");
403
490
  wrap = false;
404
491
  }
405
- this.#settings = { navigationOnly, noMemory, noStart, typeahead, wrap };
406
- direction && Object.assign(this.#settings, { direction });
407
- selector && Object.assign(this.#settings, { selector });
492
+ this.#settings = {
493
+ direction,
494
+ navigationOnly,
495
+ noMemory,
496
+ noStart,
497
+ selector,
498
+ typeahead,
499
+ wrap
500
+ };
408
501
  this.#selectorFilter = this.#createSelectorFilter();
409
502
  this.#initialize();
410
503
  }
@@ -415,7 +508,10 @@ var RovingTabIndex = class _RovingTabIndex {
415
508
  this.#isDestroyed = true;
416
509
  this.#controller?.abort();
417
510
  this.#controller = null;
418
- restoreAttributes([...this.#focusables]);
511
+ this.#focusables.forEach((focusable) => {
512
+ _RovingTabIndex.#initialized.delete(focusable);
513
+ restoreAttributes2(focusable);
514
+ });
419
515
  this.#focusables.clear();
420
516
  this.#focusablesByFirstChar.clear();
421
517
  }
@@ -452,7 +548,7 @@ var RovingTabIndex = class _RovingTabIndex {
452
548
  return;
453
549
  }
454
550
  const { direction, typeahead, wrap } = this.#settings;
455
- const isBoth = !direction;
551
+ const isBoth = direction === "both";
456
552
  const isHorizontal = direction === "horizontal";
457
553
  if (![
458
554
  "End",
@@ -464,18 +560,20 @@ var RovingTabIndex = class _RovingTabIndex {
464
560
  return;
465
561
  }
466
562
  }
563
+ const candidates = this.#getFocusables().filter(
564
+ (focusable2) => this.#focusables.has(focusable2)
565
+ );
467
566
  const active = getActiveElement();
468
567
  if (!(active instanceof Element)) {
469
568
  return;
470
569
  }
471
- const current = this.#getFocusables();
472
- if (!current.includes(active)) {
570
+ if (!candidates.includes(active)) {
473
571
  return;
474
572
  }
475
573
  event.preventDefault();
476
- const currentIndex = current.indexOf(active);
477
574
  let newIndex;
478
- let target = current;
575
+ const activeIndex = candidates.indexOf(active);
576
+ let focusables = candidates;
479
577
  switch (key) {
480
578
  case "End":
481
579
  newIndex = -1;
@@ -485,37 +583,47 @@ var RovingTabIndex = class _RovingTabIndex {
485
583
  break;
486
584
  case "ArrowLeft":
487
585
  case "ArrowUp": {
488
- const rawIndex = currentIndex - 1;
586
+ const rawIndex = activeIndex - 1;
489
587
  newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
490
588
  break;
491
589
  }
492
590
  case "ArrowRight":
493
591
  case "ArrowDown": {
494
- const rawIndex = currentIndex + 1;
495
- newIndex = wrap ? rawIndex % current.length : Math.min(rawIndex, current.length - 1);
592
+ const rawIndex = activeIndex + 1;
593
+ const length = focusables.length;
594
+ newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
496
595
  break;
497
596
  }
498
597
  default: {
499
- target = this.#focusablesByFirstChar.get(key.toUpperCase()) ?? [];
500
- const foundIndex = target.findIndex(
501
- (focusable2) => current.indexOf(focusable2) > currentIndex
598
+ const focusablesByFirstChar = new Set(
599
+ this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
600
+ );
601
+ focusables = candidates.filter(
602
+ (candidate) => focusablesByFirstChar.has(candidate)
603
+ );
604
+ const afterIndex = focusables.findIndex(
605
+ (focusable2) => candidates.indexOf(focusable2) > activeIndex
502
606
  );
503
- newIndex = foundIndex >= 0 ? foundIndex : 0;
607
+ newIndex = afterIndex >= 0 ? afterIndex : 0;
504
608
  }
505
609
  }
506
- const focusable = target.at(newIndex);
610
+ const focusable = focusables.at(newIndex);
507
611
  focusable && focusElement(focusable);
508
612
  };
509
613
  #update(active) {
510
614
  const current = new Set(this.#getFocusables());
511
615
  for (const focusable of this.#focusables) {
512
616
  if (!current.has(focusable)) {
513
- focusable.isConnected && restoreAttributes([focusable]);
617
+ _RovingTabIndex.#initialized.delete(focusable);
618
+ restoreAttributes2(focusable);
514
619
  this.#focusables.delete(focusable);
515
- this.#focusablesByFirstChar.forEach((focusables) => {
620
+ for (const [key, focusables] of this.#focusablesByFirstChar) {
516
621
  const index = focusables.indexOf(focusable);
517
- index >= 0 && focusables.splice(index, 1);
518
- });
622
+ if (index >= 0) {
623
+ focusables.splice(index, 1);
624
+ !focusables.length && this.#focusablesByFirstChar.delete(key);
625
+ }
626
+ }
519
627
  }
520
628
  }
521
629
  const { navigationOnly, noStart, typeahead } = this.#settings;
@@ -524,12 +632,12 @@ var RovingTabIndex = class _RovingTabIndex {
524
632
  continue;
525
633
  }
526
634
  if (_RovingTabIndex.#initialized.has(focusable)) {
527
- throw new TypeError("Already initialized");
635
+ continue;
528
636
  }
529
637
  this.#focusables.add(focusable);
530
638
  _RovingTabIndex.#initialized.add(focusable);
531
639
  if (!navigationOnly) {
532
- saveAttributes([focusable], ["tabindex"]);
640
+ saveAttributes2(focusable, "tabindex");
533
641
  focusable.setAttribute("tabindex", "-1");
534
642
  }
535
643
  if (!typeahead) {
@@ -542,8 +650,8 @@ var RovingTabIndex = class _RovingTabIndex {
542
650
  );
543
651
  if (char) {
544
652
  keys.add(char);
545
- saveAttributes([focusable], ["aria-keyshortcuts"]);
546
- addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
653
+ saveAttributes2(focusable, "aria-keyshortcuts");
654
+ addTokenToAttribute2(focusable, "aria-keyshortcuts", char, {
547
655
  caseInsensitive: true
548
656
  });
549
657
  }
@@ -822,7 +930,7 @@ var Accordion = class _Accordion {
822
930
  );
823
931
  }
824
932
  #createBinding(trigger, content) {
825
- return { trigger, content, animation: null };
933
+ return { animation: null, content, trigger };
826
934
  }
827
935
  #isFocusable(element) {
828
936
  return !element.hasAttribute("disabled") && element.tabIndex >= 0;
@@ -853,7 +961,7 @@ function waitAnimationFinish(animation) {
853
961
  * Accordion
854
962
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
855
963
  *
856
- * @version 2.0.2
964
+ * @version 2.0.4
857
965
  * @author Yusuke Kamiyamane
858
966
  * @license MIT
859
967
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -865,7 +973,7 @@ function waitAnimationFinish(animation) {
865
973
  (**
866
974
  * Attributes Utils
867
975
  *
868
- * @version 1.1.3
976
+ * @version 2.0.0
869
977
  * @author Yusuke Kamiyamane
870
978
  * @license MIT
871
979
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -878,7 +986,7 @@ power-focusable/dist/index.js:
878
986
  * High-precision focus management utility with full composed tree support.
879
987
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
880
988
  *
881
- * @version 4.3.8
989
+ * @version 4.3.23
882
990
  * @author Yusuke Kamiyamane
883
991
  * @license MIT
884
992
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -896,13 +1004,24 @@ power-focusable/dist/index.js:
896
1004
  * @see {@link https://github.com/y14e/button}
897
1005
  *)
898
1006
 
1007
+ @y14e/attributes-utils/dist/index.js:
1008
+ (**
1009
+ * Attributes Utils
1010
+ *
1011
+ * @version 1.1.7
1012
+ * @author Yusuke Kamiyamane
1013
+ * @license MIT
1014
+ * @copyright Copyright (c) Yusuke Kamiyamane
1015
+ * @see {@link https://github.com/y14e/attributes-utils}
1016
+ *)
1017
+
899
1018
  @y14e/roving-tabindex/dist/index.js:
900
1019
  (**
901
1020
  * Roving Tabindex
902
1021
  * Lightweight roving tabindex utility with fully focus management.
903
1022
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
904
1023
  *
905
- * @version 3.1.6
1024
+ * @version 3.1.20
906
1025
  * @author Yusuke Kamiyamane
907
1026
  * @license MIT
908
1027
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1,8 +1,8 @@
1
1
  // node_modules/@y14e/attributes-utils/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,42 +13,48 @@ 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();
25
- function restoreAttributes(elements) {
26
- for (const element of elements) {
25
+ function restoreAttributes(element_or_elements) {
26
+ for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
27
27
  const snapshot = snapshots.get(element);
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(elements, attributes) {
38
- elements.forEach((element) => {
37
+ function saveAttributes(element_or_elements, name_or_names) {
38
+ 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) => {
39
40
  let snapshot = snapshots.get(element);
40
41
  if (!snapshot) {
41
42
  snapshot = /* @__PURE__ */ new Map();
42
43
  snapshots.set(element, snapshot);
43
44
  }
44
- attributes.forEach((attribute) => {
45
- snapshot.set(attribute, element.getAttribute(attribute));
45
+ names.forEach((name) => {
46
+ snapshot.set(name, element.getAttribute(name));
46
47
  });
47
48
  });
48
49
  }
50
+ var addTokenToAttribute = addAttributeToken;
49
51
 
50
52
  // node_modules/power-focusable/dist/index.js
51
53
  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"])`;
54
+ var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX = FOCUSABLE_SELECTOR.replace(
55
+ /(,\s*)?\[tabindex="-1"\]/g,
56
+ ""
57
+ );
52
58
  function getFocusables(container = document.body, options = {}) {
53
59
  if (!(container instanceof Element)) {
54
60
  console.warn("Invalid container element. Fallback: <body> element.");
@@ -85,36 +91,43 @@ function getFocusables(container = document.body, options = {}) {
85
91
  console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
86
92
  skipVisibilityCheck = false;
87
93
  }
88
- const elements = [];
94
+ const candidates = [];
89
95
  if (composed || include) {
90
96
  let traverse2 = function(node) {
91
- if (!(node instanceof Element)) {
92
- return;
93
- }
94
- if (isFocusable(node, { skipNegativeTabIndexCheck, skipVisibilityCheck }) || include?.(node)) {
95
- elements[elements.length] = node;
97
+ if (isFocusable(node, {
98
+ skipNegativeTabIndexCheck,
99
+ skipVisibilityCheck
100
+ }) || include?.(node)) {
101
+ candidates[candidates.length] = node;
96
102
  }
97
- const children = getComposedChildren(node);
98
- for (let i = 0, l = children.length; i < l; i++) {
99
- const child = children[i];
103
+ const children2 = composed ? getComposedChildren(node) : getChildren(node);
104
+ for (let i = 0, l = children2.length; i < l; i++) {
105
+ const child = children2[i];
100
106
  child && traverse2(child);
101
107
  }
102
108
  };
103
- traverse2(container);
109
+ const children = composed ? getComposedChildren(container) : getChildren(container);
110
+ for (let i = 0, l = children.length; i < l; i++) {
111
+ const child = children[i];
112
+ child && traverse2(child);
113
+ }
104
114
  } else {
105
- const candidates = container.querySelectorAll(FOCUSABLE_SELECTOR);
106
- for (let i = 0, l = candidates.length; i < l; i++) {
107
- const candidate = candidates[i];
108
- if (candidate && isFocusable(candidate, {
115
+ const matches = container.querySelectorAll(
116
+ skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
117
+ );
118
+ for (let i = 0, l = matches.length; i < l; i++) {
119
+ const matched = matches[i];
120
+ if (matched && isFocusable(matched, {
109
121
  skipNegativeTabIndexCheck,
110
122
  skipVisibilityCheck
111
123
  })) {
112
- elements[elements.length] = candidate;
124
+ candidates[candidates.length] = matched;
113
125
  }
114
126
  }
115
127
  }
116
- const unfiltered = normalizeRadioGroup(sortByTabIndex(elements));
117
- return filter ? unfiltered.filter(filter) : unfiltered;
128
+ return normalizeRadioGroup(
129
+ sortByTabIndex(filter ? candidates.filter(filter) : candidates)
130
+ );
118
131
  }
119
132
  function isFocusable(element, options = {}) {
120
133
  if (!(element instanceof Element)) {
@@ -137,7 +150,7 @@ function isFocusable(element, options = {}) {
137
150
  return false;
138
151
  }
139
152
  if (!element.matches(
140
- skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR.replace(/(,\s*)?\[tabindex="-1"\]/g, "") : FOCUSABLE_SELECTOR
153
+ skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
141
154
  )) {
142
155
  return false;
143
156
  }
@@ -195,22 +208,42 @@ function normalizeRadioGroup(elements) {
195
208
  if (!map) {
196
209
  map = /* @__PURE__ */ new Map();
197
210
  }
198
- const key = `${element.form?.id ?? "no-form"}::${element.name}`;
199
- const group = map.get(key) ?? map.set(key, []).get(key);
200
- if (group) {
201
- group[group.length] = element;
211
+ const root = element.getRootNode();
212
+ let value = map.get(root);
213
+ if (!value) {
214
+ value = /* @__PURE__ */ new Map();
215
+ map.set(root, value);
216
+ }
217
+ let v = value.get(element.form);
218
+ if (!v) {
219
+ v = /* @__PURE__ */ new Map();
220
+ value.set(element.form, v);
221
+ }
222
+ let vv = v.get(element.name);
223
+ if (!vv) {
224
+ vv = [];
225
+ v.set(element.name, vv);
202
226
  }
227
+ vv[vv.length] = element;
203
228
  }
204
229
  if (!map) {
205
230
  return elements;
206
231
  }
207
232
  const placeholder = /* @__PURE__ */ new Set();
208
- for (const group of map.values()) {
209
- placeholder.add(group.find((radio) => radio.checked) ?? group[0]);
233
+ for (const value of map.values()) {
234
+ for (const v of value.values()) {
235
+ for (const vv of v.values()) {
236
+ const radio = vv.find((element) => element.checked) ?? vv[0];
237
+ radio && placeholder.add(radio);
238
+ }
239
+ }
210
240
  }
211
- return elements.filter(
212
- (element) => isUngroupedRadio(element) ? placeholder.has(element) : true
213
- );
241
+ return elements.filter((element) => {
242
+ if (!(element instanceof HTMLInputElement)) {
243
+ return true;
244
+ }
245
+ return !isUngroupedRadio(element) || placeholder.has(element);
246
+ });
214
247
  }
215
248
  function sortByTabIndex(elements) {
216
249
  const ordered = [];
@@ -282,7 +315,7 @@ function isInert(element) {
282
315
  return "inert" in element && !!element.inert;
283
316
  }
284
317
  function isUngroupedRadio(element) {
285
- return element instanceof HTMLInputElement && element.type === "radio" && !!element.name;
318
+ return element.type === "radio" && !!element.name;
286
319
  }
287
320
 
288
321
  // node_modules/@y14e/button/dist/index.js
@@ -334,6 +367,56 @@ var Button = class {
334
367
  };
335
368
  };
336
369
 
370
+ // node_modules/@y14e/roving-tabindex/node_modules/@y14e/attributes-utils/dist/index.js
371
+ var DEFAULT_PARSER2 = (value) => value.split(/\s+/);
372
+ var DEFAULT_SERIALIZER2 = (tokens) => tokens.join(" ");
373
+ function addTokenToAttribute2(element, name, token, options = {}) {
374
+ const value = element.getAttribute(name)?.trim();
375
+ const {
376
+ caseInsensitive = false,
377
+ parse = DEFAULT_PARSER2,
378
+ serialize = DEFAULT_SERIALIZER2
379
+ } = options;
380
+ const tokens = value ? parse(value).filter(Boolean) : [];
381
+ if (caseInsensitive) {
382
+ const lower = token.toLowerCase();
383
+ if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
384
+ tokens.push(token);
385
+ element.setAttribute(name, serialize(tokens));
386
+ }
387
+ } else {
388
+ const set = new Set(tokens);
389
+ set.add(token);
390
+ element.setAttribute(name, serialize([...set]));
391
+ }
392
+ }
393
+ var snapshots2 = /* @__PURE__ */ new WeakMap();
394
+ function restoreAttributes2(element_or_elements) {
395
+ for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
396
+ const snapshot = snapshots2.get(element);
397
+ if (!snapshot) {
398
+ continue;
399
+ }
400
+ for (const [name, value] of snapshot.entries()) {
401
+ value === null ? element.removeAttribute(name) : element.setAttribute(name, value);
402
+ }
403
+ snapshots2.delete(element);
404
+ }
405
+ }
406
+ function saveAttributes2(element_or_elements, name_or_names) {
407
+ const names = Array.isArray(name_or_names) ? name_or_names : [name_or_names];
408
+ (Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
409
+ let snapshot = snapshots2.get(element);
410
+ if (!snapshot) {
411
+ snapshot = /* @__PURE__ */ new Map();
412
+ snapshots2.set(element, snapshot);
413
+ }
414
+ names.forEach((name) => {
415
+ snapshot.set(name, element.getAttribute(name));
416
+ });
417
+ });
418
+ }
419
+
337
420
  // node_modules/@y14e/roving-tabindex/dist/index.js
338
421
  function createRovingTabIndex(container, options = {}) {
339
422
  if (!(container instanceof Element)) {
@@ -341,14 +424,8 @@ function createRovingTabIndex(container, options = {}) {
341
424
  return () => {
342
425
  };
343
426
  }
344
- try {
345
- const roving = new RovingTabIndex(container, options);
346
- return () => roving.destroy();
347
- } catch (error) {
348
- error instanceof Error && console.warn(error.message || error);
349
- return () => {
350
- };
351
- }
427
+ const roving = new RovingTabIndex(container, options);
428
+ return () => roving.destroy();
352
429
  }
353
430
  var RovingTabIndex = class _RovingTabIndex {
354
431
  static #initialized = /* @__PURE__ */ new Set();
@@ -362,17 +439,17 @@ var RovingTabIndex = class _RovingTabIndex {
362
439
  constructor(container, options = {}) {
363
440
  this.#container = container;
364
441
  let {
365
- direction,
442
+ direction = "both",
366
443
  navigationOnly = false,
367
444
  noMemory = false,
368
445
  noStart = false,
369
- selector,
446
+ selector = "",
370
447
  typeahead = false,
371
448
  wrap = false
372
449
  } = options;
373
- if (typeof direction !== "undefined" && !["horizontal", "vertical"].includes(direction)) {
374
- console.warn("Invalid direction option. Fallback: both (undefined).");
375
- direction = void 0;
450
+ if (!["both", "horizontal", "vertical"].includes(direction)) {
451
+ console.warn("Invalid direction option. Fallback: 'both'.");
452
+ direction = "both";
376
453
  }
377
454
  if (typeof navigationOnly !== "boolean") {
378
455
  console.warn("Invalid navigationOnly option. Fallback: false.");
@@ -386,11 +463,21 @@ var RovingTabIndex = class _RovingTabIndex {
386
463
  console.warn("Invalid noStart option. Fallback: false.");
387
464
  noStart = false;
388
465
  }
389
- if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
390
- console.warn(
391
- "Invalid selector. Fallback: all focusable elements (undefined)."
392
- );
393
- selector = void 0;
466
+ if (selector !== "") {
467
+ let hasError = false;
468
+ if (typeof selector !== "string" || !selector.trim()) {
469
+ hasError = true;
470
+ } else {
471
+ try {
472
+ this.#container.querySelector(selector);
473
+ } catch {
474
+ hasError = true;
475
+ }
476
+ }
477
+ if (hasError) {
478
+ console.warn("Invalid selector. Fallback: no selector string.");
479
+ selector = "";
480
+ }
394
481
  }
395
482
  if (typeof typeahead !== "boolean") {
396
483
  console.warn("Invalid typeahead option. Fallback: false.");
@@ -400,9 +487,15 @@ var RovingTabIndex = class _RovingTabIndex {
400
487
  console.warn("Invalid wrap option. Fallback: false.");
401
488
  wrap = false;
402
489
  }
403
- this.#settings = { navigationOnly, noMemory, noStart, typeahead, wrap };
404
- direction && Object.assign(this.#settings, { direction });
405
- selector && Object.assign(this.#settings, { selector });
490
+ this.#settings = {
491
+ direction,
492
+ navigationOnly,
493
+ noMemory,
494
+ noStart,
495
+ selector,
496
+ typeahead,
497
+ wrap
498
+ };
406
499
  this.#selectorFilter = this.#createSelectorFilter();
407
500
  this.#initialize();
408
501
  }
@@ -413,7 +506,10 @@ var RovingTabIndex = class _RovingTabIndex {
413
506
  this.#isDestroyed = true;
414
507
  this.#controller?.abort();
415
508
  this.#controller = null;
416
- restoreAttributes([...this.#focusables]);
509
+ this.#focusables.forEach((focusable) => {
510
+ _RovingTabIndex.#initialized.delete(focusable);
511
+ restoreAttributes2(focusable);
512
+ });
417
513
  this.#focusables.clear();
418
514
  this.#focusablesByFirstChar.clear();
419
515
  }
@@ -450,7 +546,7 @@ var RovingTabIndex = class _RovingTabIndex {
450
546
  return;
451
547
  }
452
548
  const { direction, typeahead, wrap } = this.#settings;
453
- const isBoth = !direction;
549
+ const isBoth = direction === "both";
454
550
  const isHorizontal = direction === "horizontal";
455
551
  if (![
456
552
  "End",
@@ -462,18 +558,20 @@ var RovingTabIndex = class _RovingTabIndex {
462
558
  return;
463
559
  }
464
560
  }
561
+ const candidates = this.#getFocusables().filter(
562
+ (focusable2) => this.#focusables.has(focusable2)
563
+ );
465
564
  const active = getActiveElement();
466
565
  if (!(active instanceof Element)) {
467
566
  return;
468
567
  }
469
- const current = this.#getFocusables();
470
- if (!current.includes(active)) {
568
+ if (!candidates.includes(active)) {
471
569
  return;
472
570
  }
473
571
  event.preventDefault();
474
- const currentIndex = current.indexOf(active);
475
572
  let newIndex;
476
- let target = current;
573
+ const activeIndex = candidates.indexOf(active);
574
+ let focusables = candidates;
477
575
  switch (key) {
478
576
  case "End":
479
577
  newIndex = -1;
@@ -483,37 +581,47 @@ var RovingTabIndex = class _RovingTabIndex {
483
581
  break;
484
582
  case "ArrowLeft":
485
583
  case "ArrowUp": {
486
- const rawIndex = currentIndex - 1;
584
+ const rawIndex = activeIndex - 1;
487
585
  newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
488
586
  break;
489
587
  }
490
588
  case "ArrowRight":
491
589
  case "ArrowDown": {
492
- const rawIndex = currentIndex + 1;
493
- newIndex = wrap ? rawIndex % current.length : Math.min(rawIndex, current.length - 1);
590
+ const rawIndex = activeIndex + 1;
591
+ const length = focusables.length;
592
+ newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
494
593
  break;
495
594
  }
496
595
  default: {
497
- target = this.#focusablesByFirstChar.get(key.toUpperCase()) ?? [];
498
- const foundIndex = target.findIndex(
499
- (focusable2) => current.indexOf(focusable2) > currentIndex
596
+ const focusablesByFirstChar = new Set(
597
+ this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
598
+ );
599
+ focusables = candidates.filter(
600
+ (candidate) => focusablesByFirstChar.has(candidate)
601
+ );
602
+ const afterIndex = focusables.findIndex(
603
+ (focusable2) => candidates.indexOf(focusable2) > activeIndex
500
604
  );
501
- newIndex = foundIndex >= 0 ? foundIndex : 0;
605
+ newIndex = afterIndex >= 0 ? afterIndex : 0;
502
606
  }
503
607
  }
504
- const focusable = target.at(newIndex);
608
+ const focusable = focusables.at(newIndex);
505
609
  focusable && focusElement(focusable);
506
610
  };
507
611
  #update(active) {
508
612
  const current = new Set(this.#getFocusables());
509
613
  for (const focusable of this.#focusables) {
510
614
  if (!current.has(focusable)) {
511
- focusable.isConnected && restoreAttributes([focusable]);
615
+ _RovingTabIndex.#initialized.delete(focusable);
616
+ restoreAttributes2(focusable);
512
617
  this.#focusables.delete(focusable);
513
- this.#focusablesByFirstChar.forEach((focusables) => {
618
+ for (const [key, focusables] of this.#focusablesByFirstChar) {
514
619
  const index = focusables.indexOf(focusable);
515
- index >= 0 && focusables.splice(index, 1);
516
- });
620
+ if (index >= 0) {
621
+ focusables.splice(index, 1);
622
+ !focusables.length && this.#focusablesByFirstChar.delete(key);
623
+ }
624
+ }
517
625
  }
518
626
  }
519
627
  const { navigationOnly, noStart, typeahead } = this.#settings;
@@ -522,12 +630,12 @@ var RovingTabIndex = class _RovingTabIndex {
522
630
  continue;
523
631
  }
524
632
  if (_RovingTabIndex.#initialized.has(focusable)) {
525
- throw new TypeError("Already initialized");
633
+ continue;
526
634
  }
527
635
  this.#focusables.add(focusable);
528
636
  _RovingTabIndex.#initialized.add(focusable);
529
637
  if (!navigationOnly) {
530
- saveAttributes([focusable], ["tabindex"]);
638
+ saveAttributes2(focusable, "tabindex");
531
639
  focusable.setAttribute("tabindex", "-1");
532
640
  }
533
641
  if (!typeahead) {
@@ -540,8 +648,8 @@ var RovingTabIndex = class _RovingTabIndex {
540
648
  );
541
649
  if (char) {
542
650
  keys.add(char);
543
- saveAttributes([focusable], ["aria-keyshortcuts"]);
544
- addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
651
+ saveAttributes2(focusable, "aria-keyshortcuts");
652
+ addTokenToAttribute2(focusable, "aria-keyshortcuts", char, {
545
653
  caseInsensitive: true
546
654
  });
547
655
  }
@@ -820,7 +928,7 @@ var Accordion = class _Accordion {
820
928
  );
821
929
  }
822
930
  #createBinding(trigger, content) {
823
- return { trigger, content, animation: null };
931
+ return { animation: null, content, trigger };
824
932
  }
825
933
  #isFocusable(element) {
826
934
  return !element.hasAttribute("disabled") && element.tabIndex >= 0;
@@ -851,7 +959,7 @@ function waitAnimationFinish(animation) {
851
959
  * Accordion
852
960
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
853
961
  *
854
- * @version 2.0.2
962
+ * @version 2.0.4
855
963
  * @author Yusuke Kamiyamane
856
964
  * @license MIT
857
965
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -863,7 +971,7 @@ function waitAnimationFinish(animation) {
863
971
  (**
864
972
  * Attributes Utils
865
973
  *
866
- * @version 1.1.3
974
+ * @version 2.0.0
867
975
  * @author Yusuke Kamiyamane
868
976
  * @license MIT
869
977
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -876,7 +984,7 @@ power-focusable/dist/index.js:
876
984
  * High-precision focus management utility with full composed tree support.
877
985
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
878
986
  *
879
- * @version 4.3.8
987
+ * @version 4.3.23
880
988
  * @author Yusuke Kamiyamane
881
989
  * @license MIT
882
990
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -894,13 +1002,24 @@ power-focusable/dist/index.js:
894
1002
  * @see {@link https://github.com/y14e/button}
895
1003
  *)
896
1004
 
1005
+ @y14e/attributes-utils/dist/index.js:
1006
+ (**
1007
+ * Attributes Utils
1008
+ *
1009
+ * @version 1.1.7
1010
+ * @author Yusuke Kamiyamane
1011
+ * @license MIT
1012
+ * @copyright Copyright (c) Yusuke Kamiyamane
1013
+ * @see {@link https://github.com/y14e/attributes-utils}
1014
+ *)
1015
+
897
1016
  @y14e/roving-tabindex/dist/index.js:
898
1017
  (**
899
1018
  * Roving Tabindex
900
1019
  * Lightweight roving tabindex utility with fully focus management.
901
1020
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
902
1021
  *
903
- * @version 3.1.6
1022
+ * @version 3.1.20
904
1023
  * @author Yusuke Kamiyamane
905
1024
  * @license MIT
906
1025
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.cjs CHANGED
@@ -251,7 +251,7 @@ var Accordion = class _Accordion {
251
251
  );
252
252
  }
253
253
  #createBinding(trigger, content) {
254
- return { trigger, content, animation: null };
254
+ return { animation: null, content, trigger };
255
255
  }
256
256
  #isFocusable(element) {
257
257
  return !element.hasAttribute("disabled") && element.tabIndex >= 0;
@@ -282,7 +282,7 @@ function waitAnimationFinish(animation) {
282
282
  * Accordion
283
283
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
284
284
  *
285
- * @version 2.0.2
285
+ * @version 2.0.4
286
286
  * @author Yusuke Kamiyamane
287
287
  * @license MIT
288
288
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.d.cts CHANGED
@@ -2,27 +2,27 @@
2
2
  * Accordion
3
3
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
4
4
  *
5
- * @version 2.0.2
5
+ * @version 2.0.4
6
6
  * @author Yusuke Kamiyamane
7
7
  * @license MIT
8
8
  * @copyright Copyright (c) Yusuke Kamiyamane
9
9
  * @see {@link https://github.com/y14e/accordion}
10
10
  */
11
11
  interface AccordionOptions {
12
- readonly animation?: {
13
- readonly duration?: number;
14
- readonly easing?: string;
12
+ animation: {
13
+ duration: number;
14
+ easing: string;
15
15
  };
16
- readonly collapsible?: boolean;
17
- readonly selector?: {
18
- readonly content?: string;
19
- readonly trigger?: string;
16
+ collapsible: boolean;
17
+ selector: {
18
+ content: string;
19
+ trigger: string;
20
20
  };
21
21
  }
22
22
  declare class Accordion {
23
23
  #private;
24
- static defaults: AccordionOptions;
25
- constructor(root: HTMLElement, options?: AccordionOptions);
24
+ static defaults: Partial<AccordionOptions>;
25
+ constructor(root: HTMLElement, options?: Partial<AccordionOptions>);
26
26
  collapse(trigger: HTMLElement): void;
27
27
  destroy(force?: boolean): Promise<void>;
28
28
  expand(trigger: HTMLElement): void;
package/dist/index.d.ts CHANGED
@@ -2,27 +2,27 @@
2
2
  * Accordion
3
3
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
4
4
  *
5
- * @version 2.0.2
5
+ * @version 2.0.4
6
6
  * @author Yusuke Kamiyamane
7
7
  * @license MIT
8
8
  * @copyright Copyright (c) Yusuke Kamiyamane
9
9
  * @see {@link https://github.com/y14e/accordion}
10
10
  */
11
11
  interface AccordionOptions {
12
- readonly animation?: {
13
- readonly duration?: number;
14
- readonly easing?: string;
12
+ animation: {
13
+ duration: number;
14
+ easing: string;
15
15
  };
16
- readonly collapsible?: boolean;
17
- readonly selector?: {
18
- readonly content?: string;
19
- readonly trigger?: string;
16
+ collapsible: boolean;
17
+ selector: {
18
+ content: string;
19
+ trigger: string;
20
20
  };
21
21
  }
22
22
  declare class Accordion {
23
23
  #private;
24
- static defaults: AccordionOptions;
25
- constructor(root: HTMLElement, options?: AccordionOptions);
24
+ static defaults: Partial<AccordionOptions>;
25
+ constructor(root: HTMLElement, options?: Partial<AccordionOptions>);
26
26
  collapse(trigger: HTMLElement): void;
27
27
  destroy(force?: boolean): Promise<void>;
28
28
  expand(trigger: HTMLElement): void;
package/dist/index.js CHANGED
@@ -245,7 +245,7 @@ var Accordion = class _Accordion {
245
245
  );
246
246
  }
247
247
  #createBinding(trigger, content) {
248
- return { trigger, content, animation: null };
248
+ return { animation: null, content, trigger };
249
249
  }
250
250
  #isFocusable(element) {
251
251
  return !element.hasAttribute("disabled") && element.tabIndex >= 0;
@@ -276,7 +276,7 @@ function waitAnimationFinish(animation) {
276
276
  * Accordion
277
277
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
278
278
  *
279
- * @version 2.0.2
279
+ * @version 2.0.4
280
280
  * @author Yusuke Kamiyamane
281
281
  * @license MIT
282
282
  * @copyright Copyright (c) Yusuke Kamiyamane
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@y14e/accordion",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "description": "WAI-ARIA compliant accordion pattern implementation in TypeScript",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -45,15 +45,14 @@
45
45
  "devDependencies": {
46
46
  "bun-types": "latest",
47
47
  "tsup": "^8.0.0",
48
- "typescript": "^5.6.0",
49
- "utility-types": "^3.11.0"
48
+ "typescript": "^5.6.0"
50
49
  },
51
50
  "engines": {
52
51
  "node": ">=18"
53
52
  },
54
53
  "dependencies": {
55
- "@y14e/attributes-utils": "^1.1.3",
54
+ "@y14e/attributes-utils": "^2.0.0",
56
55
  "@y14e/button": "^1.0.6",
57
- "@y14e/roving-tabindex": "^3.1.6"
56
+ "@y14e/roving-tabindex": "^3.1.20"
58
57
  }
59
58
  }