@oscarpalmer/oui 0.17.0 → 0.19.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 (72) hide show
  1. package/dist/css/badge.css +13 -13
  2. package/dist/css/button.css +9 -9
  3. package/dist/css/color.css +99 -99
  4. package/dist/css/content.css +10 -12
  5. package/dist/css/flex.css +39 -39
  6. package/dist/css/form.css +47 -60
  7. package/dist/css/message.css +10 -6
  8. package/dist/css/reset.css +178 -57
  9. package/dist/css/table.css +4 -4
  10. package/dist/css/tooltip.css +26 -1
  11. package/dist/js/attributable.full.js +36 -0
  12. package/dist/js/attributable.js +30 -45
  13. package/dist/js/floatable.full.js +398 -0
  14. package/dist/js/floatable.js +254 -169
  15. package/dist/js/focus-trap/embedded.full.js +408 -0
  16. package/dist/js/focus-trap/embedded.js +131 -131
  17. package/dist/js/focus-trap/standalone.full.js +447 -0
  18. package/dist/js/focus-trap/standalone.js +4 -4
  19. package/dist/js/index.js +3 -4
  20. package/dist/js/oui.full.js +1573 -0
  21. package/dist/js/popover.full.js +760 -0
  22. package/dist/js/popover.js +84 -163
  23. package/dist/js/splitter.full.js +769 -0
  24. package/dist/js/splitter.js +264 -246
  25. package/dist/js/tooltip.full.js +613 -0
  26. package/dist/js/tooltip.js +160 -151
  27. package/package.json +35 -63
  28. package/src/css/a11y.scss +1 -1
  29. package/src/css/badge.scss +23 -19
  30. package/src/css/button.scss +9 -9
  31. package/src/css/color.scss +99 -99
  32. package/src/css/content.scss +6 -9
  33. package/src/css/flex.scss +21 -20
  34. package/src/css/form.scss +47 -62
  35. package/src/css/message.scss +11 -12
  36. package/src/css/mixins.scss +16 -10
  37. package/src/css/popover.scss +2 -2
  38. package/src/css/reset.scss +181 -55
  39. package/src/css/splitter.scss +15 -13
  40. package/src/css/table.scss +11 -11
  41. package/src/css/tooltip.scss +31 -2
  42. package/src/js/attributable.ts +3 -10
  43. package/src/js/floatable.ts +370 -141
  44. package/src/js/focus-trap/embedded.ts +141 -74
  45. package/src/js/focus-trap/standalone.ts +4 -4
  46. package/src/js/index.ts +1 -0
  47. package/src/js/popover.ts +52 -122
  48. package/src/js/splitter.ts +248 -131
  49. package/src/js/tooltip.ts +143 -68
  50. package/types/floatable.d.ts +17 -10
  51. package/types/focus-trap/embedded.d.ts +18 -5
  52. package/types/index.d.ts +1 -0
  53. package/types/popover.d.ts +2 -0
  54. package/types/splitter.d.ts +13 -1
  55. package/types/tooltip.d.ts +2 -1
  56. package/dist/css/value.css +0 -1
  57. package/dist/js/attributable.cjs +0 -51
  58. package/dist/js/floatable.cjs +0 -176
  59. package/dist/js/focus-trap/embedded.cjs +0 -150
  60. package/dist/js/focus-trap/standalone.cjs +0 -8
  61. package/dist/js/index.cjs +0 -6
  62. package/dist/js/popover.cjs +0 -166
  63. package/dist/js/splitter.cjs +0 -272
  64. package/dist/js/tooltip.cjs +0 -166
  65. package/types/attributable.d.cts +0 -5
  66. package/types/floatable.d.cts +0 -20
  67. package/types/focus-trap/embedded.d.cts +0 -15
  68. package/types/focus-trap/standalone.d.cts +0 -3
  69. package/types/index.d.cts +0 -14
  70. package/types/popover.d.cts +0 -14
  71. package/types/splitter.d.cts +0 -10
  72. package/types/tooltip.d.cts +0 -3
