@y14e/disclosure 2.1.3 → 2.2.0

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.
@@ -8,16 +8,16 @@ function addAttributeToken(element, name, token, options = {}) {
8
8
  const value = element.getAttribute(name)?.trim();
9
9
  const { caseInsensitive, parse, serialize } = resolveOptions(options);
10
10
  const tokens = value ? parse(value).filter(Boolean) : [];
11
- if (caseInsensitive) {
12
- const lower = token.toLowerCase();
13
- if (tokens.every((t) => t.toLowerCase() !== lower)) {
14
- tokens.push(token);
15
- element.setAttribute(name, serialize(tokens));
16
- }
17
- } else {
11
+ if (!caseInsensitive) {
18
12
  const set = new Set(tokens);
19
13
  set.add(token);
20
14
  element.setAttribute(name, serialize([...set]));
15
+ return;
16
+ }
17
+ const lower = token.toLowerCase();
18
+ if (tokens.every((t) => t.toLowerCase() !== lower)) {
19
+ tokens.push(token);
20
+ element.setAttribute(name, serialize(tokens));
21
21
  }
22
22
  }
23
23
  var snapshots = /* @__PURE__ */ new WeakMap();
@@ -89,79 +89,105 @@ function resolveOptions(options) {
89
89
  }
90
90
 
91
91
  // node_modules/power-focusable/dist/index.js
92
+ function getComposedChildren(node) {
93
+ if (node instanceof ShadowRoot) {
94
+ return [...node.children];
95
+ }
96
+ if (!(node instanceof Element)) {
97
+ return [];
98
+ }
99
+ if (node instanceof HTMLSlotElement) {
100
+ const assigned = node.assignedElements({ flatten: true });
101
+ if (assigned.length) {
102
+ return assigned;
103
+ }
104
+ }
105
+ if (node instanceof HTMLElement && node.shadowRoot?.mode === "open") {
106
+ return [...node.shadowRoot.children];
107
+ }
108
+ return [...node.children];
109
+ }
92
110
  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"])';
93
- var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX = FOCUSABLE_SELECTOR.replace(
94
- /(,\s*)?\[tabindex="-1"\]/g,
95
- ""
96
- );
97
- function getFocusables(container = document.body, options = {}) {
98
- if (!(container instanceof Element)) {
99
- console.warn("Invalid container element. Fallback: <body> element.");
100
- container = document.body;
111
+ var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX = FOCUSABLE_SELECTOR.replace(/(,\s*)?\[tabindex="-1"\]/g, "");
112
+ function focusElement(element) {
113
+ "focus" in element && typeof element.focus === "function" && element.focus();
114
+ }
115
+ function getActiveElement() {
116
+ let current = document.activeElement;
117
+ while (current?.shadowRoot?.activeElement) {
118
+ current = current.shadowRoot.activeElement;
101
119
  }
102
- const {
103
- composed,
120
+ return current;
121
+ }
122
+ function getTabIndex(element) {
123
+ return "tabIndex" in element ? Number(element.tabIndex) : 0;
124
+ }
125
+ function isDisabled(element) {
126
+ return "disabled" in element && !!element.disabled;
127
+ }
128
+ function isFormControl(element) {
129
+ return ["BUTTON", "INPUT", "SELECT", "TEXTAREA"].includes(element.tagName);
130
+ }
131
+ function isInert(element) {
132
+ return "inert" in element && !!element.inert;
133
+ }
134
+ function isUngroupedRadio(element) {
135
+ return element.type === "radio" && !!element.name;
136
+ }
137
+ function resolveOptions2(options) {
138
+ let {
139
+ anchor = getActiveElement(),
140
+ composed = false,
104
141
  filter,
105
142
  include,
106
- skipNegativeTabIndexCheck,
107
- skipVisibilityCheck
108
- } = resolveOptions2(options);
109
- const candidates = [];
110
- if (composed || include) {
111
- let traverse2 = function(node) {
112
- if (isFocusable(node, {
113
- skipNegativeTabIndexCheck,
114
- skipVisibilityCheck
115
- }) || include?.(node)) {
116
- candidates.push(node);
117
- }
118
- (composed ? getComposedChildren(node) : [...node.children]).map(traverse2);
119
- };
120
- (composed ? getComposedChildren(container) : [...container.children]).map(
121
- traverse2
122
- );
123
- } else {
124
- for (const match of container.querySelectorAll(
125
- skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
126
- )) {
127
- match && isFocusable(match, {
128
- skipNegativeTabIndexCheck,
129
- skipVisibilityCheck
130
- }) && candidates.push(match);
143
+ skipNegativeTabIndexCheck = false,
144
+ skipVisibilityCheck = false,
145
+ wrap = false
146
+ } = options;
147
+ if (!(anchor instanceof Element)) {
148
+ const active = getActiveElement();
149
+ if (active instanceof Element) {
150
+ console.warn("Invalid anchor element. Fallback: active element.");
151
+ anchor = active;
131
152
  }
132
153
  }
133
- return normalizeRadioGroup(
134
- sortByTabIndex(filter ? candidates.filter(filter) : candidates)
135
- );
136
- }
137
- function isFocusable(element, options = {}) {
138
- if (!(element instanceof Element)) {
139
- console.warn("Invalid element");
140
- return false;
154
+ if (typeof composed !== "boolean") {
155
+ console.warn("Invalid composed option. Fallback: false.");
156
+ composed = false;
141
157
  }
142
- const { skipNegativeTabIndexCheck, skipVisibilityCheck } = resolveOptions2(options);
143
- if (element.hasAttribute("hidden") || isInert(element)) {
144
- return false;
158
+ if (filter !== void 0 && typeof filter !== "function") {
159
+ console.warn(
160
+ "Invalid filter function. Fallback: no filter function (undefined)."
161
+ );
162
+ filter = void 0;
145
163
  }
146
- if (!skipNegativeTabIndexCheck && getTabIndex(element) < 0) {
147
- return false;
164
+ if (include !== void 0 && typeof include !== "function") {
165
+ console.warn(
166
+ "Invalid include function. Fallback: no include function (undefined)."
167
+ );
168
+ include = void 0;
148
169
  }
149
- if (!element.matches(
150
- skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
151
- )) {
152
- return false;
170
+ if (typeof skipNegativeTabIndexCheck !== "boolean") {
171
+ console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
172
+ skipNegativeTabIndexCheck = false;
153
173
  }
154
- if (isDisabledDeep(element)) {
155
- return false;
174
+ if (typeof skipVisibilityCheck !== "boolean") {
175
+ console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
176
+ skipVisibilityCheck = false;
156
177
  }
157
- if (!skipVisibilityCheck && !element.checkVisibility({
158
- contentVisibilityAuto: true,
159
- opacityProperty: true,
160
- visibilityProperty: true
161
- })) {
162
- return false;
178
+ if (typeof wrap !== "boolean") {
179
+ console.warn("Invalid wrap option. Fallback: false.");
180
+ wrap = false;
163
181
  }
164
- return true;
182
+ return {
183
+ anchor,
184
+ composed,
185
+ filter,
186
+ include,
187
+ skipNegativeTabIndexCheck,
188
+ skipVisibilityCheck,
189
+ wrap
190
+ };
165
191
  }
166
192
  function isDisabledDeep(element) {
167
193
  let current = element;
@@ -243,116 +269,143 @@ function sortByTabIndex(elements) {
243
269
  }
244
270
  return ordered.sort((a, b) => getTabIndex(a) - getTabIndex(b)).concat(natural);
245
271
  }
246
- function getComposedChildren(node) {
247
- if (node instanceof ShadowRoot) {
248
- return [...node.children];
249
- }
250
- if (!(node instanceof Element)) {
251
- return [];
272
+ function getFocusables(container = document.body, options = {}) {
273
+ if (!(container instanceof Element)) {
274
+ console.warn("Invalid container element. Fallback: <body> element.");
275
+ container = document.body;
252
276
  }
253
- if (node instanceof HTMLSlotElement) {
254
- const assigned = node.assignedElements({ flatten: true });
255
- if (assigned.length) {
256
- return assigned;
277
+ const {
278
+ composed,
279
+ filter,
280
+ include,
281
+ skipNegativeTabIndexCheck,
282
+ skipVisibilityCheck
283
+ } = resolveOptions2(options);
284
+ const candidates = [];
285
+ if (!composed && !include) {
286
+ for (const match of container.querySelectorAll(
287
+ !skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR : FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX
288
+ )) {
289
+ match && isFocusable(match, {
290
+ skipNegativeTabIndexCheck,
291
+ skipVisibilityCheck
292
+ }) && candidates.push(match);
257
293
  }
294
+ } else {
295
+ let traverse2 = function(node) {
296
+ if (isFocusable(node, {
297
+ skipNegativeTabIndexCheck,
298
+ skipVisibilityCheck
299
+ }) || include?.(node)) {
300
+ candidates.push(node);
301
+ }
302
+ (!composed ? [...node.children] : getComposedChildren(node)).map(
303
+ traverse2
304
+ );
305
+ };
306
+ (!composed ? [...container.children] : getComposedChildren(container)).map(
307
+ traverse2
308
+ );
258
309
  }
259
- if (node instanceof HTMLElement && node.shadowRoot?.mode === "open") {
260
- return [...node.shadowRoot.children];
261
- }
262
- return [...node.children];
263
- }
264
- function focusElement(element) {
265
- "focus" in element && typeof element.focus === "function" && element.focus();
310
+ return normalizeRadioGroup(
311
+ sortByTabIndex(!filter ? candidates : candidates.filter(filter))
312
+ );
266
313
  }
267
- function getActiveElement() {
268
- let current = document.activeElement;
269
- while (current?.shadowRoot?.activeElement) {
270
- current = current.shadowRoot.activeElement;
314
+ function isFocusable(element, options = {}) {
315
+ if (!(element instanceof Element)) {
316
+ console.warn("Invalid element");
317
+ return false;
271
318
  }
272
- return current;
273
- }
274
- function getTabIndex(element) {
275
- return "tabIndex" in element ? Number(element.tabIndex) : 0;
276
- }
277
- function isDisabled(element) {
278
- return "disabled" in element && !!element.disabled;
279
- }
280
- function isFormControl(element) {
281
- const name = element.tagName;
282
- return name === "BUTTON" || name === "INPUT" || name === "SELECT" || name === "TEXTAREA";
283
- }
284
- function isInert(element) {
285
- return "inert" in element && !!element.inert;
286
- }
287
- function isUngroupedRadio(element) {
288
- return element.type === "radio" && !!element.name;
319
+ const { skipNegativeTabIndexCheck, skipVisibilityCheck } = resolveOptions2(options);
320
+ if (element.hasAttribute("hidden") || isInert(element)) {
321
+ return false;
322
+ }
323
+ if (!skipNegativeTabIndexCheck && getTabIndex(element) < 0) {
324
+ return false;
325
+ }
326
+ if (!element.matches(
327
+ !skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR : FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX
328
+ )) {
329
+ return false;
330
+ }
331
+ if (isDisabledDeep(element)) {
332
+ return false;
333
+ }
334
+ if (!skipVisibilityCheck && !element.checkVisibility({
335
+ contentVisibilityAuto: true,
336
+ opacityProperty: true,
337
+ visibilityProperty: true
338
+ })) {
339
+ return false;
340
+ }
341
+ return true;
289
342
  }
290
- function resolveOptions2(options) {
343
+
344
+ // node_modules/@y14e/roving-tabindex/dist/index.js
345
+ var DIRECTIONS = ["both", "grid", "horizontal", "vertical"];
346
+ function resolveOptions3(options) {
291
347
  let {
292
- anchor = getActiveElement(),
293
- composed = false,
294
- filter,
295
- include,
296
- skipNegativeTabIndexCheck = false,
297
- skipVisibilityCheck = false,
348
+ direction = "both",
349
+ navigationOnly = false,
350
+ noMemory = false,
351
+ noStart = false,
352
+ selector = "",
353
+ typeahead = false,
298
354
  wrap = false
299
355
  } = options;
300
- if (!(anchor instanceof Element)) {
301
- const active = getActiveElement();
302
- if (active instanceof Element) {
303
- console.warn("Invalid anchor element. Fallback: active element.");
304
- anchor = active;
305
- }
356
+ if (typeof direction === "string") {
357
+ direction = direction.toLowerCase();
306
358
  }
307
- if (typeof composed !== "boolean") {
308
- console.warn("Invalid composed option. Fallback: false.");
309
- composed = false;
359
+ if (!DIRECTIONS.includes(direction)) {
360
+ console.warn("Invalid direction option. Fallback: 'both'.");
361
+ direction = "both";
310
362
  }
311
- if (filter !== void 0 && typeof filter !== "function") {
312
- console.warn(
313
- "Invalid filter function. Fallback: no filter function (undefined)."
314
- );
315
- filter = void 0;
363
+ if (typeof navigationOnly !== "boolean") {
364
+ console.warn("Invalid navigationOnly option. Fallback: false.");
365
+ navigationOnly = false;
316
366
  }
317
- if (include !== void 0 && typeof include !== "function") {
318
- console.warn(
319
- "Invalid include function. Fallback: no include function (undefined)."
320
- );
321
- include = void 0;
367
+ if (typeof noMemory !== "boolean") {
368
+ console.warn("Invalid noMemory option. Fallback: false.");
369
+ noMemory = false;
322
370
  }
323
- if (typeof skipNegativeTabIndexCheck !== "boolean") {
324
- console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
325
- skipNegativeTabIndexCheck = false;
371
+ if (typeof noStart !== "boolean") {
372
+ console.warn("Invalid noStart option. Fallback: false.");
373
+ noStart = false;
326
374
  }
327
- if (typeof skipVisibilityCheck !== "boolean") {
328
- console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
329
- skipVisibilityCheck = false;
375
+ if (selector !== "") {
376
+ try {
377
+ document.querySelector(selector);
378
+ } catch {
379
+ console.warn("Invalid selector. Fallback: no selector string.");
380
+ selector = "";
381
+ }
382
+ }
383
+ if (typeof typeahead !== "boolean") {
384
+ console.warn("Invalid typeahead option. Fallback: false.");
385
+ typeahead = false;
330
386
  }
331
387
  if (typeof wrap !== "boolean") {
332
388
  console.warn("Invalid wrap option. Fallback: false.");
333
389
  wrap = false;
334
390
  }
335
391
  return {
336
- anchor,
337
- composed,
338
- filter,
339
- include,
340
- skipNegativeTabIndexCheck,
341
- skipVisibilityCheck,
392
+ direction,
393
+ navigationOnly,
394
+ noMemory,
395
+ noStart,
396
+ selector,
397
+ typeahead,
342
398
  wrap
343
399
  };
344
400
  }
345
-
346
- // node_modules/@y14e/roving-tabindex/dist/index.js
347
- var DIRECTIONS = ["both", "grid", "horizontal", "vertical"];
348
401
  function createRovingTabIndex(container, options = {}) {
349
402
  if (!(container instanceof Element)) {
350
403
  console.warn("Invalid container element");
351
404
  return () => {
352
405
  };
353
406
  }
354
- const rovingTabIndex = new RovingTabIndex(container, options);
355
- return () => rovingTabIndex.destroy();
407
+ const instance = new RovingTabIndex(container, options);
408
+ return () => instance.destroy();
356
409
  }
357
410
  var RovingTabIndex = class _RovingTabIndex {
358
411
  static #initialized = /* @__PURE__ */ new Set();
@@ -365,7 +418,7 @@ var RovingTabIndex = class _RovingTabIndex {
365
418
  #isDestroyed = false;
366
419
  constructor(container, options = {}) {
367
420
  this.#container = container;
368
- this.#settings = this.#resolveOptions(options);
421
+ this.#settings = resolveOptions3(options);
369
422
  this.#selectorFilter = this.#createSelectorFilter();
370
423
  this.#initialize();
371
424
  }
@@ -385,32 +438,24 @@ var RovingTabIndex = class _RovingTabIndex {
385
438
  }
386
439
  #initialize() {
387
440
  this.#update(getActiveElement());
441
+ const container = this.#container;
388
442
  this.#controller = new AbortController();
389
443
  const { signal } = this.#controller;
390
- this.#container.addEventListener("focusin", this.#onFocusIn, { signal });
391
- this.#settings.noMemory && this.#container.addEventListener("focusout", this.#onFocusOut, {
444
+ container.addEventListener("focusin", this.#onFocusIn, { signal });
445
+ this.#settings.noMemory && container.addEventListener("focusout", this.#onFocusOut, {
392
446
  signal
393
447
  });
394
- this.#container.addEventListener("keydown", this.#onKeyDown, { signal });
448
+ container.addEventListener("keydown", this.#onKeyDown, { signal });
395
449
  }
396
450
  #onFocusIn = (event) => {
397
- if (!(event instanceof FocusEvent)) {
398
- return;
399
- }
400
451
  const { target } = event;
401
452
  target instanceof Element && this.#update(target);
402
453
  };
403
454
  #onFocusOut = (event) => {
404
- if (!(event instanceof FocusEvent)) {
405
- return;
406
- }
407
455
  const target = event.relatedTarget;
408
456
  (!(target instanceof Element) || !this.#focusables.has(target)) && this.#update();
409
457
  };
410
458
  #onKeyDown = (event) => {
411
- if (!(event instanceof KeyboardEvent)) {
412
- return;
413
- }
414
459
  const { direction, typeahead, wrap = false } = this.#settings;
415
460
  const isGrid = direction === "grid";
416
461
  const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
@@ -450,9 +495,9 @@ var RovingTabIndex = class _RovingTabIndex {
450
495
  if (isGrid && !ctrlKey) {
451
496
  const cell = this.#getCellsOfActiveRow().at(rawIndex);
452
497
  newIndex = cell ? candidates.indexOf(cell) : activeIndex;
453
- } else {
454
- newIndex = rawIndex;
498
+ break;
455
499
  }
500
+ newIndex = rawIndex;
456
501
  break;
457
502
  }
458
503
  case "ArrowLeft":
@@ -462,14 +507,14 @@ var RovingTabIndex = class _RovingTabIndex {
462
507
  if (["ArrowUp", "ArrowDown"].includes(key) && isGrid) {
463
508
  const cell = this.#getNextCell(key, wrap);
464
509
  newIndex = cell ? candidates.indexOf(cell) : activeIndex;
465
- } else {
466
- if (isGrid) {
467
- target = this.#getCellsOfActiveRow();
468
- }
469
- const isPrevious = ["ArrowLeft", "ArrowUp"].includes(key);
470
- const rawIndex = (isGrid ? target.indexOf(active) : activeIndex) + (isPrevious ? -1 : 1);
471
- newIndex = isPrevious ? wrap ? rawIndex : Math.max(rawIndex, 0) : wrap ? rawIndex % target.length : Math.min(rawIndex, target.length - 1);
510
+ break;
511
+ }
512
+ if (isGrid) {
513
+ target = this.#getCellsOfActiveRow();
472
514
  }
515
+ const isPrevious = ["ArrowLeft", "ArrowUp"].includes(key);
516
+ const rawIndex = (isGrid ? target.indexOf(active) : activeIndex) + (isPrevious ? -1 : 1);
517
+ newIndex = isPrevious ? !wrap ? Math.max(rawIndex, 0) : rawIndex : !wrap ? Math.min(rawIndex, target.length - 1) : rawIndex % target.length;
473
518
  break;
474
519
  }
475
520
  default: {
@@ -489,16 +534,17 @@ var RovingTabIndex = class _RovingTabIndex {
489
534
  #update(active) {
490
535
  const current = new Set(this.#getFocusables());
491
536
  for (const focusable of this.#focusables) {
492
- if (!current.has(focusable)) {
493
- _RovingTabIndex.#initialized.delete(focusable);
494
- restoreAttributes(focusable);
495
- this.#focusables.delete(focusable);
496
- for (const [key, focusables] of this.#focusablesByFirstChar) {
497
- const index = focusables.indexOf(focusable);
498
- if (index >= 0) {
499
- focusables.splice(index, 1);
500
- !focusables.length && this.#focusablesByFirstChar.delete(key);
501
- }
537
+ if (current.has(focusable)) {
538
+ continue;
539
+ }
540
+ _RovingTabIndex.#initialized.delete(focusable);
541
+ restoreAttributes(focusable);
542
+ this.#focusables.delete(focusable);
543
+ for (const [key, focusables] of this.#focusablesByFirstChar) {
544
+ const index = focusables.indexOf(focusable);
545
+ if (index >= 0) {
546
+ focusables.splice(index, 1);
547
+ !focusables.length && this.#focusablesByFirstChar.delete(key);
502
548
  }
503
549
  }
504
550
  }
@@ -542,11 +588,11 @@ var RovingTabIndex = class _RovingTabIndex {
542
588
  for (const focusable of this.#focusables) {
543
589
  focusable.setAttribute("tabindex", focusable === active ? "0" : "-1");
544
590
  }
545
- } else {
546
- [...this.#focusables].forEach((focusable, i) => {
547
- focusable.setAttribute("tabindex", i || noStart ? "-1" : "0");
548
- });
591
+ return;
549
592
  }
593
+ [...this.#focusables].forEach((focusable, i) => {
594
+ focusable.setAttribute("tabindex", !i && !noStart ? "0" : "-1");
595
+ });
550
596
  }
551
597
  }
552
598
  #createSelectorFilter() {
@@ -555,10 +601,7 @@ var RovingTabIndex = class _RovingTabIndex {
555
601
  }
556
602
  #getCellCoords(cell) {
557
603
  const { left, top, width, height } = cell.getBoundingClientRect();
558
- return {
559
- x: left + width / 2,
560
- y: top + height / 2
561
- };
604
+ return { x: left + width / 2, y: top + height / 2 };
562
605
  }
563
606
  #getCellsOfActiveRow() {
564
607
  const active = getActiveElement();
@@ -623,72 +666,54 @@ var RovingTabIndex = class _RovingTabIndex {
623
666
  }
624
667
  return result;
625
668
  }
626
- #resolveOptions(options) {
627
- let {
628
- direction = "both",
629
- navigationOnly = false,
630
- noMemory = false,
631
- noStart = false,
632
- selector = "",
633
- typeahead = false,
634
- wrap = false
635
- } = options;
636
- direction = direction.toLowerCase();
637
- if (!DIRECTIONS.includes(direction)) {
638
- console.warn("Invalid direction option. Fallback: 'both'.");
639
- direction = "both";
640
- }
641
- if (typeof navigationOnly !== "boolean") {
642
- console.warn("Invalid navigationOnly option. Fallback: false.");
643
- navigationOnly = false;
644
- }
645
- if (typeof noMemory !== "boolean") {
646
- console.warn("Invalid noMemory option. Fallback: false.");
647
- noMemory = false;
648
- }
649
- if (typeof noStart !== "boolean") {
650
- console.warn("Invalid noStart option. Fallback: false.");
651
- noStart = false;
652
- }
653
- if (selector !== "") {
654
- try {
655
- document.querySelector(selector);
656
- } catch {
657
- console.warn("Invalid selector. Fallback: no selector string.");
658
- selector = "";
659
- }
660
- }
661
- if (typeof typeahead !== "boolean") {
662
- console.warn("Invalid typeahead option. Fallback: false.");
663
- typeahead = false;
664
- }
665
- if (typeof wrap !== "boolean") {
666
- console.warn("Invalid wrap option. Fallback: false.");
667
- wrap = false;
668
- }
669
- return {
670
- direction,
671
- navigationOnly,
672
- noMemory,
673
- noStart,
674
- selector,
675
- typeahead,
676
- wrap
677
- };
678
- }
679
669
  };
680
670
 
671
+ // src/defaults.ts
672
+ var defaults = {
673
+ animation: {
674
+ duration: 300,
675
+ easing: "ease"
676
+ },
677
+ collapsible: true
678
+ };
679
+
680
+ // src/options.ts
681
+ function resolveOptions4(defaults2, source) {
682
+ const merged = {
683
+ ...defaults2,
684
+ ...source,
685
+ animation: { ...defaults2.animation, ...source.animation ?? {} }
686
+ };
687
+ const mergedAnimation = merged.animation;
688
+ const duration = mergedAnimation.duration;
689
+ const defaultAnimation = defaults2.animation;
690
+ if (typeof duration !== "number" || Number.isNaN(duration)) {
691
+ const duration2 = defaultAnimation.duration;
692
+ console.warn(`Invalid animation duration. Fallback: ${duration2} (ms).`);
693
+ mergedAnimation.duration = duration2;
694
+ }
695
+ if (duration < 0) {
696
+ console.warn("Invalid animation duration. Fallback: 0 (ms).");
697
+ mergedAnimation.duration = 0;
698
+ }
699
+ if (!CSS.supports("animation-timing-function", mergedAnimation.easing)) {
700
+ const easing = defaultAnimation.easing;
701
+ console.warn(`Invalid animation easing. Fallback: '${easing}'.`);
702
+ mergedAnimation.easing = easing;
703
+ }
704
+ if (typeof merged.collapsible !== "boolean") {
705
+ const collapsible = defaults2.collapsible;
706
+ console.warn(`Invalid collapsible option. Fallback: ${collapsible}.`);
707
+ merged.collapsible = collapsible;
708
+ }
709
+ return merged;
710
+ }
711
+
681
712
  // src/index.ts
682
713
  var Disclosure = class _Disclosure {
683
714
  static defaults = {};
684
715
  #rootElement;
685
- #defaults = {
686
- animation: {
687
- duration: 300,
688
- easing: "ease"
689
- },
690
- collapsible: true
691
- };
716
+ #defaults = defaults;
692
717
  #settings;
693
718
  #detailsElements;
694
719
  #summaryElements;
@@ -708,8 +733,8 @@ var Disclosure = class _Disclosure {
708
733
  return;
709
734
  }
710
735
  this.#rootElement = root;
711
- this.#defaults = this.#resolveOptions(this.#defaults, _Disclosure.defaults);
712
- this.#settings = this.#resolveOptions(this.#defaults, options);
736
+ this.#defaults = resolveOptions4(this.#defaults, _Disclosure.defaults);
737
+ this.#settings = resolveOptions4(this.#defaults, options);
713
738
  matchMedia("(prefers-reduced-motion: reduce)").matches && Object.assign(this.#settings.animation, { duration: 0 });
714
739
  const NOT_NESTED = ":not(:scope summary + * *)";
715
740
  this.#detailsElements = [
@@ -932,37 +957,6 @@ var Disclosure = class _Disclosure {
932
957
  #isFocusable(element) {
933
958
  return element.tabIndex >= 0;
934
959
  }
935
- #resolveOptions(target, source) {
936
- const merged = {
937
- ...target,
938
- ...source,
939
- animation: { ...target.animation, ...source.animation ?? {} }
940
- };
941
- const mergedAnimation = merged.animation;
942
- const duration = mergedAnimation.duration;
943
- const defaults = this.#defaults;
944
- const defaultAnimation = defaults.animation;
945
- if (typeof duration !== "number" || Number.isNaN(duration)) {
946
- const duration2 = defaultAnimation.duration;
947
- console.warn(`Invalid animation duration. Fallback: ${duration2} (ms).`);
948
- mergedAnimation.duration = duration2;
949
- }
950
- if (duration < 0) {
951
- console.warn("Invalid animation duration. Fallback: 0 (ms).");
952
- mergedAnimation.duration = 0;
953
- }
954
- if (!CSS.supports("animation-timing-function", mergedAnimation.easing)) {
955
- const easing = defaultAnimation.easing;
956
- console.warn(`Invalid animation easing. Fallback: '${easing}'.`);
957
- mergedAnimation.easing = easing;
958
- }
959
- if (typeof merged.collapsible !== "boolean") {
960
- const collapsible = defaults.collapsible;
961
- console.warn(`Invalid collapsible option. Fallback: ${collapsible}.`);
962
- merged.collapsible = collapsible;
963
- }
964
- return merged;
965
- }
966
960
  async #waitAnimationsFinish() {
967
961
  const promises = [];
968
962
  for (const content of this.#contentElements) {