@oscarpalmer/oui 0.23.1 → 0.25.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 (40) hide show
  1. package/dist/css/{tooltip.css → floatable.css} +59 -24
  2. package/dist/css/reset.css +17 -0
  3. package/dist/js/dialog.d.mts +38 -0
  4. package/dist/js/dialog.mjs +92 -0
  5. package/dist/js/embedded-84gxpReS.d.mts +64 -0
  6. package/dist/js/embedded-BpwzMSEF.d.mts +26 -0
  7. package/dist/js/floatable/embedded.d.mts +2 -0
  8. package/dist/js/floatable/embedded.mjs +146 -0
  9. package/dist/js/floatable/standalone.d.mts +2 -0
  10. package/dist/js/floatable/standalone.mjs +2 -0
  11. package/dist/js/focus-trap/embedded.d.mts +1 -25
  12. package/dist/js/focus-trap/embedded.mjs +1 -1
  13. package/dist/js/index.d.mts +5 -2
  14. package/dist/js/index.mjs +7 -4
  15. package/dist/js/internal/attributable.mjs +4 -3
  16. package/dist/js/internal/draggable.mjs +1 -1
  17. package/dist/js/popover.d.mts +38 -1
  18. package/dist/js/popover.mjs +81 -38
  19. package/dist/js/sortable.mjs +7 -5
  20. package/dist/js/splitter.mjs +18 -14
  21. package/dist/js/tooltip.d.mts +33 -1
  22. package/dist/js/tooltip.mjs +91 -48
  23. package/package.json +2 -2
  24. package/src/css/{tooltip.scss → floatable.scss} +47 -5
  25. package/src/css/mixins.scss +0 -2
  26. package/src/css/reset.scss +17 -0
  27. package/src/js/dialog.ts +188 -0
  28. package/src/js/floatable/embedded.ts +302 -0
  29. package/src/js/floatable/standalone.ts +1 -0
  30. package/src/js/index.ts +4 -2
  31. package/src/js/internal/attributable.ts +5 -3
  32. package/src/js/popover.ts +146 -48
  33. package/src/js/sortable.ts +8 -5
  34. package/src/js/splitter.ts +26 -9
  35. package/src/js/tooltip.ts +138 -51
  36. package/dist/css/popover.css +0 -30
  37. package/dist/js/internal/floatable.d.mts +0 -18
  38. package/dist/js/internal/floatable.mjs +0 -67
  39. package/src/css/popover.scss +0 -10
  40. package/src/js/internal/floatable.ts +0 -118
package/src/js/popover.ts CHANGED
@@ -1,62 +1,136 @@
1
1
  import {on} from '@oscarpalmer/toretto/event';
2
+ import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
2
3
  import type {RemovableEventListener} from '@oscarpalmer/toretto/models';
