zero-tooltip 1.0.1 → 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 +49 -9
- 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
|
@@ -53,9 +53,11 @@ app.directive('tooltip', ZeroTooltip({
|
|
|
53
53
|
}))
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
Tooltip component is fully customizable by giving config object:
|
|
56
|
+
Tooltip component is fully customizable by giving config object when declaring global tooltip directive:
|
|
57
57
|
```ts
|
|
58
|
-
|
|
58
|
+
import ZeroTooltipConfig from 'zero-tooltip'
|
|
59
|
+
|
|
60
|
+
const tooltipConfig: ZeroTooltipConfig = {
|
|
59
61
|
defaultPosition: ... ,
|
|
60
62
|
positions: ... ,
|
|
61
63
|
offsetFromSource: ... ,
|
|
@@ -68,26 +70,64 @@ app.directive('tooltip', ZeroTooltip({
|
|
|
68
70
|
arrowSize: ... ,
|
|
69
71
|
arrowClasses: ... ,
|
|
70
72
|
arrowMinOffsetFromTooltipCorner: ... ,
|
|
71
|
-
|
|
73
|
+
zIndex: ...
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
app.directive('tooltip', ZeroTooltip(tooltipConfig))
|
|
72
77
|
```
|
|
73
78
|
|
|
74
79
|
All above settings are optional.
|
|
75
80
|
|
|
76
|
-
|
|
81
|
+
Tooltip can be customizable also for each usage (locally) using same config as follows:
|
|
82
|
+
```html
|
|
83
|
+
<template>
|
|
84
|
+
<button v-tooltip:right="tooltipConfig">Submit</button>
|
|
85
|
+
</template>
|
|
86
|
+
|
|
87
|
+
<script setup lang="ts">
|
|
88
|
+
import ZeroTooltipLocalConfig from 'zero-tooltip'
|
|
89
|
+
|
|
90
|
+
const tooltipConfig: ZeroTooltipLocalConfig = {
|
|
91
|
+
content: 'This is tooltip'
|
|
92
|
+
defaultPosition: ... ,
|
|
93
|
+
positions: ... ,
|
|
94
|
+
offsetFromSource: ... ,
|
|
95
|
+
offsetFromViewport: ... ,
|
|
96
|
+
minWidth: ... ,
|
|
97
|
+
maxWidth: ... ,
|
|
98
|
+
tooltipBorderWidth: ... ,
|
|
99
|
+
tooltipClasses: ... ,
|
|
100
|
+
textClasses: ... ,
|
|
101
|
+
arrowSize: ... ,
|
|
102
|
+
arrowClasses: ... ,
|
|
103
|
+
arrowMinOffsetFromTooltipCorner: ... ,
|
|
104
|
+
zIndex: ...
|
|
105
|
+
}
|
|
106
|
+
</script>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## ZeroTooltipConfig
|
|
77
110
|
| Property | <div style="width:260px">Default value</div> | Type | Details |
|
|
78
111
|
|---|---|---|---|
|
|
79
|
-
| defaultPosition | *top* | TooltipPosition |
|
|
112
|
+
| defaultPosition | *top* | TooltipPosition | Position of tooltip component relative to element that is being hovered |
|
|
80
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. |
|
|
81
114
|
| offsetFromSource | *10* | number | Tooltip offset in `px` from element that's being hovered *(arrow size is not added to this value)* |
|
|
82
|
-
| offsetFromViewport | *20* | number | Minimal allowed tooltip offset in `px` from
|
|
115
|
+
| offsetFromViewport | *20* | number | Minimal allowed tooltip offset in `px` from viewport sides |
|
|
83
116
|
| minWidth | *100* | number | Minimal tooltip width in `px` that will be allowed to render |
|
|
84
117
|
| maxWidth | *250* | number | Maximal tooltip width in `px` that will be allowed to render |
|
|
85
118
|
| tooltipBorderWidth | *0* | number | Tooltip container border width in `px` |
|
|
86
119
|
| tooltipClasses | *undefined* | string | List of classes that will be added to tooltip element |
|
|
87
120
|
| textClasses | *undefined* | string | List of classes that will be added to text element |
|
|
88
|
-
| 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) |
|
|
89
122
|
| arrowClasses | *undefined* | string | List of classes that will be added to arrow element |
|
|
90
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 |
|
|
125
|
+
|
|
126
|
+
## ZeroTooltipLocalConfig
|
|
127
|
+
Same as [ZeroTooltipConfig](#ZeroTooltipConfig) with following additions:
|
|
128
|
+
| Property | <div style="width:260px">Default value</div> | Type | Details |
|
|
129
|
+
|---|---|---|---|
|
|
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>` |
|
|
91
131
|
|
|
92
|
-
##
|
|
93
|
-
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) {
|