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