3
- import {createFocusTrap, removeFocusTrap, type FocusTrap} from './focus-trap/embedded';
4
- import {attributable} from './internal/attributable';
5
4
  import {
5
+ ATTRIBUTE_FLOATABLE,
6
6
  createFloatable,
7
- removeFloatable,
8
- type Floatable,
9
- type FloatableOptions,
10
- } from './internal/floatable';
11
-
12
- class Popover {
13
- anchor: HTMLElement | null;
14
- floatable?: Floatable;
15
- focusTrap?: FocusTrap;
16
- listener: RemovableEventListener;
17
-
18
- constructor(public element: HTMLElement) {
19
- this.anchor = element.ownerDocument.querySelector(`[popovertarget="${element.id}"]`);
7
+ getOnBeforeToggleListener,
8
+ type OuiFloatable,
9
+ type OuiFloatableOptions,
10
+ } from './floatable/embedded';
11
+ import {createFocusTrap, type FocusTrap} from './focus-trap/embedded';
12
+ import {attributable} from './internal/attributable';
20
13
 
21
- this.floatable = createFloatable(this.anchor as HTMLElement, element, options);
14
+ // #region Types
22
15
 
23
- this.focusTrap = createFocusTrap(element, {
24
- noescape: true,
25
- });
16
+ class OuiPopover {
17
+ readonly #state: OuiPopoverState;
26
18
 
27
- this.listener = on(element, EVENT_TOGGLE, event => {
28
- if (event.newState === STATE_OPEN) {
29
- ignoreFocus = false;
19
+ /**
20
+ * Is the popover open?
21
+ */
22
+ get open(): boolean {
23
+ return this.#state.content.checkVisibility();
24
+ }
30
25
 
31
- this.floatable?.update();
26
+ constructor(state: OuiPopoverState) {
27
+ this.#state = state;
32
28
 
33
- element.focus();
34
- } else if (!ignoreFocus) {
35
- this.anchor?.focus();
36
- }
37
- });
29
+ this.#state.floatable.update();
30
+ }
38
31
 
39
- this.element.setAttribute(ATTRIBUTE_CONTENT, '');
32
+ /**
33
+ * Closes the popover
34
+ */
35
+ hide(): void {
36
+ this.#state.floatable.hide();
37
+ }
40
38
 
41
- this.floatable?.update();
39
+ /**
40
+ * Opens the popover
41
+ */
42
+ show(): void {
43
+ this.#state.floatable.show();
42
44
  }
45
+ }
43
46
 
44
- destroy(): void {
45
- this.focusTrap?.destroy();
47
+ type OuiPopoverState = {
48
+ anchor: HTMLElement;
49
+ content: HTMLElement;
50
+ floatable: OuiFloatable;
51
+ focusTrap?: FocusTrap;
52
+ listeners: RemovableEventListener[];
53
+ popover: OuiPopover;
54
+ };
55
+
56
+ // #endregion
46
57
 
47
- removeFloatable(this.element);
48
- removeFocusTrap(this.element);
58
+ // #region Functions
49
59
 
50
- this.element.removeAttribute(ATTRIBUTE_CONTENT);
60
+ function destroyPopover(state: OuiPopoverState): void {
61
+ state.floatable.destroy();
62
+ state.focusTrap?.destroy();
51
63
 
52
- this.anchor = null;
53
- this.element = null as never;
64
+ for (const listener of state.listeners) {
65
+ listener();
54
66
  }
67
+
68
+ state.anchor = undefined as never;
69
+ state.content = undefined as never;
70
+ state.floatable = undefined as never;
71
+ state.focusTrap = undefined as never;
72
+ state.listeners = undefined as never;
73
+ state.popover = undefined as never;
74
+ }
75
+
76
+ /**
77
+ * Get the _OuiPopover_ for an element
78
+ *
79
+ * @param element Element to get _OuiPopover_ for
80
+ * @returns _OuiPopover_ instance
81
+ */
82
+ function getPopover(element: HTMLElement): OuiPopover | undefined {
83
+ return states.get(element)?.popover;
84
+ }
85
+
86
+ function getState(anchor: HTMLElement, content: HTMLElement): OuiPopoverState {
87
+ const state: OuiPopoverState = {
88
+ anchor,
89
+ content,
90
+ floatable: createFloatable(anchor, content, options, false),
91
+ focusTrap:
92
+ content.getAttribute(ARIA_MODAL) === TRUE
93
+ ? createFocusTrap(content, {
94
+ noescape: true,
95
+ })
96
+ : undefined,
97
+ listeners: [
98
+ getOnBeforeToggleListener(content),
99
+ on(content, EVENT_TOGGLE, event => {
100
+ if (event.newState === STATE_OPEN) {
101
+ ignoreFocus = false;
102
+
103
+ state.floatable?.update();
104
+
105
+ content.setAttribute(ATTRIBUTE_OPEN, '');
106
+
107
+ content.focus();
108
+ } else {
109
+ content.removeAttribute(ATTRIBUTE_OPEN);
110
+
111
+ if (!ignoreFocus) {
112
+ anchor?.focus();
113
+ }
114
+ }
115
+ }),
116
+ ],
117
+ popover: undefined as never,
118
+ };
119
+
120
+ state.popover = new OuiPopover(state);
121
+
122
+ return state;
55
123
  }
56
124
 
57
125
  function onAdd(element: HTMLElement): void {
58
- if (!instances.has(element) && element.getAttribute(ATTRIBUTE) !== POPOVER_HINT) {
59
- instances.set(element, new Popover(element));
126
+ if (states.has(element) || element.hasAttribute(ATTRIBUTE_FLOATABLE)) {
127
+ return;
128
+ }
129
+
130
+ const anchor = element.ownerDocument.querySelector(`[popovertarget="${element.id}"]`);
131
+
132
+ if (isHTMLOrSVGElement(anchor)) {
133
+ states.set(element, getState(anchor, element));
60
134
  }
61
135
  }
62
136
 
@@ -65,32 +139,56 @@ function onPointerdown(): void {
65
139
  }
66
140
 
67
141
  function onRemove(element: HTMLElement): void {
68
- instances.get(element)?.destroy();
142
+ const state = states.get(element);
143
+
144
+ if (state == null) {
145
+ return;
146
+ }
69
147
 
70
- instances.delete(element);
148
+ destroyPopover(state);
149
+
150
+ states.delete(element);
71
151
  }
72
152
 
73
- const ATTRIBUTE = 'popover';
153
+ // #endregion
74
154
 
75
- const ATTRIBUTE_CONTENT = 'oui-popover-content';
155
+ // #region Variables
76
156
 
77
- const EVENT_TOGGLE = 'toggle';
157
+ const ATTRIBUTE = 'oui-popover';
158
+
159
+ const ARIA_MODAL = 'aria-modal';
160
+
161
+ const ATTRIBUTE_OPEN = `${ATTRIBUTE}-open`;
78
162
 
79
- const POPOVER_HINT = 'hint';
163
+ const EVENT_TOGGLE = 'toggle';
80
164
 
81
165
  const STATE_OPEN = 'open';
82
166
 
83
- const instances = new WeakMap<HTMLElement, Popover>();
167
+ const TRUE = 'true';
84
168
 
85
- const options: FloatableOptions = {
86
- attribute: 'position',
169
+ const options: OuiFloatableOptions = {
170
+ attribute: `${ATTRIBUTE}position`,
87
171
  position: 'below-start',
88
172
  };
89
173
 
174
+ const states = new WeakMap<HTMLElement, OuiPopoverState>();
175
+
90
176
  let ignoreFocus = false;
91
177
 
178
+ // #endregion
179
+
180
+ // #region Initialization
181
+
92
182
  on(document, 'pointerdown', onPointerdown, {
93
183
  capture: true,
94
184
  });
95
185
 
96
186
  attributable(ATTRIBUTE, onAdd, onRemove);
187
+
188
+ // #endregion
189
+
190
+ // #region Exports
191
+
192
+ export {getPopover, type OuiPopover};
193
+
194
+ // #endregion
@@ -2,6 +2,7 @@ import type {EventPosition, PlainObject} from '@oscarpalmer/atoms/models';
2
2
  import {createElement} from '@oscarpalmer/toretto/create';
3
3
  import {getPosition} from '@oscarpalmer/toretto/event';
4
4
  import {findAncestor, getElementFromPosition} from '@oscarpalmer/toretto/find';
5
+ import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
5
6
  import {attributable} from './internal/attributable';
6
7
  import {
7
8
  addDraggable,
@@ -333,17 +334,19 @@ function setPlaceholder(state: DraggableState, sortable: Sortable, origin: HTMLE
333
334
  parent: sortable.element,
334
335
  placeholder: element,
335
336
  create: (value: unknown) => {
336
- if (!(value instanceof HTMLElement)) {
337
+ if (!isHTMLOrSVGElement(value)) {
337
338
  return;
338
339
  }
339
340
 
340
- placeholder.drag.custom = value;
341
+ const element = value as HTMLElement;
341
342
 
342
- updatePlaceholder(sortable, value);
343
+ placeholder.drag.custom = element;
344
+
345
+ updatePlaceholder(sortable, element);
343
346
 
344
347
  state.element = {
345
- rectangle: value.getBoundingClientRect(),
346
- node: value,
348
+ rectangle: element.getBoundingClientRect(),
349
+ node: element,
347
350
  };
348
351
  },
349
352
  },
@@ -12,8 +12,21 @@ declare global {
12
12
  }
13
13
  }
14
14
 
15
+ const ATTRIBUTE_MAX = 'max';
16
+
17
+ const ATTRIBUTE_MIN = 'min';
18
+
19
+ const ATTRIBUTE_SIZE = 'size';
20
+
21
+ const ATTRIBUTE_TYPE = 'type';
22
+
15
23
  export class OuiSplitterElement extends HTMLElement {
16
- static readonly observedAttributes = ['max', 'min', 'size', 'type'];
24
+ static readonly observedAttributes = [
25
+ ATTRIBUTE_MAX,
26
+ ATTRIBUTE_MIN,
27
+ ATTRIBUTE_SIZE,
28
+ ATTRIBUTE_TYPE,
29
+ ];
17
30
 
18
31
  readonly #splitter: Splitter;
19
32
 
@@ -24,7 +37,7 @@ export class OuiSplitterElement extends HTMLElement {
24
37
  }
25
38
 
26
39
  set max(value: number) {
27
- this.setAttribute('max', String(value));
40
+ this.setAttribute(ATTRIBUTE_MAX, String(value));
28
41
  }
29
42
 
30
43
  get min(): number {
@@ -77,13 +90,13 @@ export class OuiSplitterElement extends HTMLElement {
77
90
 
78
91
  attributeChangedCallback(name: string): void {
79
92
  switch (name) {
80
- case 'max':
81
- case 'min':
82
- case 'size':
93
+ case ATTRIBUTE_MAX:
94
+ case ATTRIBUTE_MIN:
95
+ case ATTRIBUTE_SIZE:
83
96
  this.#splitter.updateValues();
84
97
  break;
85
98
 
86
- case 'type':
99
+ case ATTRIBUTE_TYPE:
87
100
  this.#splitter.updateOrientation();
88
101
  break;
89
102
 
@@ -271,15 +284,19 @@ function getValue(element: HTMLElement, name: string, defaultValue: number): num
271
284
 
272
285
  function getValues(element: OuiSplitterElement): Values {
273
286
  const values: Values = {
274
- max: getValue(element, 'max', NAVIGATION_MAXIMUM_PERCENTAGE),
275
- min: getValue(element, 'min', NAVIGATION_MINIMUM_PERCENTAGE),
287
+ max: getValue(element, ATTRIBUTE_MAX, NAVIGATION_MAXIMUM_PERCENTAGE),
288
+ min: getValue(element, ATTRIBUTE_MIN, NAVIGATION_MINIMUM_PERCENTAGE),
276
289
  now: {
277
290
  current: 0.5,
278
291
  previous: 0.5,
279
292
  },
280
293
  };
281
294
 
282
- const value = getContained(values.min, getValue(element, 'size', values.now.current), values.max);
295
+ const value = getContained(
296
+ values.min,
297
+ getValue(element, ATTRIBUTE_SIZE, values.now.current),
298
+ values.max,
299
+ );
283
300
 
284
301
  values.now.current = value;
285
302
  values.now.previous = value;
package/src/js/tooltip.ts CHANGED
@@ -2,97 +2,136 @@ import {isNullableOrWhitespace} from '@oscarpalmer/atoms/is';
2
2
  import {createElement} from '@oscarpalmer/toretto/create';
3
3
  import {on} from '@oscarpalmer/toretto/event';
4
4
  import {findAncestor} from '@oscarpalmer/toretto/find';
5
+ import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
6
+ import {createFloatable, type OuiFloatable, type OuiFloatableOptions} from './floatable/embedded';
5
7
  import {attributable} from './internal/attributable';
6
- import {Floatable, type FloatableOptions} from './internal/floatable';
7
8
 
8
- class Tooltip {
9
- floatable: Floatable;
9
+ // #region Types
10
10
 
11
- timer: number | undefined;
11
+ class OuiTooltip {
12
+ readonly #state: OuiTooltipState;
12
13
 
13
- constructor(
14
- public anchor: HTMLElement,
15
- public content: HTMLElement,
16
- ) {
17
- instances.set(content, this);
18
-
19
- anchor.insertAdjacentElement('afterend', content);
14
+ /**
15
+ * Is the tooltip open?
16
+ */
17
+ get open(): boolean {
18
+ return this.#state.content.checkVisibility();
19
+ }
20
20
 
21
- this.floatable = new Floatable(anchor, content, options);
21
+ constructor(state: OuiTooltipState) {
22
+ this.#state = state;
22
23
 
23
- this.floatable.update();
24
+ state.floatable.update();
24
25
  }
25
26
 
26
- destroy(): void {
27
- instances.delete(this.content);
27
+ /**
28
+ * Closes the tooltip
29
+ */
30
+ hide(): void {
31
+ this.#state.floatable.hide();
32
+ }
28
33
 
29
- this.anchor = null as never;
30
- this.content = null as never;
34
+ /**
35
+ * Opens the tooltip
36
+ */
37
+ show(): void {
38
+ this.#state.floatable.show();
31
39
  }
32
40
  }
33
41
 
42
+ type OuiTooltipState = {
43
+ anchor: HTMLElement;
44
+ content: HTMLElement;
45
+ floatable: OuiFloatable;
46
+ timer?: number;
47
+ tooltip: OuiTooltip;
48
+ };
49
+
50
+ // #endregion
51
+
52
+ // #region Functions
53
+
34
54
  function activate(event: Event, focus: boolean): void {
35
55
  const anchor = findAncestor(event, SELECTOR) as HTMLElement | null;
36
56
  const content = findAncestor(event, SELECTOR_CONTENT) as HTMLElement | null;
37
57
 
38
58
  if (anchor == null && content == null) {
39
59
  if (!focused) {
40
- closeTooltip(active);
60
+ closeTooltip(activeState);
41
61
 
42
- active = undefined;
62
+ activeState = undefined;
63
+ activeTooltip = undefined;
43
64
  }
44
65
 
45
66
  return;
46
67
  }
47
68
 
48
- const instance = instances.get((anchor ?? content)!);
69
+ const state = states.get((anchor ?? content)!);
49
70
 
50
- if (instance == null || instance === active) {
71
+ if (state == null || state.tooltip === activeTooltip) {
51
72
  return;
52
73
  }
53
74
 
54
- const shouldDelay = active == null;
75
+ const shouldDelay = activeTooltip == null;
55
76
 
56
- closeTooltip(active);
77
+ closeTooltip(activeState);
78
+
79
+ activeState = state;
80
+ activeTooltip = state.tooltip;
57
81
 
58
- active = instance;
59
82
  focused = focus;
60
83
 
61
- instance.timer = setTimeout(
84
+ state.timer = setTimeout(
62
85
  () => {
63
- instance.content.showPopover({
64
- source: instance.anchor,
86
+ state.content.showPopover({
87
+ source: state.anchor as HTMLElement,
65
88
  });
66
89
 
67
90
  setTimeout(() => {
68
- instance.floatable.update();
91
+ state.floatable.update();
69
92
 
70
- instance.content.setAttribute(ATTRIBUTE_CONTENT_ACTIVE, '');
93
+ state.content.setAttribute(ATTRIBUTE_CONTENT_OPEN, '');
71
94
  });
72
95
  },
73
96
  shouldDelay ? delay : 0,
74
97
  );
75
98
  }
76
99
 
77
- function closeTooltip(instance?: Tooltip): void {
78
- if (instance == null) {
100
+ function closeTooltip(state?: OuiTooltipState): void {
101
+ if (state == null) {
79
102
  return;
80
103
  }
81
104
 
82
- if (instance.timer != null) {
83
- clearTimeout(instance.timer);
105
+ if (state.timer != null) {
106
+ clearTimeout(state.timer);
84
107
  }
85
108
 
86
- instance.content?.hidePopover();
87
- instance.content?.removeAttribute(ATTRIBUTE_CONTENT_ACTIVE);
109
+ state.content?.hidePopover();
110
+ state.content?.removeAttribute(ATTRIBUTE_CONTENT_OPEN);
88
111
  }
89
112
 
90
113
  function createTooltip(anchor: HTMLElement): void {
91
114
  const content = getContent(anchor);
92
115
 
93
- if (content != null) {
94
- instances.set(anchor, new Tooltip(anchor, content));
116
+ if (content == null) {
117
+ return;
95
118
  }
119
+
120
+ anchor.insertAdjacentElement('afterend', content);
121
+
122
+ states.set(anchor, getState(anchor, content));
123
+ }
124
+
125
+ function destroyTooltip(state: OuiTooltipState): void {
126
+ clearTimeout(state.timer);
127
+
128
+ state.content.remove();
129
+ state.floatable.destroy();
130
+
131
+ state.anchor = undefined as never;
132
+ state.content = undefined as never;
133
+ state.floatable = undefined as never;
134
+ state.tooltip = undefined as never;
96
135
  }
97
136
 
98
137
  function findElements(attribute: string | null): HTMLElement[] {
@@ -106,7 +145,7 @@ function findElements(attribute: string | null): HTMLElement[] {
106
145
 
107
146
  const element = document.querySelector(`#${id}`);
108
147
 
109
- if (element instanceof HTMLElement) {
148
+ if (isHTMLOrSVGElement(element)) {
110
149
  const cloned = element.cloneNode(true) as HTMLElement;
111
150
 
112
151
  cloned.hidden = false;
@@ -168,8 +207,25 @@ function getElements(anchor: HTMLElement): HTMLElement[] | undefined {
168
207
  return [paragraph];
169
208
  }
170
209
 
210
+ function getState(anchor: HTMLElement, content: HTMLElement): OuiTooltipState {
211
+ const state: OuiTooltipState = {
212
+ anchor,
213
+ content,
214
+ floatable: createFloatable(anchor, content, options, false),
215
+ tooltip: null as never,
216
+ };
217
+
218
+ state.tooltip = new OuiTooltip(state);
219
+
220
+ return state;
221
+ }
222
+
223
+ function getTooltip(element: HTMLElement): OuiTooltip | undefined {
224
+ return states.get(element)?.tooltip;
225
+ }
226
+
171
227
  function onAdd(element: HTMLElement): void {
172
- if (!instances.has(element)) {
228
+ if (!states.has(element)) {
173
229
  createTooltip(element);
174
230
  }
175
231
  }
@@ -179,7 +235,7 @@ function onFocusin(event: Event): void {
179
235
  }
180
236
 
181
237
  function onFocusout(): void {
182
- if (active == null) {
238
+ if (activeTooltip == null) {
183
239
  return;
184
240
  }
185
241
 
@@ -189,16 +245,17 @@ function onFocusout(): void {
189
245
 
190
246
  focusTimer = setTimeout(() => {
191
247
  if (
192
- active == null ||
248
+ activeTooltip == null ||
193
249
  document.activeElement == null ||
194
250
  findAncestor(document.activeElement, SELECTOR) != null
195
251
  ) {
196
252
  return;
197
253
  }
198
254
 
199
- closeTooltip(active);
255
+ closeTooltip(activeState);
200
256
 
201
- active = undefined;
257
+ activeState = undefined;
258
+ activeTooltip = undefined;
202
259
  });
203
260
  }
204
261
 
@@ -207,17 +264,33 @@ function onPointermove(event: Event): void {
207
264
  }
208
265
 
209
266
  function onRemove(element: HTMLElement): void {
210
- instances.get(element)?.destroy();
267
+ const state = states.get(element);
211
268
 
212
- instances.delete(element);
269
+ if (state == null) {
270
+ return;
271
+ }
272
+
273
+ destroyTooltip(state);
274
+
275
+ states.delete(element);
213
276
  }
214
277
 
215
- export function setTooltipDelay(value: number): void {
278
+ /**
279
+ * Set the delay before showing the tooltip, in milliseconds
280
+ *
281
+ * _(Default delay is half a second, or 500 milliseconds)_
282
+ * @param value Delay in milliseconds
283
+ */
284
+ function setTooltipDelay(value: number): void {
216
285
  if (typeof value === 'number' && !Number.isNaN(value) && value >= 0) {
217
286
  delay = value;
218
287
  }
219
288
  }
220
289
 
290
+ // #endregion
291
+
292
+ // #region Variables
293
+
221
294
  const ARIA_DESCRIBEDBY = 'aria-describedby';
222
295
 
223
296
  const ARIA_DESCRIPTION = 'aria-description';
@@ -234,16 +307,16 @@ const ATTRIBUTE = 'oui-tooltip';
234
307
 
235
308
  const ATTRIBUTE_CONTENT = `${ATTRIBUTE}-content`;
236
309
 
237
- const ATTRIBUTE_CONTENT_ACTIVE = `${ATTRIBUTE_CONTENT}-active`;
310
+ const ATTRIBUTE_CONTENT_OPEN = `${ATTRIBUTE_CONTENT}-open`;
238
311
 
239
312
  const SELECTOR = `[${ATTRIBUTE}]`;
240
313
 
241
314
  const SELECTOR_CONTENT = `[${ATTRIBUTE_CONTENT}]`;
242
315
 
243
- const instances = new WeakMap<HTMLElement, Tooltip>();
316
+ const states = new WeakMap<HTMLElement, OuiTooltipState>();
244
317
 
245
- const options: FloatableOptions = {
246
- attribute: 'oui-tooltip-position',
318
+ const options: OuiFloatableOptions = {
319
+ attribute: `${ATTRIBUTE}-position`,
247
320
  position: 'above',
248
321
  };
249
322
 
@@ -251,12 +324,26 @@ let delay = 500;
251
324
 
252
325
  let focused = false;
253
326
 
254
- let active: Tooltip | undefined;
327
+ let activeState: OuiTooltipState | undefined;
328
+
329
+ let activeTooltip: OuiTooltip | undefined;
255
330
 
256
331
  let focusTimer: number | undefined;
257
332
 
333
+ // #endregion
334
+
335
+ // #region Initialization
336
+
258
337
  on(document, 'focusin', onFocusin);
259
338
  on(document, 'focusout', onFocusout);
260
339
  on(document, 'pointermove', onPointermove);
261
340
 
262
341
  attributable(ATTRIBUTE, onAdd, onRemove);
342
+
343
+ // #endregion
344
+
345
+ // #region Exports
346
+
347
+ export {getTooltip, setTooltipDelay, type OuiTooltip};
348
+
349
+ // #endregion
@@ -1,30 +0,0 @@
1
-
2
- :where([oui-popover-content]) {
3
- box-shadow: inset 0 1px 0 0 transparent, 0 0 0 1px rgba(0, 0, 0, 0.05), 0 1px 2px -0.5px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.05), 0 4px 8px -2px rgba(0, 0, 0, 0.05), 0 8px 16px -4px rgba(0, 0, 0, 0.05), 0 16px 32px -8px rgba(0, 0, 0, 0.05), 0 32px 64px -16px rgba(0, 0, 0, 0.05), 0 64px 128px -32px rgba(0, 0, 0, 0.05);
4
- --margin-bottom: 0.5em;
5
- --margin-left: 0.5em;
6
- --margin-right: 0.5em;
7
- --margin-top: 0.5em;
8
- inset-block: var(--margin-top) var(--margin-bottom);
9
- inset-inline: var(--margin-left) var(--margin-right);
10
- }
11
- :where([oui-popover-content])[oui-position$=bottom] {
12
- --margin-bottom: 0;
13
- }
14
- :where([oui-popover-content])[oui-position$=end] {
15
- --margin-right: 0;
16
- }
17
- :where([oui-popover-content])[oui-position$=start] {
18
- --margin-left: 0;
19
- }
20
- :where([oui-popover-content])[oui-position$=top] {
21
- --margin-top: 0;
22
- }
23
- :where([oui-popover-content]) {
24
- padding: 1rem;
25
- background-color: var(--oui-absolute);
26
- border: none;
27
- border-radius: 0.25rem;
28
- }
29
-
30
-