@oscarpalmer/oui 0.17.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 (58) 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/reset.css +176 -56
  6. package/dist/css/tooltip.css +8 -0
  7. package/dist/js/attributable.full.js +48 -0
  8. package/dist/js/attributable.js +30 -45
  9. package/dist/js/floatable.full.js +413 -0
  10. package/dist/js/floatable.js +254 -169
  11. package/dist/js/focus-trap/embedded.full.js +351 -0
  12. package/dist/js/focus-trap/embedded.js +131 -131
  13. package/dist/js/focus-trap/standalone.full.js +402 -0
  14. package/dist/js/focus-trap/standalone.js +4 -4
  15. package/dist/js/index.js +4 -5
  16. package/dist/js/oui.full.js +1596 -0
  17. package/dist/js/popover.full.js +822 -0
  18. package/dist/js/popover.js +83 -162
  19. package/dist/js/splitter.full.js +605 -0
  20. package/dist/js/splitter.js +263 -245
  21. package/dist/js/tooltip.full.js +679 -0
  22. package/dist/js/tooltip.js +159 -150
  23. package/package.json +31 -59
  24. package/src/css/content.scss +1 -2
  25. package/src/css/form.scss +12 -4
  26. package/src/css/message.scss +3 -0
  27. package/src/css/mixins.scss +7 -0
  28. package/src/css/reset.scss +180 -54
  29. package/src/css/tooltip.scss +8 -0
  30. package/src/js/floatable.ts +380 -133
  31. package/src/js/focus-trap/embedded.ts +149 -64
  32. package/src/js/focus-trap/standalone.ts +4 -4
  33. package/src/js/index.ts +1 -0
  34. package/src/js/popover.ts +50 -120
  35. package/src/js/splitter.ts +250 -103
  36. package/src/js/tooltip.ts +155 -68
  37. package/types/floatable.d.ts +17 -10
  38. package/types/focus-trap/embedded.d.ts +18 -5
  39. package/types/index.d.ts +1 -0
  40. package/types/popover.d.ts +2 -0
  41. package/types/splitter.d.ts +13 -1
  42. package/types/tooltip.d.ts +2 -1
  43. package/dist/js/attributable.cjs +0 -51
  44. package/dist/js/floatable.cjs +0 -176
  45. package/dist/js/focus-trap/embedded.cjs +0 -150
  46. package/dist/js/focus-trap/standalone.cjs +0 -8
  47. package/dist/js/index.cjs +0 -6
  48. package/dist/js/popover.cjs +0 -166
  49. package/dist/js/splitter.cjs +0 -272
  50. package/dist/js/tooltip.cjs +0 -166
  51. package/types/attributable.d.cts +0 -5
  52. package/types/floatable.d.cts +0 -20
  53. package/types/focus-trap/embedded.d.cts +0 -15
  54. package/types/focus-trap/standalone.d.cts +0 -3
  55. package/types/index.d.cts +0 -14
  56. package/types/popover.d.cts +0 -14
  57. package/types/splitter.d.cts +0 -10
  58. 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,40 +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(
54
- toggle,
49
+ this.#floatable = new Floatable({
55
50
  content,
56
- 'position',
57
- 'below-start',
58
- false,
59
- );
60
-
61
- this.#focusTrap = createFocusTrap(content);
62
-
63
- mapped.set(toggle, this.#floatable);
64
- mapped.set(content, this.#floatable);
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);
65
71
  }
66
72
 
67
73
  close(): void {
68
74
  this.hidePopover();
69
75
  }
70
76
 
