@haiilo/catalyst 0.0.11 → 0.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.
Files changed (78) hide show
  1. package/LICENSE +1 -1
  2. package/dist/catalyst/catalyst.css +1 -1403
  3. package/dist/catalyst/catalyst.esm.js +1 -126
  4. package/dist/catalyst/index.esm.js +0 -1
  5. package/dist/catalyst/p-4c438c2d.entry.js +11 -0
  6. package/dist/catalyst/p-73ee291d.js +1 -0
  7. package/dist/catalyst/p-94273abf.js +1 -0
  8. package/dist/cjs/app-globals-a3b3cf88.js +135 -0
  9. package/dist/cjs/cat-alert_7.cjs.entry.js +3115 -0
  10. package/dist/cjs/cat-icon-registry-eeff9b7d.js +1359 -0
  11. package/dist/cjs/catalyst.cjs.js +21 -0
  12. package/dist/cjs/index.cjs.js +2 -0
  13. package/dist/cjs/loader.cjs.js +23 -0
  14. package/dist/collection/collection-manifest.json +19 -0
  15. package/dist/collection/components/cat-alert/cat-alert.css +57 -0
  16. package/dist/collection/components/cat-alert/cat-alert.js +49 -0
  17. package/dist/collection/components/cat-badge/cat-badge.css +154 -0
  18. package/dist/collection/components/cat-badge/cat-badge.js +141 -0
  19. package/dist/collection/components/cat-button/cat-button.css +319 -0
  20. package/dist/collection/components/cat-button/cat-button.js +590 -0
  21. package/dist/collection/components/cat-icon/cat-icon-registry.js +41 -0
  22. package/dist/collection/components/cat-icon/cat-icon.css +50 -0
  23. package/dist/collection/components/cat-icon/cat-icon.js +89 -0
  24. package/dist/collection/components/cat-menu/cat-menu.css +33 -0
  25. package/dist/collection/components/cat-menu/cat-menu.js +185 -0
  26. package/dist/collection/components/cat-skeleton/cat-skeleton.css +177 -0
  27. package/dist/collection/components/cat-skeleton/cat-skeleton.js +130 -0
  28. package/dist/collection/components/cat-spinner/cat-spinner.css +63 -0
  29. package/dist/collection/components/cat-spinner/cat-spinner.js +64 -0
  30. package/dist/collection/index.cdn.js +21 -0
  31. package/dist/collection/index.js +1 -0
  32. package/dist/collection/init.js +8 -0
  33. package/dist/collection/utils/breakpoints.js +11 -0
  34. package/dist/collection/utils/media-matcher.js +54 -0
  35. package/dist/collection/utils/platform.js +49 -0
  36. package/dist/collection/utils/utils.js +3 -0
  37. package/dist/components/cat-alert.d.ts +11 -0
  38. package/dist/components/cat-alert.js +43 -0
  39. package/dist/components/cat-badge.d.ts +11 -0
  40. package/dist/components/cat-badge.js +67 -0
  41. package/dist/{catalyst/cat-button.entry.js → components/cat-button.js} +76 -44
  42. package/dist/{catalyst/cat-icon-registry-59da2e37.js → components/cat-icon-registry.js} +0 -0
  43. package/dist/components/cat-icon.js +6 -0
  44. package/dist/components/cat-icon2.js +47 -0
  45. package/dist/components/cat-menu.d.ts +11 -0
  46. package/dist/components/cat-menu.js +2378 -0
  47. package/dist/components/cat-skeleton.d.ts +11 -0
  48. package/dist/components/cat-skeleton.js +77 -0
  49. package/dist/components/cat-spinner.js +6 -0
  50. package/dist/{catalyst/cat-spinner.entry.js → components/cat-spinner2.js} +25 -6
  51. package/dist/components/index.js +134 -0
  52. package/dist/esm/app-globals-fc0806a7.js +133 -0
  53. package/dist/esm/cat-alert_7.entry.js +3105 -0
  54. package/dist/esm/cat-icon-registry-d877de13.js +1331 -0
  55. package/dist/esm/catalyst.js +19 -0
  56. package/dist/esm/index.js +1 -0
  57. package/dist/esm/loader.js +19 -0
  58. package/dist/esm/polyfills/core-js.js +11 -0
  59. package/dist/esm/polyfills/css-shim.js +1 -0
  60. package/dist/esm/polyfills/dom.js +79 -0
  61. package/dist/esm/polyfills/es5-html-element.js +1 -0
  62. package/dist/esm/polyfills/index.js +34 -0
  63. package/dist/esm/polyfills/system.js +6 -0
  64. package/dist/index.cjs.js +1 -0
  65. package/dist/index.js +1 -0
  66. package/dist/types/components/cat-alert/cat-alert.d.ts +12 -0
  67. package/dist/types/components/cat-badge/cat-badge.d.ts +28 -0
  68. package/dist/types/components/cat-button/cat-button.d.ts +6 -0
  69. package/dist/types/components/cat-menu/cat-menu.d.ts +32 -0
  70. package/dist/types/components/cat-skeleton/cat-skeleton.d.ts +28 -0
  71. package/dist/types/components.d.ts +153 -0
  72. package/package.json +9 -6
  73. package/dist/catalyst/app-globals-54573336.js +0 -716
  74. package/dist/catalyst/cat-icon.entry.js +0 -27
  75. package/dist/catalyst/css-shim-20dbffa5.js +0 -4
  76. package/dist/catalyst/dom-c5ed0ba5.js +0 -73
  77. package/dist/catalyst/index-6672be93.js +0 -3031
  78. package/dist/catalyst/shadow-css-8c625855.js +0 -388
