@y14e/disclosure 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/disclosure
10
10
 
11
11
  ```ts
12
12
  // npm
13
- import Disclosure from '@y14e/disclosure';
13
+ import Disclosure from "@y14e/disclosure";
14
14
 
15
15
  // CDNs
16
- import Disclosure from 'https://esm.sh/@y14e/disclosure@2.0.2';
16
+ import Disclosure from "https://esm.sh/@y14e/disclosure@2.0.4";
17
17
  // or
18
- import Disclosure from 'https://cdn.jsdelivr.net/npm/@y14e/disclosure@2.0.2/+esm';
18
+ import Disclosure from "https://cdn.jsdelivr.net/npm/@y14e/disclosure@2.0.4/+esm";
19
19
  // or
20
- import Disclosure from 'https://esm.unpkg.com/@y14e/disclosure@2.0.2';
20
+ import Disclosure from "https://esm.unpkg.com/@y14e/disclosure@2.0.4";
21
21
  ```
22
22
 
23
23
  ## Usage
@@ -34,11 +34,11 @@ new Disclosure(root, options);
34
34
 
35
35
  ```ts
36
36
  interface DisclosureOptions {
37
- animation?: {
38
- duration?: number; // ms (default: 300)
39
- easing?: string; // <easing-function> (default: 'ease')
37
+ animation: {
38
+ duration: number; // ms (default: 300)
39
+ easing: string; // <easing-function> (default: 'ease')
40
40
  };
41
- collapsible?: boolean; // default: true
41
+ collapsible: boolean; // default: true
42
42
  }
43
43
  ```
44
44
 