71
- hidePopover(): void {
72
- if (this.#floatable.active) {
73
- closeAbove(this.#floatable.content);
74
- deactivate(this.#floatable, active, order);
77
+ connectedCallback(): void {
78
+ this.#floatable.enable();
79
+ this.#focusTrap.connect();
80
+ }
75
81
 
76
- 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);
77
90
  }
78
91
  }
79
92
 
@@ -82,8 +95,8 @@ export class OuiPopoverElement extends HTMLElement {
82
95
  }
83
96
 
84
97
  showPopover(): void {
85
- if (!this.#floatable.active) {
86
- toggle(this.#floatable.anchor);
98
+ if (!this.#floatable.active && this.isConnected) {
99
+ this.#floatable.toggle(true);
87
100
  }
88
101
  }
89
102
 
@@ -116,32 +129,6 @@ export class OuiPopoverElement extends HTMLElement {
116
129
 
117
130
  //
118
131
 
119
- function closeAll(): void {
120
- for (const floatable of active) {
121
- deactivate(floatable, active, order);
122
- }
123
- }
124
-
125
- function closeAbove(element: HTMLElement): void {
126
- const index = order.findIndex(
127
- floatable => floatable.anchor === element || floatable.content === element,
128
- );
129
-
130
- if (index === -1 || index === order.length - 1) {
131
- return;
132
- }
133
-
134
- while (index < order.length - 1) {
135
- const floatable = order.pop();
136
-
137
- if (floatable != null) {
138
- deactivate(floatable, active, order);
139
- }
140
- }
141
-
142
- focus(order[index].content);
143
- }
144
-
145
132
  function focus(content: HTMLElement): void {
146
133
  let target = getFocusable(content)[0];
147
134
 
@@ -154,75 +141,18 @@ function focus(content: HTMLElement): void {
154
141
  });
155
142
  }
156
143
 
157
- function onClick(event: MouseEvent): void {
158
- const related = findAncestor(
159
- event.target as never,
160
- '[oui-popover-toggle], [oui-popover-content]',
161
- );
162
-
163
- if (!(related instanceof HTMLElement)) {
164
- closeAll();
165
- } else if (related.hasAttribute('oui-popover-content')) {
166
- closeAbove(related);
167
- } else {
168
- toggle(related);
169
- }
170
- }
171
-
172
- function onKeydown(event: KeyboardEvent): void {
173
- if (event.key !== 'Escape' || order.length === 0) {
174
- return;
175
- }
176
-
177
- const related = findAncestor(event.target as never, '[oui-popover-content]');
178
-
179
- if (!(related instanceof HTMLElement)) {
180
- return;
181
- }
182
-
183
- closeAbove(related);
184
-
185
- const floatable = mapped.get(related);
186
-
187
- if (floatable != null) {
188
- deactivate(floatable, active, order);
189
-
190
- floatable.anchor.focus();
191
- }
192
- }
193
-
194
- function toggle(anchor: HTMLElement): void {
195
- const content = findAncestor(anchor, '[oui-popover-content]');
144
+ //
196
145
 
197
- if (content instanceof HTMLElement) {
198
- closeAbove(content);
199
- } else {
200
- closeAll();
201
- }
146
+ const ATTRIBUTE_ID_PREFIX = 'oui_popover_content_';
202
147
 
203
- const floatable = mapped.get(anchor);
148
+ const POPOVERS: Map<HTMLElement, Floatable> = new Map();
204
149
 
205
- if (floatable == null) {
206
- return;
207
- }
150
+ const SELECTOR = 'oui-popover';
208
151
 
209
- if (floatable.active) {
210
- deactivate(floatable, active, order);
211
- } else {
212
- activate(floatable, active, order);
213
- focus(floatable.content);
214
- }
215
- }
216
-
217
- //
152
+ const SELECTOR_CONTENT = `:scope > [${SELECTOR}-content]`;
218
153
 
219
- customElements.define('oui-popover', OuiPopoverElement);
220
-
221
- on(document, 'click', onClick);
222
- on(document, 'keydown', onKeydown);
154
+ const SELECTOR_TOGGLE = `:scope > [${SELECTOR}-toggle]`;
223
155
 
224
156
  //
225
157
 
226
- const active = new Set<Floatable>();
227
-
228
- const order: Floatable[] = [];
158
+ customElements.define(SELECTOR, OuiPopoverElement);