@oscarpalmer/oui 0.18.0 → 0.20.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 (67) hide show
  1. package/dist/css/a11y.css +0 -1
  2. package/dist/css/badge.css +10 -10
  3. package/dist/css/button.css +9 -9
  4. package/dist/css/color.css +99 -99
  5. package/dist/css/content.css +1 -1
  6. package/dist/css/flex.css +39 -39
  7. package/dist/css/form.css +29 -57
  8. package/dist/css/message.css +6 -6
  9. package/dist/css/popover.css +22 -0
  10. package/dist/css/reset.css +11 -10
  11. package/dist/css/table.css +5 -5
  12. package/dist/css/tooltip.css +61 -1
  13. package/dist/js/attributable.d.mts +4 -0
  14. package/dist/js/{attributable.js → attributable.mjs} +8 -1
  15. package/dist/js/floatable.d.mts +26 -0
  16. package/dist/js/{floatable.js → floatable.mjs} +73 -50
  17. package/dist/js/focus-trap/embedded.d.mts +26 -0
  18. package/dist/js/focus-trap/{embedded.js → embedded.mjs} +10 -8
  19. package/dist/js/focus-trap/standalone.d.mts +1 -0
  20. package/dist/js/focus-trap/{standalone.js → standalone.mjs} +5 -2
  21. package/dist/js/index.d.mts +4 -0
  22. package/dist/js/index.mjs +5 -0
  23. package/dist/js/popover.d.mts +20 -0
  24. package/dist/js/{popover.js → popover.mjs} +11 -9
  25. package/dist/js/splitter.d.mts +25 -0
  26. package/dist/js/{splitter.js → splitter.mjs} +60 -58
  27. package/dist/js/tooltip.d.mts +4 -0
  28. package/dist/js/{tooltip.js → tooltip.mjs} +21 -19
  29. package/package.json +65 -70
  30. package/src/css/a11y.scss +1 -1
  31. package/src/css/badge.scss +23 -19
  32. package/src/css/button.scss +9 -9
  33. package/src/css/color.scss +99 -99
  34. package/src/css/content.scss +6 -8
  35. package/src/css/flex.scss +21 -20
  36. package/src/css/form.scss +37 -60
  37. package/src/css/message.scss +8 -12
  38. package/src/css/mixins.scss +41 -13
  39. package/src/css/popover.scss +7 -2
  40. package/src/css/reset.scss +18 -18
  41. package/src/css/splitter.scss +15 -13
  42. package/src/css/table.scss +12 -12
  43. package/src/css/tooltip.scss +79 -4
  44. package/src/js/attributable.ts +14 -11
  45. package/src/js/floatable.ts +134 -74
  46. package/src/js/focus-trap/embedded.ts +7 -31
  47. package/src/js/popover.ts +3 -3
  48. package/src/js/splitter.ts +10 -43
  49. package/src/js/tooltip.ts +8 -20
  50. package/dist/css/value.css +0 -1
  51. package/dist/js/attributable.full.js +0 -48
  52. package/dist/js/floatable.full.js +0 -413
  53. package/dist/js/focus-trap/embedded.full.js +0 -351
  54. package/dist/js/focus-trap/standalone.full.js +0 -402
  55. package/dist/js/index.js +0 -5
  56. package/dist/js/oui.full.js +0 -1596
  57. package/dist/js/popover.full.js +0 -822
  58. package/dist/js/splitter.full.js +0 -605
  59. package/dist/js/tooltip.full.js +0 -679
  60. package/types/attributable.d.ts +0 -1
  61. package/types/floatable.d.ts +0 -24
  62. package/types/focus-trap/embedded.d.ts +0 -24
  63. package/types/focus-trap/standalone.d.ts +0 -1
  64. package/types/index.d.ts +0 -4
  65. package/types/popover.d.ts +0 -17
  66. package/types/splitter.d.ts +0 -23
  67. package/types/tooltip.d.ts +0 -2
@@ -7,7 +7,6 @@ import {type StyleToggler, toggleStyles} from '@oscarpalmer/toretto/style';
7
7
  import supportsTouch from '@oscarpalmer/toretto/touch';