@@ -47,7 +47,7 @@ interface DisclosureOptions {
47
47
  Override the global default settings applied to all disclosure instances.
48
48
 
49
49
  ```ts
50
- import Disclosure from '@y14e/disclosure';
50
+ import Disclosure from "@y14e/disclosure";
51
51
 
52
52
  Disclosure.defaults = {
53
53
  animation: {
@@ -1,10 +1,38 @@
1
1
  'use strict';
2
2
 
3
3
  // node_modules/@y14e/attributes-utils/dist/index.js
4
+ var snapshots = /* @__PURE__ */ new WeakMap();
5
+ function restoreAttributes(element_or_elements) {
6
+ for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
7
+ const snapshot = snapshots.get(element);
8
+ if (!snapshot) {
9
+ continue;
10
+ }
11
+ for (const [name, value] of snapshot.entries()) {
12
+ value === null ? element.removeAttribute(name) : element.setAttribute(name, value);
13
+ }
14
+ snapshots.delete(element);
15
+ }
16
+ }
17
+ function saveAttributes(element_or_elements, name_or_names) {
18
+ const names = Array.isArray(name_or_names) ? name_or_names : [name_or_names];
19
+ (Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
20
+ let snapshot = snapshots.get(element);
21
+ if (!snapshot) {
22
+ snapshot = /* @__PURE__ */ new Map();
23
+ snapshots.set(element, snapshot);
24
+ }
25
+ names.forEach((name) => {
26
+ snapshot.set(name, element.getAttribute(name));
27
+ });
28
+ });
29
+ }
30
+
31
+ // node_modules/@y14e/roving-tabindex/node_modules/@y14e/attributes-utils/dist/index.js
4
32
  var DEFAULT_PARSER = (value) => value.split(/\s+/);
5
33
  var DEFAULT_SERIALIZER = (tokens) => tokens.join(" ");
6
- function addTokenToAttribute(element, attribute, token, options = {}) {
7
- const value = element.getAttribute(attribute)?.trim();
34
+ function addTokenToAttribute(element, name, token, options = {}) {
35
+ const value = element.getAttribute(name)?.trim();
8
36
  const {
9
37
  caseInsensitive = false,
10
38
  parse = DEFAULT_PARSER,
@@ -15,42 +43,47 @@ function addTokenToAttribute(element, attribute, token, options = {}) {
15
43
  const lower = token.toLowerCase();
16
44
  if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
17
45
  tokens.push(token);
18
- element.setAttribute(attribute, serialize(tokens));
46
+ element.setAttribute(name, serialize(tokens));
19
47
  }
20
48
  } else {
21
49
  const set = new Set(tokens);
22
50
  set.add(token);
23
- element.setAttribute(attribute, serialize([...set]));
51
+ element.setAttribute(name, serialize([...set]));
24
52
  }
25
53
  }
26
- var snapshots = /* @__PURE__ */ new WeakMap();
27
- function restoreAttributes(elements) {
28
- for (const element of elements) {
29
- const snapshot = snapshots.get(element);
54
+ var snapshots2 = /* @__PURE__ */ new WeakMap();
55
+ function restoreAttributes2(element_or_elements) {
56
+ for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
57
+ const snapshot = snapshots2.get(element);
30
58
  if (!snapshot) {
31
59
  continue;
32
60
  }
33
- for (const [attribute, value] of snapshot.entries()) {
34
- value === null ? element.removeAttribute(attribute) : element.setAttribute(attribute, value);
61
+ for (const [name, value] of snapshot.entries()) {
62
+ value === null ? element.removeAttribute(name) : element.setAttribute(name, value);
35
63
  }
36
- snapshots.delete(element);
64
+ snapshots2.delete(element);
37
65
  }
38
66
  }
39
- function saveAttributes(elements, attributes) {
40
- elements.forEach((element) => {
41
- let snapshot = snapshots.get(element);
67
+ function saveAttributes2(element_or_elements, name_or_names) {
68
+ const names = Array.isArray(name_or_names) ? name_or_names : [name_or_names];
69
+ (Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
70
+ let snapshot = snapshots2.get(element);
42
71
  if (!snapshot) {
43
72
  snapshot = /* @__PURE__ */ new Map();
44
- snapshots.set(element, snapshot);
73
+ snapshots2.set(element, snapshot);
45
74
  }
46
- attributes.forEach((attribute) => {
47
- snapshot.set(attribute, element.getAttribute(attribute));
75
+ names.forEach((name) => {
76
+ snapshot.set(name, element.getAttribute(name));
48
77
  });
49
78
  });
50
79
  }
51
80
 
52
81
  // node_modules/power-focusable/dist/index.js
53
82
  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"])`;
83
+ var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX = FOCUSABLE_SELECTOR.replace(
84
+ /(,\s*)?\[tabindex="-1"\]/g,
85
+ ""
86
+ );
54
87
  function getFocusables(container = document.body, options = {}) {
55
88
  if (!(container instanceof Element)) {
56
89
  console.warn("Invalid container element. Fallback: <body> element.");
@@ -87,36 +120,43 @@ function getFocusables(container = document.body, options = {}) {
87
120
  console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
88
121
  skipVisibilityCheck = false;
89
122
  }
90
- const elements = [];
123
+ const candidates = [];
91
124
  if (composed || include) {
92
125
  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;
126
+ if (isFocusable(node, {
127
+ skipNegativeTabIndexCheck,
128
+ skipVisibilityCheck
129
+ }) || include?.(node)) {
130
+ candidates[candidates.length] = node;
98
131
  }
99
- const children = getComposedChildren(node);
100
- for (let i = 0, l = children.length; i < l; i++) {
101
- const child = children[i];
132
+ const children2 = composed ? getComposedChildren(node) : getChildren(node);
133
+ for (let i = 0, l = children2.length; i < l; i++) {
134
+ const child = children2[i];
102
135
  child && traverse2(child);
103
136
  }
104
137
  };
105
- traverse2(container);
138
+ const children = composed ? getComposedChildren(container) : getChildren(container);
139
+ for (let i = 0, l = children.length; i < l; i++) {
140
+ const child = children[i];
141
+ child && traverse2(child);
142
+ }
106
143
  } 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, {
144
+ const matches = container.querySelectorAll(
145
+ skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
146
+ );
147
+ for (let i = 0, l = matches.length; i < l; i++) {
148
+ const matched = matches[i];
149
+ if (matched && isFocusable(matched, {
111
150
  skipNegativeTabIndexCheck,
112
151
  skipVisibilityCheck
113
152
  })) {
114
- elements[elements.length] = candidate;
153
+ candidates[candidates.length] = matched;
115
154
  }
116
155
  }
117
156
  }
118
- const unfiltered = normalizeRadioGroup(sortByTabIndex(elements));
119
- return filter ? unfiltered.filter(filter) : unfiltered;
157
+ return normalizeRadioGroup(
158
+ sortByTabIndex(filter ? candidates.filter(filter) : candidates)
159
+ );
120
160
  }
121
161
  function isFocusable(element, options = {}) {
122
162
  if (!(element instanceof Element)) {
@@ -139,7 +179,7 @@ function isFocusable(element, options = {}) {
139
179
  return false;
140
180
  }
141
181
  if (!element.matches(
142
- skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR.replace(/(,\s*)?\[tabindex="-1"\]/g, "") : FOCUSABLE_SELECTOR
182
+ skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
143
183
  )) {
144
184
  return false;
145
185
  }
@@ -197,22 +237,42 @@ function normalizeRadioGroup(elements) {
197
237
  if (!map) {
198
238
  map = /* @__PURE__ */ new Map();
199
239
  }
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;
240
+ const root = element.getRootNode();
241
+ let value = map.get(root);
242
+ if (!value) {
243
+ value = /* @__PURE__ */ new Map();
244
+ map.set(root, value);
204
245
  }
246
+ let v = value.get(element.form);
247
+ if (!v) {
248
+ v = /* @__PURE__ */ new Map();
249
+ value.set(element.form, v);
250
+ }
251
+ let vv = v.get(element.name);
252
+ if (!vv) {
253
+ vv = [];
254
+ v.set(element.name, vv);
255
+ }
256
+ vv[vv.length] = element;
205
257
  }
206
258
  if (!map) {
207
259
  return elements;
208
260
  }
209
261
  const placeholder = /* @__PURE__ */ new Set();
210
- for (const group of map.values()) {
211
- placeholder.add(group.find((radio) => radio.checked) ?? group[0]);
262
+ for (const value of map.values()) {
263
+ for (const v of value.values()) {
264
+ for (const vv of v.values()) {
265
+ const radio = vv.find((element) => element.checked) ?? vv[0];
266
+ radio && placeholder.add(radio);
267
+ }
268
+ }
212
269
  }
213
- return elements.filter(
214
- (element) => isUngroupedRadio(element) ? placeholder.has(element) : true
215
- );
270
+ return elements.filter((element) => {
271
+ if (!(element instanceof HTMLInputElement)) {
272
+ return true;
273
+ }
274
+ return !isUngroupedRadio(element) || placeholder.has(element);
275
+ });
216
276
  }
217
277
  function sortByTabIndex(elements) {
218
278
  const ordered = [];
@@ -284,7 +344,7 @@ function isInert(element) {
284
344
  return "inert" in element && !!element.inert;
285
345
  }
286
346
  function isUngroupedRadio(element) {
287
- return element instanceof HTMLInputElement && element.type === "radio" && !!element.name;
347
+ return element.type === "radio" && !!element.name;
288
348
  }
289
349
 
290
350
  // node_modules/@y14e/roving-tabindex/dist/index.js
@@ -294,14 +354,8 @@ function createRovingTabIndex(container, options = {}) {
294
354
  return () => {
295
355
  };
296
356
  }
297
- try {
298
- const roving = new RovingTabIndex(container, options);
299
- return () => roving.destroy();
300
- } catch (error) {
301
- error instanceof Error && console.warn(error.message || error);
302
- return () => {
303
- };
304
- }
357
+ const roving = new RovingTabIndex(container, options);
358
+ return () => roving.destroy();
305
359
  }
306
360
  var RovingTabIndex = class _RovingTabIndex {
307
361
  static #initialized = /* @__PURE__ */ new Set();
@@ -315,17 +369,17 @@ var RovingTabIndex = class _RovingTabIndex {
315
369
  constructor(container, options = {}) {
316
370
  this.#container = container;
317
371
  let {
318
- direction,
372
+ direction = "both",
319
373
  navigationOnly = false,
320
374
  noMemory = false,
321
375
  noStart = false,
322
- selector,
376
+ selector = "",
323
377
  typeahead = false,
324
378
  wrap = false
325
379
  } = options;
326
- if (typeof direction !== "undefined" && !["horizontal", "vertical"].includes(direction)) {
327
- console.warn("Invalid direction option. Fallback: both (undefined).");
328
- direction = void 0;
380
+ if (!["both", "horizontal", "vertical"].includes(direction)) {
381
+ console.warn("Invalid direction option. Fallback: 'both'.");
382
+ direction = "both";
329
383
  }
330
384
  if (typeof navigationOnly !== "boolean") {
331
385
  console.warn("Invalid navigationOnly option. Fallback: false.");
@@ -339,11 +393,21 @@ var RovingTabIndex = class _RovingTabIndex {
339
393
  console.warn("Invalid noStart option. Fallback: false.");
340
394
  noStart = false;
341
395
  }
342
- if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
343
- console.warn(
344
- "Invalid selector. Fallback: all focusable elements (undefined)."
345
- );
346
- selector = void 0;
396
+ if (selector !== "") {
397
+ let hasError = false;
398
+ if (typeof selector !== "string" || !selector.trim()) {
399
+ hasError = true;
400
+ } else {
401
+ try {
402
+ this.#container.querySelector(selector);
403
+ } catch {
404
+ hasError = true;
405
+ }
406
+ }
407
+ if (hasError) {
408
+ console.warn("Invalid selector. Fallback: no selector string.");
409
+ selector = "";
410
+ }
347
411
  }
348
412
  if (typeof typeahead !== "boolean") {
349
413
  console.warn("Invalid typeahead option. Fallback: false.");
@@ -353,9 +417,15 @@ var RovingTabIndex = class _RovingTabIndex {
353
417
  console.warn("Invalid wrap option. Fallback: false.");
354
418
  wrap = false;
355
419
  }
356
- this.#settings = { navigationOnly, noMemory, noStart, typeahead, wrap };
357
- direction && Object.assign(this.#settings, { direction });
358
- selector && Object.assign(this.#settings, { selector });
420
+ this.#settings = {
421
+ direction,
422
+ navigationOnly,
423
+ noMemory,
424
+ noStart,
425
+ selector,
426
+ typeahead,
427
+ wrap
428
+ };
359
429
  this.#selectorFilter = this.#createSelectorFilter();
360
430
  this.#initialize();
361
431
  }
@@ -366,7 +436,10 @@ var RovingTabIndex = class _RovingTabIndex {
366
436
  this.#isDestroyed = true;
367
437
  this.#controller?.abort();
368
438
  this.#controller = null;
369
- restoreAttributes([...this.#focusables]);
439
+ this.#focusables.forEach((focusable) => {
440
+ _RovingTabIndex.#initialized.delete(focusable);
441
+ restoreAttributes2(focusable);
442
+ });
370
443
  this.#focusables.clear();
371
444
  this.#focusablesByFirstChar.clear();
372
445
  }
@@ -403,7 +476,7 @@ var RovingTabIndex = class _RovingTabIndex {
403
476
  return;
404
477
  }
405
478
  const { direction, typeahead, wrap } = this.#settings;
406
- const isBoth = !direction;
479
+ const isBoth = direction === "both";
407
480
  const isHorizontal = direction === "horizontal";
408
481
  if (![
409
482
  "End",
@@ -415,18 +488,20 @@ var RovingTabIndex = class _RovingTabIndex {
415
488
  return;
416
489
  }
417
490
  }
491
+ const candidates = this.#getFocusables().filter(
492
+ (focusable2) => this.#focusables.has(focusable2)
493
+ );
418
494
  const active = getActiveElement();
419
495
  if (!(active instanceof Element)) {
420
496
  return;
421
497
  }
422
- const current = this.#getFocusables();
423
- if (!current.includes(active)) {
498
+ if (!candidates.includes(active)) {
424
499
  return;
425
500
  }
426
501
  event.preventDefault();
427
- const currentIndex = current.indexOf(active);
428
502
  let newIndex;
429
- let target = current;
503
+ const activeIndex = candidates.indexOf(active);
504
+ let focusables = candidates;
430
505
  switch (key) {
431
506
  case "End":
432
507
  newIndex = -1;
@@ -436,37 +511,47 @@ var RovingTabIndex = class _RovingTabIndex {
436
511
  break;
437
512
  case "ArrowLeft":
438
513
  case "ArrowUp": {
439
- const rawIndex = currentIndex - 1;
514
+ const rawIndex = activeIndex - 1;
440
515
  newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
441
516
  break;
442
517
  }
443
518
  case "ArrowRight":
444
519
  case "ArrowDown": {
445
- const rawIndex = currentIndex + 1;
446
- newIndex = wrap ? rawIndex % current.length : Math.min(rawIndex, current.length - 1);
520
+ const rawIndex = activeIndex + 1;
521
+ const length = focusables.length;
522
+ newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
447
523
  break;
448
524
  }
449
525
  default: {
450
- target = this.#focusablesByFirstChar.get(key.toUpperCase()) ?? [];
451
- const foundIndex = target.findIndex(
452
- (focusable2) => current.indexOf(focusable2) > currentIndex
526
+ const focusablesByFirstChar = new Set(
527
+ this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
528
+ );
529
+ focusables = candidates.filter(
530
+ (candidate) => focusablesByFirstChar.has(candidate)
453
531
  );
454
- newIndex = foundIndex >= 0 ? foundIndex : 0;
532
+ const afterIndex = focusables.findIndex(
533
+ (focusable2) => candidates.indexOf(focusable2) > activeIndex
534
+ );
535
+ newIndex = afterIndex >= 0 ? afterIndex : 0;
455
536
  }
456
537
  }
457
- const focusable = target.at(newIndex);
538
+ const focusable = focusables.at(newIndex);
458
539
  focusable && focusElement(focusable);
459
540
  };
460
541
  #update(active) {
461
542
  const current = new Set(this.#getFocusables());
462
543
  for (const focusable of this.#focusables) {
463
544
  if (!current.has(focusable)) {
464
- focusable.isConnected && restoreAttributes([focusable]);
545
+ _RovingTabIndex.#initialized.delete(focusable);
546
+ restoreAttributes2(focusable);
465
547
  this.#focusables.delete(focusable);
466
- this.#focusablesByFirstChar.forEach((focusables) => {
548
+ for (const [key, focusables] of this.#focusablesByFirstChar) {
467
549
  const index = focusables.indexOf(focusable);
468
- index >= 0 && focusables.splice(index, 1);
469
- });
550
+ if (index >= 0) {
551
+ focusables.splice(index, 1);
552
+ !focusables.length && this.#focusablesByFirstChar.delete(key);
553
+ }
554
+ }
470
555
  }
471
556
  }
472
557
  const { navigationOnly, noStart, typeahead } = this.#settings;
@@ -475,12 +560,12 @@ var RovingTabIndex = class _RovingTabIndex {
475
560
  continue;
476
561
  }
477
562
  if (_RovingTabIndex.#initialized.has(focusable)) {
478
- throw new TypeError("Already initialized");
563
+ continue;
479
564
  }
480
565
  this.#focusables.add(focusable);
481
566
  _RovingTabIndex.#initialized.add(focusable);
482
567
  if (!navigationOnly) {
483
- saveAttributes([focusable], ["tabindex"]);
568
+ saveAttributes2(focusable, "tabindex");
484
569
  focusable.setAttribute("tabindex", "-1");
485
570
  }
486
571
  if (!typeahead) {
@@ -493,7 +578,7 @@ var RovingTabIndex = class _RovingTabIndex {
493
578
  );
494
579
  if (char) {
495
580
  keys.add(char);
496
- saveAttributes([focusable], ["aria-keyshortcuts"]);
581
+ saveAttributes2(focusable, "aria-keyshortcuts");
497
582
  addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
498
583
  caseInsensitive: true
499
584
  });
@@ -779,7 +864,7 @@ var Disclosure = class _Disclosure {
779
864
  );
780
865
  }
781
866
  #createBinding(details, summary, content) {
782
- return { details, summary, content, animation: null };
867
+ return { animation: null, content, details, summary };
783
868
  }
784
869
  #isFocusable(element) {
785
870
  return element.tabIndex >= 0;
@@ -810,7 +895,7 @@ function waitAnimationFinish(animation) {
810
895
  * WAI-ARIA compliant disclosure pattern implementation in TypeScript.
811
896
  * Using the <details> and <summary> element.
812
897
  *
813
- * @version 2.0.2
898
+ * @version 2.0.4
814
899
  * @author Yusuke Kamiyamane
815
900
  * @license MIT
816
901
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -822,7 +907,18 @@ function waitAnimationFinish(animation) {
822
907
  (**
823
908
  * Attributes Utils
824
909
  *
825
- * @version 1.1.3
910
+ * @version 2.0.0
911
+ * @author Yusuke Kamiyamane
912
+ * @license MIT
913
+ * @copyright Copyright (c) Yusuke Kamiyamane
914
+ * @see {@link https://github.com/y14e/attributes-utils}
915
+ *)
916
+
917
+ @y14e/attributes-utils/dist/index.js:
918
+ (**
919
+ * Attributes Utils
920
+ *
921
+ * @version 1.1.7
826
922
  * @author Yusuke Kamiyamane
827
923
  * @license MIT
828
924
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -835,7 +931,7 @@ power-focusable/dist/index.js:
835
931
  * High-precision focus management utility with full composed tree support.
836
932
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
837
933
  *
838
- * @version 4.3.8
934
+ * @version 4.3.23
839
935
  * @author Yusuke Kamiyamane
840
936
  * @license MIT
841
937
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -848,7 +944,7 @@ power-focusable/dist/index.js:
848
944
  * Lightweight roving tabindex utility with fully focus management.
849
945
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
850
946
  *
851
- * @version 3.1.6
947
+ * @version 3.1.20
852
948
  * @author Yusuke Kamiyamane
853
949
  * @license MIT
854
950
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1,8 +1,36 @@
1
1
  // node_modules/@y14e/attributes-utils/dist/index.js
2
+ var snapshots = /* @__PURE__ */ new WeakMap();
3
+ function restoreAttributes(element_or_elements) {
4
+ for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
5
+ const snapshot = snapshots.get(element);
6
+ if (!snapshot) {
7
+ continue;
8
+ }
9
+ for (const [name, value] of snapshot.entries()) {
10
+ value === null ? element.removeAttribute(name) : element.setAttribute(name, value);
11
+ }
12
+ snapshots.delete(element);
13
+ }
14
+ }
15
+ function saveAttributes(element_or_elements, name_or_names) {
16
+ const names = Array.isArray(name_or_names) ? name_or_names : [name_or_names];
17
+ (Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
18
+ let snapshot = snapshots.get(element);
19
+ if (!snapshot) {
20
+ snapshot = /* @__PURE__ */ new Map();
21
+ snapshots.set(element, snapshot);
22
+ }
23
+ names.forEach((name) => {
24
+ snapshot.set(name, element.getAttribute(name));
25
+ });
26
+ });
27
+ }
28
+
29
+ // node_modules/@y14e/roving-tabindex/node_modules/@y14e/attributes-utils/dist/index.js
2
30
  var DEFAULT_PARSER = (value) => value.split(/\s+/);
3
31
  var DEFAULT_SERIALIZER = (tokens) => tokens.join(" ");
4
- function addTokenToAttribute(element, attribute, token, options = {}) {
5
- const value = element.getAttribute(attribute)?.trim();
32
+ function addTokenToAttribute(element, name, token, options = {}) {
33
+ const value = element.getAttribute(name)?.trim();
6
34
  const {
7
35
  caseInsensitive = false,
8
36
  parse = DEFAULT_PARSER,
@@ -13,42 +41,47 @@ function addTokenToAttribute(element, attribute, token, options = {}) {
13
41
  const lower = token.toLowerCase();
14
42
  if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
15
43
  tokens.push(token);
16
- element.setAttribute(attribute, serialize(tokens));
44
+ element.setAttribute(name, serialize(tokens));
17
45
  }
18
46
  } else {
19
47
  const set = new Set(tokens);
20
48
  set.add(token);
21
- element.setAttribute(attribute, serialize([...set]));
49
+ element.setAttribute(name, serialize([...set]));
22
50
  }
23
51
  }
24
- var snapshots = /* @__PURE__ */ new WeakMap();
25
- function restoreAttributes(elements) {
26
- for (const element of elements) {
27
- const snapshot = snapshots.get(element);
52
+ var snapshots2 = /* @__PURE__ */ new WeakMap();
53
+ function restoreAttributes2(element_or_elements) {
54
+ for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
55
+ const snapshot = snapshots2.get(element);
28
56
  if (!snapshot) {
29
57
  continue;
30
58
  }
31
- for (const [attribute, value] of snapshot.entries()) {
32
- value === null ? element.removeAttribute(attribute) : element.setAttribute(attribute, value);
59
+ for (const [name, value] of snapshot.entries()) {
60
+ value === null ? element.removeAttribute(name) : element.setAttribute(name, value);
33
61
  }
34
- snapshots.delete(element);
62
+ snapshots2.delete(element);
35
63
  }
36
64
  }
37
- function saveAttributes(elements, attributes) {
38
- elements.forEach((element) => {
39
- let snapshot = snapshots.get(element);
65
+ function saveAttributes2(element_or_elements, name_or_names) {
66
+ const names = Array.isArray(name_or_names) ? name_or_names : [name_or_names];
67
+ (Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
68
+ let snapshot = snapshots2.get(element);
40
69
  if (!snapshot) {
41
70
  snapshot = /* @__PURE__ */ new Map();
42
- snapshots.set(element, snapshot);
71
+ snapshots2.set(element, snapshot);
43
72
  }
44
- attributes.forEach((attribute) => {
45
- snapshot.set(attribute, element.getAttribute(attribute));
73
+ names.forEach((name) => {
74
+ snapshot.set(name, element.getAttribute(name));
46
75
  });
47
76
  });
48
77
  }
49
78
 
50
79
  // node_modules/power-focusable/dist/index.js
51
80
  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"])`;
81
+ var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX = FOCUSABLE_SELECTOR.replace(
82
+ /(,\s*)?\[tabindex="-1"\]/g,
83
+ ""
84
+ );
52
85
  function getFocusables(container = document.body, options = {}) {
53
86
  if (!(container instanceof Element)) {
54
87
  console.warn("Invalid container element. Fallback: <body> element.");
@@ -85,36 +118,43 @@ function getFocusables(container = document.body, options = {}) {
85
118
  console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
86
119
  skipVisibilityCheck = false;
87
120
  }
88
- const elements = [];
121
+ const candidates = [];
89
122
  if (composed || include) {
90
123
  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;
124
+ if (isFocusable(node, {
125
+ skipNegativeTabIndexCheck,
126
+ skipVisibilityCheck
127
+ }) || include?.(node)) {
128
+ candidates[candidates.length] = node;
96
129
  }
97
- const children = getComposedChildren(node);
98
- for (let i = 0, l = children.length; i < l; i++) {
99
- const child = children[i];
130
+ const children2 = composed ? getComposedChildren(node) : getChildren(node);
131
+ for (let i = 0, l = children2.length; i < l; i++) {
132
+ const child = children2[i];
100
133
  child && traverse2(child);
101
134
  }
102
135
  };
103
- traverse2(container);
136
+ const children = composed ? getComposedChildren(container) : getChildren(container);
137
+ for (let i = 0, l = children.length; i < l; i++) {
138
+ const child = children[i];
139
+ child && traverse2(child);
140
+ }
104
141
  } 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, {
142
+ const matches = container.querySelectorAll(
143
+ skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
144
+ );
145
+ for (let i = 0, l = matches.length; i < l; i++) {
146
+ const matched = matches[i];
147
+ if (matched && isFocusable(matched, {
109
148
  skipNegativeTabIndexCheck,
110
149
  skipVisibilityCheck
111
150
  })) {
112
- elements[elements.length] = candidate;
151
+ candidates[candidates.length] = matched;
113
152
  }
114
153
  }
115
154
  }
116
- const unfiltered = normalizeRadioGroup(sortByTabIndex(elements));
117
- return filter ? unfiltered.filter(filter) : unfiltered;
155
+ return normalizeRadioGroup(
156
+ sortByTabIndex(filter ? candidates.filter(filter) : candidates)
157
+ );
118
158
  }
119
159
  function isFocusable(element, options = {}) {
120
160
  if (!(element instanceof Element)) {
@@ -137,7 +177,7 @@ function isFocusable(element, options = {}) {
137
177
  return false;
138
178
  }
139
179
  if (!element.matches(
140
- skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR.replace(/(,\s*)?\[tabindex="-1"\]/g, "") : FOCUSABLE_SELECTOR
180
+ skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
141
181
  )) {
142
182
  return false;
143
183
  }
@@ -195,22 +235,42 @@ function normalizeRadioGroup(elements) {
195
235
  if (!map) {
196
236
  map = /* @__PURE__ */ new Map();
197
237
  }
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;
238
+ const root = element.getRootNode();
239
+ let value = map.get(root);
240
+ if (!value) {
241
+ value = /* @__PURE__ */ new Map();
242
+ map.set(root, value);
202
243
  }
244
+ let v = value.get(element.form);
245
+ if (!v) {
246
+ v = /* @__PURE__ */ new Map();
247
+ value.set(element.form, v);
248
+ }
249
+ let vv = v.get(element.name);
250
+ if (!vv) {
251
+ vv = [];
252
+ v.set(element.name, vv);
253
+ }
254
+ vv[vv.length] = element;
203
255
  }
204
256
  if (!map) {
205
257
  return elements;
206
258
  }
207
259
  const placeholder = /* @__PURE__ */ new Set();
208
- for (const group of map.values()) {
209
- placeholder.add(group.find((radio) => radio.checked) ?? group[0]);
260
+ for (const value of map.values()) {
261
+ for (const v of value.values()) {
262
+ for (const vv of v.values()) {
263
+ const radio = vv.find((element) => element.checked) ?? vv[0];
264
+ radio && placeholder.add(radio);
265
+ }
266
+ }
210
267
  }
211
- return elements.filter(
212
- (element) => isUngroupedRadio(element) ? placeholder.has(element) : true
213
- );
268
+ return elements.filter((element) => {
269
+ if (!(element instanceof HTMLInputElement)) {
270
+ return true;
271
+ }
272
+ return !isUngroupedRadio(element) || placeholder.has(element);
273
+ });
214
274
  }
215
275
  function sortByTabIndex(elements) {
216
276
  const ordered = [];
@@ -282,7 +342,7 @@ function isInert(element) {
282
342
  return "inert" in element && !!element.inert;
283
343
  }
284
344
  function isUngroupedRadio(element) {
285
- return element instanceof HTMLInputElement && element.type === "radio" && !!element.name;
345
+ return element.type === "radio" && !!element.name;
286
346
  }
287
347
 
288
348
  // node_modules/@y14e/roving-tabindex/dist/index.js
@@ -292,14 +352,8 @@ function createRovingTabIndex(container, options = {}) {
292
352
  return () => {
293
353
  };
294
354
  }
295
- try {
296
- const roving = new RovingTabIndex(container, options);
297
- return () => roving.destroy();
298
- } catch (error) {
299
- error instanceof Error && console.warn(error.message || error);
300
- return () => {
301
- };
302
- }
355
+ const roving = new RovingTabIndex(container, options);
356
+ return () => roving.destroy();
303
357
  }
304
358
  var RovingTabIndex = class _RovingTabIndex {
305
359
  static #initialized = /* @__PURE__ */ new Set();
@@ -313,17 +367,17 @@ var RovingTabIndex = class _RovingTabIndex {
313
367
  constructor(container, options = {}) {
314
368
  this.#container = container;
315
369
  let {
316
- direction,
370
+ direction = "both",
317
371
  navigationOnly = false,
318
372
  noMemory = false,
319
373
  noStart = false,
320
- selector,
374
+ selector = "",
321
375
  typeahead = false,
322
376
  wrap = false
323
377
  } = options;
324
- if (typeof direction !== "undefined" && !["horizontal", "vertical"].includes(direction)) {
325
- console.warn("Invalid direction option. Fallback: both (undefined).");
326
- direction = void 0;
378
+ if (!["both", "horizontal", "vertical"].includes(direction)) {
379
+ console.warn("Invalid direction option. Fallback: 'both'.");
380
+ direction = "both";
327
381
  }
328
382
  if (typeof navigationOnly !== "boolean") {
329
383
  console.warn("Invalid navigationOnly option. Fallback: false.");
@@ -337,11 +391,21 @@ var RovingTabIndex = class _RovingTabIndex {
337
391
  console.warn("Invalid noStart option. Fallback: false.");
338
392
  noStart = false;
339
393
  }
340
- if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
341
- console.warn(
342
- "Invalid selector. Fallback: all focusable elements (undefined)."
343
- );
344
- selector = void 0;
394
+ if (selector !== "") {
395
+ let hasError = false;
396
+ if (typeof selector !== "string" || !selector.trim()) {
397
+ hasError = true;
398
+ } else {
399
+ try {
400
+ this.#container.querySelector(selector);
401
+ } catch {
402
+ hasError = true;
403
+ }
404
+ }
405
+ if (hasError) {
406
+ console.warn("Invalid selector. Fallback: no selector string.");
407
+ selector = "";
408
+ }
345
409
  }
346
410
  if (typeof typeahead !== "boolean") {
347
411
  console.warn("Invalid typeahead option. Fallback: false.");
@@ -351,9 +415,15 @@ var RovingTabIndex = class _RovingTabIndex {
351
415
  console.warn("Invalid wrap option. Fallback: false.");
352
416
  wrap = false;
353
417
  }
354
- this.#settings = { navigationOnly, noMemory, noStart, typeahead, wrap };
355
- direction && Object.assign(this.#settings, { direction });
356
- selector && Object.assign(this.#settings, { selector });
418
+ this.#settings = {
419
+ direction,
420
+ navigationOnly,
421
+ noMemory,
422
+ noStart,
423
+ selector,
424
+ typeahead,
425
+ wrap
426
+ };
357
427
  this.#selectorFilter = this.#createSelectorFilter();
358
428
  this.#initialize();
359
429
  }
@@ -364,7 +434,10 @@ var RovingTabIndex = class _RovingTabIndex {
364
434
  this.#isDestroyed = true;
365
435
  this.#controller?.abort();
366
436
  this.#controller = null;
367
- restoreAttributes([...this.#focusables]);
437
+ this.#focusables.forEach((focusable) => {
438
+ _RovingTabIndex.#initialized.delete(focusable);
439
+ restoreAttributes2(focusable);
440
+ });
368
441
  this.#focusables.clear();
369
442
  this.#focusablesByFirstChar.clear();
370
443
  }
@@ -401,7 +474,7 @@ var RovingTabIndex = class _RovingTabIndex {
401
474
  return;
402
475
  }
403
476
  const { direction, typeahead, wrap } = this.#settings;
404
- const isBoth = !direction;
477
+ const isBoth = direction === "both";
405
478
  const isHorizontal = direction === "horizontal";
406
479
  if (![
407
480
  "End",
@@ -413,18 +486,20 @@ var RovingTabIndex = class _RovingTabIndex {
413
486
  return;
414
487
  }
415
488
  }
489
+ const candidates = this.#getFocusables().filter(
490
+ (focusable2) => this.#focusables.has(focusable2)
491
+ );
416
492
  const active = getActiveElement();
417
493
  if (!(active instanceof Element)) {
418
494
  return;
419
495
  }
420
- const current = this.#getFocusables();
421
- if (!current.includes(active)) {
496
+ if (!candidates.includes(active)) {
422
497
  return;
423
498
  }
424
499
  event.preventDefault();
425
- const currentIndex = current.indexOf(active);
426
500
  let newIndex;
427
- let target = current;
501
+ const activeIndex = candidates.indexOf(active);
502
+ let focusables = candidates;
428
503
  switch (key) {
429
504
  case "End":
430
505
  newIndex = -1;
@@ -434,37 +509,47 @@ var RovingTabIndex = class _RovingTabIndex {
434
509
  break;
435
510
  case "ArrowLeft":
436
511
  case "ArrowUp": {
437
- const rawIndex = currentIndex - 1;
512
+ const rawIndex = activeIndex - 1;
438
513
  newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
439
514
  break;
440
515
  }
441
516
  case "ArrowRight":
442
517
  case "ArrowDown": {
443
- const rawIndex = currentIndex + 1;
444
- newIndex = wrap ? rawIndex % current.length : Math.min(rawIndex, current.length - 1);
518
+ const rawIndex = activeIndex + 1;
519
+ const length = focusables.length;
520
+ newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
445
521
  break;
446
522
  }
447
523
  default: {
448
- target = this.#focusablesByFirstChar.get(key.toUpperCase()) ?? [];
449
- const foundIndex = target.findIndex(
450
- (focusable2) => current.indexOf(focusable2) > currentIndex
524
+ const focusablesByFirstChar = new Set(
525
+ this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
526
+ );
527
+ focusables = candidates.filter(
528
+ (candidate) => focusablesByFirstChar.has(candidate)
451
529
  );
452
- newIndex = foundIndex >= 0 ? foundIndex : 0;
530
+ const afterIndex = focusables.findIndex(
531
+ (focusable2) => candidates.indexOf(focusable2) > activeIndex
532
+ );
533
+ newIndex = afterIndex >= 0 ? afterIndex : 0;
453
534
  }
454
535
  }
455
- const focusable = target.at(newIndex);
536
+ const focusable = focusables.at(newIndex);
456
537
  focusable && focusElement(focusable);
457
538
  };
458
539
  #update(active) {
459
540
  const current = new Set(this.#getFocusables());
460
541
  for (const focusable of this.#focusables) {
461
542
  if (!current.has(focusable)) {
462
- focusable.isConnected && restoreAttributes([focusable]);
543
+ _RovingTabIndex.#initialized.delete(focusable);
544
+ restoreAttributes2(focusable);
463
545
  this.#focusables.delete(focusable);
464
- this.#focusablesByFirstChar.forEach((focusables) => {
546
+ for (const [key, focusables] of this.#focusablesByFirstChar) {
465
547
  const index = focusables.indexOf(focusable);
466
- index >= 0 && focusables.splice(index, 1);
467
- });
548
+ if (index >= 0) {
549
+ focusables.splice(index, 1);
550
+ !focusables.length && this.#focusablesByFirstChar.delete(key);
551
+ }
552
+ }
468
553
  }
469
554
  }
470
555
  const { navigationOnly, noStart, typeahead } = this.#settings;
@@ -473,12 +558,12 @@ var RovingTabIndex = class _RovingTabIndex {
473
558
  continue;
474
559
  }
475
560
  if (_RovingTabIndex.#initialized.has(focusable)) {
476
- throw new TypeError("Already initialized");
561
+ continue;
477
562
  }
478
563
  this.#focusables.add(focusable);
479
564
  _RovingTabIndex.#initialized.add(focusable);
480
565
  if (!navigationOnly) {
481
- saveAttributes([focusable], ["tabindex"]);
566
+ saveAttributes2(focusable, "tabindex");
482
567
  focusable.setAttribute("tabindex", "-1");
483
568
  }
484
569
  if (!typeahead) {
@@ -491,7 +576,7 @@ var RovingTabIndex = class _RovingTabIndex {
491
576
  );
492
577
  if (char) {
493
578
  keys.add(char);
494
- saveAttributes([focusable], ["aria-keyshortcuts"]);
579
+ saveAttributes2(focusable, "aria-keyshortcuts");
495
580
  addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
496
581
  caseInsensitive: true
497
582
  });
@@ -777,7 +862,7 @@ var Disclosure = class _Disclosure {
777
862
  );
778
863
  }
779
864
  #createBinding(details, summary, content) {
780
- return { details, summary, content, animation: null };
865
+ return { animation: null, content, details, summary };
781
866
  }
782
867
  #isFocusable(element) {
783
868
  return element.tabIndex >= 0;
@@ -808,7 +893,7 @@ function waitAnimationFinish(animation) {
808
893
  * WAI-ARIA compliant disclosure pattern implementation in TypeScript.
809
894
  * Using the <details> and <summary> element.
810
895
  *
811
- * @version 2.0.2
896
+ * @version 2.0.4
812
897
  * @author Yusuke Kamiyamane
813
898
  * @license MIT
814
899
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -820,7 +905,18 @@ function waitAnimationFinish(animation) {
820
905
  (**
821
906
  * Attributes Utils
822
907
  *
823
- * @version 1.1.3
908
+ * @version 2.0.0
909
+ * @author Yusuke Kamiyamane
910
+ * @license MIT
911
+ * @copyright Copyright (c) Yusuke Kamiyamane
912
+ * @see {@link https://github.com/y14e/attributes-utils}
913
+ *)
914
+
915
+ @y14e/attributes-utils/dist/index.js:
916
+ (**
917
+ * Attributes Utils
918
+ *
919
+ * @version 1.1.7
824
920
  * @author Yusuke Kamiyamane
825
921
  * @license MIT
826
922
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -833,7 +929,7 @@ power-focusable/dist/index.js:
833
929
  * High-precision focus management utility with full composed tree support.
834
930
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
835
931
  *
836
- * @version 4.3.8
932
+ * @version 4.3.23
837
933
  * @author Yusuke Kamiyamane
838
934
  * @license MIT
839
935
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -846,7 +942,7 @@ power-focusable/dist/index.js:
846
942
  * Lightweight roving tabindex utility with fully focus management.
847
943
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
848
944
  *
849
- * @version 3.1.6
945
+ * @version 3.1.20
850
946
  * @author Yusuke Kamiyamane
851
947
  * @license MIT
852
948
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.cjs CHANGED
@@ -252,7 +252,7 @@ var Disclosure = class _Disclosure {
252
252
  );
253
253
  }
254
254
  #createBinding(details, summary, content) {
255
- return { details, summary, content, animation: null };
255
+ return { animation: null, content, details, summary };
256
256
  }
257
257
  #isFocusable(element) {
258
258
  return element.tabIndex >= 0;
@@ -283,7 +283,7 @@ function waitAnimationFinish(animation) {
283
283
  * WAI-ARIA compliant disclosure pattern implementation in TypeScript.
284
284
  * Using the <details> and <summary> element.
285
285
  *
286
- * @version 2.0.2
286
+ * @version 2.0.4
287
287
  * @author Yusuke Kamiyamane
288
288
  * @license MIT
289
289
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.d.cts CHANGED
@@ -3,23 +3,23 @@
3
3
  * WAI-ARIA compliant disclosure pattern implementation in TypeScript.
4
4
  * Using the <details> and <summary> element.
5
5
  *
6
- * @version 2.0.2
6
+ * @version 2.0.4
7
7
  * @author Yusuke Kamiyamane
8
8
  * @license MIT
9
9
  * @copyright Copyright (c) Yusuke Kamiyamane
10
10
  * @see {@link https://github.com/y14e/disclosure}
11
11
  */
12
12
  interface DisclosureOptions {
13
- readonly animation?: {
14
- readonly duration?: number;
15
- readonly easing?: string;
13
+ animation: {
14
+ duration: number;
15
+ easing: string;
16
16
  };
17
- readonly collapsible?: boolean;
17
+ collapsible: boolean;
18
18
  }
19
19
  declare class Disclosure {
20
20
  #private;
21
- static defaults: DisclosureOptions;
22
- constructor(root: HTMLElement, options?: DisclosureOptions);
21
+ static defaults: Partial<DisclosureOptions>;
22
+ constructor(root: HTMLElement, options?: Partial<DisclosureOptions>);
23
23
  collapse(details: HTMLDetailsElement): void;
24
24
  destroy(force?: boolean): Promise<void>;
25
25
  expand(details: HTMLDetailsElement): void;
package/dist/index.d.ts CHANGED
@@ -3,23 +3,23 @@
3
3
  * WAI-ARIA compliant disclosure pattern implementation in TypeScript.
4
4
  * Using the <details> and <summary> element.
5
5
  *
6
- * @version 2.0.2
6
+ * @version 2.0.4
7
7
  * @author Yusuke Kamiyamane
8
8
  * @license MIT
9
9
  * @copyright Copyright (c) Yusuke Kamiyamane
10
10
  * @see {@link https://github.com/y14e/disclosure}
11
11
  */
12
12
  interface DisclosureOptions {
13
- readonly animation?: {
14
- readonly duration?: number;
15
- readonly easing?: string;
13
+ animation: {
14
+ duration: number;
15
+ easing: string;
16
16
  };
17
- readonly collapsible?: boolean;
17
+ collapsible: boolean;
18
18
  }
19
19
  declare class Disclosure {
20
20
  #private;
21
- static defaults: DisclosureOptions;
22
- constructor(root: HTMLElement, options?: DisclosureOptions);
21
+ static defaults: Partial<DisclosureOptions>;
22
+ constructor(root: HTMLElement, options?: Partial<DisclosureOptions>);
23
23
  collapse(details: HTMLDetailsElement): void;
24
24
  destroy(force?: boolean): Promise<void>;
25
25
  expand(details: HTMLDetailsElement): void;
package/dist/index.js CHANGED
@@ -250,7 +250,7 @@ var Disclosure = class _Disclosure {
250
250
  );
251
251
  }
252
252
  #createBinding(details, summary, content) {
253
- return { details, summary, content, animation: null };
253
+ return { animation: null, content, details, summary };
254
254
  }
255
255
  #isFocusable(element) {
256
256
  return element.tabIndex >= 0;
@@ -281,7 +281,7 @@ function waitAnimationFinish(animation) {
281
281
  * WAI-ARIA compliant disclosure pattern implementation in TypeScript.
282
282
  * Using the <details> and <summary> element.
283
283
  *
284
- * @version 2.0.2
284
+ * @version 2.0.4
285
285
  * @author Yusuke Kamiyamane
286
286
  * @license MIT
287
287
  * @copyright Copyright (c) Yusuke Kamiyamane
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@y14e/disclosure",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "description": "WAI-ARIA compliant disclosure pattern implementation in TypeScript",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -45,14 +45,13 @@
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",
56
- "@y14e/roving-tabindex": "^3.1.6"
54
+ "@y14e/attributes-utils": "^2.0.0",
55
+ "@y14e/roving-tabindex": "^3.1.20"
57
56
  }
58
57
  }