zero-tooltip 1.0.2 → 1.0.3
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/README.md +8 -5
- package/dist/index.d.ts +1 -0
- package/dist/zero-tooltip.js +125 -109
- package/dist/zero-tooltip.umd.cjs +1 -1
- package/package.json +1 -1
- package/src/composables/useHideOnResize.ts +36 -0
- package/src/tooltip.ts +28 -9
- package/src/types/tooltipConfig.ts +2 -1
package/README.md
CHANGED
|
@@ -70,6 +70,7 @@ const tooltipConfig: ZeroTooltipConfig = {
|
|
|
70
70
|
arrowSize: ... ,
|
|
71
71
|
arrowClasses: ... ,
|
|
72
72
|
arrowMinOffsetFromTooltipCorner: ... ,
|
|
73
|
+
zIndex: ...
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
app.directive('tooltip', ZeroTooltip(tooltipConfig))
|
|
@@ -100,6 +101,7 @@ const tooltipConfig: ZeroTooltipLocalConfig = {
|
|
|
100
101
|
arrowSize: ... ,
|
|
101
102
|
arrowClasses: ... ,
|
|
102
103
|
arrowMinOffsetFromTooltipCorner: ... ,
|
|
104
|
+
zIndex: ...
|
|
103
105
|
}
|
|
104
106
|
</script>
|
|
105
107
|
```
|
|
@@ -107,18 +109,19 @@ const tooltipConfig: ZeroTooltipLocalConfig = {
|
|
|
107
109
|
## ZeroTooltipConfig
|
|
108
110
|
| Property | <div style="width:260px">Default value</div> | Type | Details |
|
|
109
111
|
|---|---|---|---|
|
|
110
|
-
| defaultPosition | *top* | TooltipPosition |
|
|
112
|
+
| defaultPosition | *top* | TooltipPosition | Position of tooltip component relative to element that is being hovered |
|
|
111
113
|
| positions | *{ <br>   left: ['left', 'right', 'top', 'bottom'], <br>   top: ['top', 'bottom', 'right', 'left'], <br>   right: ['right', 'left', 'top', 'bottom'], <br>   bottom: ['bottom', 'top', 'right', 'left'], <br> }* | TooltipPositions | Ordered list of fallback positions in case tooltip does not have enough space in default position. If none of given positions will have enough space for tooltip, then it will not be rendered. |
|
|
112
114
|
| offsetFromSource | *10* | number | Tooltip offset in `px` from element that's being hovered *(arrow size is not added to this value)* |
|
|
113
|
-
| offsetFromViewport | *20* | number | Minimal allowed tooltip offset in `px` from
|
|
115
|
+
| offsetFromViewport | *20* | number | Minimal allowed tooltip offset in `px` from viewport sides |
|
|
114
116
|
| minWidth | *100* | number | Minimal tooltip width in `px` that will be allowed to render |
|
|
115
117
|
| maxWidth | *250* | number | Maximal tooltip width in `px` that will be allowed to render |
|
|
116
118
|
| tooltipBorderWidth | *0* | number | Tooltip container border width in `px` |
|
|
117
119
|
| tooltipClasses | *undefined* | string | List of classes that will be added to tooltip element |
|
|
118
120
|
| textClasses | *undefined* | string | List of classes that will be added to text element |
|
|
119
|
-
| arrowSize | *5* | number |
|
|
121
|
+
| arrowSize | *5* | number | Length of arrow hypotenuse in `px` (arrow is generated using border width property, creating square which gets divided in four triangles, thus `arrowSize` is length of square side) |
|
|
120
122
|
| arrowClasses | *undefined* | string | List of classes that will be added to arrow element |
|
|
121
123
|
| arrowMinOffsetFromTooltipCorner | *6* | number | Minimal allowed arrow offset in `px` from tooltip corner. Used in situations when tooltip does not have enough space to be centered relative to element that is being hover, thus arrow is rendered closer to one of the tooltip corners |
|
|
124
|
+
| zIndex | *1* | number | `z-index` css property value of tooltip |
|
|
122
125
|
|
|
123
126
|
## ZeroTooltipLocalConfig
|
|
124
127
|
Same as [ZeroTooltipConfig](#ZeroTooltipConfig) with following additions:
|
|
@@ -126,5 +129,5 @@ Same as [ZeroTooltipConfig](#ZeroTooltipConfig) with following additions:
|
|
|
126
129
|
|---|---|---|---|
|
|
127
130
|
| content | *undefined* | string | ***REQUIRED***. Tooltip text. Text is rendered as HTML, thus it's possible to give simple HTML structure, e.g., `<h1>Tooltip text</h1>` |
|
|
128
131
|
|
|
129
|
-
##
|
|
130
|
-
The
|
|
132
|
+
## License
|
|
133
|
+
The license is MIT, so any extension, forking is welcome. `zero-tooltip` is designed as fully customizable, zero dependency, simple tooltip for Vue.js.
|
package/dist/index.d.ts
CHANGED
package/dist/zero-tooltip.js
CHANGED
|
@@ -1,163 +1,179 @@
|
|
|
1
|
-
function
|
|
2
|
-
let
|
|
3
|
-
const
|
|
4
|
-
if (m(
|
|
5
|
-
for (const
|
|
6
|
-
|
|
1
|
+
function Q() {
|
|
2
|
+
let t = [];
|
|
3
|
+
const a = (w, n) => {
|
|
4
|
+
if (m(w), t.length > 0)
|
|
5
|
+
for (const l of t)
|
|
6
|
+
l.addEventListener("scroll", n);
|
|
7
7
|
window.addEventListener("scroll", () => {
|
|
8
|
-
|
|
8
|
+
n(), s(n);
|
|
9
9
|
});
|
|
10
|
-
}, m = (
|
|
11
|
-
let
|
|
12
|
-
for (;
|
|
13
|
-
if (
|
|
14
|
-
const
|
|
15
|
-
(
|
|
10
|
+
}, m = (w) => {
|
|
11
|
+
let n = w;
|
|
12
|
+
for (; n !== null && n.tagName !== "HTML"; ) {
|
|
13
|
+
if (n.scrollHeight !== n.clientHeight) {
|
|
14
|
+
const l = window.getComputedStyle(n);
|
|
15
|
+
(l.overflow === "auto" || l.overflow === "scroll") && t.push(n);
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
n = n.parentElement;
|
|
18
18
|
}
|
|
19
|
-
}, s = (
|
|
20
|
-
if (
|
|
21
|
-
for (const
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
}, s = (w) => {
|
|
20
|
+
if (t.length > 0) {
|
|
21
|
+
for (const n of t)
|
|
22
|
+
n.removeEventListener("scroll", w);
|
|
23
|
+
t = [];
|
|
24
24
|
}
|
|
25
|
-
window.removeEventListener("scroll",
|
|
25
|
+
window.removeEventListener("scroll", w);
|
|
26
26
|
};
|
|
27
|
-
return { handleHideOnScroll:
|
|
27
|
+
return { handleHideOnScroll: a };
|
|
28
28
|
}
|
|
29
|
-
|
|
29
|
+
function U() {
|
|
30
|
+
let t = null, a = null;
|
|
31
|
+
return { handleHideOnResize: (w, n) => {
|
|
32
|
+
t = new ResizeObserver((l) => {
|
|
33
|
+
const W = l[0].target;
|
|
34
|
+
if (a === null)
|
|
35
|
+
a = w.getBoundingClientRect();
|
|
36
|
+
else {
|
|
37
|
+
const C = W.getBoundingClientRect();
|
|
38
|
+
(C.left !== a.left || C.top !== a.top || C.width !== a.width || C.height !== a.height) && n();
|
|
39
|
+
}
|
|
40
|
+
}), t.observe(w);
|
|
41
|
+
}, resetResizeReferences: () => {
|
|
42
|
+
t !== null && t.disconnect(), t = null, a = null;
|
|
43
|
+
} };
|
|
44
|
+
}
|
|
45
|
+
const { handleHideOnScroll: X } = Q(), { handleHideOnResize: Y, resetResizeReferences: E } = U(), H = "zero-tooltip__container", R = "zero-tooltip__text", q = "zero-tooltip__arrow", v = {
|
|
30
46
|
left: ["left", "right", "top", "bottom"],
|
|
31
47
|
top: ["top", "bottom", "right", "left"],
|
|
32
48
|
right: ["right", "left", "top", "bottom"],
|
|
33
49
|
bottom: ["bottom", "top", "right", "left"]
|
|
34
50
|
};
|
|
35
|
-
let
|
|
36
|
-
const
|
|
37
|
-
var
|
|
38
|
-
|
|
39
|
-
let
|
|
40
|
-
left: ((
|
|
41
|
-
top: ((
|
|
42
|
-
right: ((
|
|
43
|
-
bottom: ((
|
|
44
|
-
}, m = (
|
|
51
|
+
let c = "top";
|
|
52
|
+
const V = 10, g = 20, tt = 100, et = 250, ot = 0, rt = "zt-fixed zt-opacity-0 zt-inline-block zt-w-fit zt-py-1.5 zt-px-2.5 zt-rounded-md zt-bg-[#495057] zt-shadow-[0_2px_12px_0_rgba(0,0,0,0.1)] zt-box-border", st = "zt-text-sm zt-text-white zt-whitespace-pre-wrap zt-break-words", lt = 5, it = "zt-absolute zt-border-solid zt-border-[#495057]", pt = 6, dt = 1, at = (t) => {
|
|
53
|
+
var F, $, A, B;
|
|
54
|
+
t != null && t.defaultPosition && (c = t.defaultPosition);
|
|
55
|
+
let a = {
|
|
56
|
+
left: ((F = t == null ? void 0 : t.positions) == null ? void 0 : F.left) ?? v.left,
|
|
57
|
+
top: (($ = t == null ? void 0 : t.positions) == null ? void 0 : $.top) ?? v.top,
|
|
58
|
+
right: ((A = t == null ? void 0 : t.positions) == null ? void 0 : A.right) ?? v.right,
|
|
59
|
+
bottom: ((B = t == null ? void 0 : t.positions) == null ? void 0 : B.bottom) ?? v.bottom
|
|
60
|
+
}, m = (t == null ? void 0 : t.offsetFromSource) ?? V, s = (t == null ? void 0 : t.offsetFromViewport) ?? g, w = (t == null ? void 0 : t.minWidth) ?? tt, n = (t == null ? void 0 : t.maxWidth) ?? et, l = (t == null ? void 0 : t.tooltipBorderWidth) ?? ot, W = H + " " + rt + " " + (t == null ? void 0 : t.tooltipClasses), C = R + " " + st + " " + (t == null ? void 0 : t.textClasses), x = (t == null ? void 0 : t.arrowSize) ?? lt, f = (t == null ? void 0 : t.arrowMinOffsetFromTooltipCorner) ?? pt, b = (t == null ? void 0 : t.zIndex) ?? dt;
|
|
45
61
|
return {
|
|
46
|
-
mounted: (
|
|
47
|
-
let
|
|
48
|
-
typeof
|
|
49
|
-
const P =
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
i == null || i.appendChild(
|
|
55
|
-
let o = !1,
|
|
56
|
-
for (let r = 0; r < 4 && (
|
|
62
|
+
mounted: (y, M) => {
|
|
63
|
+
let L = M.arg ?? c;
|
|
64
|
+
typeof M.value != "string" && j(M.value);
|
|
65
|
+
const P = nt(M.value), O = document.createElement("p");
|
|
66
|
+
O.classList.add(...C.split(" ")), O.innerHTML = P;
|
|
67
|
+
const d = document.createElement("div");
|
|
68
|
+
d.classList.add(...W.split(" ")), d.style.borderWidth = `${l}px`, d.appendChild(O), y.addEventListener("mouseenter", () => {
|
|
69
|
+
const e = y.getBoundingClientRect(), i = document.querySelector("body");
|
|
70
|
+
i == null || i.appendChild(d);
|
|
71
|
+
let o = !1, p = L;
|
|
72
|
+
for (let r = 0; r < 4 && (p = a[L][r], p === "left" ? o = N(e) : p === "top" ? o = D(e) : p === "right" ? o = Z(e) : p === "bottom" && (o = G(e)), !o); r++)
|
|
57
73
|
;
|
|
58
|
-
o && (
|
|
59
|
-
}),
|
|
60
|
-
function
|
|
61
|
-
|
|
74
|
+
o && (J(e, p), d.style.opacity = "1", d.style.zIndex = b.toString(), X(y, () => S()), Y(y, () => S()));
|
|
75
|
+
}), y.addEventListener("mouseleave", () => S());
|
|
76
|
+
function j(e) {
|
|
77
|
+
e.defaultPosition && (L = e.defaultPosition), e.positions && (a = { ...a, ...e.positions }), e.offsetFromSource && (m = e.offsetFromSource), e.offsetFromViewport && (s = e.offsetFromViewport), e.minWidth && (w = e.minWidth), e.maxWidth && (n = e.maxWidth), e.tooltipBorderWidth && (l = e.tooltipBorderWidth), e.tooltipClasses && (W = e.tooltipClasses), e.textClasses && (C = e.textClasses), e.arrowSize && (x = e.arrowSize), e.arrowMinOffsetFromTooltipCorner && (f = e.arrowMinOffsetFromTooltipCorner), e.zIndex && (b = e.zIndex);
|
|
62
78
|
}
|
|
63
|
-
function
|
|
64
|
-
const i = Math.min(
|
|
65
|
-
if (i <
|
|
79
|
+
function N(e) {
|
|
80
|
+
const i = Math.min(e.left - m - s, n), o = e.top >= s, p = window.innerHeight - e.bottom >= s;
|
|
81
|
+
if (i < w || !o || !p)
|
|
66
82
|
return !1;
|
|
67
|
-
|
|
68
|
-
const r =
|
|
69
|
-
let
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
return
|
|
83
|
+
d.style.maxWidth = `${i}px`;
|
|
84
|
+
const r = d.getBoundingClientRect();
|
|
85
|
+
let h = e.top + e.height / 2 - r.height / 2;
|
|
86
|
+
h < s ? h = s : h + r.height > window.innerHeight - s && (h = window.innerHeight - s - r.height);
|
|
87
|
+
const u = e.left - m - r.width;
|
|
88
|
+
return e.bottom < h + f * 2 || e.top > h + r.height - f * 2 ? !1 : (d.style.top = `${h}px`, d.style.left = `${u}px`, !0);
|
|
73
89
|
}
|
|
74
|
-
function
|
|
75
|
-
const i = Math.min(window.innerWidth - (
|
|
76
|
-
if (i <
|
|
90
|
+
function Z(e) {
|
|
91
|
+
const i = Math.min(window.innerWidth - (e.right + m) - s, n), o = e.top >= s, p = window.innerHeight - e.bottom >= s;
|
|
92
|
+
if (i < w || !o || !p)
|
|
77
93
|
return !1;
|
|
78
|
-
|
|
79
|
-
const r =
|
|
80
|
-
let
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
return
|
|
94
|
+
d.style.maxWidth = `${i}px`;
|
|
95
|
+
const r = d.getBoundingClientRect();
|
|
96
|
+
let h = e.top + e.height / 2 - r.height / 2;
|
|
97
|
+
h < s ? h = s : h + r.height > window.innerHeight - s && (h = window.innerHeight - s - r.height);
|
|
98
|
+
const u = e.right + m;
|
|
99
|
+
return e.bottom < h + f * 2 || e.top > h + r.height - f * 2 ? !1 : (d.style.top = `${h}px`, d.style.left = `${u}px`, !0);
|
|
84
100
|
}
|
|
85
|
-
function
|
|
86
|
-
const i = Math.min(window.innerWidth - s * 2,
|
|
87
|
-
|
|
88
|
-
const o =
|
|
89
|
-
let
|
|
90
|
-
if (
|
|
101
|
+
function D(e) {
|
|
102
|
+
const i = Math.min(window.innerWidth - s * 2, n);
|
|
103
|
+
d.style.maxWidth = `${i}px`;
|
|
104
|
+
const o = d.getBoundingClientRect();
|
|
105
|
+
let p = e.top - m - o.height;
|
|
106
|
+
if (p < s)
|
|
91
107
|
return !1;
|
|
92
|
-
let r =
|
|
93
|
-
return r < s ? r = s : r + o.width > window.innerWidth - s && (r = window.innerWidth - s - o.width),
|
|
108
|
+
let r = e.left + e.width / 2 - o.width / 2;
|
|
109
|
+
return r < s ? r = s : r + o.width > window.innerWidth - s && (r = window.innerWidth - s - o.width), e.left > r + o.width - f * 2 || e.right < r + f * 2 ? !1 : (d.style.top = `${p}px`, d.style.left = `${r}px`, !0);
|
|
94
110
|
}
|
|
95
|
-
function
|
|
96
|
-
const i = Math.min(window.innerWidth - s * 2,
|
|
97
|
-
|
|
98
|
-
const o =
|
|
99
|
-
let
|
|
100
|
-
if (
|
|
111
|
+
function G(e) {
|
|
112
|
+
const i = Math.min(window.innerWidth - s * 2, n);
|
|
113
|
+
d.style.maxWidth = `${i}px`;
|
|
114
|
+
const o = d.getBoundingClientRect();
|
|
115
|
+
let p = e.bottom + m;
|
|
116
|
+
if (p + o.height > window.innerHeight - s)
|
|
101
117
|
return !1;
|
|
102
|
-
let r =
|
|
103
|
-
return r < s ? r = s : r + o.width > window.innerWidth - s && (r = window.innerWidth - s - o.width),
|
|
118
|
+
let r = e.left + e.width / 2 - o.width / 2;
|
|
119
|
+
return r < s ? r = s : r + o.width > window.innerWidth - s && (r = window.innerWidth - s - o.width), e.left > r + o.width - f * 2 || e.right < r + f * 2 ? !1 : (d.style.top = `${p}px`, d.style.left = `${r}px`, !0);
|
|
104
120
|
}
|
|
105
|
-
function
|
|
106
|
-
var
|
|
107
|
-
const o = document.createElement("div"),
|
|
108
|
-
let
|
|
121
|
+
function J(e, i) {
|
|
122
|
+
var I;
|
|
123
|
+
const o = document.createElement("div"), p = d.getBoundingClientRect(), r = Math.sin(45 * (180 / Math.PI)) * x, h = 1;
|
|
124
|
+
let u = 0, z = 0, T = "";
|
|
109
125
|
switch (i) {
|
|
110
126
|
case "left":
|
|
111
|
-
|
|
127
|
+
T = "!zt-border-y-transparent !zt-border-r-transparent", u = e.top - p.top + e.height / 2 - r - l, z = p.width - l - h;
|
|
112
128
|
break;
|
|
113
129
|
case "top":
|
|
114
|
-
|
|
130
|
+
T = "!zt-border-x-transparent !zt-border-b-transparent", u = p.height - l - h, z = e.left - p.left + e.width / 2 - r - l;
|
|
115
131
|
break;
|
|
116
132
|
case "right":
|
|
117
|
-
|
|
133
|
+
T = "!zt-border-y-transparent !zt-border-l-transparent", u = e.top - p.top + e.height / 2 - r - l, z = -x * 2 - l + h;
|
|
118
134
|
break;
|
|
119
135
|
case "bottom":
|
|
120
|
-
|
|
136
|
+
T = "!zt-border-x-transparent !zt-border-t-transparent", u = -x * 2 - l + h, z = e.left - p.left + e.width / 2 - r - l;
|
|
121
137
|
break;
|
|
122
138
|
}
|
|
123
|
-
i === "left" || i === "right" ?
|
|
124
|
-
const
|
|
125
|
-
o.classList.add(...
|
|
139
|
+
i === "left" || i === "right" ? _(i, p, u) || (u = k(i, p, u)) : _(i, p, z) || (z = k(i, p, z));
|
|
140
|
+
const K = q + " " + it + " " + T + " " + (t == null ? void 0 : t.arrowClasses);
|
|
141
|
+
o.classList.add(...K.split(" ")), o.style.top = `${u}px`, o.style.left = `${z}px`, o.style.borderWidth = `${x}px`, (I = document.querySelector(`.${H}`)) == null || I.appendChild(o);
|
|
126
142
|
}
|
|
127
|
-
function
|
|
128
|
-
switch (
|
|
143
|
+
function _(e, i, o) {
|
|
144
|
+
switch (e) {
|
|
129
145
|
case "left":
|
|
130
146
|
case "right":
|
|
131
|
-
return o >
|
|
147
|
+
return o > f - l && o < i.height + l - f - x * 2;
|
|
132
148
|
case "top":
|
|
133
149
|
case "bottom":
|
|
134
|
-
return o >
|
|
150
|
+
return o > f - l && o < i.width + l - f - x * 2;
|
|
135
151
|
}
|
|
136
152
|
}
|
|
137
|
-
function
|
|
138
|
-
switch (
|
|
153
|
+
function k(e, i, o) {
|
|
154
|
+
switch (e) {
|
|
139
155
|
case "left":
|
|
140
156
|
case "right":
|
|
141
|
-
return o <
|
|
157
|
+
return o < f - l ? f - l : i.height - l - f - x * 2;
|
|
142
158
|
case "top":
|
|
143
159
|
case "bottom":
|
|
144
|
-
return o <
|
|
160
|
+
return o < f - l ? f - l : i.width - l - f - x * 2;
|
|
145
161
|
}
|
|
146
162
|
}
|
|
147
163
|
}
|
|
148
164
|
};
|
|
149
165
|
};
|
|
150
|
-
function
|
|
151
|
-
var
|
|
152
|
-
const
|
|
153
|
-
|
|
166
|
+
function S() {
|
|
167
|
+
var a;
|
|
168
|
+
const t = document.querySelector(`.${H}`);
|
|
169
|
+
t && t instanceof HTMLElement && (E(), (a = t.querySelector(`.${q}`)) == null || a.remove(), t.style.left = "0", t.style.top = "0", t.remove());
|
|
154
170
|
}
|
|
155
|
-
function
|
|
156
|
-
let
|
|
157
|
-
if (typeof
|
|
171
|
+
function nt(t) {
|
|
172
|
+
let a = "";
|
|
173
|
+
if (typeof t == "string" ? a = t : a = t.content, !a)
|
|
158
174
|
throw new Error("Please enter valid tooltip value");
|
|
159
|
-
return
|
|
175
|
+
return a;
|
|
160
176
|
}
|
|
161
177
|
export {
|
|
162
|
-
|
|
178
|
+
at as default
|
|
163
179
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(y,T){typeof exports=="object"&&typeof module<"u"?module.exports=T():typeof define=="function"&&define.amd?define(T):(y=typeof globalThis<"u"?globalThis:y||self,y.ZeroTooltip=T())})(this,function(){"use strict";function y(){let t=[];const h=(w,n)=>{if(m(w),t.length>0)for(const i of t)i.addEventListener("scroll",n);window.addEventListener("scroll",()=>{n(),r(n)})},m=w=>{let n=w;for(;n!==null&&n.tagName!=="HTML";){if(n.scrollHeight!==n.clientHeight){const i=window.getComputedStyle(n);(i.overflow==="auto"||i.overflow==="scroll")&&t.push(n)}n=n.parentElement}},r=w=>{if(t.length>0){for(const n of t)n.removeEventListener("scroll",w);t=[]}window.removeEventListener("scroll",w)};return{handleHideOnScroll:h}}function T(){let t=null,h=null;return{handleHideOnResize:(w,n)=>{t=new ResizeObserver(i=>{const L=i[0].target;if(h===null)h=w.getBoundingClientRect();else{const C=L.getBoundingClientRect();(C.left!==h.left||C.top!==h.top||C.width!==h.width||C.height!==h.height)&&n()}}),t.observe(w)},resetResizeReferences:()=>{t!==null&&t.disconnect(),t=null,h=null}}}const{handleHideOnScroll:Z}=y(),{handleHideOnResize:N,resetResizeReferences:D}=T(),S="zero-tooltip__container",G="zero-tooltip__text",$="zero-tooltip__arrow",v={left:["left","right","top","bottom"],top:["top","bottom","right","left"],right:["right","left","top","bottom"],bottom:["bottom","top","right","left"]};let A="top";const J=10,K=20,Q=100,U=250,X=0,Y="zt-fixed zt-opacity-0 zt-inline-block zt-w-fit zt-py-1.5 zt-px-2.5 zt-rounded-md zt-bg-[#495057] zt-shadow-[0_2px_12px_0_rgba(0,0,0,0.1)] zt-box-border",E="zt-text-sm zt-text-white zt-whitespace-pre-wrap zt-break-words",R=5,V="zt-absolute zt-border-solid zt-border-[#495057]",g=6,tt=1,et=t=>{var _,c,k,I;t!=null&&t.defaultPosition&&(A=t.defaultPosition);let h={left:((_=t==null?void 0:t.positions)==null?void 0:_.left)??v.left,top:((c=t==null?void 0:t.positions)==null?void 0:c.top)??v.top,right:((k=t==null?void 0:t.positions)==null?void 0:k.right)??v.right,bottom:((I=t==null?void 0:t.positions)==null?void 0:I.bottom)??v.bottom},m=(t==null?void 0:t.offsetFromSource)??J,r=(t==null?void 0:t.offsetFromViewport)??K,w=(t==null?void 0:t.minWidth)??Q,n=(t==null?void 0:t.maxWidth)??U,i=(t==null?void 0:t.tooltipBorderWidth)??X,L=S+" "+Y+" "+(t==null?void 0:t.tooltipClasses),C=G+" "+E+" "+(t==null?void 0:t.textClasses),x=(t==null?void 0:t.arrowSize)??R,f=(t==null?void 0:t.arrowMinOffsetFromTooltipCorner)??g,B=(t==null?void 0:t.zIndex)??tt;return{mounted:(W,O)=>{let b=O.arg??A;typeof O.value!="string"&&rt(O.value);const st=ot(O.value),F=document.createElement("p");F.classList.add(...C.split(" ")),F.innerHTML=st;const d=document.createElement("div");d.classList.add(...L.split(" ")),d.style.borderWidth=`${i}px`,d.appendChild(F),W.addEventListener("mouseenter",()=>{const e=W.getBoundingClientRect(),l=document.querySelector("body");l==null||l.appendChild(d);let o=!1,p=b;for(let s=0;s<4&&(p=h[b][s],p==="left"?o=it(e):p==="top"?o=pt(e):p==="right"?o=lt(e):p==="bottom"&&(o=dt(e)),!o);s++);o&&(nt(e,p),d.style.opacity="1",d.style.zIndex=B.toString(),Z(W,()=>H()),N(W,()=>H()))}),W.addEventListener("mouseleave",()=>H());function rt(e){e.defaultPosition&&(b=e.defaultPosition),e.positions&&(h={...h,...e.positions}),e.offsetFromSource&&(m=e.offsetFromSource),e.offsetFromViewport&&(r=e.offsetFromViewport),e.minWidth&&(w=e.minWidth),e.maxWidth&&(n=e.maxWidth),e.tooltipBorderWidth&&(i=e.tooltipBorderWidth),e.tooltipClasses&&(L=e.tooltipClasses),e.textClasses&&(C=e.textClasses),e.arrowSize&&(x=e.arrowSize),e.arrowMinOffsetFromTooltipCorner&&(f=e.arrowMinOffsetFromTooltipCorner),e.zIndex&&(B=e.zIndex)}function it(e){const l=Math.min(e.left-m-r,n),o=e.top>=r,p=window.innerHeight-e.bottom>=r;if(l<w||!o||!p)return!1;d.style.maxWidth=`${l}px`;const s=d.getBoundingClientRect();let a=e.top+e.height/2-s.height/2;a<r?a=r:a+s.height>window.innerHeight-r&&(a=window.innerHeight-r-s.height);const u=e.left-m-s.width;return e.bottom<a+f*2||e.top>a+s.height-f*2?!1:(d.style.top=`${a}px`,d.style.left=`${u}px`,!0)}function lt(e){const l=Math.min(window.innerWidth-(e.right+m)-r,n),o=e.top>=r,p=window.innerHeight-e.bottom>=r;if(l<w||!o||!p)return!1;d.style.maxWidth=`${l}px`;const s=d.getBoundingClientRect();let a=e.top+e.height/2-s.height/2;a<r?a=r:a+s.height>window.innerHeight-r&&(a=window.innerHeight-r-s.height);const u=e.right+m;return e.bottom<a+f*2||e.top>a+s.height-f*2?!1:(d.style.top=`${a}px`,d.style.left=`${u}px`,!0)}function pt(e){const l=Math.min(window.innerWidth-r*2,n);d.style.maxWidth=`${l}px`;const o=d.getBoundingClientRect();let p=e.top-m-o.height;if(p<r)return!1;let s=e.left+e.width/2-o.width/2;return s<r?s=r:s+o.width>window.innerWidth-r&&(s=window.innerWidth-r-o.width),e.left>s+o.width-f*2||e.right<s+f*2?!1:(d.style.top=`${p}px`,d.style.left=`${s}px`,!0)}function dt(e){const l=Math.min(window.innerWidth-r*2,n);d.style.maxWidth=`${l}px`;const o=d.getBoundingClientRect();let p=e.bottom+m;if(p+o.height>window.innerHeight-r)return!1;let s=e.left+e.width/2-o.width/2;return s<r?s=r:s+o.width>window.innerWidth-r&&(s=window.innerWidth-r-o.width),e.left>s+o.width-f*2||e.right<s+f*2?!1:(d.style.top=`${p}px`,d.style.left=`${s}px`,!0)}function nt(e,l){var j;const o=document.createElement("div"),p=d.getBoundingClientRect(),s=Math.sin(45*(180/Math.PI))*x,a=1;let u=0,z=0,M="";switch(l){case"left":M="!zt-border-y-transparent !zt-border-r-transparent",u=e.top-p.top+e.height/2-s-i,z=p.width-i-a;break;case"top":M="!zt-border-x-transparent !zt-border-b-transparent",u=p.height-i-a,z=e.left-p.left+e.width/2-s-i;break;case"right":M="!zt-border-y-transparent !zt-border-l-transparent",u=e.top-p.top+e.height/2-s-i,z=-x*2-i+a;break;case"bottom":M="!zt-border-x-transparent !zt-border-t-transparent",u=-x*2-i+a,z=e.left-p.left+e.width/2-s-i;break}l==="left"||l==="right"?q(l,p,u)||(u=P(l,p,u)):q(l,p,z)||(z=P(l,p,z));const ht=$+" "+V+" "+M+" "+(t==null?void 0:t.arrowClasses);o.classList.add(...ht.split(" ")),o.style.top=`${u}px`,o.style.left=`${z}px`,o.style.borderWidth=`${x}px`,(j=document.querySelector(`.${S}`))==null||j.appendChild(o)}function q(e,l,o){switch(e){case"left":case"right":return o>f-i&&o<l.height+i-f-x*2;case"top":case"bottom":return o>f-i&&o<l.width+i-f-x*2}}function P(e,l,o){switch(e){case"left":case"right":return o<f-i?f-i:l.height-i-f-x*2;case"top":case"bottom":return o<f-i?f-i:l.width-i-f-x*2}}}}};function H(){var h;const t=document.querySelector(`.${S}`);t&&t instanceof HTMLElement&&(D(),(h=t.querySelector(`.${$}`))==null||h.remove(),t.style.left="0",t.style.top="0",t.remove())}function ot(t){let h="";if(typeof t=="string"?h=t:h=t.content,!h)throw new Error("Please enter valid tooltip value");return h}return et});
|
package/package.json
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export default function useHideOnResize() {
|
|
2
|
+
let anchorElementResizeObserver: ResizeObserver | null = null
|
|
3
|
+
let anchorElementRect: DOMRect | null = null
|
|
4
|
+
|
|
5
|
+
const handleHideOnResize = (anchorElement: HTMLElement, hideOverlay: () => void) => {
|
|
6
|
+
anchorElementResizeObserver = new ResizeObserver((entries) => {
|
|
7
|
+
const targetElement = entries[0].target
|
|
8
|
+
|
|
9
|
+
if (anchorElementRect === null) {
|
|
10
|
+
// On initial trigger set initial values
|
|
11
|
+
anchorElementRect = anchorElement.getBoundingClientRect()
|
|
12
|
+
} else {
|
|
13
|
+
const targetElementRect = targetElement.getBoundingClientRect()
|
|
14
|
+
|
|
15
|
+
// Check if anchor element has moved or resized
|
|
16
|
+
if (targetElementRect.left !== anchorElementRect.left
|
|
17
|
+
|| targetElementRect.top !== anchorElementRect.top
|
|
18
|
+
|| targetElementRect.width !== anchorElementRect.width
|
|
19
|
+
|| targetElementRect.height !== anchorElementRect.height) {
|
|
20
|
+
hideOverlay()
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
anchorElementResizeObserver.observe(anchorElement)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const resetResizeReferences = () => {
|
|
29
|
+
if (anchorElementResizeObserver !== null) anchorElementResizeObserver.disconnect()
|
|
30
|
+
|
|
31
|
+
anchorElementResizeObserver = null
|
|
32
|
+
anchorElementRect = null
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return { handleHideOnResize, resetResizeReferences }
|
|
36
|
+
}
|
package/src/tooltip.ts
CHANGED
|
@@ -2,10 +2,12 @@ import { Directive } from "vue"
|
|
|
2
2
|
import TooltipConfig from "./types/tooltipConfig"
|
|
3
3
|
import TooltipPosition from "./types/tooltipPosition"
|
|
4
4
|
import TooltipPositions from "./types/tooltipPositions"
|
|
5
|
-
import useHideOnScroll from './composables/useHideOnScroll'
|
|
6
5
|
import TooltipLocalConfig from "./types/tooltipLocalConfig"
|
|
6
|
+
import useHideOnScroll from './composables/useHideOnScroll'
|
|
7
|
+
import useHideOnResize from "./composables/useHideOnResize"
|
|
7
8
|
|
|
8
9
|
const { handleHideOnScroll } = useHideOnScroll()
|
|
10
|
+
const { handleHideOnResize, resetResizeReferences } = useHideOnResize()
|
|
9
11
|
|
|
10
12
|
const tooltipElementClass = 'zero-tooltip__container'
|
|
11
13
|
const textElementClass = 'zero-tooltip__text'
|
|
@@ -31,6 +33,7 @@ const defaultTextClasses = 'zt-text-sm zt-text-white zt-whitespace-pre-wrap zt-b
|
|
|
31
33
|
const defaultArrowSize = 5
|
|
32
34
|
const defaultArrowClasses = 'zt-absolute zt-border-solid zt-border-[#495057]'
|
|
33
35
|
const defaultMinArrowOffsetFromTooltipCorner = 6
|
|
36
|
+
const defaultZIndex = 1
|
|
34
37
|
|
|
35
38
|
const ZeroTooltip = (config?: TooltipConfig): Directive => {
|
|
36
39
|
if (config?.defaultPosition) {
|
|
@@ -53,6 +56,7 @@ const ZeroTooltip = (config?: TooltipConfig): Directive => {
|
|
|
53
56
|
let textClasses = textElementClass + ' ' + defaultTextClasses + ' ' + config?.textClasses ?? ''
|
|
54
57
|
let arrowSize = config?.arrowSize ?? defaultArrowSize
|
|
55
58
|
let arrowMinOffsetFromTooltipCorner = config?.arrowMinOffsetFromTooltipCorner ?? defaultMinArrowOffsetFromTooltipCorner
|
|
59
|
+
let zIndex = config?.zIndex ?? defaultZIndex
|
|
56
60
|
|
|
57
61
|
return {
|
|
58
62
|
mounted: (anchorElement: HTMLElement, binding) => {
|
|
@@ -105,11 +109,14 @@ const ZeroTooltip = (config?: TooltipConfig): Directive => {
|
|
|
105
109
|
drawArrow(anchorElementRect, currentTooltipPosition)
|
|
106
110
|
|
|
107
111
|
tooltipElement.style.opacity = '1'
|
|
112
|
+
tooltipElement.style.zIndex = zIndex.toString()
|
|
113
|
+
|
|
108
114
|
handleHideOnScroll(anchorElement, () => hideTooltip())
|
|
115
|
+
handleHideOnResize(anchorElement, () => hideTooltip())
|
|
109
116
|
}
|
|
110
117
|
})
|
|
111
118
|
|
|
112
|
-
// Add
|
|
119
|
+
// Add listeners for hiding Tooltip element
|
|
113
120
|
anchorElement.addEventListener('mouseleave', () => hideTooltip())
|
|
114
121
|
|
|
115
122
|
// --- Helper functions (placed here because of variables scopes are local (don't wan to use a lot of parameters)) --- //
|
|
@@ -125,6 +132,7 @@ const ZeroTooltip = (config?: TooltipConfig): Directive => {
|
|
|
125
132
|
if (bindingValue.textClasses) textClasses = bindingValue.textClasses
|
|
126
133
|
if (bindingValue.arrowSize) arrowSize = bindingValue.arrowSize
|
|
127
134
|
if (bindingValue.arrowMinOffsetFromTooltipCorner) arrowMinOffsetFromTooltipCorner = bindingValue.arrowMinOffsetFromTooltipCorner
|
|
135
|
+
if (bindingValue.zIndex) zIndex = bindingValue.zIndex
|
|
128
136
|
}
|
|
129
137
|
|
|
130
138
|
function tryMountTooltipOnLeft(anchorElementRect: DOMRect) {
|
|
@@ -268,6 +276,9 @@ const ZeroTooltip = (config?: TooltipConfig): Directive => {
|
|
|
268
276
|
const tooltipElementRect = tooltipElement.getBoundingClientRect()
|
|
269
277
|
const arrowHalfLengthOfLongSide = Math.sin(45 * (180 / Math.PI)) * arrowSize
|
|
270
278
|
|
|
279
|
+
// Adjusts arrow position by `x` pixels to handle browsers sometimes not rendering border in it's full width, e.g., 4.8px instead of 5px
|
|
280
|
+
const arrowPositionAdjuster = 1;
|
|
281
|
+
|
|
271
282
|
// Arrow top/left 0 is Tooltip top/left 0
|
|
272
283
|
let arrowTop = 0
|
|
273
284
|
let arrowLeft = 0
|
|
@@ -278,21 +289,21 @@ const ZeroTooltip = (config?: TooltipConfig): Directive => {
|
|
|
278
289
|
case "left":
|
|
279
290
|
arrowClassForCorrectAngle = '!zt-border-y-transparent !zt-border-r-transparent'
|
|
280
291
|
arrowTop = anchorElementRect.top - tooltipElementRect.top + (anchorElementRect.height / 2) - arrowHalfLengthOfLongSide - tooltipBorderWidth
|
|
281
|
-
arrowLeft = tooltipElementRect.width - tooltipBorderWidth
|
|
292
|
+
arrowLeft = tooltipElementRect.width - tooltipBorderWidth - arrowPositionAdjuster
|
|
282
293
|
break;
|
|
283
294
|
case "top":
|
|
284
295
|
arrowClassForCorrectAngle = '!zt-border-x-transparent !zt-border-b-transparent'
|
|
285
|
-
arrowTop = tooltipElementRect.height - tooltipBorderWidth
|
|
296
|
+
arrowTop = tooltipElementRect.height - tooltipBorderWidth - arrowPositionAdjuster
|
|
286
297
|
arrowLeft = anchorElementRect.left - tooltipElementRect.left + (anchorElementRect.width / 2) - arrowHalfLengthOfLongSide - tooltipBorderWidth
|
|
287
298
|
break;
|
|
288
299
|
case "right":
|
|
289
300
|
arrowClassForCorrectAngle = '!zt-border-y-transparent !zt-border-l-transparent'
|
|
290
301
|
arrowTop = anchorElementRect.top - tooltipElementRect.top + (anchorElementRect.height / 2) - arrowHalfLengthOfLongSide - tooltipBorderWidth
|
|
291
|
-
arrowLeft = (-arrowSize * 2) - tooltipBorderWidth
|
|
302
|
+
arrowLeft = (-arrowSize * 2) - tooltipBorderWidth + arrowPositionAdjuster
|
|
292
303
|
break;
|
|
293
304
|
case "bottom":
|
|
294
305
|
arrowClassForCorrectAngle = '!zt-border-x-transparent !zt-border-t-transparent'
|
|
295
|
-
arrowTop = (-arrowSize * 2) - tooltipBorderWidth
|
|
306
|
+
arrowTop = (-arrowSize * 2) - tooltipBorderWidth + arrowPositionAdjuster
|
|
296
307
|
arrowLeft = anchorElementRect.left - tooltipElementRect.left + (anchorElementRect.width / 2) - arrowHalfLengthOfLongSide - tooltipBorderWidth
|
|
297
308
|
break;
|
|
298
309
|
}
|
|
@@ -362,10 +373,18 @@ const ZeroTooltip = (config?: TooltipConfig): Directive => {
|
|
|
362
373
|
function hideTooltip() {
|
|
363
374
|
const tooltipElement = document.querySelector(`.${tooltipElementClass}`)
|
|
364
375
|
|
|
365
|
-
|
|
366
|
-
|
|
376
|
+
if (tooltipElement && tooltipElement instanceof HTMLElement) {
|
|
377
|
+
resetResizeReferences()
|
|
367
378
|
|
|
368
|
-
|
|
379
|
+
// Remove Arrow element from Tooltip, because it needs to be rebuilt every time Tooltip is showed again
|
|
380
|
+
tooltipElement.querySelector(`.${arrowElementClass}`)?.remove()
|
|
381
|
+
|
|
382
|
+
// Reset position so that old position does not effect new position (when zooming old position could be off screen)
|
|
383
|
+
tooltipElement.style.left = '0'
|
|
384
|
+
tooltipElement.style.top = '0'
|
|
385
|
+
|
|
386
|
+
tooltipElement.remove()
|
|
387
|
+
}
|
|
369
388
|
}
|
|
370
389
|
|
|
371
390
|
function getTooltipText(bindingValue: string | TooltipLocalConfig) {
|