@oscarpalmer/oui 0.16.0 → 0.18.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 (62) hide show
  1. package/dist/css/badge.css +3 -3
  2. package/dist/css/content.css +9 -11
  3. package/dist/css/form.css +36 -22
  4. package/dist/css/message.css +4 -0
  5. package/dist/css/popover.css +3 -0
  6. package/dist/css/reset.css +176 -56
  7. package/dist/css/splitter.css +3 -3
  8. package/dist/css/tooltip.css +8 -0
  9. package/dist/js/attributable.full.js +48 -0
  10. package/dist/js/attributable.js +30 -45
  11. package/dist/js/floatable.full.js +413 -0
  12. package/dist/js/floatable.js +259 -132
  13. package/dist/js/focus-trap/embedded.full.js +351 -0
  14. package/dist/js/focus-trap/embedded.js +131 -131
  15. package/dist/js/focus-trap/standalone.full.js +402 -0
  16. package/dist/js/focus-trap/standalone.js +4 -4
  17. package/dist/js/index.js +4 -5
  18. package/dist/js/oui.full.js +1596 -0
  19. package/dist/js/popover.full.js +822 -0
  20. package/dist/js/popover.js +83 -156
  21. package/dist/js/splitter.full.js +605 -0
  22. package/dist/js/splitter.js +279 -200
  23. package/dist/js/tooltip.full.js +679 -0
  24. package/dist/js/tooltip.js +159 -144
  25. package/package.json +31 -59
  26. package/src/css/content.scss +1 -2
  27. package/src/css/form.scss +12 -4
  28. package/src/css/message.scss +3 -0
  29. package/src/css/mixins.scss +7 -0
  30. package/src/css/popover.scss +4 -0
  31. package/src/css/reset.scss +180 -54
  32. package/src/css/splitter.scss +3 -3
  33. package/src/css/tooltip.scss +8 -0
  34. package/src/js/floatable.ts +458 -124
  35. package/src/js/focus-trap/embedded.ts +149 -64
  36. package/src/js/focus-trap/standalone.ts +4 -4
  37. package/src/js/index.ts +1 -0
  38. package/src/js/popover.ts +51 -114
  39. package/src/js/splitter.ts +346 -109
  40. package/src/js/tooltip.ts +157 -63
  41. package/types/floatable.d.ts +19 -7
  42. package/types/focus-trap/embedded.d.ts +18 -5
  43. package/types/index.d.ts +1 -0
  44. package/types/popover.d.ts +2 -0
  45. package/types/splitter.d.ts +13 -1
  46. package/types/tooltip.d.ts +2 -1
  47. package/dist/js/attributable.cjs +0 -51
  48. package/dist/js/floatable.cjs +0 -134
  49. package/dist/js/focus-trap/embedded.cjs +0 -150
  50. package/dist/js/focus-trap/standalone.cjs +0 -8
  51. package/dist/js/index.cjs +0 -6
  52. package/dist/js/popover.cjs +0 -160
  53. package/dist/js/splitter.cjs +0 -211
  54. package/dist/js/tooltip.cjs +0 -160
  55. package/types/attributable.d.cts +0 -5
  56. package/types/floatable.d.cts +0 -16
  57. package/types/focus-trap/embedded.d.cts +0 -15
  58. package/types/focus-trap/standalone.d.cts +0 -3
  59. package/types/index.d.cts +0 -14
  60. package/types/popover.d.cts +0 -14
  61. package/types/splitter.d.cts +0 -10
  62. package/types/tooltip.d.cts +0 -3
@@ -4,57 +4,128 @@ import {findAncestor} from '@oscarpalmer/toretto/find';
4
4
  import {getFocusable} from '@oscarpalmer/toretto/focusable';
5
5
 