@@ -0,0 +1,2378 @@
1
+ import { HTMLElement, createEvent, h, Host, proxyCustomElement } from '@stencil/core/internal/client';
2
+
3
+ function getSide(placement) {
4
+ return placement.split('-')[0];
5
+ }
6
+
7
+ function getAlignment(placement) {
8
+ return placement.split('-')[1];
9
+ }
10
+
11
+ function getMainAxisFromPlacement(placement) {
12
+ return ['top', 'bottom'].includes(getSide(placement)) ? 'x' : 'y';
13
+ }
14
+
15
+ function getLengthFromAxis(axis) {
16
+ return axis === 'y' ? 'height' : 'width';
17
+ }
18
+
19
+ function computeCoordsFromPlacement(_ref, placement, rtl) {
20
+ let {
21
+ reference,
22
+ floating
23
+ } = _ref;
24
+ const commonX = reference.x + reference.width / 2 - floating.width / 2;
25
+ const commonY = reference.y + reference.height / 2 - floating.height / 2;
26
+ const mainAxis = getMainAxisFromPlacement(placement);
27
+ const length = getLengthFromAxis(mainAxis);
28
+ const commonAlign = reference[length] / 2 - floating[length] / 2;
29
+ const side = getSide(placement);
30
+ const isVertical = mainAxis === 'x';
31
+ let coords;
32
+
33
+ switch (side) {
34
+ case 'top':
35
+ coords = {
36
+ x: commonX,
37
+ y: reference.y - floating.height
38
+ };
39
+ break;
40
+
41
+ case 'bottom':
42
+ coords = {
43
+ x: commonX,
44
+ y: reference.y + reference.height
45
+ };
46
+ break;
47
+
48
+ case 'right':
49
+ coords = {
50
+ x: reference.x + reference.width,
51
+ y: commonY
52
+ };
53
+ break;
54
+
55
+ case 'left':
56
+ coords = {
57
+ x: reference.x - floating.width,
58
+ y: commonY
59
+ };
60
+ break;
61
+
62
+ default:
63
+ coords = {
64
+ x: reference.x,
65
+ y: reference.y
66
+ };
67
+ }
68
+
69
+ switch (getAlignment(placement)) {
70
+ case 'start':
71
+ coords[mainAxis] -= commonAlign * (rtl && isVertical ? -1 : 1);
72
+ break;
73
+
74
+ case 'end':
75
+ coords[mainAxis] += commonAlign * (rtl && isVertical ? -1 : 1);
76
+ break;
77
+ }
78
+
79
+ return coords;
80
+ }
81
+
82
+ /**
83
+ * Computes the `x` and `y` coordinates that will place the floating element
84
+ * next to a reference element when it is given a certain positioning strategy.
85
+ *
86
+ * This export does not have any `platform` interface logic. You will need to
87
+ * write one for the platform you are using Floating UI with.
88
+ */
89
+
90
+ const computePosition$1 = async (reference, floating, config) => {
91
+ const {
92
+ placement = 'bottom',
93
+ strategy = 'absolute',
94
+ middleware = [],
95
+ platform
96
+ } = config;
97
+ const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(floating));
98
+
99
+ let rects = await platform.getElementRects({
100
+ reference,
101
+ floating,
102
+ strategy
103
+ });
104
+ let {
105
+ x,
106
+ y
107
+ } = computeCoordsFromPlacement(rects, placement, rtl);
108
+ let statefulPlacement = placement;
109
+ let middlewareData = {};
110
+
111
+ for (let i = 0; i < middleware.length; i++) {
112
+
113
+ const {
114
+ name,
115
+ fn
116
+ } = middleware[i];
117
+ const {
118
+ x: nextX,
119
+ y: nextY,
120
+ data,
121
+ reset
122
+ } = await fn({
123
+ x,
124
+ y,
125
+ initialPlacement: placement,
126
+ placement: statefulPlacement,
127
+ strategy,
128
+ middlewareData,
129
+ rects,
130
+ platform,
131
+ elements: {
132
+ reference,
133
+ floating
134
+ }
135
+ });
136
+ x = nextX != null ? nextX : x;
137
+ y = nextY != null ? nextY : y;
138
+ middlewareData = { ...middlewareData,
139
+ [name]: { ...middlewareData[name],
140
+ ...data
141
+ }
142
+ };
143
+
144
+ if (reset) {
145
+ if (typeof reset === 'object') {
146
+ if (reset.placement) {
147
+ statefulPlacement = reset.placement;
148
+ }
149
+
150
+ if (reset.rects) {
151
+ rects = reset.rects === true ? await platform.getElementRects({
152
+ reference,
153
+ floating,
154
+ strategy
155
+ }) : reset.rects;
156
+ }
157
+
158
+ ({
159
+ x,
160
+ y
161
+ } = computeCoordsFromPlacement(rects, statefulPlacement, rtl));
162
+ }
163
+
164
+ i = -1;
165
+ continue;
166
+ }
167
+ }
168
+
169
+ return {
170
+ x,
171
+ y,
172
+ placement: statefulPlacement,
173
+ strategy,
174
+ middlewareData
175
+ };
176
+ };
177
+
178
+ function expandPaddingObject(padding) {
179
+ return {
180
+ top: 0,
181
+ right: 0,
182
+ bottom: 0,
183
+ left: 0,
184
+ ...padding
185
+ };
186
+ }
187
+
188
+ function getSideObjectFromPadding(padding) {
189
+ return typeof padding !== 'number' ? expandPaddingObject(padding) : {
190
+ top: padding,
191
+ right: padding,
192
+ bottom: padding,
193
+ left: padding
194
+ };
195
+ }
196
+
197
+ function rectToClientRect(rect) {
198
+ return { ...rect,
199
+ top: rect.y,
200
+ left: rect.x,
201
+ right: rect.x + rect.width,
202
+ bottom: rect.y + rect.height
203
+ };
204
+ }
205
+
206
+ /**
207
+ * Resolves with an object of overflow side offsets that determine how much the
208
+ * element is overflowing a given clipping boundary.
209
+ * - positive = overflowing the boundary by that number of pixels
210
+ * - negative = how many pixels left before it will overflow
211
+ * - 0 = lies flush with the boundary
212
+ * @see https://floating-ui.com/docs/detectOverflow
213
+ */
214
+ async function detectOverflow(middlewareArguments, options) {
215
+ var _await$platform$isEle;
216
+
217
+ if (options === void 0) {
218
+ options = {};
219
+ }
220
+
221
+ const {
222
+ x,
223
+ y,
224
+ platform,
225
+ rects,
226
+ elements,
227
+ strategy
228
+ } = middlewareArguments;
229
+ const {
230
+ boundary = 'clippingAncestors',
231
+ rootBoundary = 'viewport',
232
+ elementContext = 'floating',
233
+ altBoundary = false,
234
+ padding = 0
235
+ } = options;
236
+ const paddingObject = getSideObjectFromPadding(padding);
237
+ const altContext = elementContext === 'floating' ? 'reference' : 'floating';
238
+ const element = elements[altBoundary ? altContext : elementContext];
239
+ const clippingClientRect = rectToClientRect(await platform.getClippingRect({
240
+ element: ((_await$platform$isEle = await (platform.isElement == null ? void 0 : platform.isElement(element))) != null ? _await$platform$isEle : true) ? element : element.contextElement || (await (platform.getDocumentElement == null ? void 0 : platform.getDocumentElement(elements.floating))),
241
+ boundary,
242
+ rootBoundary,
243
+ strategy
244
+ }));
245
+ const elementClientRect = rectToClientRect(platform.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform.convertOffsetParentRelativeRectToViewportRelativeRect({
246
+ rect: elementContext === 'floating' ? { ...rects.floating,
247
+ x,
248
+ y
249
+ } : rects.reference,
250
+ offsetParent: await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating)),
251
+ strategy
252
+ }) : rects[elementContext]); // positive = overflowing the clipping rect
253
+ // 0 or negative = within the clipping rect
254
+
255
+ return {
256
+ top: clippingClientRect.top - elementClientRect.top + paddingObject.top,
257
+ bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom,
258
+ left: clippingClientRect.left - elementClientRect.left + paddingObject.left,
259
+ right: elementClientRect.right - clippingClientRect.right + paddingObject.right
260
+ };
261
+ }
262
+
263
+ const hash$1 = {
264
+ left: 'right',
265
+ right: 'left',
266
+ bottom: 'top',
267
+ top: 'bottom'
268
+ };
269
+ function getOppositePlacement(placement) {
270
+ return placement.replace(/left|right|bottom|top/g, matched => hash$1[matched]);
271
+ }
272
+
273
+ function getAlignmentSides(placement, rects, rtl) {
274
+ if (rtl === void 0) {
275
+ rtl = false;
276
+ }
277
+
278
+ const alignment = getAlignment(placement);
279
+ const mainAxis = getMainAxisFromPlacement(placement);
280
+ const length = getLengthFromAxis(mainAxis);
281
+ let mainAlignmentSide = mainAxis === 'x' ? alignment === (rtl ? 'end' : 'start') ? 'right' : 'left' : alignment === 'start' ? 'bottom' : 'top';
282
+
283
+ if (rects.reference[length] > rects.floating[length]) {
284
+ mainAlignmentSide = getOppositePlacement(mainAlignmentSide);
285
+ }
286
+
287
+ return {
288
+ main: mainAlignmentSide,
289
+ cross: getOppositePlacement(mainAlignmentSide)
290
+ };
291
+ }
292
+
293
+ const hash = {
294
+ start: 'end',
295
+ end: 'start'
296
+ };
297
+ function getOppositeAlignmentPlacement(placement) {
298
+ return placement.replace(/start|end/g, matched => hash[matched]);
299
+ }
300
+
301
+ function getExpandedPlacements(placement) {
302
+ const oppositePlacement = getOppositePlacement(placement);
303
+ return [getOppositeAlignmentPlacement(placement), oppositePlacement, getOppositeAlignmentPlacement(oppositePlacement)];
304
+ }
305
+
306
+ /**
307
+ * Changes the placement of the floating element to one that will fit if the
308
+ * initially specified `placement` does not.
309
+ * @see https://floating-ui.com/docs/flip
310
+ */
311
+ const flip = function (options) {
312
+ if (options === void 0) {
313
+ options = {};
314
+ }
315
+
316
+ return {
317
+ name: 'flip',
318
+ options,
319
+
320
+ async fn(middlewareArguments) {
321
+ var _middlewareData$flip;
322
+
323
+ const {
324
+ placement,
325
+ middlewareData,
326
+ rects,
327
+ initialPlacement,
328
+ platform,
329
+ elements
330
+ } = middlewareArguments;
331
+ const {
332
+ mainAxis: checkMainAxis = true,
333
+ crossAxis: checkCrossAxis = true,
334
+ fallbackPlacements: specifiedFallbackPlacements,
335
+ fallbackStrategy = 'bestFit',
336
+ flipAlignment = true,
337
+ ...detectOverflowOptions
338
+ } = options;
339
+ const side = getSide(placement);
340
+ const isBasePlacement = side === initialPlacement;
341
+ const fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipAlignment ? [getOppositePlacement(initialPlacement)] : getExpandedPlacements(initialPlacement));
342
+ const placements = [initialPlacement, ...fallbackPlacements];
343
+ const overflow = await detectOverflow(middlewareArguments, detectOverflowOptions);
344
+ const overflows = [];
345
+ let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || [];
346
+
347
+ if (checkMainAxis) {
348
+ overflows.push(overflow[side]);
349
+ }
350
+
351
+ if (checkCrossAxis) {
352
+ const {
353
+ main,
354
+ cross
355
+ } = getAlignmentSides(placement, rects, await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)));
356
+ overflows.push(overflow[main], overflow[cross]);
357
+ }
358
+
359
+ overflowsData = [...overflowsData, {
360
+ placement,
361
+ overflows
362
+ }]; // One or more sides is overflowing
363
+
364
+ if (!overflows.every(side => side <= 0)) {
365
+ var _middlewareData$flip$, _middlewareData$flip2;
366
+
367
+ const nextIndex = ((_middlewareData$flip$ = (_middlewareData$flip2 = middlewareData.flip) == null ? void 0 : _middlewareData$flip2.index) != null ? _middlewareData$flip$ : 0) + 1;
368
+ const nextPlacement = placements[nextIndex];
369
+
370
+ if (nextPlacement) {
371
+ // Try next placement and re-run the lifecycle
372
+ return {
373
+ data: {
374
+ index: nextIndex,
375
+ overflows: overflowsData
376
+ },
377
+ reset: {
378
+ placement: nextPlacement
379
+ }
380
+ };
381
+ }
382
+
383
+ let resetPlacement = 'bottom';
384
+
385
+ switch (fallbackStrategy) {
386
+ case 'bestFit':
387
+ {
388
+ var _overflowsData$slice$;
389
+
390
+ const placement = (_overflowsData$slice$ = overflowsData.slice().sort((a, b) => a.overflows.filter(overflow => overflow > 0).reduce((acc, overflow) => acc + overflow, 0) - b.overflows.filter(overflow => overflow > 0).reduce((acc, overflow) => acc + overflow, 0))[0]) == null ? void 0 : _overflowsData$slice$.placement;
391
+
392
+ if (placement) {
393
+ resetPlacement = placement;
394
+ }
395
+
396
+ break;
397
+ }
398
+
399
+ case 'initialPlacement':
400
+ resetPlacement = initialPlacement;
401
+ break;
402
+ }
403
+
404
+ if (placement !== resetPlacement) {
405
+ return {
406
+ reset: {
407
+ placement: resetPlacement
408
+ }
409
+ };
410
+ }
411
+ }
412
+
413
+ return {};
414
+ }
415
+
416
+ };
417
+ };
418
+
419
+ function convertValueToCoords(placement, rects, value, rtl) {
420
+ if (rtl === void 0) {
421
+ rtl = false;
422
+ }
423
+
424
+ const side = getSide(placement);
425
+ const alignment = getAlignment(placement);
426
+ const isVertical = getMainAxisFromPlacement(placement) === 'x';
427
+ const mainAxisMulti = ['left', 'top'].includes(side) ? -1 : 1;
428
+ const crossAxisMulti = rtl && isVertical ? -1 : 1;
429
+ const rawValue = typeof value === 'function' ? value({ ...rects,
430
+ placement
431
+ }) : value;
432
+ const isNumber = typeof rawValue === 'number'; // eslint-disable-next-line prefer-const
433
+
434
+ let {
435
+ mainAxis,
436
+ crossAxis,
437
+ alignmentAxis
438
+ } = isNumber ? {
439
+ mainAxis: rawValue,
440
+ crossAxis: 0,
441
+ alignmentAxis: null
442
+ } : {
443
+ mainAxis: 0,
444
+ crossAxis: 0,
445
+ alignmentAxis: null,
446
+ ...rawValue
447
+ };
448
+
449
+ if (alignment && typeof alignmentAxis === 'number') {
450
+ crossAxis = alignment === 'end' ? alignmentAxis * -1 : alignmentAxis;
451
+ }
452
+
453
+ return isVertical ? {
454
+ x: crossAxis * crossAxisMulti,
455
+ y: mainAxis * mainAxisMulti
456
+ } : {
457
+ x: mainAxis * mainAxisMulti,
458
+ y: crossAxis * crossAxisMulti
459
+ };
460
+ }
461
+ /**
462
+ * Displaces the floating element from its reference element.
463
+ * @see https://floating-ui.com/docs/offset
464
+ */
465
+
466
+ const offset = function (value) {
467
+ if (value === void 0) {
468
+ value = 0;
469
+ }
470
+
471
+ return {
472
+ name: 'offset',
473
+ options: value,
474
+
475
+ async fn(middlewareArguments) {
476
+ const {
477
+ x,
478
+ y,
479
+ placement,
480
+ rects,
481
+ platform,
482
+ elements
483
+ } = middlewareArguments;
484
+ const diffCoords = convertValueToCoords(placement, rects, value, await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)));
485
+ return {
486
+ x: x + diffCoords.x,
487
+ y: y + diffCoords.y,
488
+ data: diffCoords
489
+ };
490
+ }
491
+
492
+ };
493
+ };
494
+
495
+ function isWindow(value) {
496
+ return (value == null ? void 0 : value.toString()) === '[object Window]';
497
+ }
498
+ function getWindow(node) {
499
+ if (node == null) {
500
+ return window;
501
+ }
502
+
503
+ if (!isWindow(node)) {
504
+ const ownerDocument = node.ownerDocument;
505
+ return ownerDocument ? ownerDocument.defaultView || window : window;
506
+ }
507
+
508
+ return node;
509
+ }
510
+
511
+ function getComputedStyle$1(element) {
512
+ return getWindow(element).getComputedStyle(element);
513
+ }
514
+
515
+ function getNodeName(node) {
516
+ return isWindow(node) ? '' : node ? (node.nodeName || '').toLowerCase() : '';
517
+ }
518
+
519
+ function isHTMLElement(value) {
520
+ return value instanceof getWindow(value).HTMLElement;
521
+ }
522
+ function isElement(value) {
523
+ return value instanceof getWindow(value).Element;
524
+ }
525
+ function isNode(value) {
526
+ return value instanceof getWindow(value).Node;
527
+ }
528
+ function isShadowRoot(node) {
529
+ const OwnElement = getWindow(node).ShadowRoot;
530
+ return node instanceof OwnElement || node instanceof ShadowRoot;
531
+ }
532
+ function isOverflowElement(element) {
533
+ // Firefox wants us to check `-x` and `-y` variations as well
534
+ const {
535
+ overflow,
536
+ overflowX,
537
+ overflowY
538
+ } = getComputedStyle$1(element);
539
+ return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX);
540
+ }
541
+ function isTableElement(element) {
542
+ return ['table', 'td', 'th'].includes(getNodeName(element));
543
+ }
544
+ function isContainingBlock(element) {
545
+ // TODO: Try and use feature detection here instead
546
+ const isFirefox = navigator.userAgent.toLowerCase().includes('firefox');
547
+ const css = getComputedStyle$1(element); // This is non-exhaustive but covers the most common CSS properties that
548
+ // create a containing block.
549
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
550
+
551
+ return css.transform !== 'none' || css.perspective !== 'none' || css.contain === 'paint' || ['transform', 'perspective'].includes(css.willChange) || isFirefox && css.willChange === 'filter' || isFirefox && (css.filter ? css.filter !== 'none' : false);
552
+ }
553
+ function isLayoutViewport() {
554
+ // Not Safari
555
+ return !/^((?!chrome|android).)*safari/i.test(navigator.userAgent); // Feature detection for this fails in various ways
556
+ // • Always-visible scrollbar or not
557
+ // • Width of <html>, etc.
558
+ // const vV = win.visualViewport;
559
+ // return vV ? Math.abs(win.innerWidth / vV.scale - vV.width) < 0.5 : true;
560
+ }
561
+
562
+ const min = Math.min;
563
+ const max = Math.max;
564
+ const round = Math.round;
565
+
566
+ function getBoundingClientRect(element, includeScale, isFixedStrategy) {
567
+ if (includeScale === void 0) {
568
+ includeScale = false;
569
+ }
570
+
571
+ if (isFixedStrategy === void 0) {
572
+ isFixedStrategy = false;
573
+ }
574
+
575
+ const clientRect = element.getBoundingClientRect();
576
+ let scaleX = 1;
577
+ let scaleY = 1;
578
+
579
+ if (includeScale && isHTMLElement(element)) {
580
+ scaleX = element.offsetWidth > 0 ? round(clientRect.width) / element.offsetWidth || 1 : 1;
581
+ scaleY = element.offsetHeight > 0 ? round(clientRect.height) / element.offsetHeight || 1 : 1;
582
+ }
583
+
584
+ const win = isElement(element) ? getWindow(element) : window;
585
+ const addVisualOffsets = !isLayoutViewport() && isFixedStrategy;
586
+ const x = (clientRect.left + (addVisualOffsets ? win.visualViewport.offsetLeft : 0)) / scaleX;
587
+ const y = (clientRect.top + (addVisualOffsets ? win.visualViewport.offsetTop : 0)) / scaleY;
588
+ const width = clientRect.width / scaleX;
589
+ const height = clientRect.height / scaleY;
590
+ return {
591
+ width,
592
+ height,
593
+ top: y,
594
+ right: x + width,
595
+ bottom: y + height,
596
+ left: x,
597
+ x,
598
+ y
599
+ };
600
+ }
601
+
602
+ function getDocumentElement(node) {
603
+ return ((isNode(node) ? node.ownerDocument : node.document) || window.document).documentElement;
604
+ }
605
+
606
+ function getNodeScroll(element) {
607
+ if (isWindow(element)) {
608
+ return {
609
+ scrollLeft: element.pageXOffset,
610
+ scrollTop: element.pageYOffset
611
+ };
612
+ }
613
+
614
+ return {
615
+ scrollLeft: element.scrollLeft,
616
+ scrollTop: element.scrollTop
617
+ };
618
+ }
619
+
620
+ function getWindowScrollBarX(element) {
621
+ // If <html> has a CSS width greater than the viewport, then this will be
622
+ // incorrect for RTL.
623
+ return getBoundingClientRect(getDocumentElement(element)).left + getNodeScroll(element).scrollLeft;
624
+ }
625
+
626
+ function isScaled(element) {
627
+ const rect = getBoundingClientRect(element);
628
+ return round(rect.width) !== element.offsetWidth || round(rect.height) !== element.offsetHeight;
629
+ }
630
+
631
+ function getRectRelativeToOffsetParent(element, offsetParent, strategy) {
632
+ const isOffsetParentAnElement = isHTMLElement(offsetParent);
633
+ const documentElement = getDocumentElement(offsetParent);
634
+ const rect = getBoundingClientRect(element, isOffsetParentAnElement && isScaled(offsetParent), strategy === 'fixed');
635
+ let scroll = {
636
+ scrollLeft: 0,
637
+ scrollTop: 0
638
+ };
639
+ const offsets = {
640
+ x: 0,
641
+ y: 0
642
+ };
643
+
644
+ if (isOffsetParentAnElement || !isOffsetParentAnElement && strategy !== 'fixed') {
645
+ if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
646
+ scroll = getNodeScroll(offsetParent);
647
+ }
648
+
649
+ if (isHTMLElement(offsetParent)) {
650
+ const offsetRect = getBoundingClientRect(offsetParent, true);
651
+ offsets.x = offsetRect.x + offsetParent.clientLeft;
652
+ offsets.y = offsetRect.y + offsetParent.clientTop;
653
+ } else if (documentElement) {
654
+ offsets.x = getWindowScrollBarX(documentElement);
655
+ }
656
+ }
657
+
658
+ return {
659
+ x: rect.left + scroll.scrollLeft - offsets.x,
660
+ y: rect.top + scroll.scrollTop - offsets.y,
661
+ width: rect.width,
662
+ height: rect.height
663
+ };
664
+ }
665
+
666
+ function getParentNode(node) {
667
+ if (getNodeName(node) === 'html') {
668
+ return node;
669
+ }
670
+
671
+ return (// this is a quicker (but less type safe) way to save quite some bytes from the bundle
672
+ // @ts-ignore
673
+ node.assignedSlot || // step into the shadow DOM of the parent of a slotted node
674
+ node.parentNode || ( // DOM Element detected
675
+ isShadowRoot(node) ? node.host : null) || // ShadowRoot detected
676
+ getDocumentElement(node) // fallback
677
+
678
+ );
679
+ }
680
+
681
+ function getTrueOffsetParent(element) {
682
+ if (!isHTMLElement(element) || getComputedStyle(element).position === 'fixed') {
683
+ return null;
684
+ }
685
+
686
+ return element.offsetParent;
687
+ }
688
+
689
+ function getContainingBlock(element) {
690
+ let currentNode = getParentNode(element);
691
+
692
+ if (isShadowRoot(currentNode)) {
693
+ currentNode = currentNode.host;
694
+ }
695
+
696
+ while (isHTMLElement(currentNode) && !['html', 'body'].includes(getNodeName(currentNode))) {
697
+ if (isContainingBlock(currentNode)) {
698
+ return currentNode;
699
+ } else {
700
+ currentNode = currentNode.parentNode;
701
+ }
702
+ }
703
+
704
+ return null;
705
+ } // Gets the closest ancestor positioned element. Handles some edge cases,
706
+ // such as table ancestors and cross browser bugs.
707
+
708
+
709
+ function getOffsetParent(element) {
710
+ const window = getWindow(element);
711
+ let offsetParent = getTrueOffsetParent(element);
712
+
713
+ while (offsetParent && isTableElement(offsetParent) && getComputedStyle(offsetParent).position === 'static') {
714
+ offsetParent = getTrueOffsetParent(offsetParent);
715
+ }
716
+
717
+ if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static' && !isContainingBlock(offsetParent))) {
718
+ return window;
719
+ }
720
+
721
+ return offsetParent || getContainingBlock(element) || window;
722
+ }
723
+
724
+ function getDimensions(element) {
725
+ if (isHTMLElement(element)) {
726
+ return {
727
+ width: element.offsetWidth,
728
+ height: element.offsetHeight
729
+ };
730
+ }
731
+
732
+ const rect = getBoundingClientRect(element);
733
+ return {
734
+ width: rect.width,
735
+ height: rect.height
736
+ };
737
+ }
738
+
739
+ function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
740
+ let {
741
+ rect,
742
+ offsetParent,
743
+ strategy
744
+ } = _ref;
745
+ const isOffsetParentAnElement = isHTMLElement(offsetParent);
746
+ const documentElement = getDocumentElement(offsetParent);
747
+
748
+ if (offsetParent === documentElement) {
749
+ return rect;
750
+ }
751
+
752
+ let scroll = {
753
+ scrollLeft: 0,
754
+ scrollTop: 0
755
+ };
756
+ const offsets = {
757
+ x: 0,
758
+ y: 0
759
+ };
760
+
761
+ if (isOffsetParentAnElement || !isOffsetParentAnElement && strategy !== 'fixed') {
762
+ if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
763
+ scroll = getNodeScroll(offsetParent);
764
+ }
765
+
766
+ if (isHTMLElement(offsetParent)) {
767
+ const offsetRect = getBoundingClientRect(offsetParent, true);
768
+ offsets.x = offsetRect.x + offsetParent.clientLeft;
769
+ offsets.y = offsetRect.y + offsetParent.clientTop;
770
+ } // This doesn't appear to be need to be negated.
771
+ // else if (documentElement) {
772
+ // offsets.x = getWindowScrollBarX(documentElement);
773
+ // }
774
+
775
+ }
776
+
777
+ return { ...rect,
778
+ x: rect.x - scroll.scrollLeft + offsets.x,
779
+ y: rect.y - scroll.scrollTop + offsets.y
780
+ };
781
+ }
782
+
783
+ function getViewportRect(element, strategy) {
784
+ const win = getWindow(element);
785
+ const html = getDocumentElement(element);
786
+ const visualViewport = win.visualViewport;
787
+ let width = html.clientWidth;
788
+ let height = html.clientHeight;
789
+ let x = 0;
790
+ let y = 0;
791
+
792
+ if (visualViewport) {
793
+ width = visualViewport.width;
794
+ height = visualViewport.height;
795
+ const layoutViewport = isLayoutViewport();
796
+
797
+ if (layoutViewport || !layoutViewport && strategy === 'fixed') {
798
+ x = visualViewport.offsetLeft;
799
+ y = visualViewport.offsetTop;
800
+ }
801
+ }
802
+
803
+ return {
804
+ width,
805
+ height,
806
+ x,
807
+ y
808
+ };
809
+ }
810
+
811
+ // of the `<html>` and `<body>` rect bounds if horizontally scrollable
812
+
813
+ function getDocumentRect(element) {
814
+ var _element$ownerDocumen;
815
+
816
+ const html = getDocumentElement(element);
817
+ const scroll = getNodeScroll(element);
818
+ const body = (_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body;
819
+ const width = max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0);
820
+ const height = max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0);
821
+ let x = -scroll.scrollLeft + getWindowScrollBarX(element);
822
+ const y = -scroll.scrollTop;
823
+
824
+ if (getComputedStyle$1(body || html).direction === 'rtl') {
825
+ x += max(html.clientWidth, body ? body.clientWidth : 0) - width;
826
+ }
827
+
828
+ return {
829
+ width,
830
+ height,
831
+ x,
832
+ y
833
+ };
834
+ }
835
+
836
+ function getNearestOverflowAncestor(node) {
837
+ const parentNode = getParentNode(node);
838
+
839
+ if (['html', 'body', '#document'].includes(getNodeName(parentNode))) {
840
+ // @ts-ignore assume body is always available
841
+ return node.ownerDocument.body;
842
+ }
843
+
844
+ if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) {
845
+ return parentNode;
846
+ }
847
+
848
+ return getNearestOverflowAncestor(parentNode);
849
+ }
850
+
851
+ function getOverflowAncestors(node, list) {
852
+ var _node$ownerDocument;
853
+
854
+ if (list === void 0) {
855
+ list = [];
856
+ }
857
+
858
+ const scrollableAncestor = getNearestOverflowAncestor(node);
859
+ const isBody = scrollableAncestor === ((_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.body);
860
+ const win = getWindow(scrollableAncestor);
861
+ const target = isBody ? [win].concat(win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : []) : scrollableAncestor;
862
+ const updatedList = list.concat(target);
863
+ return isBody ? updatedList : // @ts-ignore: isBody tells us target will be an HTMLElement here
864
+ updatedList.concat(getOverflowAncestors(getParentNode(target)));
865
+ }
866
+
867
+ function contains(parent, child) {
868
+ const rootNode = child.getRootNode == null ? void 0 : child.getRootNode(); // First, attempt with faster native method
869
+
870
+ if (parent.contains(child)) {
871
+ return true;
872
+ } // then fallback to custom implementation with Shadow DOM support
873
+ else if (rootNode && isShadowRoot(rootNode)) {
874
+ let next = child;
875
+
876
+ do {
877
+ // use `===` replace node.isSameNode()
878
+ if (next && parent === next) {
879
+ return true;
880
+ } // @ts-ignore: need a better way to handle this...
881
+
882
+
883
+ next = next.parentNode || next.host;
884
+ } while (next);
885
+ }
886
+
887
+ return false;
888
+ }
889
+
890
+ function getInnerBoundingClientRect(element, strategy) {
891
+ const clientRect = getBoundingClientRect(element, false, strategy === 'fixed');
892
+ const top = clientRect.top + element.clientTop;
893
+ const left = clientRect.left + element.clientLeft;
894
+ return {
895
+ top,
896
+ left,
897
+ x: left,
898
+ y: top,
899
+ right: left + element.clientWidth,
900
+ bottom: top + element.clientHeight,
901
+ width: element.clientWidth,
902
+ height: element.clientHeight
903
+ };
904
+ }
905
+
906
+ function getClientRectFromClippingAncestor(element, clippingParent, strategy) {
907
+ if (clippingParent === 'viewport') {
908
+ return rectToClientRect(getViewportRect(element, strategy));
909
+ }
910
+
911
+ if (isElement(clippingParent)) {
912
+ return getInnerBoundingClientRect(clippingParent, strategy);
913
+ }
914
+
915
+ return rectToClientRect(getDocumentRect(getDocumentElement(element)));
916
+ } // A "clipping ancestor" is an overflowable container with the characteristic of
917
+ // clipping (or hiding) overflowing elements with a position different from
918
+ // `initial`
919
+
920
+
921
+ function getClippingAncestors(element) {
922
+ const clippingAncestors = getOverflowAncestors(element);
923
+ const canEscapeClipping = ['absolute', 'fixed'].includes(getComputedStyle$1(element).position);
924
+ const clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element;
925
+
926
+ if (!isElement(clipperElement)) {
927
+ return [];
928
+ } // @ts-ignore isElement check ensures we return Array<Element>
929
+
930
+
931
+ return clippingAncestors.filter(clippingAncestors => isElement(clippingAncestors) && contains(clippingAncestors, clipperElement) && getNodeName(clippingAncestors) !== 'body');
932
+ } // Gets the maximum area that the element is visible in due to any number of
933
+ // clipping ancestors
934
+
935
+
936
+ function getClippingRect(_ref) {
937
+ let {
938
+ element,
939
+ boundary,
940
+ rootBoundary,
941
+ strategy
942
+ } = _ref;
943
+ const mainClippingAncestors = boundary === 'clippingAncestors' ? getClippingAncestors(element) : [].concat(boundary);
944
+ const clippingAncestors = [...mainClippingAncestors, rootBoundary];
945
+ const firstClippingAncestor = clippingAncestors[0];
946
+ const clippingRect = clippingAncestors.reduce((accRect, clippingAncestor) => {
947
+ const rect = getClientRectFromClippingAncestor(element, clippingAncestor, strategy);
948
+ accRect.top = max(rect.top, accRect.top);
949
+ accRect.right = min(rect.right, accRect.right);
950
+ accRect.bottom = min(rect.bottom, accRect.bottom);
951
+ accRect.left = max(rect.left, accRect.left);
952
+ return accRect;
953
+ }, getClientRectFromClippingAncestor(element, firstClippingAncestor, strategy));
954
+ return {
955
+ width: clippingRect.right - clippingRect.left,
956
+ height: clippingRect.bottom - clippingRect.top,
957
+ x: clippingRect.left,
958
+ y: clippingRect.top
959
+ };
960
+ }
961
+
962
+ const platform = {
963
+ getClippingRect,
964
+ convertOffsetParentRelativeRectToViewportRelativeRect,
965
+ isElement,
966
+ getDimensions,
967
+ getOffsetParent,
968
+ getDocumentElement,
969
+ getElementRects: _ref => {
970
+ let {
971
+ reference,
972
+ floating,
973
+ strategy
974
+ } = _ref;
975
+ return {
976
+ reference: getRectRelativeToOffsetParent(reference, getOffsetParent(floating), strategy),
977
+ floating: { ...getDimensions(floating),
978
+ x: 0,
979
+ y: 0
980
+ }
981
+ };
982
+ },
983
+ getClientRects: element => Array.from(element.getClientRects()),
984
+ isRTL: element => getComputedStyle$1(element).direction === 'rtl'
985
+ };
986
+
987
+ /**
988
+ * Automatically updates the position of the floating element when necessary.
989
+ * @see https://floating-ui.com/docs/autoUpdate
990
+ */
991
+ function autoUpdate(reference, floating, update, options) {
992
+ if (options === void 0) {
993
+ options = {};
994
+ }
995
+
996
+ const {
997
+ ancestorScroll: _ancestorScroll = true,
998
+ ancestorResize: _ancestorResize = true,
999
+ elementResize: _elementResize = true,
1000
+ animationFrame = false
1001
+ } = options;
1002
+ let cleanedUp = false;
1003
+ const ancestorScroll = _ancestorScroll && !animationFrame;
1004
+ const ancestorResize = _ancestorResize && !animationFrame;
1005
+ const elementResize = _elementResize && !animationFrame;
1006
+ const ancestors = ancestorScroll || ancestorResize ? [...(isElement(reference) ? getOverflowAncestors(reference) : []), ...getOverflowAncestors(floating)] : [];
1007
+ ancestors.forEach(ancestor => {
1008
+ ancestorScroll && ancestor.addEventListener('scroll', update, {
1009
+ passive: true
1010
+ });
1011
+ ancestorResize && ancestor.addEventListener('resize', update);
1012
+ });
1013
+ let observer = null;
1014
+
1015
+ if (elementResize) {
1016
+ observer = new ResizeObserver(update);
1017
+ isElement(reference) && observer.observe(reference);
1018
+ observer.observe(floating);
1019
+ }
1020
+
1021
+ let frameId;
1022
+ let prevRefRect = animationFrame ? getBoundingClientRect(reference) : null;
1023
+
1024
+ if (animationFrame) {
1025
+ frameLoop();
1026
+ }
1027
+
1028
+ function frameLoop() {
1029
+ if (cleanedUp) {
1030
+ return;
1031
+ }
1032
+
1033
+ const nextRefRect = getBoundingClientRect(reference);
1034
+
1035
+ if (prevRefRect && (nextRefRect.x !== prevRefRect.x || nextRefRect.y !== prevRefRect.y || nextRefRect.width !== prevRefRect.width || nextRefRect.height !== prevRefRect.height)) {
1036
+ update();
1037
+ }
1038
+
1039
+ prevRefRect = nextRefRect;
1040
+ frameId = requestAnimationFrame(frameLoop);
1041
+ }
1042
+
1043
+ return () => {
1044
+ var _observer;
1045
+
1046
+ cleanedUp = true;
1047
+ ancestors.forEach(ancestor => {
1048
+ ancestorScroll && ancestor.removeEventListener('scroll', update);
1049
+ ancestorResize && ancestor.removeEventListener('resize', update);
1050
+ });
1051
+ (_observer = observer) == null ? void 0 : _observer.disconnect();
1052
+ observer = null;
1053
+
1054
+ if (animationFrame) {
1055
+ cancelAnimationFrame(frameId);
1056
+ }
1057
+ };
1058
+ }
1059
+
1060
+ /**
1061
+ * Computes the `x` and `y` coordinates that will place the floating element
1062
+ * next to a reference element when it is given a certain CSS positioning
1063
+ * strategy.
1064
+ */
1065
+
1066
+ const computePosition = (reference, floating, options) => computePosition$1(reference, floating, {
1067
+ platform,
1068
+ ...options
1069
+ });
1070
+
1071
+ /*!
1072
+ * tabbable 5.3.0-beta.1
1073
+ * @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE
1074
+ */
1075
+ var candidateSelectors = ['input', 'select', 'textarea', 'a[href]', 'button', '[tabindex]:not(slot)', 'audio[controls]', 'video[controls]', '[contenteditable]:not([contenteditable="false"])', 'details>summary:first-of-type', 'details'];
1076
+ var candidateSelector = /* #__PURE__ */candidateSelectors.join(',');
1077
+ var NoElement = typeof Element === 'undefined';
1078
+ var matches = NoElement ? function () {} : Element.prototype.matches || Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
1079
+ var getRootNode = !NoElement && Element.prototype.getRootNode ? function (element) {
1080
+ return element.getRootNode();
1081
+ } : function (element) {
1082
+ return element.ownerDocument;
1083
+ };
1084
+ /**
1085
+ * @param {Element} el container to check in
1086
+ * @param {boolean} includeContainer add container to check
1087
+ * @param {(node: Element) => boolean} filter filter candidates
1088
+ * @returns {Element[]}
1089
+ */
1090
+
1091
+ var getCandidates = function getCandidates(el, includeContainer, filter) {
1092
+ var candidates = Array.prototype.slice.apply(el.querySelectorAll(candidateSelector));
1093
+
1094
+ if (includeContainer && matches.call(el, candidateSelector)) {
1095
+ candidates.unshift(el);
1096
+ }
1097
+
1098
+ candidates = candidates.filter(filter);
1099
+ return candidates;
1100
+ };
1101
+ /**
1102
+ * @callback GetShadowRoot
1103
+ * @param {Element} element to check for shadow root
1104
+ * @returns {ShadowRoot|boolean} ShadowRoot if available or boolean indicating if a shadowRoot is attached but not available.
1105
+ */
1106
+
1107
+ /**
1108
+ * @typedef {Object} CandidatesScope
1109
+ * @property {Element} scope contains inner candidates
1110
+ * @property {Element[]} candidates
1111
+ */
1112
+
1113
+ /**
1114
+ * @typedef {Object} IterativeOptions
1115
+ * @property {GetShadowRoot|boolean} getShadowRoot true if shadow support is enabled; falsy if not;
1116
+ * if a function, implies shadow support is enabled and either returns the shadow root of an element
1117
+ * or a boolean stating if it has an undisclosed shadow root
1118
+ * @property {(node: Element) => boolean} filter filter candidates
1119
+ * @property {boolean} flatten if true then result will flatten any CandidatesScope into the returned list
1120
+ */
1121
+
1122
+ /**
1123
+ * @param {Element[]} elements list of element containers to match candidates from
1124
+ * @param {boolean} includeContainer add container list to check
1125
+ * @param {IterativeOptions} options
1126
+ * @returns {Array.<Element|CandidatesScope>}
1127
+ */
1128
+
1129
+
1130
+ var getCandidatesIteratively = function getCandidatesIteratively(elements, includeContainer, options) {
1131
+ var candidates = [];
1132
+ var elementsToCheck = Array.from(elements);
1133
+
1134
+ while (elementsToCheck.length) {
1135
+ var element = elementsToCheck.shift();
1136
+
1137
+ if (element.tagName === 'SLOT') {
1138
+ // add shadow dom slot scope (slot itself cannot be focusable)
1139
+ var assigned = element.assignedElements();
1140
+ var content = assigned.length ? assigned : element.children;
1141
+ var nestedCandidates = getCandidatesIteratively(content, true, options);
1142
+
1143
+ if (options.flatten) {
1144
+ candidates.push.apply(candidates, nestedCandidates);
1145
+ } else {
1146
+ candidates.push({
1147
+ scope: element,
1148
+ candidates: nestedCandidates
1149
+ });
1150
+ }
1151
+ } else {
1152
+ // check candidate element
1153
+ var validCandidate = matches.call(element, candidateSelector);
1154
+
1155
+ if (validCandidate && options.filter(element) && (includeContainer || !elements.includes(element))) {
1156
+ candidates.push(element);
1157
+ } // iterate over shadow content if possible
1158
+
1159
+
1160
+ var shadowRoot = element.shadowRoot || // check for an undisclosed shadow
1161
+ typeof options.getShadowRoot === 'function' && options.getShadowRoot(element);
1162
+
1163
+ if (shadowRoot) {
1164
+ // add shadow dom scope IIF a shadow root node was given; otherwise, an undisclosed
1165
+ // shadow exists, so look at light dom children as fallback BUT create a scope for any
1166
+ // child candidates found because they're likely slotted elements (elements that are
1167
+ // children of the web component element (which has the shadow), in the light dom, but
1168
+ // slotted somewhere _inside_ the undisclosed shadow) -- the scope is created below,
1169
+ // _after_ we return from this recursive call
1170
+ var _nestedCandidates = getCandidatesIteratively(shadowRoot === true ? element.children : shadowRoot.children, true, options);
1171
+
1172
+ if (options.flatten) {
1173
+ candidates.push.apply(candidates, _nestedCandidates);
1174
+ } else {
1175
+ candidates.push({
1176
+ scope: element,
1177
+ candidates: _nestedCandidates
1178
+ });
1179
+ }
1180
+ } else {
1181
+ // there's not shadow so just dig into the element's (light dom) children
1182
+ // __without__ giving the element special scope treatment
1183
+ elementsToCheck.unshift.apply(elementsToCheck, element.children);
1184
+ }
1185
+ }
1186
+ }
1187
+
1188
+ return candidates;
1189
+ };
1190
+
1191
+ var isContentEditable = function isContentEditable(node) {
1192
+ return node.contentEditable === 'true';
1193
+ };
1194
+
1195
+ var getTabindex = function getTabindex(node, isScope) {
1196
+ var tabindexAttr = parseInt(node.getAttribute('tabindex'), 10);
1197
+
1198
+ if (!isNaN(tabindexAttr)) {
1199
+ return tabindexAttr;
1200
+ } // Browsers do not return `tabIndex` correctly for contentEditable nodes;
1201
+ // so if they don't have a tabindex attribute specifically set, assume it's 0.
1202
+
1203
+
1204
+ if (isContentEditable(node)) {
1205
+ return 0;
1206
+ } // in Chrome, <details/>, <audio controls/> and <video controls/> elements get a default
1207
+ // `tabIndex` of -1 when the 'tabindex' attribute isn't specified in the DOM,
1208
+ // yet they are still part of the regular tab order; in FF, they get a default
1209
+ // `tabIndex` of 0; since Chrome still puts those elements in the regular tab
1210
+ // order, consider their tab index to be 0.
1211
+ //
1212
+ // isScope is positive for custom element with shadow root or slot that by default
1213
+ // have tabIndex -1, but need to be sorted by document order in order for their
1214
+ // content to be inserted in the correct position
1215
+
1216
+
1217
+ if ((isScope || node.nodeName === 'AUDIO' || node.nodeName === 'VIDEO' || node.nodeName === 'DETAILS') && node.getAttribute('tabindex') === null) {
1218
+ return 0;
1219
+ }
1220
+
1221
+ return node.tabIndex;
1222
+ };
1223
+
1224
+ var sortOrderedTabbables = function sortOrderedTabbables(a, b) {
1225
+ return a.tabIndex === b.tabIndex ? a.documentOrder - b.documentOrder : a.tabIndex - b.tabIndex;
1226
+ };
1227
+
1228
+ var isInput = function isInput(node) {
1229
+ return node.tagName === 'INPUT';
1230
+ };
1231
+
1232
+ var isHiddenInput = function isHiddenInput(node) {
1233
+ return isInput(node) && node.type === 'hidden';
1234
+ };
1235
+
1236
+ var isDetailsWithSummary = function isDetailsWithSummary(node) {
1237
+ var r = node.tagName === 'DETAILS' && Array.prototype.slice.apply(node.children).some(function (child) {
1238
+ return child.tagName === 'SUMMARY';
1239
+ });
1240
+ return r;
1241
+ };
1242
+
1243
+ var getCheckedRadio = function getCheckedRadio(nodes, form) {
1244
+ for (var i = 0; i < nodes.length; i++) {
1245
+ if (nodes[i].checked && nodes[i].form === form) {
1246
+ return nodes[i];
1247
+ }
1248
+ }
1249
+ };
1250
+
1251
+ var isTabbableRadio = function isTabbableRadio(node) {
1252
+ if (!node.name) {
1253
+ return true;
1254
+ }
1255
+
1256
+ var radioScope = node.form || getRootNode(node);
1257
+
1258
+ var queryRadios = function queryRadios(name) {
1259
+ return radioScope.querySelectorAll('input[type="radio"][name="' + name + '"]');
1260
+ };
1261
+
1262
+ var radioSet;
1263
+
1264
+ if (typeof window !== 'undefined' && typeof window.CSS !== 'undefined' && typeof window.CSS.escape === 'function') {
1265
+ radioSet = queryRadios(window.CSS.escape(node.name));
1266
+ } else {
1267
+ try {
1268
+ radioSet = queryRadios(node.name);
1269
+ } catch (err) {
1270
+ // eslint-disable-next-line no-console
1271
+ console.error('Looks like you have a radio button with a name attribute containing invalid CSS selector characters and need the CSS.escape polyfill: %s', err.message);
1272
+ return false;
1273
+ }
1274
+ }
1275
+
1276
+ var checked = getCheckedRadio(radioSet, node.form);
1277
+ return !checked || checked === node;
1278
+ };
1279
+
1280
+ var isRadio = function isRadio(node) {
1281
+ return isInput(node) && node.type === 'radio';
1282
+ };
1283
+
1284
+ var isNonTabbableRadio = function isNonTabbableRadio(node) {
1285
+ return isRadio(node) && !isTabbableRadio(node);
1286
+ };
1287
+
1288
+ var isZeroArea = function isZeroArea(node) {
1289
+ var _node$getBoundingClie = node.getBoundingClientRect(),
1290
+ width = _node$getBoundingClie.width,
1291
+ height = _node$getBoundingClie.height;
1292
+
1293
+ return width === 0 && height === 0;
1294
+ };
1295
+
1296
+ var isHidden = function isHidden(node, _ref) {
1297
+ var displayCheck = _ref.displayCheck,
1298
+ getShadowRoot = _ref.getShadowRoot;
1299
+
1300
+ if (getComputedStyle(node).visibility === 'hidden') {
1301
+ return true;
1302
+ }
1303
+
1304
+ var isDirectSummary = matches.call(node, 'details>summary:first-of-type');
1305
+ var nodeUnderDetails = isDirectSummary ? node.parentElement : node;
1306
+
1307
+ if (matches.call(nodeUnderDetails, 'details:not([open]) *')) {
1308
+ return true;
1309
+ }
1310
+
1311
+ if (!displayCheck || displayCheck === 'full') {
1312
+ if (typeof getShadowRoot === 'function') {
1313
+ // figure out if we should consider the node to be in an undisclosed shadow and use the
1314
+ // 'non-zero-area' fallback
1315
+ var originalNode = node;
1316
+
1317
+ while (node) {
1318
+ var parentElement = node.parentElement;
1319
+ var rootNode = getRootNode(node);
1320
+
1321
+ if (parentElement && !parentElement.shadowRoot && getShadowRoot(parentElement) === true // check if there's an undisclosed shadow
1322
+ ) {
1323
+ // node has an undisclosed shadow which means we can only treat it as a black box, so we
1324
+ // fall back to a non-zero-area test
1325
+ return isZeroArea(node);
1326
+ } else if (node.assignedSlot) {
1327
+ // iterate up slot
1328
+ node = node.assignedSlot;
1329
+ } else if (!parentElement && rootNode !== node.ownerDocument) {
1330
+ // cross shadow boundary
1331
+ node = rootNode.host;
1332
+ } else {
1333
+ // iterate up normal dom
1334
+ node = parentElement;
1335
+ }
1336
+ }
1337
+
1338
+ node = originalNode;
1339
+ } // else, `getShadowRoot` might be true, but all that does is enable shadow DOM support
1340
+ // (i.e. it does not also presume that all nodes might have undisclosed shadows); or
1341
+ // it might be a falsy value, which means shadow DOM support is disabled
1342
+ // didn't find it sitting in an undisclosed shadow (or shadows are disabled) so now we
1343
+ // can just test to see if it would normally be visible or not
1344
+ // this works wherever the node is: if there's at least one client rect, it's
1345
+ // somehow displayed; it also covers the CSS 'display: contents' case where the
1346
+ // node itself is hidden in place of its contents; and there's no need to search
1347
+ // up the hierarchy either
1348
+
1349
+
1350
+ return !node.getClientRects().length;
1351
+ } else if (displayCheck === 'non-zero-area') {
1352
+ return isZeroArea(node);
1353
+ }
1354
+
1355
+ return false;
1356
+ }; // form fields (nested) inside a disabled fieldset are not focusable/tabbable
1357
+ // unless they are in the _first_ <legend> element of the top-most disabled
1358
+ // fieldset
1359
+
1360
+
1361
+ var isDisabledFromFieldset = function isDisabledFromFieldset(node) {
1362
+ if (/^(INPUT|BUTTON|SELECT|TEXTAREA)$/.test(node.tagName)) {
1363
+ var parentNode = node.parentElement; // check if `node` is contained in a disabled <fieldset>
1364
+
1365
+ while (parentNode) {
1366
+ if (parentNode.tagName === 'FIELDSET' && parentNode.disabled) {
1367
+ // look for the first <legend> among the children of the disabled <fieldset>
1368
+ for (var i = 0; i < parentNode.children.length; i++) {
1369
+ var child = parentNode.children.item(i); // when the first <legend> (in document order) is found
1370
+
1371
+ if (child.tagName === 'LEGEND') {
1372
+ // if its parent <fieldset> is not nested in another disabled <fieldset>,
1373
+ // return whether `node` is a descendant of its first <legend>
1374
+ return matches.call(parentNode, 'fieldset[disabled] *') ? true : !child.contains(node);
1375
+ }
1376
+ } // the disabled <fieldset> containing `node` has no <legend>
1377
+
1378
+
1379
+ return true;
1380
+ }
1381
+
1382
+ parentNode = parentNode.parentElement;
1383
+ }
1384
+ } // else, node's tabbable/focusable state should not be affected by a fieldset's
1385
+ // enabled/disabled state
1386
+
1387
+
1388
+ return false;
1389
+ };
1390
+
1391
+ var isNodeMatchingSelectorFocusable = function isNodeMatchingSelectorFocusable(options, node) {
1392
+ if (node.disabled || isHiddenInput(node) || isHidden(node, options) || // For a details element with a summary, the summary element gets the focus
1393
+ isDetailsWithSummary(node) || isDisabledFromFieldset(node)) {
1394
+ return false;
1395
+ }
1396
+
1397
+ return true;
1398
+ };
1399
+
1400
+ var isNodeMatchingSelectorTabbable = function isNodeMatchingSelectorTabbable(options, node) {
1401
+ if (!isNodeMatchingSelectorFocusable(options, node) || isNonTabbableRadio(node) || getTabindex(node) < 0) {
1402
+ return false;
1403
+ }
1404
+
1405
+ return true;
1406
+ };
1407
+ /**
1408
+ * @param {Array.<Element|CandidatesScope>} candidates
1409
+ * @returns Element[]
1410
+ */
1411
+
1412
+
1413
+ var sortByOrder = function sortByOrder(candidates) {
1414
+ var regularTabbables = [];
1415
+ var orderedTabbables = [];
1416
+ candidates.forEach(function (item, i) {
1417
+ var isScope = !!item.scope;
1418
+ var element = isScope ? item.scope : item;
1419
+ var candidateTabindex = getTabindex(element, isScope);
1420
+ var elements = isScope ? sortByOrder(item.candidates) : element;
1421
+
1422
+ if (candidateTabindex === 0) {
1423
+ isScope ? regularTabbables.push.apply(regularTabbables, elements) : regularTabbables.push(element);
1424
+ } else {
1425
+ orderedTabbables.push({
1426
+ documentOrder: i,
1427
+ tabIndex: candidateTabindex,
1428
+ item: item,
1429
+ isScope: isScope,
1430
+ content: elements
1431
+ });
1432
+ }
1433
+ });
1434
+ return orderedTabbables.sort(sortOrderedTabbables).reduce(function (acc, sortable) {
1435
+ sortable.isScope ? acc.push.apply(acc, sortable.content) : acc.push(sortable.content);
1436
+ return acc;
1437
+ }, []).concat(regularTabbables);
1438
+ };
1439
+
1440
+ var tabbable = function tabbable(el, options) {
1441
+ options = options || {};
1442
+ var candidates;
1443
+
1444
+ if (options.getShadowRoot) {
1445
+ candidates = getCandidatesIteratively([el], options.includeContainer, {
1446
+ filter: isNodeMatchingSelectorTabbable.bind(null, options),
1447
+ flatten: false,
1448
+ getShadowRoot: options.getShadowRoot
1449
+ });
1450
+ } else {
1451
+ candidates = getCandidates(el, options.includeContainer, isNodeMatchingSelectorTabbable.bind(null, options));
1452
+ }
1453
+
1454
+ return sortByOrder(candidates);
1455
+ };
1456
+
1457
+ var focusable = function focusable(el, options) {
1458
+ options = options || {};
1459
+ var candidates;
1460
+
1461
+ if (options.getShadowRoot) {
1462
+ candidates = getCandidatesIteratively([el], options.includeContainer, {
1463
+ filter: isNodeMatchingSelectorFocusable.bind(null, options),
1464
+ flatten: true,
1465
+ getShadowRoot: options.getShadowRoot
1466
+ });
1467
+ } else {
1468
+ candidates = getCandidates(el, options.includeContainer, isNodeMatchingSelectorFocusable.bind(null, options));
1469
+ }
1470
+
1471
+ return candidates;
1472
+ };
1473
+
1474
+ var isTabbable = function isTabbable(node, options) {
1475
+ options = options || {};
1476
+
1477
+ if (!node) {
1478
+ throw new Error('No node provided');
1479
+ }
1480
+
1481
+ if (matches.call(node, candidateSelector) === false) {
1482
+ return false;
1483
+ }
1484
+
1485
+ return isNodeMatchingSelectorTabbable(options, node);
1486
+ };
1487
+
1488
+ var focusableCandidateSelector = /* #__PURE__ */candidateSelectors.concat('iframe').join(',');
1489
+
1490
+ var isFocusable = function isFocusable(node, options) {
1491
+ options = options || {};
1492
+
1493
+ if (!node) {
1494
+ throw new Error('No node provided');
1495
+ }
1496
+
1497
+ if (matches.call(node, focusableCandidateSelector) === false) {
1498
+ return false;
1499
+ }
1500
+
1501
+ return isNodeMatchingSelectorFocusable(options, node);
1502
+ };
1503
+
1504
+ /*!
1505
+ * focus-trap 6.8.0-beta.2
1506
+ * @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE
1507
+ */
1508
+
1509
+ function ownKeys(object, enumerableOnly) {
1510
+ var keys = Object.keys(object);
1511
+
1512
+ if (Object.getOwnPropertySymbols) {
1513
+ var symbols = Object.getOwnPropertySymbols(object);
1514
+ enumerableOnly && (symbols = symbols.filter(function (sym) {
1515
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
1516
+ })), keys.push.apply(keys, symbols);
1517
+ }
1518
+
1519
+ return keys;
1520
+ }
1521
+
1522
+ function _objectSpread2(target) {
1523
+ for (var i = 1; i < arguments.length; i++) {
1524
+ var source = null != arguments[i] ? arguments[i] : {};
1525
+ i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
1526
+ _defineProperty(target, key, source[key]);
1527
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
1528
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
1529
+ });
1530
+ }
1531
+
1532
+ return target;
1533
+ }
1534
+
1535
+ function _defineProperty(obj, key, value) {
1536
+ if (key in obj) {
1537
+ Object.defineProperty(obj, key, {
1538
+ value: value,
1539
+ enumerable: true,
1540
+ configurable: true,
1541
+ writable: true
1542
+ });
1543
+ } else {
1544
+ obj[key] = value;
1545
+ }
1546
+
1547
+ return obj;
1548
+ }
1549
+
1550
+ var activeFocusTraps = function () {
1551
+ var trapQueue = [];
1552
+ return {
1553
+ activateTrap: function activateTrap(trap) {
1554
+ if (trapQueue.length > 0) {
1555
+ var activeTrap = trapQueue[trapQueue.length - 1];
1556
+
1557
+ if (activeTrap !== trap) {
1558
+ activeTrap.pause();
1559
+ }
1560
+ }
1561
+
1562
+ var trapIndex = trapQueue.indexOf(trap);
1563
+
1564
+ if (trapIndex === -1) {
1565
+ trapQueue.push(trap);
1566
+ } else {
1567
+ // move this existing trap to the front of the queue
1568
+ trapQueue.splice(trapIndex, 1);
1569
+ trapQueue.push(trap);
1570
+ }
1571
+ },
1572
+ deactivateTrap: function deactivateTrap(trap) {
1573
+ var trapIndex = trapQueue.indexOf(trap);
1574
+
1575
+ if (trapIndex !== -1) {
1576
+ trapQueue.splice(trapIndex, 1);
1577
+ }
1578
+
1579
+ if (trapQueue.length > 0) {
1580
+ trapQueue[trapQueue.length - 1].unpause();
1581
+ }
1582
+ }
1583
+ };
1584
+ }();
1585
+
1586
+ var isSelectableInput = function isSelectableInput(node) {
1587
+ return node.tagName && node.tagName.toLowerCase() === 'input' && typeof node.select === 'function';
1588
+ };
1589
+
1590
+ var isEscapeEvent = function isEscapeEvent(e) {
1591
+ return e.key === 'Escape' || e.key === 'Esc' || e.keyCode === 27;
1592
+ };
1593
+
1594
+ var isTabEvent = function isTabEvent(e) {
1595
+ return e.key === 'Tab' || e.keyCode === 9;
1596
+ };
1597
+
1598
+ var delay = function delay(fn) {
1599
+ return setTimeout(fn, 0);
1600
+ }; // Array.find/findIndex() are not supported on IE; this replicates enough
1601
+ // of Array.findIndex() for our needs
1602
+
1603
+
1604
+ var findIndex = function findIndex(arr, fn) {
1605
+ var idx = -1;
1606
+ arr.every(function (value, i) {
1607
+ if (fn(value)) {
1608
+ idx = i;
1609
+ return false; // break
1610
+ }
1611
+
1612
+ return true; // next
1613
+ });
1614
+ return idx;
1615
+ };
1616
+ /**
1617
+ * Get an option's value when it could be a plain value, or a handler that provides
1618
+ * the value.
1619
+ * @param {*} value Option's value to check.
1620
+ * @param {...*} [params] Any parameters to pass to the handler, if `value` is a function.
1621
+ * @returns {*} The `value`, or the handler's returned value.
1622
+ */
1623
+
1624
+
1625
+ var valueOrHandler = function valueOrHandler(value) {
1626
+ for (var _len = arguments.length, params = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
1627
+ params[_key - 1] = arguments[_key];
1628
+ }
1629
+
1630
+ return typeof value === 'function' ? value.apply(void 0, params) : value;
1631
+ };
1632
+
1633
+ var getActualTarget = function getActualTarget(event) {
1634
+ // NOTE: If the trap is _inside_ a shadow DOM, event.target will always be the
1635
+ // shadow host. However, event.target.composedPath() will be an array of
1636
+ // nodes "clicked" from inner-most (the actual element inside the shadow) to
1637
+ // outer-most (the host HTML document). If we have access to composedPath(),
1638
+ // then use its first element; otherwise, fall back to event.target (and
1639
+ // this only works for an _open_ shadow DOM; otherwise,
1640
+ // composedPath()[0] === event.target always).
1641
+ return event.target.shadowRoot && typeof event.composedPath === 'function' ? event.composedPath()[0] : event.target;
1642
+ };
1643
+
1644
+ var createFocusTrap = function createFocusTrap(elements, userOptions) {
1645
+ // SSR: a live trap shouldn't be created in this type of environment so this
1646
+ // should be safe code to execute if the `document` option isn't specified
1647
+ var doc = (userOptions === null || userOptions === void 0 ? void 0 : userOptions.document) || document;
1648
+
1649
+ var config = _objectSpread2({
1650
+ returnFocusOnDeactivate: true,
1651
+ escapeDeactivates: true,
1652
+ delayInitialFocus: true
1653
+ }, userOptions);
1654
+
1655
+ var state = {
1656
+ // containers given to createFocusTrap()
1657
+ // @type {Array<HTMLElement>}
1658
+ containers: [],
1659
+ // list of objects identifying tabbable nodes in `containers` in the trap
1660
+ // NOTE: it's possible that a group has no tabbable nodes if nodes get removed while the trap
1661
+ // is active, but the trap should never get to a state where there isn't at least one group
1662
+ // with at least one tabbable node in it (that would lead to an error condition that would
1663
+ // result in an error being thrown)
1664
+ // @type {Array<{
1665
+ // container: HTMLElement,
1666
+ // tabbableNodes: Array<HTMLElement>, // empty if none
1667
+ // focusableNodes: Array<HTMLElement>, // empty if none
1668
+ // firstTabbableNode: HTMLElement|null,
1669
+ // lastTabbableNode: HTMLElement|null,
1670
+ // nextTabbableNode: (node: HTMLElement, forward: boolean) => HTMLElement|undefined
1671
+ // }>}
1672
+ containerGroups: [],
1673
+ // same order/length as `containers` list
1674
+ // references to objects in `containerGroups`, but only those that actually have
1675
+ // tabbable nodes in them
1676
+ // NOTE: same order as `containers` and `containerGroups`, but __not necessarily__
1677
+ // the same length
1678
+ tabbableGroups: [],
1679
+ nodeFocusedBeforeActivation: null,
1680
+ mostRecentlyFocusedNode: null,
1681
+ active: false,
1682
+ paused: false,
1683
+ // timer ID for when delayInitialFocus is true and initial focus in this trap
1684
+ // has been delayed during activation
1685
+ delayInitialFocusTimer: undefined
1686
+ };
1687
+ var trap; // eslint-disable-line prefer-const -- some private functions reference it, and its methods reference private functions, so we must declare here and define later
1688
+
1689
+ /**
1690
+ * Gets a configuration option value.
1691
+ * @param {Object|undefined} configOverrideOptions If true, and option is defined in this set,
1692
+ * value will be taken from this object. Otherwise, value will be taken from base configuration.
1693
+ * @param {string} optionName Name of the option whose value is sought.
1694
+ * @param {string|undefined} [configOptionName] Name of option to use __instead of__ `optionName`
1695
+ * IIF `configOverrideOptions` is not defined. Otherwise, `optionName` is used.
1696
+ */
1697
+
1698
+ var getOption = function getOption(configOverrideOptions, optionName, configOptionName) {
1699
+ return configOverrideOptions && configOverrideOptions[optionName] !== undefined ? configOverrideOptions[optionName] : config[configOptionName || optionName];
1700
+ };
1701
+ /**
1702
+ * Finds the index of the container that contains the element.
1703
+ * @param {HTMLElement} element
1704
+ * @returns {number} Index of the container in either `state.containers` or
1705
+ * `state.containerGroups` (the order/length of these lists are the same); -1
1706
+ * if the element isn't found.
1707
+ */
1708
+
1709
+
1710
+ var findContainerIndex = function findContainerIndex(element) {
1711
+ // NOTE: search `containerGroups` because it's possible a group contains no tabbable
1712
+ // nodes, but still contains focusable nodes (e.g. if they all have `tabindex=-1`)
1713
+ // and we still need to find the element in there
1714
+ return state.containerGroups.findIndex(function (_ref) {
1715
+ var container = _ref.container,
1716
+ tabbableNodes = _ref.tabbableNodes;
1717
+ return container.contains(element) || // fall back to explicit tabbable search which will take into consideration any
1718
+ // web components if the `tabbableOptions.getShadowRoot` option was used for
1719
+ // the trap, enabling shadow DOM support in tabbable (`Node.contains()` doesn't
1720
+ // look inside web components even if open)
1721
+ tabbableNodes.find(function (node) {
1722
+ return node === element;
1723
+ });
1724
+ });
1725
+ };
1726
+ /**
1727
+ * Gets the node for the given option, which is expected to be an option that
1728
+ * can be either a DOM node, a string that is a selector to get a node, `false`
1729
+ * (if a node is explicitly NOT given), or a function that returns any of these
1730
+ * values.
1731
+ * @param {string} optionName
1732
+ * @returns {undefined | false | HTMLElement | SVGElement} Returns
1733
+ * `undefined` if the option is not specified; `false` if the option
1734
+ * resolved to `false` (node explicitly not given); otherwise, the resolved
1735
+ * DOM node.
1736
+ * @throws {Error} If the option is set, not `false`, and is not, or does not
1737
+ * resolve to a node.
1738
+ */
1739
+
1740
+
1741
+ var getNodeForOption = function getNodeForOption(optionName) {
1742
+ var optionValue = config[optionName];
1743
+
1744
+ if (typeof optionValue === 'function') {
1745
+ for (var _len2 = arguments.length, params = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
1746
+ params[_key2 - 1] = arguments[_key2];
1747
+ }
1748
+
1749
+ optionValue = optionValue.apply(void 0, params);
1750
+ }
1751
+
1752
+ if (!optionValue) {
1753
+ if (optionValue === undefined || optionValue === false) {
1754
+ return optionValue;
1755
+ } // else, empty string (invalid), null (invalid), 0 (invalid)
1756
+
1757
+
1758
+ throw new Error("`".concat(optionName, "` was specified but was not a node, or did not return a node"));
1759
+ }
1760
+
1761
+ var node = optionValue; // could be HTMLElement, SVGElement, or non-empty string at this point
1762
+
1763
+ if (typeof optionValue === 'string') {
1764
+ node = doc.querySelector(optionValue); // resolve to node, or null if fails
1765
+
1766
+ if (!node) {
1767
+ throw new Error("`".concat(optionName, "` as selector refers to no known node"));
1768
+ }
1769
+ }
1770
+
1771
+ return node;
1772
+ };
1773
+
1774
+ var getInitialFocusNode = function getInitialFocusNode() {
1775
+ var node = getNodeForOption('initialFocus'); // false explicitly indicates we want no initialFocus at all
1776
+
1777
+ if (node === false) {
1778
+ return false;
1779
+ }
1780
+
1781
+ if (node === undefined) {
1782
+ // option not specified: use fallback options
1783
+ if (findContainerIndex(doc.activeElement) >= 0) {
1784
+ node = doc.activeElement;
1785
+ } else {
1786
+ var firstTabbableGroup = state.tabbableGroups[0];
1787
+ var firstTabbableNode = firstTabbableGroup && firstTabbableGroup.firstTabbableNode; // NOTE: `fallbackFocus` option function cannot return `false` (not supported)
1788
+
1789
+ node = firstTabbableNode || getNodeForOption('fallbackFocus');
1790
+ }
1791
+ }
1792
+
1793
+ if (!node) {
1794
+ throw new Error('Your focus-trap needs to have at least one focusable element');
1795
+ }
1796
+
1797
+ return node;
1798
+ };
1799
+
1800
+ var updateTabbableNodes = function updateTabbableNodes() {
1801
+ state.containerGroups = state.containers.map(function (container) {
1802
+ var _config$tabbableOptio, _config$tabbableOptio2;
1803
+
1804
+ var tabbableNodes = tabbable(container, {
1805
+ getShadowRoot: (_config$tabbableOptio = config.tabbableOptions) === null || _config$tabbableOptio === void 0 ? void 0 : _config$tabbableOptio.getShadowRoot
1806
+ }); // NOTE: if we have tabbable nodes, we must have focusable nodes; focusable nodes
1807
+ // are a superset of tabbable nodes
1808
+
1809
+ var focusableNodes = focusable(container, {
1810
+ getShadowRoot: (_config$tabbableOptio2 = config.tabbableOptions) === null || _config$tabbableOptio2 === void 0 ? void 0 : _config$tabbableOptio2.getShadowRoot
1811
+ });
1812
+ return {
1813
+ container: container,
1814
+ tabbableNodes: tabbableNodes,
1815
+ focusableNodes: focusableNodes,
1816
+ firstTabbableNode: tabbableNodes.length > 0 ? tabbableNodes[0] : null,
1817
+ lastTabbableNode: tabbableNodes.length > 0 ? tabbableNodes[tabbableNodes.length - 1] : null,
1818
+
1819
+ /**
1820
+ * Finds the __tabbable__ node that follows the given node in the specified direction,
1821
+ * in this container, if any.
1822
+ * @param {HTMLElement} node
1823
+ * @param {boolean} [forward] True if going in forward tab order; false if going
1824
+ * in reverse.
1825
+ * @returns {HTMLElement|undefined} The next tabbable node, if any.
1826
+ */
1827
+ nextTabbableNode: function nextTabbableNode(node) {
1828
+ var forward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
1829
+ // NOTE: If tabindex is positive (in order to manipulate the tab order separate
1830
+ // from the DOM order), this __will not work__ because the list of focusableNodes,
1831
+ // while it contains tabbable nodes, does not sort its nodes in any order other
1832
+ // than DOM order, because it can't: Where would you place focusable (but not
1833
+ // tabbable) nodes in that order? They have no order, because they aren't tabbale...
1834
+ // Support for positive tabindex is already broken and hard to manage (possibly
1835
+ // not supportable, TBD), so this isn't going to make things worse than they
1836
+ // already are, and at least makes things better for the majority of cases where
1837
+ // tabindex is either 0/unset or negative.
1838
+ // FYI, positive tabindex issue: https://github.com/focus-trap/focus-trap/issues/375
1839
+ var nodeIdx = focusableNodes.findIndex(function (n) {
1840
+ return n === node;
1841
+ });
1842
+
1843
+ if (nodeIdx < 0) {
1844
+ return undefined;
1845
+ }
1846
+
1847
+ if (forward) {
1848
+ return focusableNodes.slice(nodeIdx + 1).find(function (n) {
1849
+ return isTabbable(n);
1850
+ });
1851
+ }
1852
+
1853
+ return focusableNodes.slice(0, nodeIdx).reverse().find(function (n) {
1854
+ return isTabbable(n);
1855
+ });
1856
+ }
1857
+ };
1858
+ });
1859
+ state.tabbableGroups = state.containerGroups.filter(function (group) {
1860
+ return group.tabbableNodes.length > 0;
1861
+ }); // throw if no groups have tabbable nodes and we don't have a fallback focus node either
1862
+
1863
+ if (state.tabbableGroups.length <= 0 && !getNodeForOption('fallbackFocus') // returning false not supported for this option
1864
+ ) {
1865
+ throw new Error('Your focus-trap must have at least one container with at least one tabbable node in it at all times');
1866
+ }
1867
+ };
1868
+
1869
+ var tryFocus = function tryFocus(node) {
1870
+ if (node === false) {
1871
+ return;
1872
+ }
1873
+
1874
+ if (node === doc.activeElement) {
1875
+ return;
1876
+ }
1877
+
1878
+ if (!node || !node.focus) {
1879
+ tryFocus(getInitialFocusNode());
1880
+ return;
1881
+ }
1882
+
1883
+ node.focus({
1884
+ preventScroll: !!config.preventScroll
1885
+ });
1886
+ state.mostRecentlyFocusedNode = node;
1887
+
1888
+ if (isSelectableInput(node)) {
1889
+ node.select();
1890
+ }
1891
+ };
1892
+
1893
+ var getReturnFocusNode = function getReturnFocusNode(previousActiveElement) {
1894
+ var node = getNodeForOption('setReturnFocus', previousActiveElement);
1895
+ return node ? node : node === false ? false : previousActiveElement;
1896
+ }; // This needs to be done on mousedown and touchstart instead of click
1897
+ // so that it precedes the focus event.
1898
+
1899
+
1900
+ var checkPointerDown = function checkPointerDown(e) {
1901
+ var target = getActualTarget(e);
1902
+
1903
+ if (findContainerIndex(target) >= 0) {
1904
+ // allow the click since it ocurred inside the trap
1905
+ return;
1906
+ }
1907
+
1908
+ if (valueOrHandler(config.clickOutsideDeactivates, e)) {
1909
+ // immediately deactivate the trap
1910
+ trap.deactivate({
1911
+ // if, on deactivation, we should return focus to the node originally-focused
1912
+ // when the trap was activated (or the configured `setReturnFocus` node),
1913
+ // then assume it's also OK to return focus to the outside node that was
1914
+ // just clicked, causing deactivation, as long as that node is focusable;
1915
+ // if it isn't focusable, then return focus to the original node focused
1916
+ // on activation (or the configured `setReturnFocus` node)
1917
+ // NOTE: by setting `returnFocus: false`, deactivate() will do nothing,
1918
+ // which will result in the outside click setting focus to the node
1919
+ // that was clicked, whether it's focusable or not; by setting
1920
+ // `returnFocus: true`, we'll attempt to re-focus the node originally-focused
1921
+ // on activation (or the configured `setReturnFocus` node)
1922
+ returnFocus: config.returnFocusOnDeactivate && !isFocusable(target)
1923
+ });
1924
+ return;
1925
+ } // This is needed for mobile devices.
1926
+ // (If we'll only let `click` events through,
1927
+ // then on mobile they will be blocked anyways if `touchstart` is blocked.)
1928
+
1929
+
1930
+ if (valueOrHandler(config.allowOutsideClick, e)) {
1931
+ // allow the click outside the trap to take place
1932
+ return;
1933
+ } // otherwise, prevent the click
1934
+
1935
+
1936
+ e.preventDefault();
1937
+ }; // In case focus escapes the trap for some strange reason, pull it back in.
1938
+
1939
+
1940
+ var checkFocusIn = function checkFocusIn(e) {
1941
+ var target = getActualTarget(e);
1942
+ var targetContained = findContainerIndex(target) >= 0; // In Firefox when you Tab out of an iframe the Document is briefly focused.
1943
+
1944
+ if (targetContained || target instanceof Document) {
1945
+ if (targetContained) {
1946
+ state.mostRecentlyFocusedNode = target;
1947
+ }
1948
+ } else {
1949
+ // escaped! pull it back in to where it just left
1950
+ e.stopImmediatePropagation();
1951
+ tryFocus(state.mostRecentlyFocusedNode || getInitialFocusNode());
1952
+ }
1953
+ }; // Hijack Tab events on the first and last focusable nodes of the trap,
1954
+ // in order to prevent focus from escaping. If it escapes for even a
1955
+ // moment it can end up scrolling the page and causing confusion so we
1956
+ // kind of need to capture the action at the keydown phase.
1957
+
1958
+
1959
+ var checkTab = function checkTab(e) {
1960
+ var target = getActualTarget(e);
1961
+ updateTabbableNodes();
1962
+ var destinationNode = null;
1963
+
1964
+ if (state.tabbableGroups.length > 0) {
1965
+ // make sure the target is actually contained in a group
1966
+ // NOTE: the target may also be the container itself if it's focusable
1967
+ // with tabIndex='-1' and was given initial focus
1968
+ var containerIndex = findContainerIndex(target);
1969
+ var containerGroup = containerIndex >= 0 ? state.containerGroups[containerIndex] : undefined;
1970
+
1971
+ if (containerIndex < 0) {
1972
+ // target not found in any group: quite possible focus has escaped the trap,
1973
+ // so bring it back in to...
1974
+ if (e.shiftKey) {
1975
+ // ...the last node in the last group
1976
+ destinationNode = state.tabbableGroups[state.tabbableGroups.length - 1].lastTabbableNode;
1977
+ } else {
1978
+ // ...the first node in the first group
1979
+ destinationNode = state.tabbableGroups[0].firstTabbableNode;
1980
+ }
1981
+ } else if (e.shiftKey) {
1982
+ // REVERSE
1983
+ // is the target the first tabbable node in a group?
1984
+ var startOfGroupIndex = findIndex(state.tabbableGroups, function (_ref2) {
1985
+ var firstTabbableNode = _ref2.firstTabbableNode;
1986
+ return target === firstTabbableNode;
1987
+ });
1988
+
1989
+ if (startOfGroupIndex < 0 && (containerGroup.container === target || isFocusable(target) && !isTabbable(target) && !containerGroup.nextTabbableNode(target, false))) {
1990
+ // an exception case where the target is either the container itself, or
1991
+ // a non-tabbable node that was given focus (i.e. tabindex is negative
1992
+ // and user clicked on it or node was programmatically given focus)
1993
+ // and is not followed by any other tabbable node, in which
1994
+ // case, we should handle shift+tab as if focus were on the container's
1995
+ // first tabbable node, and go to the last tabbable node of the LAST group
1996
+ startOfGroupIndex = containerIndex;
1997
+ }
1998
+
1999
+ if (startOfGroupIndex >= 0) {
2000
+ // YES: then shift+tab should go to the last tabbable node in the
2001
+ // previous group (and wrap around to the last tabbable node of
2002
+ // the LAST group if it's the first tabbable node of the FIRST group)
2003
+ var destinationGroupIndex = startOfGroupIndex === 0 ? state.tabbableGroups.length - 1 : startOfGroupIndex - 1;
2004
+ var destinationGroup = state.tabbableGroups[destinationGroupIndex];
2005
+ destinationNode = destinationGroup.lastTabbableNode;
2006
+ }
2007
+ } else {
2008
+ // FORWARD
2009
+ // is the target the last tabbable node in a group?
2010
+ var lastOfGroupIndex = findIndex(state.tabbableGroups, function (_ref3) {
2011
+ var lastTabbableNode = _ref3.lastTabbableNode;
2012
+ return target === lastTabbableNode;
2013
+ });
2014
+
2015
+ if (lastOfGroupIndex < 0 && (containerGroup.container === target || isFocusable(target) && !isTabbable(target) && !containerGroup.nextTabbableNode(target))) {
2016
+ // an exception case where the target is the container itself, or
2017
+ // a non-tabbable node that was given focus (i.e. tabindex is negative
2018
+ // and user clicked on it or node was programmatically given focus)
2019
+ // and is not followed by any other tabbable node, in which
2020
+ // case, we should handle tab as if focus were on the container's
2021
+ // last tabbable node, and go to the first tabbable node of the FIRST group
2022
+ lastOfGroupIndex = containerIndex;
2023
+ }
2024
+
2025
+ if (lastOfGroupIndex >= 0) {
2026
+ // YES: then tab should go to the first tabbable node in the next
2027
+ // group (and wrap around to the first tabbable node of the FIRST
2028
+ // group if it's the last tabbable node of the LAST group)
2029
+ var _destinationGroupIndex = lastOfGroupIndex === state.tabbableGroups.length - 1 ? 0 : lastOfGroupIndex + 1;
2030
+
2031
+ var _destinationGroup = state.tabbableGroups[_destinationGroupIndex];
2032
+ destinationNode = _destinationGroup.firstTabbableNode;
2033
+ }
2034
+ }
2035
+ } else {
2036
+ // NOTE: the fallbackFocus option does not support returning false to opt-out
2037
+ destinationNode = getNodeForOption('fallbackFocus');
2038
+ }
2039
+
2040
+ if (destinationNode) {
2041
+ e.preventDefault();
2042
+ tryFocus(destinationNode);
2043
+ } // else, let the browser take care of [shift+]tab and move the focus
2044
+
2045
+ };
2046
+
2047
+ var checkKey = function checkKey(e) {
2048
+ if (isEscapeEvent(e) && valueOrHandler(config.escapeDeactivates, e) !== false) {
2049
+ e.preventDefault();
2050
+ trap.deactivate();
2051
+ return;
2052
+ }
2053
+
2054
+ if (isTabEvent(e)) {
2055
+ checkTab(e);
2056
+ return;
2057
+ }
2058
+ };
2059
+
2060
+ var checkClick = function checkClick(e) {
2061
+ if (valueOrHandler(config.clickOutsideDeactivates, e)) {
2062
+ return;
2063
+ }
2064
+
2065
+ var target = getActualTarget(e);
2066
+
2067
+ if (findContainerIndex(target) >= 0) {
2068
+ return;
2069
+ }
2070
+
2071
+ if (valueOrHandler(config.allowOutsideClick, e)) {
2072
+ return;
2073
+ }
2074
+
2075
+ e.preventDefault();
2076
+ e.stopImmediatePropagation();
2077
+ }; //
2078
+ // EVENT LISTENERS
2079
+ //
2080
+
2081
+
2082
+ var addListeners = function addListeners() {
2083
+ if (!state.active) {
2084
+ return;
2085
+ } // There can be only one listening focus trap at a time
2086
+
2087
+
2088
+ activeFocusTraps.activateTrap(trap); // Delay ensures that the focused element doesn't capture the event
2089
+ // that caused the focus trap activation.
2090
+
2091
+ state.delayInitialFocusTimer = config.delayInitialFocus ? delay(function () {
2092
+ tryFocus(getInitialFocusNode());
2093
+ }) : tryFocus(getInitialFocusNode());
2094
+ doc.addEventListener('focusin', checkFocusIn, true);
2095
+ doc.addEventListener('mousedown', checkPointerDown, {
2096
+ capture: true,
2097
+ passive: false
2098
+ });
2099
+ doc.addEventListener('touchstart', checkPointerDown, {
2100
+ capture: true,
2101
+ passive: false
2102
+ });
2103
+ doc.addEventListener('click', checkClick, {
2104
+ capture: true,
2105
+ passive: false
2106
+ });
2107
+ doc.addEventListener('keydown', checkKey, {
2108
+ capture: true,
2109
+ passive: false
2110
+ });
2111
+ return trap;
2112
+ };
2113
+
2114
+ var removeListeners = function removeListeners() {
2115
+ if (!state.active) {
2116
+ return;
2117
+ }
2118
+
2119
+ doc.removeEventListener('focusin', checkFocusIn, true);
2120
+ doc.removeEventListener('mousedown', checkPointerDown, true);
2121
+ doc.removeEventListener('touchstart', checkPointerDown, true);
2122
+ doc.removeEventListener('click', checkClick, true);
2123
+ doc.removeEventListener('keydown', checkKey, true);
2124
+ return trap;
2125
+ }; //
2126
+ // TRAP DEFINITION
2127
+ //
2128
+
2129
+
2130
+ trap = {
2131
+ activate: function activate(activateOptions) {
2132
+ if (state.active) {
2133
+ return this;
2134
+ }
2135
+
2136
+ var onActivate = getOption(activateOptions, 'onActivate');
2137
+ var onPostActivate = getOption(activateOptions, 'onPostActivate');
2138
+ var checkCanFocusTrap = getOption(activateOptions, 'checkCanFocusTrap');
2139
+
2140
+ if (!checkCanFocusTrap) {
2141
+ updateTabbableNodes();
2142
+ }
2143
+
2144
+ state.active = true;
2145
+ state.paused = false;
2146
+ state.nodeFocusedBeforeActivation = doc.activeElement;
2147
+
2148
+ if (onActivate) {
2149
+ onActivate();
2150
+ }
2151
+
2152
+ var finishActivation = function finishActivation() {
2153
+ if (checkCanFocusTrap) {
2154
+ updateTabbableNodes();
2155
+ }
2156
+
2157
+ addListeners();
2158
+
2159
+ if (onPostActivate) {
2160
+ onPostActivate();
2161
+ }
2162
+ };
2163
+
2164
+ if (checkCanFocusTrap) {
2165
+ checkCanFocusTrap(state.containers.concat()).then(finishActivation, finishActivation);
2166
+ return this;
2167
+ }
2168
+
2169
+ finishActivation();
2170
+ return this;
2171
+ },
2172
+ deactivate: function deactivate(deactivateOptions) {
2173
+ if (!state.active) {
2174
+ return this;
2175
+ }
2176
+
2177
+ clearTimeout(state.delayInitialFocusTimer); // noop if undefined
2178
+
2179
+ state.delayInitialFocusTimer = undefined;
2180
+ removeListeners();
2181
+ state.active = false;
2182
+ state.paused = false;
2183
+ activeFocusTraps.deactivateTrap(trap);
2184
+ var onDeactivate = getOption(deactivateOptions, 'onDeactivate');
2185
+ var onPostDeactivate = getOption(deactivateOptions, 'onPostDeactivate');
2186
+ var checkCanReturnFocus = getOption(deactivateOptions, 'checkCanReturnFocus');
2187
+
2188
+ if (onDeactivate) {
2189
+ onDeactivate();
2190
+ }
2191
+
2192
+ var returnFocus = getOption(deactivateOptions, 'returnFocus', 'returnFocusOnDeactivate');
2193
+
2194
+ var finishDeactivation = function finishDeactivation() {
2195
+ delay(function () {
2196
+ if (returnFocus) {
2197
+ tryFocus(getReturnFocusNode(state.nodeFocusedBeforeActivation));
2198
+ }
2199
+
2200
+ if (onPostDeactivate) {
2201
+ onPostDeactivate();
2202
+ }
2203
+ });
2204
+ };
2205
+
2206
+ if (returnFocus && checkCanReturnFocus) {
2207
+ checkCanReturnFocus(getReturnFocusNode(state.nodeFocusedBeforeActivation)).then(finishDeactivation, finishDeactivation);
2208
+ return this;
2209
+ }
2210
+
2211
+ finishDeactivation();
2212
+ return this;
2213
+ },
2214
+ pause: function pause() {
2215
+ if (state.paused || !state.active) {
2216
+ return this;
2217
+ }
2218
+
2219
+ state.paused = true;
2220
+ removeListeners();
2221
+ return this;
2222
+ },
2223
+ unpause: function unpause() {
2224
+ if (!state.paused || !state.active) {
2225
+ return this;
2226
+ }
2227
+
2228
+ state.paused = false;
2229
+ updateTabbableNodes();
2230
+ addListeners();
2231
+ return this;
2232
+ },
2233
+ updateContainerElements: function updateContainerElements(containerElements) {
2234
+ var elementsAsArray = [].concat(containerElements).filter(Boolean);
2235
+ state.containers = elementsAsArray.map(function (element) {
2236
+ return typeof element === 'string' ? doc.querySelector(element) : element;
2237
+ });
2238
+
2239
+ if (state.active) {
2240
+ updateTabbableNodes();
2241
+ }
2242
+
2243
+ return this;
2244
+ }
2245
+ }; // initialize container elements
2246
+
2247
+ trap.updateContainerElements(elements);
2248
+ return trap;
2249
+ };
2250
+
2251
+ const catMenuCss = ":host{display:inline-block}:host([hidden]){display:none}.content{padding-top:0.5rem;padding-bottom:0.5rem;position:absolute;background:white;display:none;overflow:auto;-webkit-overflow-scrolling:touch;min-width:8rem;max-width:16rem;min-height:2rem;max-height:calc(100vh - 48px);box-shadow:0 1px 4px 0 rgba(16, 29, 48, 0.2);border-radius:0.25rem}";
2252
+
2253
+ let nextUniqueId = 0;
2254
+ let CatMenu$1 = class extends HTMLElement {
2255
+ constructor() {
2256
+ super();
2257
+ this.__registerHost();
2258
+ this.__attachShadow();
2259
+ this.catOpen = createEvent(this, "catOpen", 7);
2260
+ this.catClose = createEvent(this, "catClose", 7);
2261
+ this.id = nextUniqueId++;
2262
+ /**
2263
+ * The placement of the menu.
2264
+ */
2265
+ this.placement = 'bottom-start';
2266
+ }
2267
+ clickHandler(event) {
2268
+ var _a;
2269
+ // hide menu on button click
2270
+ if (this.content && event.composedPath().includes(this.content)) {
2271
+ (_a = this.trap) === null || _a === void 0 ? void 0 : _a.deactivate();
2272
+ this.hide();
2273
+ }
2274
+ }
2275
+ componentDidLoad() {
2276
+ var _a, _b, _c, _d, _e;
2277
+ this.trigger = this.firstTabbable(this.triggerSlot);
2278
+ (_a = this.trigger) === null || _a === void 0 ? void 0 : _a.setAttribute('aria-haspopup', 'true');
2279
+ (_b = this.trigger) === null || _b === void 0 ? void 0 : _b.setAttribute('aria-expanded', 'false');
2280
+ (_c = this.trigger) === null || _c === void 0 ? void 0 : _c.setAttribute('aria-controls', this.contentId);
2281
+ (_d = this.content) === null || _d === void 0 ? void 0 : _d.setAttribute('id', this.contentId);
2282
+ if (this.trigger && this.content) {
2283
+ (_e = this.trigger) === null || _e === void 0 ? void 0 : _e.addEventListener('click', () => this.show());
2284
+ autoUpdate(this.trigger, this.content, () => this.update());
2285
+ }
2286
+ this.keyListener = event => {
2287
+ if (this.content && ['ArrowDown', 'ArrowUp'].includes(event.key)) {
2288
+ const targetElements = tabbable(this.content, { includeContainer: false, getShadowRoot: true });
2289
+ const activeElement = this.firstTabbable(document.activeElement);
2290
+ const activeIdx = activeElement ? targetElements.indexOf(activeElement) : -1;
2291
+ const activeOff = event.key === 'ArrowDown' ? 1 : -1;
2292
+ const targetIdx = activeIdx < 0 ? 0 : (activeIdx + activeOff + targetElements.length) % targetElements.length;
2293
+ targetElements[targetIdx].focus();
2294
+ event.preventDefault();
2295
+ }
2296
+ };
2297
+ document.addEventListener('keydown', this.keyListener);
2298
+ }
2299
+ disconnectedCallback() {
2300
+ if (this.keyListener) {
2301
+ document.removeEventListener('keydown', this.keyListener);
2302
+ }
2303
+ }
2304
+ render() {
2305
+ return (h(Host, null, h("slot", { name: "trigger", ref: el => (this.triggerSlot = el) }), h("div", { class: "content", ref: el => (this.content = el) }, h("slot", { name: "content" }))));
2306
+ }
2307
+ get contentId() {
2308
+ return `cat-menu-${this.id}`;
2309
+ }
2310
+ show() {
2311
+ var _a;
2312
+ if (this.content) {
2313
+ this.content.style.display = 'block';
2314
+ (_a = this.trigger) === null || _a === void 0 ? void 0 : _a.setAttribute('aria-expanded', 'true');
2315
+ this.catOpen.emit();
2316
+ this.trap = this.trap
2317
+ ? this.trap.updateContainerElements(this.content)
2318
+ : createFocusTrap(this.content, {
2319
+ tabbableOptions: {
2320
+ getShadowRoot: true
2321
+ },
2322
+ allowOutsideClick: true,
2323
+ clickOutsideDeactivates: event => !this.content || !event.composedPath().includes(this.content),
2324
+ onPostDeactivate: () => this.hide()
2325
+ });
2326
+ this.trap.activate();
2327
+ }
2328
+ }
2329
+ hide() {
2330
+ var _a;
2331
+ if (this.content) {
2332
+ this.content.style.display = '';
2333
+ (_a = this.trigger) === null || _a === void 0 ? void 0 : _a.setAttribute('aria-expanded', 'false');
2334
+ this.catClose.emit();
2335
+ }
2336
+ }
2337
+ update() {
2338
+ if (this.trigger && this.content) {
2339
+ computePosition(this.trigger, this.content, {
2340
+ placement: this.placement,
2341
+ middleware: [offset(CatMenu$1.OFFSET), flip()]
2342
+ }).then(({ x, y }) => {
2343
+ if (this.content) {
2344
+ Object.assign(this.content.style, {
2345
+ left: `${x}px`,
2346
+ top: `${y}px`
2347
+ });
2348
+ }
2349
+ });
2350
+ }
2351
+ }
2352
+ firstTabbable(container) {
2353
+ return (container ? tabbable(container, { includeContainer: true, getShadowRoot: true }) : []).shift();
2354
+ }
2355
+ static get style() { return catMenuCss; }
2356
+ };
2357
+ CatMenu$1.OFFSET = 4;
2358
+ CatMenu$1 = /*@__PURE__*/ proxyCustomElement(CatMenu$1, [1, "cat-menu", {
2359
+ "placement": [1]
2360
+ }, [[0, "catClick", "clickHandler"]]]);
2361
+ function defineCustomElement$1() {
2362
+ if (typeof customElements === "undefined") {
2363
+ return;
2364
+ }
2365
+ const components = ["cat-menu"];
2366
+ components.forEach(tagName => { switch (tagName) {
2367
+ case "cat-menu":
2368
+ if (!customElements.get(tagName)) {
2369
+ customElements.define(tagName, CatMenu$1);
2370
+ }
2371
+ break;
2372
+ } });
2373
+ }
2374
+
2375
+ const CatMenu = CatMenu$1;
2376
+ const defineCustomElement = defineCustomElement$1;
2377
+
2378
+ export { CatMenu, defineCustomElement };