package/src/js/tooltip.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import {isNullableOrWhitespace} from '@oscarpalmer/atoms/is';
2
2
  import {on} from '@oscarpalmer/toretto/event';
3
+ import {findAncestor} from '@oscarpalmer/toretto/find';
3
4
  import {attributable} from './attributable';
4
- import {activate, deactivate, Floatable} from './floatable';
5
+ import {Floatable} from './floatable';
5
6
 
6
7
  type Attributes = {
7
8
  ariaDescribedby: string | null;
@@ -14,47 +15,78 @@ type Content = {
14
15
  };
15
16
 
16
17
  class Tooltip {
17
- abortController = new AbortController();
18
18
  attributes: Attributes;
19
+
19
20
  floatable: Floatable;
20
21
 
22
+ timer: number | undefined;
23
+
21
24
  constructor(anchor: HTMLElement, content: Content) {
22
25
  this.attributes = content.attributes;
23
26
 
24
- this.floatable = new Floatable(
27
+ this.floatable = new Floatable({
25
28
  anchor,
26
- content.element,
27
- `${selector}-position`,
28
- 'vertical',
29
- true,
30
- );
29
+ content: content.element,
30
+ defaultPosition: 'vertical',
31
+ interactive: false,
32
+ preferAbove: true,
33
+ positionAttribute: ATTRIBUTE_POSITION,
34
+ });
31
35
 
32
- initialize(this);
36
+ anchor.insertAdjacentElement('afterend', content.element);
37
+
38
+ TOOLTIPS_ALL.set(content.element, this);
33
39
  }
34
40
 
35
41
  destroy(): void {
36
- deactivate(this.floatable, active);
37
- reset(this.floatable.anchor, this.attributes);
42
+ const {attributes, floatable} = this;
43
+
44
+ TOOLTIPS_ACTIVE.delete(this);
45
+ TOOLTIPS_ALL.delete(floatable.options.anchor);
46
+ TOOLTIPS_ALL.delete(floatable.options.content);
38
47
 
39
- this.abortController.abort();
40
- this.floatable.content.remove();
41
- this.floatable.destroy();
48
+ reset(floatable.options.anchor, attributes);
49
+
50
+ floatable.options.content.remove();
51
+ floatable.destroy();
42
52
 
43
- this.abortController = undefined as never;
44
53
  this.attributes = undefined as never;
45
54
  this.floatable = undefined as never;
46
55
  }
47
56
  }
48
57
 
49
58
  function addTooltip(anchor: HTMLElement): void {
50
- if (tooltips.has(anchor)) {
59
+ if (TOOLTIPS_ALL.has(anchor)) {
51
60
  return;
52
61
  }
53
62
 
54
63
  const content = getContent(anchor);
55
64
 
56
65
  if (content != null) {
57
- tooltips.set(anchor, new Tooltip(anchor, content));
66
+ TOOLTIPS_ALL.set(anchor, new Tooltip(anchor, content));
67
+ }
68
+ }
69
+
70
+ function closeTooltips(next: Tooltip | undefined): void {
71
+ const tooltips = [...TOOLTIPS_ACTIVE];
72
+
73
+ for (const active of tooltips) {
74
+ if (active === next) {
75
+ continue;
76
+ }
77
+
78
+ if (active.timer != null) {
79
+ clearTimeout(active.timer);
80
+ }
81
+
82
+ active.floatable.options.content.removeAttribute('oui-tooltip-content-active');
83
+
84
+ requestAnimationFrame(() => {
85
+ active.timer = setTimeout(() => {
86
+ TOOLTIPS_ACTIVE.delete(active);
87
+ active.floatable.toggle(false);
88
+ }, delay) as never;
89
+ });
58
90
  }
59
91
  }
60
92
 
@@ -119,7 +151,7 @@ function getContent(anchor: HTMLElement): Content | undefined {
119
151
  }
120
152
 
121
153
  function getElements(attribute: string | null): HTMLElement[] {
122
- const ids = attribute?.split(/\s+/) ?? [];
154
+ const ids = attribute?.split(EXPRESSION_WHITESPACE) ?? [];
123
155
  const elements: HTMLElement[] = [];
124
156
 
125
157
  for (const id of ids) {
@@ -144,57 +176,82 @@ function getElements(attribute: string | null): HTMLElement[] {
144
176
  function getWrapper(anchor: HTMLElement): HTMLElement {
145
177
  const wrapper = document.createElement('div');
146
178
 
147
- wrapper.setAttribute(`${selector}-content`, '');
179
+ wrapper.setAttribute(ATTRIBUTE_CONTENT, '');
148
180
 
149
- wrapper.className = anchor.getAttribute(`${selector}-class`) ?? '';
181
+ wrapper.className = anchor.getAttribute(ATTRIBUTE_CLASS) ?? '';
150
182
  wrapper.hidden = true;
151
- wrapper.id = `${selector}-${++index}`;
183
+ wrapper.id = `${SELECTOR}-${++index}`;
152
184
  wrapper.role = 'tooltip';
153
185
  wrapper.tabIndex = -1;
154
186
 
155
187
  return wrapper;
156
188
  }
157
189
 
158
- function initialize(tooltip: Tooltip): void {
159
- const {abortController, floatable} = tooltip;
160
- const {anchor, content} = floatable;
161
-
162
- anchor.insertAdjacentElement('afterend', content);
163
-
164
- const elements = [anchor, content];
165
-
166
- for (const element of elements) {
167
- for (const event of activateEvents) {
168
- on(
169
- element,
170
- event,
171
- () => {
172
- activate(floatable, active, undefined, 250);
173
- },
174
- {
175
- signal: abortController.signal,
176
- },
177
- );
190
+ function onActivate(event: Event): void {
191
+ onToggle(event, true);
192
+ }
193
+
194
+ function onClick(event: Event): void {
195
+ if (findAncestor(event.target as HTMLElement, SELECTOR_CONTENT) != null) {
196
+ event.stopPropagation();
197
+ }
198
+ }
199
+
200
+ function onDeactivate(event: Event): void {
201
+ onToggle(event, false);
202
+ }
203
+
204
+ function onToggle(event: Event, activate: boolean): void {
205
+ if (toggle != null) {
206
+ cancelAnimationFrame(toggle);
207
+ }
208
+
209
+ toggle = requestAnimationFrame(() => {
210
+ toggle = undefined;
211
+
212
+ const element = findAncestor(event.target as HTMLElement, SELECTOR_FULL) as HTMLElement;
213
+
214
+ const tooltip = TOOLTIPS_ALL.get(element);
215
+
216
+ if (TOOLTIPS_ACTIVE.size > 0) {
217
+ closeTooltips(tooltip);
178
218
  }
179
219
 
180
- for (const event of deactivateEvents) {
181
- on(
182
- element,
183
- event,
184
- () => {
185
- deactivate(floatable, active, undefined, 250);
186
- },
187
- {
188
- signal: abortController.signal,
189
- },
190
- );
220
+ if (
221
+ tooltip == null ||
222
+ tooltip.floatable.options.content.hasAttribute('oui-tooltip-content-active') === activate
223
+ ) {
224
+ return;
191
225
  }
192
- }
226
+
227
+ if (activate) {
228
+ if (tooltip.timer != null) {
229
+ clearTimeout(tooltip.timer);
230
+ }
231
+
232
+ TOOLTIPS_ACTIVE.add(tooltip);
233
+ tooltip.floatable.toggle(true);
234
+
235
+ requestAnimationFrame(() => {
236
+ tooltip.floatable.options.content.setAttribute('oui-tooltip-content-active', '');
237
+ });
238
+
239
+ return;
240
+ }
241
+
242
+ tooltip.floatable.options.content.removeAttribute('oui-tooltip-content-active');
243
+
244
+ tooltip.timer ??= setTimeout(() => {
245
+ TOOLTIPS_ACTIVE.delete(tooltip);
246
+ tooltip.floatable.toggle(false);
247
+ }, delay) as never;
248
+ });
193
249
  }
194
250
 
195
251
  function removeTooltip(element: HTMLElement): void {
196
- tooltips.get(element)?.destroy();
197
- tooltips.delete(element);
252
+ if (!element.hasAttribute(ATTRIBUTE_CONTENT)) {
253
+ TOOLTIPS_ALL.get(element)?.destroy();
254
+ }
198
255
  }
199
256
 
200
257
  function reset(anchor: HTMLElement, attributes: Attributes): void {
@@ -205,28 +262,46 @@ function reset(anchor: HTMLElement, attributes: Attributes): void {
205
262
  }
206
263
  }
207
264
 
265
+ function setDelay(value: number): void {
266
+ delay = typeof value === 'number' && value >= 0 ? value : delay;
267
+ }
268
+
208
269
  //
209
270
 
210
- const active = new Set<Floatable>();
271
+ const SELECTOR = 'oui-tooltip';
272
+
273
+ const ATTRIBUTE_CLASS = `${SELECTOR}-class`;
274
+
275
+ const ATTRIBUTE_CONTENT = `${SELECTOR}-content`;
276
+
277
+ const ATTRIBUTE_POSITION = `${SELECTOR}-position`;
278
+
279
+ const SELECTOR_CONTENT = `[${ATTRIBUTE_CONTENT}]`;
280
+
281
+ const SELECTOR_FULL = `[${SELECTOR}], [${ATTRIBUTE_CONTENT}]`;
211
282
 
212
- const activateEvents = ['focus', 'mouseenter', 'touchstart'];
283
+ const EXPRESSION_WHITESPACE = /\s+/;
213
284
 
214
- const deactivateEvents = ['blur', 'mouseleave'];
285
+ const TOOLTIPS_ACTIVE: Set<Tooltip> = new Set();
215
286
 
216
- const selector = 'oui-tooltip';
287
+ const TOOLTIPS_ALL: WeakMap<HTMLElement, Tooltip> = new WeakMap();
217
288
 
218
- const tooltips = new WeakMap<HTMLElement, Tooltip>();
289
+ let delay = 250;
219
290
 
220
291
  let index = 0;
221
292
 
293
+ let toggle: DOMHighResTimeStamp | undefined;
294
+
222
295
  //
223
296
 
224
- attributable(selector, addTooltip, removeTooltip);
297
+ attributable(SELECTOR, addTooltip, removeTooltip);
225
298
 
226
- on(document, 'keydown', event => {
227
- if (event.key === 'Escape') {
228
- for (const floatable of active) {
229
- deactivate(floatable, active);
230
- }
231
- }
232
- });
299
+ on(document, 'click', onClick, {capture: true});
300
+ on(document, 'focusin', onActivate);
301
+ on(document, 'focusout', onDeactivate);
302
+ on(document, 'mousemove', onActivate);
303
+ on(document, 'touchstart', onActivate);
304
+
305
+ //
306
+
307
+ export {setDelay};
@@ -1,17 +1,24 @@
1
1
  export declare class Floatable {
2
- anchor: HTMLElement;
3
- content: HTMLElement;
4
- readonly attribute: string;
5
- readonly position: Position;
6
- readonly preferAbove: boolean;
7
- activate: number | undefined;
2
+ readonly options: Options;
8
3
  active: boolean;
9
- deactivate: number | undefined;
4
+ disabled: boolean;
10
5
  frame: DOMHighResTimeStamp | undefined;
11
- constructor(anchor: HTMLElement, content: HTMLElement, attribute: string, position: Position, preferAbove: boolean);
6
+ ignoreFocus: boolean;
7
+ constructor(options: Options);
12
8
  destroy(): void;
9
+ disable(): void;
10
+ enable(): void;
11
+ toggle(active: boolean, ignoreFocus?: boolean): void;
13
12
  }
13
+ type Options = {
14
+ anchor: HTMLElement;
15
+ content: HTMLElement;
16
+ defaultPosition: Position;
17
+ interactive: boolean;
18
+ positionAttribute: string;
19
+ preferAbove: boolean;
20
+ onAfter?: (active: boolean) => void;
21
+ };
14
22
  type Position = 'above' | 'above-end' | 'above-start' | 'below' | 'below-end' | 'below-start' | 'end' | 'end-bottom' | 'end-top' | 'horizontal' | 'horizontal-bottom' | 'horizontal-top' | 'start' | 'start-bottom' | 'start-top' | 'vertical' | 'vertical-end' | 'vertical-start';
15
- export declare function activate(floatable: Floatable, active: Set<Floatable>, order?: Floatable[], time?: number): void;
16
- export declare function deactivate(floatable: Floatable, active: Set<Floatable>, order?: Floatable[], time?: number): void;
23
+ export declare function deactivate(floatable: Floatable): void;
17
24
  export {};
@@ -1,11 +1,24 @@
1
1
  export declare class FocusTrap {
2
+ disabled: boolean;
3
+ connected: boolean;
2
4
  element: HTMLElement;
3
- active: boolean;
4
- constructor(element: HTMLElement);
5
+ embedded: boolean;
6
+ get contain(): boolean;
7
+ get noescape(): boolean;
8
+ constructor(element: HTMLElement, options?: Options);
9
+ connect(): void;
5
10
  destroy(): void;
6
11
  disable(): void;
12
+ disconnect(): void;
7
13
  enable(): void;
14
+ focus(last: boolean): void;
8
15
  }
9
- export declare function createFocusTrap(element: HTMLElement): FocusTrap;
10
- export declare const focusTraps: WeakMap<HTMLElement, FocusTrap>;
11
- export declare const selector = "oui-focus-trap";
16
+ type Options = {
17
+ noescape: boolean;
18
+ };
19
+ export declare function createFocusTrap(element: HTMLElement, options?: Options): FocusTrap;
20
+ export declare const FOCUS_TRAP_SELECTOR = "oui-focus-trap";
21
+ export declare const FOCUS_TRAP_CONTAIN = "oui-focus-trap-contain";
22
+ export declare const FOCUS_TRAP_NOESCAPE = "oui-focus-trap-noescape";
23
+ export declare const FOCUSTRAPS_ALL: WeakMap<HTMLElement, FocusTrap>;
24
+ export {};
package/types/index.d.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';
@@ -7,6 +7,8 @@ export declare class OuiPopoverElement extends HTMLElement {
7
7
  #private;
8
8
  constructor();
9
9
  close(): void;
10
+ connectedCallback(): void;
11
+ disconnectedCallback(): void;
10
12
  hidePopover(): void;
11
13
  open(): void;
12
14
  showPopover(): void;
@@ -1,11 +1,23 @@
1
1
  declare global {
2
2
  interface HTMLElementTagNameMap {
3
- 'oui-splitter': OuiSplitterElement;
3
+ [SELECTOR]: OuiSplitterElement;
4
4
  }
5
5
  }
6
6
  export declare class OuiSplitterElement extends HTMLElement {
7
7
  #private;
8
+ static readonly observedAttributes: string[];
9
+ get max(): number;
10
+ set max(value: number);
11
+ get min(): number;
12
+ set min(value: number);
13
+ get size(): number;
14
+ set size(value: number);
15
+ get type(): string;
16
+ set type(value: string);
8
17
  constructor();
9
18
  connectedCallback(): void;
10
19
  disconnectedCallback(): void;
20
+ attributeChangedCallback(name: string): void;
11
21
  }
22
+ declare const SELECTOR = "oui-splitter";
23
+ export {};
@@ -1 +1,2 @@
1
- export {};
1
+ declare function setDelay(value: number): void;
2
+ export { setDelay };
@@ -1 +0,0 @@
1
-
@@ -1,51 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- function attributable(attribute, add, remove) {
4
- const observer = new MutationObserver((entries) => {
5
- const { length } = entries;
6
- for (let index = 0; index < length; index += 1) {
7
- const entry = entries[index];
8
- if (entry.type === "attributes" && entry.target instanceof HTMLElement) {
9
- if (entry.target.hasAttribute(attribute)) {
10
- handleAdded(attribute, [entry.target], add);
11
- } else {
12
- handleRemoved([entry.target], remove);
13
- }
14
- } else if (entry.type === "childList") {
15
- handleAdded(attribute, entry.addedNodes, add);
16
- handleRemoved(entry.removedNodes, remove);
17
- }
18
- }
19
- });
20
- observer.observe(document, {
21
- attributeFilter: [attribute],
22
- attributes: true,
23
- childList: true,
24
- subtree: true
25
- });
26
- requestAnimationFrame(() => {
27
- handleAdded(attribute, document.querySelectorAll(`[${attribute}]`), add);
28
- });
29
- }
30
- function handleAdded(attribute, nodes, add) {
31
- const elements = [...nodes].filter(
32
- (node) => node instanceof HTMLElement
33
- );
34
- const { length } = elements;
35
- for (let index = 0; index < length; index += 1) {
36
- const element = elements[index];
37
- if (element.hasAttribute(attribute)) {
38
- add(element);
39
- }
40
- }
41
- }
42
- function handleRemoved(nodes, remove) {
43
- const elements = [...nodes].filter(
44
- (node) => node instanceof HTMLElement
45
- );
46
- const { length } = elements;
47
- for (let index = 0; index < length; index += 1) {
48
- remove(elements[index]);
49
- }
50
- }
51
- exports.attributable = attributable;
@@ -1,176 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- class Floatable {
4
- constructor(anchor, content, attribute, position, preferAbove) {
5
- this.anchor = anchor;
6
- this.content = content;
7
- this.attribute = attribute;
8
- this.position = position;
9
- this.preferAbove = preferAbove;
10
- setStyles(content);
11
- }
12
- activate;
13
- active = false;
14
- deactivate;
15
- frame;
16
- destroy() {
17
- this.activate = void 0;
18
- this.deactivate = void 0;
19
- this.frame = void 0;
20
- this.anchor = void 0;
21
- this.content = void 0;
22
- }
23
- }
24
- function activate(floatable, active, order, time) {
25
- stop(floatable);
26
- if (floatable.active) {
27
- return;
28
- }
29
- if (time == null || time === 0) {
30
- onActivate(floatable, active, order);
31
- } else {
32
- floatable.activate = +setTimeout(() => {
33
- onActivate(floatable, active, order);
34
- }, time);
35
- }
36
- }
37
- function deactivate(floatable, active, order, time) {
38
- stop(floatable);
39
- if (!floatable.active) {
40
- return;
41
- }
42
- if (time == null || time === 0) {
43
- onDeactivate(floatable, active, order);
44
- } else {
45
- floatable.deactivate = +setTimeout(() => {
46
- onDeactivate(floatable, active, order);
47
- }, time);
48
- }
49
- }
50
- function getX(anchor, content, position) {
51
- if (position.endsWith("-end")) {
52
- const end = anchor.right - content.width;
53
- return end - margin < 0 ? margin : end;
54
- }
55
- if (position.endsWith("-start")) {
56
- const start = anchor.left;
57
- return start + content.width + margin > window.innerWidth ? window.innerWidth - content.width - margin : start;
58
- }
59
- if (position.startsWith("end")) {
60
- return anchor.right + margin;
61
- }
62
- if (position.startsWith("start")) {
63
- return anchor.left - content.width - margin;
64
- }
65
- if (position.startsWith("horizontal")) {
66
- if (anchor.right + content.width + margin <= window.innerWidth) {
67
- return anchor.right + margin;
68
- }
69
- return anchor.left - content.width - margin;
70
- }
71
- return anchor.left + (anchor.width - content.width) / 2;
72
- }
73
- function getY(anchor, content, position, preferAbove) {
74
- if (position.startsWith("above")) {
75
- return anchor.top - content.height - margin;
76
- }
77
- if (position.startsWith("below")) {
78
- return anchor.bottom + margin;
79
- }
80
- if (position.endsWith("bottom")) {
81
- const bottom = anchor.bottom - content.height;
82
- return bottom + margin < 0 ? margin : bottom;
83
- }
84
- if (position.endsWith("top")) {
85
- const top = anchor.top;
86
- return top + content.height + margin > window.innerHeight ? window.innerHeight - content.height - margin : top;
87
- }
88
- if (position.startsWith("vertical")) {
89
- if (preferAbove && anchor.top - content.height - margin >= 0) {
90
- return anchor.top - content.height - margin;
91
- }
92
- if (anchor.bottom + content.height + margin <= document.body.clientHeight) {
93
- return anchor.bottom + margin;
94
- }
95
- return anchor.top - content.height - margin;
96
- }
97
- return anchor.top + (anchor.height - content.height) / 2;
98
- }
99
- function onActivate(floatable, active, order) {
100
- floatable.active = true;
101
- active.add(floatable);
102
- if (order != null) {
103
- order.push(floatable);
104
- }
105
- document.body.append(floatable.content);
106
- floatable.content.hidden = false;
107
- update(floatable);
108
- }
109
- function onDeactivate(floatable, active, order) {
110
- floatable.active = false;
111
- active.delete(floatable);
112
- const index = order?.indexOf(floatable) ?? -1;
113
- if (index > -1) {
114
- order?.splice(index, 1);
115
- }
116
- floatable.content.hidden = true;
117
- floatable.anchor.insertAdjacentElement("afterend", floatable.content);
118
- }
119
- function update(floatable) {
120
- let position = floatable.anchor.getAttribute(floatable.attribute)?.trim() ?? floatable.position;
121
- if (!positions.has(position)) {
122
- position = floatable.position;
123
- }
124
- function run() {
125
- const anchor = floatable.anchor.getBoundingClientRect();
126
- const content = floatable.content.getBoundingClientRect();
127
- const left = getX(anchor, content, position);
128
- const top = getY(anchor, content, position, floatable.preferAbove);
129
- floatable.content.style.inset = `${top}px auto auto ${left}px`;
130
- floatable.frame = requestAnimationFrame(run);
131
- }
132
- floatable.frame = requestAnimationFrame(run);
133
- }
134
- function setStyles(content) {
135
- content.style.position = "fixed";
136
- content.style.inset = "0 auto auto 0";
137
- content.style.zIndex = "10";
138
- }
139
- function stop(floatable) {
140
- if (floatable.frame != null) {
141
- cancelAnimationFrame(floatable.frame);
142
- }
143
- if (floatable.activate != null) {
144
- clearTimeout(floatable.activate);
145
- }
146
- if (floatable.deactivate != null) {
147
- clearTimeout(floatable.deactivate);
148
- }
149
- floatable.activate = void 0;
150
- floatable.deactivate = void 0;
151
- floatable.frame = void 0;
152
- }
153
- const margin = Number.parseInt(getComputedStyle(document.documentElement).fontSize, 10) / 2;
154
- const positions = /* @__PURE__ */ new Set([
155
- "above",
156
- "above-end",
157
- "above-start",
158
- "below",
159
- "below-end",
160
- "below-start",
161
- "end",
162
- "end-bottom",
163
- "end-top",
164
- "horizontal",
165
- "horizontal-bottom",
166
- "horizontal-top",
167
- "start",
168
- "start-bottom",
169
- "start-top",
170
- "vertical",
171
- "vertical-end",
172
- "vertical-start"
173
- ]);
174
- exports.Floatable = Floatable;
175
- exports.activate = activate;
176
- exports.deactivate = deactivate;