@oscarpalmer/oui 0.21.0 → 0.22.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.
- package/dist/css/popover.css +9 -9
- package/dist/css/tooltip.css +20 -20
- package/dist/js/index.d.mts +46 -3
- package/dist/js/index.mjs +2536 -6
- package/dist/js/internal/draggable.d.mts +1 -1
- package/dist/js/internal/draggable.mjs +3 -0
- package/dist/js/internal/floatable.d.mts +2 -2
- package/dist/js/internal/floatable.mjs +38 -135
- package/dist/js/movable.d.mts +1 -1
- package/dist/js/popover.mjs +1 -1
- package/dist/js/sortable.d.mts +1 -1
- package/dist/js/tooltip.d.mts +1 -1
- package/dist/js/tooltip.mjs +95 -97
- package/package.json +13 -5
- package/src/css/mixins.scss +8 -12
- package/src/css/popover.scss +1 -1
- package/src/css/tooltip.scss +22 -22
- package/src/js/internal/floatable.ts +53 -270
- package/src/js/popover.ts +1 -1
- package/src/js/tooltip.ts +129 -131
- /package/dist/js/{movable-BEo2LbUI.d.mts → movable-BKFgoaOl.d.mts} +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as DraggableState, i as DraggableBound, n as DragMovePosition, o as addDraggable, r as Draggable, s as removeDraggable } from "../movable-
|
|
1
|
+
import { a as DraggableState, i as DraggableBound, n as DragMovePosition, o as addDraggable, r as Draggable, s as removeDraggable } from "../movable-BKFgoaOl.mjs";
|
|
2
2
|
export { DragMovePosition, Draggable, DraggableBound, DraggableState, addDraggable, removeDraggable };
|
|
@@ -5,6 +5,9 @@ import { toggleStyles } from "@oscarpalmer/toretto/style";
|
|
|
5
5
|
import supportsTouch from "@oscarpalmer/toretto/touch";
|
|
6
6
|
//#region src/js/internal/draggable.ts
|
|
7
7
|
var Draggable = class {
|
|
8
|
+
prefix;
|
|
9
|
+
element;
|
|
10
|
+
options;
|
|
8
11
|
container;
|
|
9
12
|
hasHandles;
|
|
10
13
|
horizontal = true;
|
|
@@ -17,10 +17,10 @@ type Options = {
|
|
|
17
17
|
defaultPosition: Position;
|
|
18
18
|
interactive: boolean;
|
|
19
19
|
positionAttribute: string;
|
|
20
|
-
|
|
20
|
+
reusable: boolean;
|
|
21
21
|
onAfter?: (active: boolean) => void;
|
|
22
22
|
};
|
|
23
|
-
type Position = 'above' | 'above-end' | 'above-start' | 'below' | 'below-end' | 'below-start' | 'end' | 'end-bottom' | 'end-top' | '
|
|
23
|
+
type Position = 'above' | 'above-end' | 'above-start' | 'below' | 'below-end' | 'below-start' | 'end' | 'end-bottom' | 'end-top' | 'start' | 'start-bottom' | 'start-top';
|
|
24
24
|
declare function deactivate(floatable: Floatable): void;
|
|
25
25
|
//#endregion
|
|
26
26
|
export { Floatable, deactivate };
|
|
@@ -2,6 +2,7 @@ import { on } from "@oscarpalmer/toretto/event";
|
|
|
2
2
|
import { findAncestor } from "@oscarpalmer/toretto/find";
|
|
3
3
|
//#region src/js/internal/floatable.ts
|
|
4
4
|
var Floatable = class {
|
|
5
|
+
options;
|
|
5
6
|
active = false;
|
|
6
7
|
disabled = false;
|
|
7
8
|
frame;
|
|
@@ -51,7 +52,7 @@ function activate(floatable) {
|
|
|
51
52
|
floatable.active = true;
|
|
52
53
|
document.body.append(floatable.options.content);
|
|
53
54
|
floatable.options.content.hidden = false;
|
|
54
|
-
|
|
55
|
+
setPosition(floatable);
|
|
55
56
|
}
|
|
56
57
|
function closeAbove(element) {
|
|
57
58
|
const state = getState();
|
|
@@ -71,82 +72,30 @@ function closeNonInteractive(state) {
|
|
|
71
72
|
}
|
|
72
73
|
function deactivate(floatable) {
|
|
73
74
|
floatable.active = false;
|
|
74
|
-
floatable.options.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
function getAttribute(position, anchor, top, left) {
|
|
79
|
-
switch (position) {
|
|
80
|
-
case "horizontal":
|
|
81
|
-
case "horizontal-bottom":
|
|
82
|
-
case "horizontal-top": return position.replace("horizontal", left >= anchor.right ? "right" : "left");
|
|
83
|
-
case "vertical":
|
|
84
|
-
case "vertical-end":
|
|
85
|
-
case "vertical-start": return position.replace("vertical", top >= anchor.bottom ? "bottom" : "top");
|
|
86
|
-
default: break;
|
|
75
|
+
if (!floatable.options.reusable) {
|
|
76
|
+
floatable.options.content.hidden = true;
|
|
77
|
+
floatable.options.anchor.insertAdjacentElement(INSERT_AFTEREND, floatable.options.content);
|
|
87
78
|
}
|
|
79
|
+
floatable.options.onAfter?.(false);
|
|
88
80
|
}
|
|
89
|
-
function
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (Number.isNaN(fontsize)) return 5;
|
|
93
|
-
const margin = fontsize / 2;
|
|
94
|
-
return margin < 5 ? 5 : margin;
|
|
95
|
-
} catch {
|
|
96
|
-
return 5;
|
|
97
|
-
}
|
|
81
|
+
function getAnchorName() {
|
|
82
|
+
index += 1;
|
|
83
|
+
return `--oui-floatable-anchor-${index}`;
|
|
98
84
|
}
|
|
99
85
|
function getState() {
|
|
100
86
|
return window._oscarpalmer_oui_floatable;
|
|
101
87
|
}
|
|
102
|
-
function getX(anchor, content, position, margin) {
|
|
103
|
-
if (position === "above" || position === "below" || position === "vertical") {
|
|
104
|
-
const center = anchor.left + anchor.width / 2;
|
|
105
|
-
const width = content.width / 2;
|
|
106
|
-
if (center + width + margin >= document.body.clientWidth) return document.body.clientWidth - content.width - margin / 2;
|
|
107
|
-
if (center - width - margin <= 0) return margin / 2;
|
|
108
|
-
return center - width;
|
|
109
|
-
}
|
|
110
|
-
if (position.startsWith("end")) return anchor.right;
|
|
111
|
-
if (position.startsWith("start")) return anchor.left - content.width;
|
|
112
|
-
if (position.endsWith("end")) return anchor.right - content.width - margin <= 0 ? margin / 2 : anchor.right - content.width;
|
|
113
|
-
if (position.endsWith("start")) {
|
|
114
|
-
if (anchor.left + content.width + margin >= document.body.clientWidth) return document.body.clientWidth - content.width - margin / 2;
|
|
115
|
-
return anchor.left - margin <= 0 ? margin / 2 : anchor.left;
|
|
116
|
-
}
|
|
117
|
-
if (!position.startsWith("horizontal")) return 0;
|
|
118
|
-
if (anchor.right + content.width + margin >= document.body.clientWidth) return anchor.left - content.width;
|
|
119
|
-
return anchor.right;
|
|
120
|
-
}
|
|
121
|
-
function getY(anchor, content, position, margin, preferAbove) {
|
|
122
|
-
if (position === "end" || position === "start" || position === "horizontal") {
|
|
123
|
-
const center = anchor.top + anchor.height / 2;
|
|
124
|
-
const height = content.height / 2;
|
|
125
|
-
if (center + height + margin >= document.body.clientHeight) return document.body.clientHeight - content.height - margin / 2;
|
|
126
|
-
if (center - height - margin <= 0) return margin / 2;
|
|
127
|
-
return center - height;
|
|
128
|
-
}
|
|
129
|
-
if (position.startsWith("above")) return anchor.top - content.height;
|
|
130
|
-
if (position.startsWith("below")) return anchor.bottom;
|
|
131
|
-
if (position.endsWith("bottom")) return anchor.bottom - content.height - margin <= 0 ? margin / 2 : anchor.bottom - content.height;
|
|
132
|
-
if (position.endsWith("top")) return anchor.top + content.height + margin >= document.body.clientHeight ? document.body.clientHeight - content.height - margin : anchor.top;
|
|
133
|
-
if (!position.startsWith("vertical")) return 0;
|
|
134
|
-
if (preferAbove) {
|
|
135
|
-
if (anchor.top - content.height - margin <= 0 && anchor.bottom + content.height + margin <= document.body.clientHeight) return anchor.bottom;
|
|
136
|
-
return anchor.top - content.height;
|
|
137
|
-
}
|
|
138
|
-
if (anchor.bottom + content.height + margin >= document.body.clientHeight) return anchor.top - content.height;
|
|
139
|
-
return anchor.bottom;
|
|
140
|
-
}
|
|
141
88
|
function initialize(floatable) {
|
|
142
89
|
const { anchor, content, interactive } = floatable.options;
|
|
143
90
|
if (interactive) {
|
|
144
91
|
anchor.setAttribute(ATTRIBUTE_ANCHOR, "");
|
|
145
92
|
content.setAttribute(ATTRIBUTE_CONTENT, "");
|
|
146
93
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
content.style.
|
|
94
|
+
const anchorName = getAnchorName();
|
|
95
|
+
anchor.style.anchorName = anchorName;
|
|
96
|
+
content.style.position = "absolute";
|
|
97
|
+
content.style.positionAnchor = anchorName;
|
|
98
|
+
content.style.positionTry = "normal flip-start";
|
|
150
99
|
const state = getState();
|
|
151
100
|
state?.mapped.set(anchor, floatable);
|
|
152
101
|
state?.mapped.set(content, floatable);
|
|
@@ -171,10 +120,13 @@ function onKeyDown(event) {
|
|
|
171
120
|
const floatable = state.mapped.get(related);
|
|
172
121
|
if (floatable != null) floatable.toggle(false);
|
|
173
122
|
}
|
|
174
|
-
function
|
|
175
|
-
let
|
|
176
|
-
if (
|
|
177
|
-
|
|
123
|
+
function setPosition(floatable) {
|
|
124
|
+
let position = floatable.options.anchor.getAttribute(floatable.options.positionAttribute) ?? floatable.options.defaultPosition;
|
|
125
|
+
if (AREAS[position] == null) position = floatable.options.defaultPosition;
|
|
126
|
+
const area = AREAS[position];
|
|
127
|
+
floatable.options.content.style.positionArea = area;
|
|
128
|
+
floatable.options.content.setAttribute(ATTRIBUTE_POSITION, POSITIONS[area]);
|
|
129
|
+
floatable.options.onAfter?.(true);
|
|
178
130
|
}
|
|
179
131
|
function stop(floatable) {
|
|
180
132
|
if (floatable.frame != null) cancelAnimationFrame(floatable.frame);
|
|
@@ -192,77 +144,28 @@ function toggle(anchor) {
|
|
|
192
144
|
else closeAbove(content);
|
|
193
145
|
floatable.toggle(!active);
|
|
194
146
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
floatable.frame = requestAnimationFrame(run);
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
} else calculated = true;
|
|
214
|
-
update(anchor, content);
|
|
215
|
-
}
|
|
216
|
-
function update(anchor, content) {
|
|
217
|
-
previousAnchor = anchor;
|
|
218
|
-
previousContent = content;
|
|
219
|
-
const left = getX(anchor, content, position, margin);
|
|
220
|
-
const top = getY(anchor, content, position, margin, floatable.options.preferAbove);
|
|
221
|
-
setAttribute(position, anchor, floatable.options.content, top, left);
|
|
222
|
-
if (top + content.height > window.innerHeight) floatable.options.content.style.height = `${window.innerHeight - top}px`;
|
|
223
|
-
else floatable.options.content.style.height = "";
|
|
224
|
-
if (left + content.width > window.innerWidth) floatable.options.content.style.width = `${window.innerWidth - left}px`;
|
|
225
|
-
else floatable.options.content.style.width = "";
|
|
226
|
-
floatable.options.content.style.transform = `translate3d(${left}px, ${top}px, 0)`;
|
|
227
|
-
floatable.frame = requestAnimationFrame(run);
|
|
228
|
-
if (!runOnAfter) {
|
|
229
|
-
runOnAfter = true;
|
|
230
|
-
floatable.options.onAfter?.(true);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
floatable.frame = requestAnimationFrame(run);
|
|
234
|
-
}
|
|
147
|
+
const AREAS = {
|
|
148
|
+
above: "block-start",
|
|
149
|
+
"above-end": "start span-start",
|
|
150
|
+
"above-start": "start span-end",
|
|
151
|
+
below: "block-end",
|
|
152
|
+
"below-end": "end span-start",
|
|
153
|
+
"below-start": "end span-end",
|
|
154
|
+
end: "center end",
|
|
155
|
+
"end-bottom": "span-start end",
|
|
156
|
+
"end-top": "span-end end",
|
|
157
|
+
start: "center start",
|
|
158
|
+
"start-bottom": "span-start start",
|
|
159
|
+
"start-top": "span-end start"
|
|
160
|
+
};
|
|
235
161
|
const ATTRIBUTE_ANCHOR = "oui-floatable-anchor";
|
|
236
162
|
const ATTRIBUTE_CONTENT = "oui-floatable-content";
|
|
163
|
+
const ATTRIBUTE_POSITION = "oui-position";
|
|
237
164
|
const INSERT_AFTEREND = "afterend";
|
|
238
|
-
const POSITIONS =
|
|
239
|
-
"above",
|
|
240
|
-
"above-end",
|
|
241
|
-
"above-start",
|
|
242
|
-
"below",
|
|
243
|
-
"below-end",
|
|
244
|
-
"below-start",
|
|
245
|
-
"end",
|
|
246
|
-
"end-bottom",
|
|
247
|
-
"end-top",
|
|
248
|
-
"horizontal",
|
|
249
|
-
"horizontal-bottom",
|
|
250
|
-
"horizontal-top",
|
|
251
|
-
"start",
|
|
252
|
-
"start-bottom",
|
|
253
|
-
"start-top",
|
|
254
|
-
"vertical",
|
|
255
|
-
"vertical-end",
|
|
256
|
-
"vertical-start"
|
|
257
|
-
]);
|
|
258
|
-
const PROPERTIES = [
|
|
259
|
-
"bottom",
|
|
260
|
-
"left",
|
|
261
|
-
"right",
|
|
262
|
-
"top"
|
|
263
|
-
];
|
|
165
|
+
const POSITIONS = Object.fromEntries(Object.entries(AREAS).map(([position, area]) => [area, position]));
|
|
264
166
|
const SELECTOR_ALL = `[${ATTRIBUTE_ANCHOR}], [${ATTRIBUTE_CONTENT}]`;
|
|
265
167
|
const SELECTOR_CONTENT = `[${ATTRIBUTE_CONTENT}]`;
|
|
168
|
+
let index = 0;
|
|
266
169
|
if (window._oscarpalmer_oui_floatable == null) {
|
|
267
170
|
Object.defineProperty(window, "_oscarpalmer_oui_floatable", {
|
|
268
171
|
enumerable: false,
|
package/dist/js/movable.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as Movable } from "./movable-
|
|
1
|
+
import { t as Movable } from "./movable-BKFgoaOl.mjs";
|
|
2
2
|
export { Movable };
|
package/dist/js/popover.mjs
CHANGED
|
@@ -25,7 +25,7 @@ var OuiPopoverElement = class extends HTMLElement {
|
|
|
25
25
|
defaultPosition: "below-start",
|
|
26
26
|
interactive: true,
|
|
27
27
|
positionAttribute: "position",
|
|
28
|
-
|
|
28
|
+
reusable: false,
|
|
29
29
|
onAfter: (active) => {
|
|
30
30
|
if (active) focus(content);
|
|
31
31
|
else if (!this.#floatable.ignoreFocus) toggle.focus();
|
package/dist/js/sortable.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { c as Sortable } from "./movable-
|
|
1
|
+
import { c as Sortable } from "./movable-BKFgoaOl.mjs";
|
|
2
2
|
export { Sortable };
|
package/dist/js/tooltip.d.mts
CHANGED
package/dist/js/tooltip.mjs
CHANGED
|
@@ -5,89 +5,74 @@ import { findAncestor } from "@oscarpalmer/toretto/find";
|
|
|
5
5
|
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
6
6
|
//#region src/js/tooltip.ts
|
|
7
7
|
var Tooltip = class {
|
|
8
|
-
|
|
8
|
+
elements;
|
|
9
9
|
floatable;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
this.
|
|
10
|
+
constructor(anchor, elements) {
|
|
11
|
+
const content = getContent();
|
|
12
|
+
this.elements = elements;
|
|
13
13
|
this.floatable = new Floatable({
|
|
14
14
|
anchor,
|
|
15
|
-
content
|
|
16
|
-
defaultPosition: "
|
|
15
|
+
content,
|
|
16
|
+
defaultPosition: "above",
|
|
17
17
|
interactive: false,
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
positionAttribute: ATTRIBUTE_POSITION,
|
|
19
|
+
reusable: true,
|
|
20
|
+
onAfter: (active) => {
|
|
21
|
+
if (active) {
|
|
22
|
+
content.innerHTML = "";
|
|
23
|
+
content.append(...this.elements);
|
|
24
|
+
}
|
|
25
|
+
if (active || TOOLTIPS_ACTIVE.size > 0) return;
|
|
26
|
+
content.removeAttribute(ATTRIBUTE_CONTENT_ACTIVE);
|
|
27
|
+
contentTimer = setTimeout(() => {
|
|
28
|
+
content.innerHTML = "";
|
|
29
|
+
content.remove();
|
|
30
|
+
}, delayClose);
|
|
31
|
+
}
|
|
20
32
|
});
|
|
21
|
-
anchor.insertAdjacentElement("afterend", content.element);
|
|
22
|
-
TOOLTIPS_ALL.set(content.element, this);
|
|
23
33
|
}
|
|
24
34
|
destroy() {
|
|
25
|
-
const {
|
|
35
|
+
const { floatable } = this;
|
|
26
36
|
TOOLTIPS_ACTIVE.delete(this);
|
|
37
|
+
TOOLTIPS_PENDING.delete(this);
|
|
27
38
|
TOOLTIPS_ALL.delete(floatable.options.anchor);
|
|
28
39
|
TOOLTIPS_ALL.delete(floatable.options.content);
|
|
29
|
-
reset(floatable.options.anchor, attributes);
|
|
30
|
-
floatable.options.content.remove();
|
|
31
40
|
floatable.destroy();
|
|
32
|
-
this.
|
|
41
|
+
this.elements = [];
|
|
33
42
|
this.floatable = void 0;
|
|
34
43
|
}
|
|
35
44
|
};
|
|
36
45
|
function addTooltip(anchor) {
|
|
37
46
|
if (TOOLTIPS_ALL.has(anchor)) return;
|
|
38
|
-
const
|
|
39
|
-
if (
|
|
47
|
+
const elements = getElements(anchor);
|
|
48
|
+
if (elements != null) TOOLTIPS_ALL.set(anchor, new Tooltip(anchor, elements));
|
|
40
49
|
}
|
|
41
|
-
function closeTooltips(
|
|
42
|
-
const
|
|
43
|
-
for (const
|
|
44
|
-
if (
|
|
45
|
-
|
|
46
|
-
active.floatable?.options.content.removeAttribute("oui-tooltip-content-active");
|
|
47
|
-
requestAnimationFrame(() => {
|
|
48
|
-
active.timer = setTimeout(() => {
|
|
49
|
-
TOOLTIPS_ACTIVE.delete(active);
|
|
50
|
-
active.floatable?.toggle(false);
|
|
51
|
-
}, delay);
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
function getContent(anchor) {
|
|
56
|
-
const attributes = {
|
|
57
|
-
ariaDescribedby: anchor.getAttribute("aria-describedby"),
|
|
58
|
-
ariaLabelledBy: anchor.getAttribute("aria-labelledby")
|
|
59
|
-
};
|
|
60
|
-
const wrapper = getWrapper(anchor);
|
|
61
|
-
const labelledElements = getElements(attributes.ariaLabelledBy);
|
|
62
|
-
if (labelledElements.length > 0) {
|
|
63
|
-
anchor.setAttribute("aria-labelledby", wrapper.id);
|
|
64
|
-
for (const element of labelledElements) wrapper.append(element);
|
|
65
|
-
return {
|
|
66
|
-
attributes,
|
|
67
|
-
element: wrapper
|
|
68
|
-
};
|
|
50
|
+
function closeTooltips(current) {
|
|
51
|
+
const pending = [...TOOLTIPS_PENDING];
|
|
52
|
+
for (const item of pending) {
|
|
53
|
+
if (item === current) continue;
|
|
54
|
+
TOOLTIPS_PENDING.delete(item);
|
|
69
55
|
}
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
attributes,
|
|
76
|
-
element: wrapper
|
|
77
|
-
};
|
|
56
|
+
const active = [...TOOLTIPS_ACTIVE];
|
|
57
|
+
for (const item of active) {
|
|
58
|
+
if (item === current) continue;
|
|
59
|
+
TOOLTIPS_ACTIVE.delete(item);
|
|
60
|
+
item.floatable.toggle(false);
|
|
78
61
|
}
|
|
79
|
-
|
|
80
|
-
|
|
62
|
+
}
|
|
63
|
+
function getElements(anchor) {
|
|
64
|
+
let elements = findElements(anchor.getAttribute(ARIA_LABELLEDBY));
|
|
65
|
+
if (elements.length > 0) return elements.map((element) => element.cloneNode(true));
|
|
66
|
+
elements = findElements(anchor.getAttribute(ARIA_DESCRIBEDBY));
|
|
67
|
+
if (elements.length > 0) return elements.map((element) => element.cloneNode(true));
|
|
68
|
+
let content = anchor.getAttribute(ARIA_LABEL);
|
|
69
|
+
if (isNullableOrWhitespace(content)) content = anchor.getAttribute(ARIA_DESCRIPTION);
|
|
81
70
|
if (isNullableOrWhitespace(content)) return;
|
|
82
71
|
const paragraph = document.createElement("p");
|
|
83
72
|
paragraph.textContent = content;
|
|
84
|
-
|
|
85
|
-
return {
|
|
86
|
-
attributes,
|
|
87
|
-
element: wrapper
|
|
88
|
-
};
|
|
73
|
+
return [paragraph];
|
|
89
74
|
}
|
|
90
|
-
function
|
|
75
|
+
function findElements(attribute) {
|
|
91
76
|
const ids = attribute?.split(EXPRESSION_WHITESPACE) ?? [];
|
|
92
77
|
const elements = [];
|
|
93
78
|
for (const id of ids) {
|
|
@@ -101,19 +86,20 @@ function getElements(attribute) {
|
|
|
101
86
|
}
|
|
102
87
|
return elements;
|
|
103
88
|
}
|
|
104
|
-
function
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
wrapper.tabIndex = -1;
|
|
112
|
-
return wrapper;
|
|
89
|
+
function getContent() {
|
|
90
|
+
if (contentElement != null) return contentElement;
|
|
91
|
+
contentElement = document.createElement("div");
|
|
92
|
+
contentElement.setAttribute(ATTRIBUTE_CONTENT, "");
|
|
93
|
+
contentElement.role = "tooltip";
|
|
94
|
+
contentElement.tabIndex = -1;
|
|
95
|
+
return contentElement;
|
|
113
96
|
}
|
|
114
97
|
function onActivate(event) {
|
|
115
98
|
onToggle(event, true);
|
|
116
99
|
}
|
|
100
|
+
function onChange() {
|
|
101
|
+
if (TOOLTIPS_ACTIVE.size === 0) return;
|
|
102
|
+
}
|
|
117
103
|
function onClick(event) {
|
|
118
104
|
if (findAncestor(event, SELECTOR_CONTENT) != null) event.stopPropagation();
|
|
119
105
|
}
|
|
@@ -122,55 +108,67 @@ function onDeactivate(event) {
|
|
|
122
108
|
}
|
|
123
109
|
function onToggle(event, activate) {
|
|
124
110
|
if (toggle != null) cancelAnimationFrame(toggle);
|
|
111
|
+
if (findAncestor(event, SELECTOR_CONTENT) != null) {
|
|
112
|
+
if (contentTimer != null) clearTimeout(contentTimer);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
125
115
|
toggle = requestAnimationFrame(() => {
|
|
126
116
|
toggle = void 0;
|
|
127
|
-
const element = findAncestor(event,
|
|
117
|
+
const element = findAncestor(event, SELECTOR);
|
|
128
118
|
const tooltip = TOOLTIPS_ALL.get(element);
|
|
129
|
-
if (TOOLTIPS_ACTIVE.size > 0) closeTooltips(tooltip);
|
|
130
|
-
if (tooltip == null || tooltip.floatable.
|
|
119
|
+
if (TOOLTIPS_ACTIVE.size > 0 || TOOLTIPS_PENDING.size > 0) closeTooltips(tooltip);
|
|
120
|
+
if (tooltip == null || tooltip.floatable.active === activate) return;
|
|
131
121
|
if (activate) {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
122
|
+
clearTimeout(contentTimer);
|
|
123
|
+
TOOLTIPS_PENDING.add(tooltip);
|
|
124
|
+
contentTimer = setTimeout(() => {
|
|
125
|
+
TOOLTIPS_ACTIVE.add(tooltip);
|
|
126
|
+
TOOLTIPS_PENDING.delete(tooltip);
|
|
127
|
+
tooltip.floatable.options.content.style.positionAnchor = tooltip.floatable.options.anchor.style.anchorName;
|
|
128
|
+
tooltip.floatable.toggle(true);
|
|
129
|
+
setTimeout(() => {
|
|
130
|
+
tooltip.floatable.options.content.setAttribute(ATTRIBUTE_CONTENT_ACTIVE, "");
|
|
131
|
+
});
|
|
132
|
+
}, delayOpen);
|
|
138
133
|
return;
|
|
139
134
|
}
|
|
140
|
-
|
|
141
|
-
tooltip.
|
|
142
|
-
TOOLTIPS_ACTIVE.delete(tooltip);
|
|
143
|
-
tooltip.floatable.toggle(false);
|
|
144
|
-
}, delay);
|
|
135
|
+
TOOLTIPS_ACTIVE.delete(tooltip);
|
|
136
|
+
tooltip.floatable.toggle(false);
|
|
145
137
|
});
|
|
146
138
|
}
|
|
147
139
|
function removeTooltip(element) {
|
|
148
140
|
if (!element.hasAttribute(ATTRIBUTE_CONTENT)) TOOLTIPS_ALL.get(element)?.destroy();
|
|
149
141
|
}
|
|
150
|
-
function
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
}
|
|
154
|
-
function setTooltipDelay(value) {
|
|
155
|
-
delay = typeof value === "number" && value >= 0 ? value : delay;
|
|
142
|
+
function setTooltipDelay(open, close) {
|
|
143
|
+
delayClose = typeof close === "number" && close >= 0 ? close : delayClose;
|
|
144
|
+
delayOpen = typeof open === "number" && open >= 0 ? open : delayOpen;
|
|
156
145
|
}
|
|
157
|
-
const
|
|
158
|
-
const
|
|
159
|
-
const
|
|
160
|
-
const
|
|
146
|
+
const ARIA_DESCRIBEDBY = "aria-describedby";
|
|
147
|
+
const ARIA_DESCRIPTION = "aria-description";
|
|
148
|
+
const ARIA_LABEL = "aria-label";
|
|
149
|
+
const ARIA_LABELLEDBY = "aria-labelledby";
|
|
150
|
+
const ATTRIBUTE = "oui-tooltip";
|
|
151
|
+
const ATTRIBUTE_CONTENT = `${ATTRIBUTE}-content`;
|
|
152
|
+
const ATTRIBUTE_CONTENT_ACTIVE = `${ATTRIBUTE_CONTENT}-active`;
|
|
153
|
+
const ATTRIBUTE_POSITION = `${ATTRIBUTE}-position`;
|
|
154
|
+
const SELECTOR = `[${ATTRIBUTE}]`;
|
|
161
155
|
const SELECTOR_CONTENT = `[${ATTRIBUTE_CONTENT}]`;
|
|
162
|
-
const SELECTOR_FULL = `[${SELECTOR}], [${ATTRIBUTE_CONTENT}]`;
|
|
163
156
|
const EXPRESSION_WHITESPACE = /\s+/;
|
|
164
157
|
const TOOLTIPS_ACTIVE = /* @__PURE__ */ new Set();
|
|
165
158
|
const TOOLTIPS_ALL = /* @__PURE__ */ new WeakMap();
|
|
166
|
-
|
|
167
|
-
let
|
|
159
|
+
const TOOLTIPS_PENDING = /* @__PURE__ */ new Set();
|
|
160
|
+
let contentElement;
|
|
161
|
+
let contentTimer;
|
|
162
|
+
let delayClose = 250;
|
|
163
|
+
let delayOpen = 500;
|
|
168
164
|
let toggle;
|
|
169
|
-
attributable(
|
|
165
|
+
attributable(ATTRIBUTE, addTooltip, removeTooltip);
|
|
170
166
|
on(document, "click", onClick, { capture: true });
|
|
171
167
|
on(document, "focusin", onActivate);
|
|
172
168
|
on(document, "focusout", onDeactivate);
|
|
173
169
|
on(document, "mousemove", onActivate);
|
|
170
|
+
on(window, "resize", onChange);
|
|
171
|
+
on(document, "scroll", onChange);
|
|
174
172
|
on(document, "touchstart", onActivate);
|
|
175
173
|
//#endregion
|
|
176
174
|
export { setTooltipDelay };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oscarpalmer/oui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "Styles, components, and utilities for building websites and applications.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"css",
|
|
@@ -37,10 +37,18 @@
|
|
|
37
37
|
"types": "./dist/js/focus-trap/standalone.d.mts",
|
|
38
38
|
"default": "./dist/js/focus-trap/standalone.mjs"
|
|
39
39
|
},
|
|
40
|
+
"./movable": {
|
|
41
|
+
"types": "./dist/js/movable.d.mts",
|
|
42
|
+
"default": "./dist/js/movable.mjs"
|
|
43
|
+
},
|
|
40
44
|
"./popover": {
|
|
41
45
|
"types": "./dist/js/popover.d.mts",
|
|
42
46
|
"default": "./dist/js/popover.mjs"
|
|
43
47
|
},
|
|
48
|
+
"./sortable": {
|
|
49
|
+
"types": "./dist/js/sortable.d.mts",
|
|
50
|
+
"default": "./dist/js/sortable.mjs"
|
|
51
|
+
},
|
|
44
52
|
"./splitter": {
|
|
45
53
|
"types": "./dist/js/splitter.d.mts",
|
|
46
54
|
"default": "./dist/js/splitter.mjs"
|
|
@@ -66,16 +74,16 @@
|
|
|
66
74
|
"@oscarpalmer/toretto": "^0.46"
|
|
67
75
|
},
|
|
68
76
|
"devDependencies": {
|
|
69
|
-
"@oxlint/plugins": "^1.
|
|
77
|
+
"@oxlint/plugins": "^1.68",
|
|
70
78
|
"@vitest/coverage-istanbul": "^4.1",
|
|
71
79
|
"autoprefixer": "^10.5",
|
|
72
|
-
"concurrently": "^
|
|
80
|
+
"concurrently": "^10",
|
|
73
81
|
"jsdom": "^29.1",
|
|
74
82
|
"postcss-cli": "^11",
|
|
75
83
|
"postcss-input-range": "^6",
|
|
76
84
|
"postcss-scss": "^4",
|
|
77
85
|
"sass": "^1.100",
|
|
78
|
-
"stylelint": "^17.
|
|
86
|
+
"stylelint": "^17.12",
|
|
79
87
|
"stylelint-config-standard-scss": "^17",
|
|
80
88
|
"tsdown": "^0.22",
|
|
81
89
|
"typescript": "^6",
|
|
@@ -84,4 +92,4 @@
|
|
|
84
92
|
"vitest": "npm:@voidzero-dev/vite-plus-test@latest"
|
|
85
93
|
},
|
|
86
94
|
"packageManager": "npm@11.12.1"
|
|
87
|
-
}
|
|
95
|
+
}
|
package/src/css/mixins.scss
CHANGED
|
@@ -60,24 +60,20 @@
|
|
|
60
60
|
margin: var(--margin-top, 0) 0 0 var(--margin-left, 0);
|
|
61
61
|
pointer-events: all !important;
|
|
62
62
|
|
|
63
|
-
&[position^='above']
|
|
64
|
-
|
|
65
|
-
--margin-top: -0.5rem;
|
|
63
|
+
&[oui-position^='above'] {
|
|
64
|
+
margin: 0 0 0.5em;
|
|
66
65
|
}
|
|
67
66
|
|
|
68
|
-
&[position^='below']
|
|
69
|
-
|
|
70
|
-
--margin-top: 0.5rem;
|
|
67
|
+
&[oui-position^='below'] {
|
|
68
|
+
margin: 0.5em 0 0;
|
|
71
69
|
}
|
|
72
70
|
|
|
73
|
-
&[position^='end']
|
|
74
|
-
|
|
75
|
-
--margin-left: 0.5rem;
|
|
71
|
+
&[oui-position^='end'] {
|
|
72
|
+
margin: 0 0 0 0.5em;
|
|
76
73
|
}
|
|
77
74
|
|
|
78
|
-
&[position^='
|
|
79
|
-
|
|
80
|
-
--margin-left: -0.5rem;
|
|
75
|
+
&[oui-position^='start'] {
|
|
76
|
+
margin: 0 0.5em 0 0;
|
|
81
77
|
}
|
|
82
78
|
}
|
|
83
79
|
|