8
8
 
9
9
  declare global {
10
- // biome-ignore lint/nursery/useConsistentTypeDefinitions: Extending builtins to allow custom element type help
11
10
  interface HTMLElementTagNameMap {
12
11
  [SELECTOR]: OuiSplitterElement;
13
12
  }
@@ -57,9 +56,7 @@ export class OuiSplitterElement extends HTMLElement {
57
56
  constructor() {
58
57
  super();
59
58
 
60
- const panels = [...this.children].filter(
61
- child => child instanceof HTMLElement,
62
- );
59
+ const panels = [...this.children].filter(child => child instanceof HTMLElement);
63
60
 
64
61
  if (panels.length !== 2) {
65
62
  throw new Error(`${SELECTOR} must have exactly two panels.`);
@@ -242,9 +239,7 @@ function getTypes(splitter: Splitter, width?: number, height?: number): Types {
242
239
  if (type === 'auto') {
243
240
  return {
244
241
  auto: true,
245
- horizontal:
246
- (height ?? splitter.rectangle.height) >
247
- (width ?? splitter.rectangle.width),
242
+ horizontal: (height ?? splitter.rectangle.height) > (width ?? splitter.rectangle.width),
248
243
  };
249
244
  }
250
245
 
@@ -254,11 +249,7 @@ function getTypes(splitter: Splitter, width?: number, height?: number): Types {
254
249
  };
255
250
  }
256
251
 
257
- function getValue(
258
- element: HTMLElement,
259
- name: string,
260
- defaultValue: number,
261
- ): number {
252
+ function getValue(element: HTMLElement, name: string, defaultValue: number): number {
262
253
  const value = element.getAttribute(name);
263
254
 
264
255
  if (isNullableOrWhitespace(value)) {
@@ -288,11 +279,7 @@ function getValues(element: OuiSplitterElement): Values {
288
279
  },
289
280
  };
290
281
 
291
- const value = getContained(
292
- values.min,
293
- getValue(element, 'size', values.now.current),
294
- values.max,
295
- );
282
+ const value = getContained(values.min, getValue(element, 'size', values.now.current), values.max);
296
283
 
297
284
  values.now.current = value;
298
285
  values.now.previous = value;
@@ -336,10 +323,7 @@ function onKeydown(event: KeyboardEvent): void {
336
323
 
337
324
  function onNavigate(event: KeyboardEvent): void {
338
325
  const splitter = MAPPED_ELEMENTS.get(
339
- findAncestor(
340
- event.target as never,
341
- '[oui-splitter-separator]',
342
- ) as HTMLSpanElement,
326
+ findAncestor(event, '[oui-splitter-separator]') as HTMLSpanElement,
343
327
  );
344
328
 
345
329
  if (splitter == null) {
@@ -365,11 +349,7 @@ function onNavigate(event: KeyboardEvent): void {
365
349
 
366
350
  setSize(
367
351
  splitter,
368
- getContained(
369
- values.min,
370
- values.now.current + offset * NAVIGATION_MODIFIER,
371
- values.max,
372
- ),
352
+ getContained(values.min, values.now.current + offset * NAVIGATION_MODIFIER, values.max),
373
353
  true,
374
354
  );
375
355
  }
@@ -387,11 +367,7 @@ function onObservation(entries: ResizeObserverEntry[]): void {
387
367
  return;
388
368
  }
389
369
 
390
- splitter.types = getTypes(
391
- splitter,
392
- entry.contentRect.width,
393
- entry.contentRect.height,
394
- );
370
+ splitter.types = getTypes(splitter, entry.contentRect.width, entry.contentRect.height);
395
371
 
396
372
  if (splitter.types.horizontal) {
397
373
  splitter.element.setAttribute(ATTRIBUTE_HORIZONTAL, '');
@@ -414,9 +390,7 @@ function onPointerdown(event: Event): void {
414
390
  return;
415
391
  }
416
392
 
417
- splitter = MAPPED_ELEMENTS.get(
418
- findAncestor(event.target as never, SELECTOR_HANDLE) as HTMLSpanElement,
419
- );
393
+ splitter = MAPPED_ELEMENTS.get(findAncestor(event, SELECTOR_HANDLE) as HTMLSpanElement);
420
394
 
421
395
  if (splitter == null) {
422
396
  return;
@@ -468,10 +442,7 @@ function setAriaValue(splitter: Splitter): void {
468
442
  splitter.separator.setAttribute('aria-valuemax', String(splitter.values.max));
469
443
  splitter.separator.setAttribute('aria-valuemin', String(splitter.values.min));
470
444
 
471
- splitter.separator.setAttribute(
472
- 'aria-valuenow',
473
- String(splitter.values.now.current),
474
- );
445
+ splitter.separator.setAttribute('aria-valuenow', String(splitter.values.now.current));
475
446
  }
476
447
 
477
448
  function setSize(splitter: Splitter, size: number, previous?: boolean): void {
@@ -506,11 +477,7 @@ const KEYS_NEGATIVE: Set<string> = new Set(['ArrowLeft', 'ArrowUp']);
506
477
 
507
478
  const KEYS_VERTICAL: Set<string> = new Set(['ArrowLeft', 'ArrowRight']);
508
479
 
509
- const KEYS_ALL: Set<string> = new Set([
510
- ...KEYS_ABSOLUTE,
511
- ...KEYS_HORIZONTAL,
512
- ...KEYS_VERTICAL,
513
- ]);
480
+ const KEYS_ALL: Set<string> = new Set([...KEYS_ABSOLUTE, ...KEYS_HORIZONTAL, ...KEYS_VERTICAL]);
514
481
 
515
482
  const MAPPED_ELEMENTS: WeakMap<HTMLElement, Splitter> = new WeakMap();
516
483
 
package/src/js/tooltip.ts CHANGED
@@ -79,14 +79,12 @@ function closeTooltips(next: Tooltip | undefined): void {
79
79
  clearTimeout(active.timer);
80
80
  }
81
81
 
82
- active.floatable.options.content.removeAttribute(
83
- 'oui-tooltip-content-active',
84
- );
82
+ active.floatable?.options.content.removeAttribute('oui-tooltip-content-active');
85
83
 
86
84
  requestAnimationFrame(() => {
87
85
  active.timer = setTimeout(() => {
88
86
  TOOLTIPS_ACTIVE.delete(active);
89
- active.floatable.toggle(false);
87
+ active.floatable?.toggle(false);
90
88
  }, delay) as never;
91
89
  });
92
90
  }
@@ -194,7 +192,7 @@ function onActivate(event: Event): void {
194
192
  }
195
193
 
196
194
  function onClick(event: Event): void {
197
- if (findAncestor(event.target as HTMLElement, SELECTOR_CONTENT) != null) {
195
+ if (findAncestor(event, SELECTOR_CONTENT) != null) {
198
196
  event.stopPropagation();
199
197
  }
200
198
  }
@@ -211,10 +209,7 @@ function onToggle(event: Event, activate: boolean): void {
211
209
  toggle = requestAnimationFrame(() => {
212
210
  toggle = undefined;
213
211
 
214
- const element = findAncestor(
215
- event.target as HTMLElement,
216
- SELECTOR_FULL,
217
- ) as HTMLElement;
212
+ const element = findAncestor(event, SELECTOR_FULL) as HTMLElement;
218
213
 
219
214
  const tooltip = TOOLTIPS_ALL.get(element);
220
215
 
@@ -224,9 +219,7 @@ function onToggle(event: Event, activate: boolean): void {
224
219
 
225
220
  if (
226
221
  tooltip == null ||
227
- tooltip.floatable.options.content.hasAttribute(
228
- 'oui-tooltip-content-active',
229
- ) === activate
222
+ tooltip.floatable.options.content.hasAttribute('oui-tooltip-content-active') === activate
230
223
  ) {
231
224
  return;
232
225
  }
@@ -240,18 +233,13 @@ function onToggle(event: Event, activate: boolean): void {
240
233
  tooltip.floatable.toggle(true);
241
234
 
242
235
  requestAnimationFrame(() => {
243
- tooltip.floatable.options.content.setAttribute(
244
- 'oui-tooltip-content-active',
245
- '',
246
- );
236
+ tooltip.floatable.options.content.setAttribute('oui-tooltip-content-active', '');
247
237
  });
248
238
 
249
239
  return;
250
240
  }
251
241
 
252
- tooltip.floatable.options.content.removeAttribute(
253
- 'oui-tooltip-content-active',
254
- );
242
+ tooltip.floatable.options.content.removeAttribute('oui-tooltip-content-active');
255
243
 
256
244
  tooltip.timer ??= setTimeout(() => {
257
245
  TOOLTIPS_ACTIVE.delete(tooltip);
@@ -298,7 +286,7 @@ const TOOLTIPS_ACTIVE: Set<Tooltip> = new Set();
298
286
 
299
287
  const TOOLTIPS_ALL: WeakMap<HTMLElement, Tooltip> = new WeakMap();
300
288
 
301
- let delay = 250;
289
+ let delay = 500;
302
290
 
303
291
  let index = 0;
304
292
 
@@ -1 +0,0 @@
1
-
@@ -1,48 +0,0 @@
1
- function attributable(attribute, add, remove) {
2
- const observer = new MutationObserver(entries => {
3
- const { length } = entries;
4
- for (let index = 0; index < length; index += 1) {
5
- const entry = entries[index];
6
- if (entry.type === 'attributes' && entry.target instanceof HTMLElement) {
7
- if (entry.target.hasAttribute(attribute)) {
8
- handleAdded(attribute, [entry.target], add);
9
- }
10
- else {
11
- handleRemoved([entry.target], remove);
12
- }
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(node => node instanceof HTMLElement);
32
- const { length } = elements;
33
- for (let index = 0; index < length; index += 1) {
34
- const element = elements[index];
35
- if (element.hasAttribute(attribute)) {
36
- add(element);
37
- }
38
- }
39
- }
40
- function handleRemoved(nodes, remove) {
41
- const elements = [...nodes].filter(node => node instanceof HTMLElement);
42
- const { length } = elements;
43
- for (let index = 0; index < length; index += 1) {
44
- remove(elements[index]);
45
- }
46
- }
47
-
48
- export { attributable };
@@ -1,413 +0,0 @@
1
- function isEventTarget(value) {
2
- return typeof value === "object" && value != null && typeof value.addEventListener === "function" && typeof value.removeEventListener === "function" && typeof value.dispatchEvent === "function";
3
- }
4
-
5
- function getBoolean(value, defaultValue) {
6
- return defaultValue ?? false;
7
- }
8
-
9
- function calculate() {
10
- return new Promise((resolve) => {
11
- const values = [];
12
- let last;
13
- function step(now) {
14
- if (last != null) values.push(now - last);
15
- last = now;
16
- if (values.length >= CALCULATION_TOTAL) {
17
- const median = values.sort().slice(2, -2).reduce((first, second) => first + second, 0) / (values.length - CALCULATION_TRIM);
18
- resolve(median);
19
- } else requestAnimationFrame(step);
20
- }
21
- requestAnimationFrame(step);
22
- });
23
- }
24
- function noop() {}
25
- var CALCULATION_TOTAL = 10;
26
- var CALCULATION_TRIM = 4;
27
- calculate().then((value) => {
28
- });
29
-
30
- function createEventOptions(options) {
31
- return {
32
- capture: getBoolean(),
33
- once: getBoolean(),
34
- passive: getBoolean(options?.passive, true),
35
- signal: options?.signal
36
- };
37
- }
38
- function on(target, type, listener, options) {
39
- if (!isEventTarget(target) || typeof type !== "string" || typeof listener !== "function") return noop;
40
- const extended = createEventOptions(options);
41
- target.addEventListener(type, listener, extended);
42
- return () => {
43
- target.removeEventListener(type, listener, extended);
44
- };
45
- }
46
-
47
- function findAncestor(origin, selector) {
48
- if (!(origin instanceof Element) || selector == null) return null;
49
- if (typeof selector === "string") {
50
- if (origin.matches?.(selector)) return origin;
51
- return origin.closest(selector);
52
- }
53
- if (typeof selector !== "function") return null;
54
- if (selector(origin)) return origin;
55
- let parent = origin.parentElement;
56
- while (parent != null && !selector(parent)) {
57
- if (parent === document.body) return null;
58
- parent = parent.parentElement;
59
- }
60
- return parent;
61
- }
62
-
63
- class Floatable {
64
- options;
65
- active = false;
66
- disabled = false;
67
- frame;
68
- ignoreFocus = false;
69
- constructor(options) {
70
- this.options = options;
71
- initialize(this);
72
- }
73
- destroy() {
74
- stop(this);
75
- const state = getState();
76
- state?.active.delete(this);
77
- state?.mapped.delete(this.options.anchor);
78
- state?.mapped.delete(this.options.content);
79
- this.options.anchor = undefined;
80
- this.options.content = undefined;
81
- }
82
- disable() {
83
- if (this.disabled) {
84
- return;
85
- }
86
- this.disabled = true;
87
- stop(this);
88
- getState()?.active.delete(this);
89
- }
90
- enable() {
91
- if (!this.disabled) {
92
- return;
93
- }
94
- this.disabled = false;
95
- initialize(this);
96
- }
97
- toggle(active, ignoreFocus) {
98
- if (this.disabled || this.active === active) {
99
- return;
100
- }
101
- const state = getState();
102
- if (state == null) {
103
- return;
104
- }
105
- this.ignoreFocus = !active && (ignoreFocus ?? false);
106
- stop(this);
107
- if (active) {
108
- state.active.add(this);
109
- }
110
- else {
111
- state.active.delete(this);
112
- }
113
- if (this.options.interactive) {
114
- if (active) {
115
- state.order.push(this);
116
- }
117
- else {
118
- const index = state.order.indexOf(this);
119
- if (index > -1) {
120
- state.order.splice(index, 1);
121
- }
122
- }
123
- }
124
- if (active) {
125
- activate(this);
126
- }
127
- else {
128
- deactivate(this);
129
- }
130
- }
131
- }
132
- //
133
- function activate(floatable) {
134
- floatable.active = true;
135
- document.body.append(floatable.options.content);
136
- floatable.options.content.hidden = false;
137
- updatePosition(floatable);
138
- }
139
- function closeAbove(element) {
140
- const state = getState();
141
- if (state == null) {
142
- return;
143
- }
144
- const index = state.order.findIndex(floatable => floatable.options.anchor === element ||
145
- floatable.options.content === element);
146
- if (index === -1 || index === state.order.length - 1) {
147
- return;
148
- }
149
- while (index < state.order.length - 1) {
150
- void state.order.pop()?.toggle(false, true);
151
- }
152
- }
153
- function closeAll() {
154
- const state = getState();
155
- const floatables = [...(state?.active ?? [])];
156
- state?.active.clear();
157
- for (const floatable of floatables) {
158
- void floatable.toggle(false, true);
159
- }
160
- }
161
- function closeNonInteractive(state) {
162
- for (const floatable of state.active) {
163
- if (!floatable.options.interactive) {
164
- void floatable.toggle(false);
165
- }
166
- }
167
- }
168
- function deactivate(floatable) {
169
- floatable.active = false;
170
- floatable.options.content.hidden = true;
171
- floatable.options.anchor.insertAdjacentElement(INSERT_AFTEREND, floatable.options.content);
172
- floatable.options.onAfter?.(false);
173
- }
174
- function getState() {
175
- return window._oscarpalmer_oui_floatable;
176
- }
177
- function getX(anchor, content, position) {
178
- if (position.endsWith(POSITION_SUFFIX_END)) {
179
- const end = anchor.right - content.width;
180
- return end < 0 ? 0 : end;
181
- }
182
- if (position.endsWith(POSITION_SUFFIX_START)) {
183
- const start = anchor.left;
184
- return start + content.width > window.innerWidth
185
- ? window.innerWidth - content.width
186
- : start;
187
- }
188
- if (position.startsWith(POSITION_END)) {
189
- return anchor.right;
190
- }
191
- if (position.startsWith(POSITION_START)) {
192
- return anchor.left - content.width;
193
- }
194
- if (position.startsWith(POSITION_HORIZONTAL)) {
195
- if (anchor.right + content.width <= window.innerWidth) {
196
- return anchor.right;
197
- }
198
- return anchor.left - content.width;
199
- }
200
- const left = anchor.left + (anchor.width - content.width) / 2;
201
- return left < 0 ? 0 : left;
202
- }
203
- function getY(anchor, content, position, preferAbove) {
204
- if (position.startsWith(POSITION_ABOVE)) {
205
- return anchor.top - content.height;
206
- }
207
- if (position.startsWith(POSITION_BELOW)) {
208
- return anchor.bottom;
209
- }
210
- if (position.endsWith(POSITION_BOTTOM)) {
211
- const bottom = anchor.bottom - content.height;
212
- return bottom < 0 ? 0 : bottom;
213
- }
214
- if (position.endsWith(POSITION_TOP)) {
215
- const top = anchor.top;
216
- return top + content.height > window.innerHeight
217
- ? window.innerHeight - content.height
218
- : top;
219
- }
220
- if (position.startsWith(POSITION_VERTICAL)) {
221
- if (preferAbove && anchor.top - content.height >= 0) {
222
- return anchor.top - content.height;
223
- }
224
- if (anchor.bottom + content.height <= document.body.clientHeight) {
225
- return anchor.bottom;
226
- }
227
- return anchor.top - content.height;
228
- }
229
- return anchor.top + (anchor.height - content.height) / 2;
230
- }
231
- function initialize(floatable) {
232
- const { anchor, content, interactive } = floatable.options;
233
- if (interactive) {
234
- anchor.setAttribute(ATTRIBUTE_ANCHOR, '');
235
- content.setAttribute(ATTRIBUTE_CONTENT, '');
236
- }
237
- content.style.position = 'fixed';
238
- content.style.inset = '0 auto auto 0';
239
- content.style.zIndex = '10';
240
- const state = getState();
241
- state?.mapped.set(anchor, floatable);
242
- state?.mapped.set(content, floatable);
243
- }
244
- function isDisabled(element) {
245
- return (element.disabled ||
246
- element.readOnly ||
247
- element.getAttribute('aria-disabled') === 'true');
248
- }
249
- function onClick(event) {
250
- const related = findAncestor(event.target, SELECTOR_ALL);
251
- if (!(related instanceof HTMLElement)) {
252
- closeAll();
253
- }
254
- else if (related.hasAttribute(ATTRIBUTE_CONTENT)) {
255
- closeAbove(related);
256
- }
257
- else if (!isDisabled(related)) {
258
- toggle(related);
259
- }
260
- }
261
- function onKeyDown(event) {
262
- if (event.key !== 'Escape') {
263
- return;
264
- }
265
- const state = getState();
266
- if (state == null || state.active.size === 0) {
267
- return;
268
- }
269
- closeNonInteractive(state);
270
- const related = findAncestor(event.target, SELECTOR_CONTENT);
271
- if (!(related instanceof HTMLElement)) {
272
- return;
273
- }
274
- closeAbove(related);
275
- const floatable = state.mapped.get(related);
276
- if (floatable != null) {
277
- void floatable.toggle(false);
278
- }
279
- }
280
- function stop(floatable) {
281
- if (floatable.frame != null) {
282
- cancelAnimationFrame(floatable.frame);
283
- }
284
- floatable.frame = undefined;
285
- }
286
- function toggle(anchor) {
287
- const floatable = getState()?.mapped.get(anchor);
288
- if (floatable == null) {
289
- closeAll();
290
- return;
291
- }
292
- const active = Boolean(floatable.active);
293
- const content = findAncestor(floatable.options.anchor, SELECTOR_CONTENT);
294
- if (content == null) {
295
- closeAll();
296
- }
297
- else {
298
- closeAbove(content);
299
- }
300
- void floatable.toggle(!active);
301
- }
302
- function updatePosition(floatable) {
303
- let position = floatable.options.anchor
304
- .getAttribute(floatable.options.positionAttribute)
305
- ?.trim() ?? floatable.options.defaultPosition;
306
- if (!POSITIONS.has(position)) {
307
- position = floatable.options.defaultPosition;
308
- }
309
- let previousAnchor;
310
- let previousContent;
311
- let calculated = false;
312
- let runOnAfter = false;
313
- function run() {
314
- const anchor = floatable.options.anchor.getBoundingClientRect();
315
- const content = floatable.options.content.getBoundingClientRect();
316
- if (calculated) {
317
- if (previousAnchor != null && previousContent != null) {
318
- if (PROPERTIES.every(property => anchor[property] === previousAnchor[property]) &&
319
- PROPERTIES.every(property => content[property] === previousContent[property])) {
320
- floatable.frame = requestAnimationFrame(run);
321
- return;
322
- }
323
- }
324
- }
325
- else {
326
- calculated = true;
327
- }
328
- update(anchor, content);
329
- }
330
- function update(anchor, content) {
331
- previousAnchor = anchor;
332
- previousContent = content;
333
- const left = getX(anchor, content, position);
334
- const top = getY(anchor, content, position, floatable.options.preferAbove);
335
- if (top + content.height > window.innerHeight) {
336
- floatable.options.content.style.height = `${window.innerHeight - top}px`;
337
- }
338
- else {
339
- floatable.options.content.style.height = '';
340
- }
341
- if (left + content.width > window.innerWidth) {
342
- floatable.options.content.style.width = `${window.innerWidth - left}px`;
343
- }
344
- else {
345
- floatable.options.content.style.width = '';
346
- }
347
- // floatable.options.content.style.inset = `${top}px auto auto ${left}px`;
348
- floatable.options.content.style.transform = `translate3d(${left}px, ${top}px, 0)`;
349
- floatable.frame = requestAnimationFrame(run);
350
- if (!runOnAfter) {
351
- runOnAfter = true;
352
- floatable.options.onAfter?.(true);
353
- }
354
- }
355
- floatable.frame = requestAnimationFrame(run);
356
- }
357
- //
358
- const ATTRIBUTE_ANCHOR = 'oui-floatable-anchor';
359
- const ATTRIBUTE_CONTENT = 'oui-floatable-content';
360
- const INSERT_AFTEREND = 'afterend';
361
- const POSITION_ABOVE = 'above';
362
- const POSITION_BELOW = 'below';
363
- const POSITION_BOTTOM = 'bottom';
364
- const POSITION_END = 'end';
365
- const POSITION_HORIZONTAL = 'horizontal';
366
- const POSITION_START = 'start';
367
- const POSITION_SUFFIX_END = '-end';
368
- const POSITION_SUFFIX_START = '-start';
369
- const POSITION_TOP = 'top';
370
- const POSITION_VERTICAL = 'vertical';
371
- const POSITIONS = new Set([
372
- 'above',
373
- 'above-end',
374
- 'above-start',
375
- 'below',
376
- 'below-end',
377
- 'below-start',
378
- 'end',
379
- 'end-bottom',
380
- 'end-top',
381
- 'horizontal',
382
- 'horizontal-bottom',
383
- 'horizontal-top',
384
- 'start',
385
- 'start-bottom',
386
- 'start-top',
387
- 'vertical',
388
- 'vertical-end',
389
- 'vertical-start',
390
- ]);
391
- const PROPERTIES = ['bottom', 'left', 'right', 'top'];
392
- const SELECTOR_ALL = `[${ATTRIBUTE_ANCHOR}], [${ATTRIBUTE_CONTENT}]`;
393
- const SELECTOR_CONTENT = `[${ATTRIBUTE_CONTENT}]`;
394
- //
395
- if (window._oscarpalmer_oui_floatable == null) {
396
- Object.defineProperty(window, '_oscarpalmer_oui_floatable', {
397
- enumerable: false,
398
- value: {
399
- active: new Set(),
400
- mapped: new Map(),
401
- order: [],
402
- },
403
- writable: false,
404
- });
405
- on(document, 'keydown', event => {
406
- onKeyDown(event);
407
- });
408
- on(document, 'click', event => {
409
- onClick(event);
410
- });
411
- }
412
-
413
- export { Floatable, deactivate };