6
6
  export class FocusTrap {
7
- active = true;
7
+ disabled = false;
8
+
9
+ connected = true;
10
+
11
+ element: HTMLElement;
12
+
13
+ embedded: boolean;
14
+
15
+ get contain(): boolean {
16
+ return this.element.hasAttribute(FOCUS_TRAP_CONTAIN);
17
+ }
18
+
19
+ get noescape(): boolean {
20
+ return this.element.hasAttribute(FOCUS_TRAP_NOESCAPE);
21
+ }
22
+
23
+ constructor(element: HTMLElement, options?: Options) {
24
+ this.element = element;
25
+ this.embedded = options != null;
8
26
 
9
- constructor(public element: HTMLElement) {
10
- element.setAttribute('aria-modal', 'true');
11
27
  element.setAttribute('tabindex', '-1');
28
+
29
+ if (options != null) {
30
+ element.setAttribute(FOCUS_TRAP_SELECTOR, '');
31
+ }
32
+
33
+ if (options?.noescape) {
34
+ element.setAttribute(FOCUS_TRAP_NOESCAPE, '');
35
+ }
36
+ }
37
+
38
+ connect(): void {
39
+ setConnected(this, true);
12
40
  }
13
41
 
14
- destroy() {
42
+ destroy(): void {
15
43
  this.element = undefined as never;
16
44
  }
17
45
 
18
- disable() {
19
- if (this.active && !this.element.hasAttribute(`${selector}-noescape`)) {
46
+ disable(): void {
47
+ if (!(this.disabled || this.noescape)) {
20
48
  setDisabled(this, true);
21
49
  }
22
50
  }
23
51
 
24
- enable() {
25
- if (!this.active) {
52
+ disconnect(): void {
53
+ setConnected(this, false);
54
+ }
55
+
56
+ enable(): void {
57
+ if (this.disabled) {
26
58
  setDisabled(this, false);
27
59
  }
28
60
  }
61
+
62
+ focus(last: boolean): void {
63
+ tabToTrap(this, getFocusable(this.element), this.element, last ? -1 : 0);
64
+ }
29
65
  }
30
66
 
67
+ type Options = {
68
+ noescape: boolean;
69
+ };
70
+
31
71
  //
32
72
 
33
- export function createFocusTrap(element: HTMLElement): FocusTrap {
34
- let focusTrap = focusTraps.get(element);
73
+ export function createFocusTrap(
74
+ element: HTMLElement,
75
+ options?: Options,
76
+ ): FocusTrap {
77
+ let focusTrap = FOCUSTRAPS_ALL.get(element);
35
78
 
36
79
  if (focusTrap == null) {
37
- focusTrap = new FocusTrap(element);
80
+ focusTrap = new FocusTrap(element, options);
38
81
 
39
- focusTraps.set(element, focusTrap);
82
+ FOCUSTRAPS_ALL.set(element, focusTrap);
40
83
  }
41
84
 
42
85
  return focusTrap;
43
86
  }
44
87
 
45
88
  function onEscape(event: KeyboardEvent): void {
46
- focusTraps
47
- .get(
48
- findAncestor(event.target as HTMLElement, `[${selector}]`) as HTMLElement,
49
- )
50
- ?.disable();
89
+ let element = findAncestor(
90
+ event.target as HTMLElement,
91
+ ATTRIBUTE_SELECTOR,
92
+ ) as HTMLElement;
93
+
94
+ let focusTrap = FOCUSTRAPS_ALL.get(element);
95
+
96
+ if (element == null || focusTrap == null) {
97
+ return;
98
+ }
99
+
100
+ while (focusTrap.disabled) {
101
+ element = findAncestor(
102
+ focusTrap.element.parentElement as HTMLElement,
103
+ ATTRIBUTE_SELECTOR,
104
+ ) as HTMLElement;
105
+
106
+ focusTrap = FOCUSTRAPS_ALL.get(element);
107
+
108
+ if (element == null || focusTrap == null) {
109
+ return;
110
+ }
111
+
112
+ if (!focusTrap.disabled) {
113
+ break;
114
+ }
115
+ }
116
+
117
+ focusTrap?.disable();
51
118
  }
52
119
 
53
120
  function onFocusIn(event: Event): void {
54
- lastTarget =
55
- findAncestor(event.target as HTMLElement, `[${selector}]`) == null
56
- ? undefined
57
- : (event.target as HTMLElement);
121
+ const focusTrap = FOCUSTRAPS_ALL.get(
122
+ findAncestor(
123
+ event.target as HTMLElement,
124
+ ATTRIBUTE_SELECTOR,
125
+ ) as HTMLElement,
126
+ );
127
+
128
+ lastTarget = focusTrap == null ? undefined : (event.target as HTMLElement);
58
129
  }
59
130
 
60
131
  function onKeydown(event: KeyboardEvent): void {
@@ -75,28 +146,29 @@ function onKeydown(event: KeyboardEvent): void {
75
146
  function onPointerdown(event: MouseEvent | TouchEvent): void {
76
147
  const lastFocusTrap = findAncestor(
77
148
  lastTarget as HTMLElement,
78
- `[${selector}]`,
149
+ ATTRIBUTE_SELECTOR,
79
150
  ) as HTMLElement;
80
151
 
81
152
  const nextFocusTrap = findAncestor(
82
153
  event.target as HTMLElement,
83
- `[${selector}]`,
154
+ ATTRIBUTE_SELECTOR,
84
155
  ) as HTMLElement;
85
156
 
86
157
  if (lastFocusTrap != null && nextFocusTrap !== lastFocusTrap) {
87
- event.preventDefault();
158
+ if (FOCUSTRAPS_ALL.get(lastFocusTrap)?.contain ?? false) {
159
+ event.preventDefault();
88
160
 
89
- lastTarget?.focus();
161
+ lastTarget?.focus();
162
+ }
90
163
  }
91
164
 
92
- if (disabled.size === 0) {
165
+ if (FOCUSTRAPS_DISABLED.size === 0) {
93
166
  return;
94
167
  }
95
168
 
96
- for (const focusTrap of disabled) {
169
+ for (const focusTrap of FOCUSTRAPS_DISABLED) {
97
170
  if (focusTrap.element !== nextFocusTrap) {
98
171
  focusTrap.enable();
99
- return;
100
172
  }
101
173
  }
102
174
  }
@@ -104,16 +176,16 @@ function onPointerdown(event: MouseEvent | TouchEvent): void {
104
176
  function onTab(event: KeyboardEvent): void {
105
177
  const element = findAncestor(
106
178
  event.target as HTMLElement,
107
- `[${selector}]`,
179
+ ATTRIBUTE_SELECTOR,
108
180
  ) as HTMLElement;
109
181
 
110
- const focusTrap = focusTraps.get(element);
182
+ const focusTrap = FOCUSTRAPS_ALL.get(element);
111
183
 
112
184
  if (focusTrap == null) {
113
185
  return;
114
186
  }
115
187
 
116
- if (focusTrap.active) {
188
+ if (!focusTrap.disabled) {
117
189
  event.preventDefault();
118
190
  }
119
191
 
@@ -124,36 +196,38 @@ function onTab(event: KeyboardEvent): void {
124
196
  if (index === -1 || elements.length === 0) {
125
197
  tabToTrap(focusTrap, elements, element);
126
198
  } else {
127
- tabToElement(event, focusTrap, elements, index);
199
+ tabToElement(focusTrap, elements, index, event.shiftKey ? -1 : 1);
128
200
  }
129
201
  }
130
202
 
131
- function setDisabled(focusTrap: FocusTrap, value: boolean): void {
132
- focusTrap.element.setAttribute('aria-modal', String(!value));
203
+ function setConnected(focusTrap: FocusTrap, value: boolean): void {
204
+ if (!focusTrap.embedded || focusTrap.connected === value) {
205
+ return;
206
+ }
207
+
208
+ focusTrap.connected = value;
209
+ }
133
210
 
134
- focusTrap.active = !value;
211
+ function setDisabled(focusTrap: FocusTrap, value: boolean): void {
212
+ focusTrap.disabled = value;
135
213
 
136
214
  if (value) {
137
- disabled.add(focusTrap);
215
+ FOCUSTRAPS_DISABLED.add(focusTrap);
138
216
  } else {
139
- disabled.delete(focusTrap);
217
+ FOCUSTRAPS_DISABLED.delete(focusTrap);
140
218
  }
141
219
  }
142
220
 
143
221
  function tabToElement(
144
- event: KeyboardEvent,
145
222
  focusTrap: FocusTrap,
146
223
  elements: Element[],
147
224
  index: number,
225
+ modifier: number,
148
226
  ): void {
149
- const next = clamp(
150
- index + (event.shiftKey ? -1 : 1),
151
- 0,
152
- elements.length - 1,
153
- true,
154
- );
227
+ const {length} = elements;
228
+ const next = clamp(index + modifier, 0, length - 1, true);
155
229
 
156
- if (!focusTrap.active) {
230
+ if (focusTrap.disabled) {
157
231
  if (
158
232
  (index === length - 1 && next === 0) ||
159
233
  (index === 0 && next === length - 1)
@@ -166,50 +240,61 @@ function tabToElement(
166
240
  return;
167
241
  }
168
242
 
169
- (elements[next] as HTMLElement).focus();
243
+ const element = elements[next] as HTMLElement;
244
+ const elementFocusTrap = FOCUSTRAPS_ALL.get(element);
170
245
 
171
- lastTarget = elements[next] as HTMLElement;
246
+ if (elementFocusTrap != null) {
247
+ elementFocusTrap.focus(modifier === -1);
248
+ } else {
249
+ (elements[next] as HTMLElement).focus();
250
+
251
+ lastTarget = elements[next] as HTMLElement;
252
+ }
172
253
  }
173
254
 
174
255
  function tabToTrap(
175
256
  focusTrap: FocusTrap,
176
257
  elements: Element[],
177
258
  element: HTMLElement,
259
+ index?: number,
178
260
  ): void {
179
- if (focusTrap.active) {
180
- const next = length === 0 ? element : elements[0];
261
+ if (focusTrap.disabled) {
262
+ lastTarget = undefined;
263
+
264
+ focusTrap.enable();
265
+ } else {
266
+ const next = elements.length === 0 ? element : elements.at(index ?? 0);
181
267
 
182
268
  (next as HTMLElement).focus();
183
269
 
184
270
  lastTarget = next as HTMLElement;
185
- } else {
186
- lastTarget = undefined;
187
-
188
- focusTrap.enable();
189
271
  }
190
272
  }
191
273
 
192
274
  //
193
275
 
194
- const disabled = new Set<FocusTrap>();
276
+ export const FOCUS_TRAP_SELECTOR = 'oui-focus-trap';
195
277
 
196
- const eventOptions = {
278
+ const ATTRIBUTE_SELECTOR = `[${FOCUS_TRAP_SELECTOR}]`;
279
+
280
+ const EVENT_OPTIONS: AddEventListenerOptions = {
197
281
  capture: true,
198
282
  passive: false,
199
283
  };
200
284
 
201
- export const focusTraps = new WeakMap<HTMLElement, FocusTrap>();
202
-
203
- let lastTarget: HTMLElement | undefined;
285
+ export const FOCUS_TRAP_CONTAIN = `${FOCUS_TRAP_SELECTOR}-contain`;
204
286
 
205
- export const selector = 'oui-focus-trap';
287
+ export const FOCUS_TRAP_NOESCAPE = `${FOCUS_TRAP_SELECTOR}-noescape`;
206
288
 
207
- //
289
+ export const FOCUSTRAPS_ALL: WeakMap<HTMLElement, FocusTrap> = new WeakMap();
208
290
 
209
- on(document, 'focusin', onFocusIn, eventOptions);
291
+ const FOCUSTRAPS_DISABLED: Set<FocusTrap> = new Set();
210
292
 
211
- on(document, 'keydown', onKeydown, eventOptions);
293
+ let lastTarget: HTMLElement | undefined;
212
294
 
213
- on(document, 'mousedown', onPointerdown, eventOptions);
295
+ //
214
296
 
215
- on(document, 'touchstart', onPointerdown, eventOptions);
297
+ on(document, 'focusin', onFocusIn, EVENT_OPTIONS);
298
+ on(document, 'keydown', onKeydown, EVENT_OPTIONS);
299
+ on(document, 'mousedown', onPointerdown, EVENT_OPTIONS);
300
+ on(document, 'touchstart', onPointerdown, EVENT_OPTIONS);
@@ -1,9 +1,9 @@
1
1
  import {attributable} from '../attributable';
2
- import {createFocusTrap, focusTraps, selector} from './embedded';
2
+ import {createFocusTrap, FOCUS_TRAP_SELECTOR, FOCUSTRAPS_ALL} from './embedded';
3
3
 
4
4
  function removeFocusTraps(element: HTMLElement): void {
5
- focusTraps.get(element)?.destroy();
6
- focusTraps.delete(element);
5
+ FOCUSTRAPS_ALL.get(element)?.destroy();
6
+ FOCUSTRAPS_ALL.delete(element);
7
7
  }
8
8
 
9
- attributable(selector, createFocusTrap, removeFocusTraps);
9
+ attributable(FOCUS_TRAP_SELECTOR, createFocusTrap, removeFocusTraps);
package/src/js/index.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './focus-trap/standalone';
2
2
  export * from './popover';
3
+ export * from './splitter';
3
4
  export * from './tooltip';
package/src/js/popover.ts CHANGED
@@ -1,29 +1,26 @@
1
1
  import {isNullableOrWhitespace} from '@oscarpalmer/atoms/is';
2
- import {on} from '@oscarpalmer/toretto/event';
3
- import {findAncestor} from '@oscarpalmer/toretto/find';
4
2
  import {getFocusable} from '@oscarpalmer/toretto/focusable';
5
- import {activate, deactivate, Floatable} from './floatable';
3
+ import {Floatable} from './floatable';
6
4
  import {createFocusTrap, type FocusTrap} from './focus-trap/embedded';
7
5
 
8
6
  declare global {
7
+ // biome-ignore lint/nursery/useConsistentTypeDefinitions: Extending builtins to allow custom element type help
9
8
  interface HTMLElementTagNameMap {
10
9
  'oui-popover': OuiPopoverElement;
11
10
  }
12
11
  }
13
12
 
14
- const mapped = new Map<HTMLElement, Floatable>();
15
-
16
13
  let index = 0;
17
14
 
18
15
  export class OuiPopoverElement extends HTMLElement {
19
- #floatable: Floatable;
20
- #focusTrap: FocusTrap;
16
+ readonly #floatable: Floatable;
17
+ readonly #focusTrap: FocusTrap;
21
18
 
22
19
  constructor() {
23
20
  super();
24
21
 
25
- const content = this.querySelector(':scope > [oui-popover-content]');
26
- const toggle = this.querySelector(':scope > [oui-popover-toggle]');
22
+ const content = this.querySelector(SELECTOR_CONTENT);
23
+ const toggle = this.querySelector(SELECTOR_TOGGLE);
27
24
 
28
25
  if (!(content instanceof HTMLElement)) {
29
26
  throw new Error(
@@ -40,33 +37,56 @@ export class OuiPopoverElement extends HTMLElement {
40
37
  content.hidden = true;
41
38
 
42
39
  content.setAttribute('role', 'dialog');
43
- content.setAttribute('oui-focus-trap', '');
44
- content.setAttribute('oui-focus-trap-noescape', '');
40
+ content.setAttribute('aria-modal', 'true');
45
41
 
46
42
  if (isNullableOrWhitespace(content.id)) {
47
- content.setAttribute('id', `oui-popover-content-${++index}`);
43
+ content.setAttribute('id', `${ATTRIBUTE_ID_PREFIX}_${++index}`);
48
44
  }
49
45
 
50
46
  toggle.setAttribute('aria-controls', content.id);
51
47
  toggle.setAttribute('aria-haspopup', 'dialog');
52
48
 
53
- this.#floatable = new Floatable(toggle, content);
54
- this.#focusTrap = createFocusTrap(content);
55
-
56
- mapped.set(toggle, this.#floatable);
57
- mapped.set(content, this.#floatable);
49
+ this.#floatable = new Floatable({
50
+ content,
51
+ anchor: toggle,
52
+ defaultPosition: 'below-start',
53
+ interactive: true,
54
+ positionAttribute: 'position',
55
+ preferAbove: false,
56
+ onAfter: (active: boolean): void => {
57
+ if (active) {
58
+ focus(content);
59
+ } else if (!this.#floatable.ignoreFocus) {
60
+ toggle.focus();
61
+ }
62
+ },
63
+ });
64
+
65
+ this.#focusTrap = createFocusTrap(content, {
66
+ noescape: true,
67
+ });
68
+
69
+ POPOVERS.set(toggle, this.#floatable);
70
+ POPOVERS.set(content, this.#floatable);
58
71
  }
59
72
 
60
73
  close(): void {
61
74
  this.hidePopover();
62
75
  }
63
76
 
64
- hidePopover(): void {
65
- if (this.#floatable.active) {
66
- closeAbove(this.#floatable.content);
67
- deactivate(this.#floatable, active, order);
77
+ connectedCallback(): void {
78
+ this.#floatable.enable();
79
+ this.#focusTrap.connect();
80
+ }
68
81
 
69
- this.#floatable.anchor.focus();
82
+ disconnectedCallback(): void {
83
+ this.#floatable.disable();
84
+ this.#focusTrap.disconnect();
85
+ }
86
+
87
+ hidePopover(): void {
88
+ if (this.#floatable.active && this.isConnected) {
89
+ this.#floatable.toggle(false);
70
90
  }
71
91
  }
72
92
 
@@ -75,8 +95,8 @@ export class OuiPopoverElement extends HTMLElement {
75
95
  }
76
96
 
77
97
  showPopover(): void {
78
- if (!this.#floatable.active) {
79
- toggle(this.#floatable.anchor);
98
+ if (!this.#floatable.active && this.isConnected) {
99
+ this.#floatable.toggle(true);
80
100
  }
81
101
  }
82
102
 
@@ -109,32 +129,6 @@ export class OuiPopoverElement extends HTMLElement {
109
129
 
110
130
  //
111
131
 
112
- function closeAll(): void {
113
- for (const floatable of active) {
114
- deactivate(floatable, active, order);
115
- }
116
- }
117
-
118
- function closeAbove(element: HTMLElement): void {
119
- const index = order.findIndex(
120
- floatable => floatable.anchor === element || floatable.content === element,
121
- );
122
-
123
- if (index === -1 || index === order.length - 1) {
124
- return;
125
- }
126
-
127
- while (index < order.length - 1) {
128
- const floatable = order.pop();
129
-
130
- if (floatable != null) {
131
- deactivate(floatable, active, order);
132
- }
133
- }
134
-
135
- focus(order[index].content);
136
- }
137
-
138
132
  function focus(content: HTMLElement): void {
139
133
  let target = getFocusable(content)[0];
140
134
 
@@ -147,75 +141,18 @@ function focus(content: HTMLElement): void {
147
141
  });
148
142
  }
149
143
 
150
- function onClick(event: MouseEvent): void {
151
- const related = findAncestor(
152
- event.target as never,
153
- '[oui-popover-toggle], [oui-popover-content]',
154
- );
155
-
156
- if (!(related instanceof HTMLElement)) {
157
- closeAll();
158
- } else if (related.hasAttribute('oui-popover-content')) {
159
- closeAbove(related);
160
- } else {
161
- toggle(related);
162
- }
163
- }
164
-
165
- function onKeydown(event: KeyboardEvent): void {
166
- if (event.key !== 'Escape' || order.length === 0) {
167
- return;
168
- }
169
-
170
- const related = findAncestor(event.target as never, '[oui-popover-content]');
171
-
172
- if (!(related instanceof HTMLElement)) {
173
- return;
174
- }
175
-
176
- closeAbove(related);
177
-
178
- const floatable = mapped.get(related);
179
-
180
- if (floatable != null) {
181
- deactivate(floatable, active, order);
182
-
183
- floatable.anchor.focus();
184
- }
185
- }
186
-
187
- function toggle(anchor: HTMLElement): void {
188
- const content = findAncestor(anchor, '[oui-popover-content]');
189
-
190
- if (content instanceof HTMLElement) {
191
- closeAbove(content);
192
- } else {
193
- closeAll();
194
- }
195
-
196
- const floatable = mapped.get(anchor);
144
+ //
197
145
 
198
- if (floatable == null) {
199
- return;
200
- }
146
+ const ATTRIBUTE_ID_PREFIX = 'oui_popover_content_';
201
147
 
202
- if (floatable.active) {
203
- deactivate(floatable, active, order);
204
- } else {
205
- activate(floatable, active, order);
206
- focus(floatable.content);
207
- }
208
- }
148
+ const POPOVERS: Map<HTMLElement, Floatable> = new Map();
209
149
 
210
- //
150
+ const SELECTOR = 'oui-popover';
211
151
 
212
- customElements.define('oui-popover', OuiPopoverElement);
152
+ const SELECTOR_CONTENT = `:scope > [${SELECTOR}-content]`;
213
153
 
214
- on(document, 'click', onClick);
215
- on(document, 'keydown', onKeydown);
154
+ const SELECTOR_TOGGLE = `:scope > [${SELECTOR}-toggle]`;
216
155
 
217
156
  //
218
157
 
219
- const active = new Set<Floatable>();
220
-
221
- const order: Floatable[] = [];
158
+ customElements.define(SELECTOR, OuiPopoverElement);