zero-tooltip 1.0.2 → 1.0.4
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 +9 -5
- package/dist/index.d.ts +3 -1
- package/dist/zero-tooltip.js +178 -145
- package/dist/zero-tooltip.umd.cjs +1 -1
- package/package.json +1 -1
- package/src/composables/useHideOnResize.ts +36 -0
- package/src/tooltip.ts +383 -301
- package/src/types/tooltipConfig.ts +2 -1
- package/src/types/tooltipLocalConfig.ts +2 -1
package/src/tooltip.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import { Directive } from "vue"
|
|
1
|
+
import { Directive, watch } 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'
|
|
@@ -20,7 +22,7 @@ const defaultTooltipPositions: TooltipPositions = {
|
|
|
20
22
|
bottom: ['bottom', 'top', 'right', 'left'],
|
|
21
23
|
}
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
const defaultTooltipPosition: TooltipPosition = 'top'
|
|
24
26
|
const defaultTooltipOffsetFromSource = 10
|
|
25
27
|
const defaultTooltipOffsetFromViewport = 20
|
|
26
28
|
const defaultTooltipMinWidth = 100
|
|
@@ -31,357 +33,437 @@ 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
|
|
37
|
+
const defaultShouldShow = true
|
|
38
|
+
|
|
39
|
+
// Tooltip config
|
|
40
|
+
let tooltipText: string
|
|
41
|
+
let tooltipPosition: TooltipPosition
|
|
42
|
+
let tooltipPositions: TooltipPositions
|
|
43
|
+
let tooltipOffsetFromSource: number
|
|
44
|
+
let tooltipOffsetFromViewport: number
|
|
45
|
+
let tooltipMinWidth: number
|
|
46
|
+
let tooltipMaxWidth: number
|
|
47
|
+
let tooltipBorderWidth: number
|
|
48
|
+
let tooltipClasses: string
|
|
49
|
+
let textClasses: string
|
|
50
|
+
let arrowSize: number
|
|
51
|
+
let arrowClasses: string
|
|
52
|
+
let arrowMinOffsetFromTooltipCorner: number
|
|
53
|
+
let zIndex: number
|
|
54
|
+
let shouldShow: boolean
|
|
55
|
+
|
|
56
|
+
// Tooltip elements
|
|
57
|
+
let anchorElement: HTMLElement
|
|
58
|
+
let tooltipTextElement: HTMLElement
|
|
59
|
+
let tooltipElement: HTMLElement
|
|
60
|
+
|
|
61
|
+
let isHovered = false
|
|
62
|
+
|
|
63
|
+
const ZeroTooltip = (globalConfig?: TooltipConfig): Directive => {
|
|
64
|
+
return {
|
|
65
|
+
mounted: (targetElement: HTMLElement, binding) => {
|
|
66
|
+
setTooltipConfig(binding.value, globalConfig, binding.arg as TooltipPosition)
|
|
67
|
+
initTooltip(targetElement)
|
|
68
|
+
|
|
69
|
+
if (typeof(binding.value) !== 'string') {
|
|
70
|
+
watch(binding.value, (newBindingValue) => {
|
|
71
|
+
setTooltipConfig(newBindingValue as string | TooltipLocalConfig, globalConfig, binding.arg as TooltipPosition)
|
|
72
|
+
initTooltip(targetElement)
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
},
|
|
34
76
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
77
|
+
updated: (targetElement: HTMLElement, binding) => {
|
|
78
|
+
if (typeof(binding.value) === 'string') {
|
|
79
|
+
setTooltipConfig(binding.value, globalConfig, binding.arg as TooltipPosition)
|
|
80
|
+
initTooltip(targetElement)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
38
83
|
}
|
|
84
|
+
}
|
|
39
85
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
86
|
+
function setTooltipConfig(localConfig: string | TooltipLocalConfig, globalConfig?: TooltipConfig, position?: TooltipPosition) {
|
|
87
|
+
tooltipText = getTooltipText(localConfig)
|
|
88
|
+
|
|
89
|
+
if (typeof(localConfig) !== 'string') {
|
|
90
|
+
tooltipPosition = position ?? localConfig.defaultPosition ?? globalConfig?.defaultPosition ?? defaultTooltipPosition;
|
|
91
|
+
tooltipPositions = {
|
|
92
|
+
left: localConfig.positions?.left ?? globalConfig?.positions?.left ?? defaultTooltipPositions.left,
|
|
93
|
+
top: localConfig.positions?.top ?? globalConfig?.positions?.top ?? defaultTooltipPositions.top,
|
|
94
|
+
right: localConfig.positions?.right ?? globalConfig?.positions?.right ?? defaultTooltipPositions.right,
|
|
95
|
+
bottom: localConfig.positions?.bottom ?? globalConfig?.positions?.bottom ?? defaultTooltipPositions.bottom,
|
|
96
|
+
}
|
|
97
|
+
tooltipOffsetFromSource = localConfig.offsetFromSource ?? globalConfig?.offsetFromSource ?? defaultTooltipOffsetFromSource
|
|
98
|
+
tooltipOffsetFromViewport = localConfig.offsetFromViewport ?? globalConfig?.offsetFromViewport ?? defaultTooltipOffsetFromViewport
|
|
99
|
+
tooltipMinWidth = localConfig.minWidth ?? globalConfig?.minWidth ?? defaultTooltipMinWidth
|
|
100
|
+
tooltipMaxWidth = localConfig.maxWidth ?? globalConfig?.maxWidth ?? defaultTooltipMaxWidth
|
|
101
|
+
tooltipBorderWidth = localConfig.tooltipBorderWidth ?? globalConfig?.tooltipBorderWidth ?? defaultTooltipBorderWidth
|
|
102
|
+
tooltipClasses = tooltipElementClass + ' ' + defaultTooltipClasses + ' ' + (localConfig.tooltipClasses ?? globalConfig?.tooltipClasses ?? '')
|
|
103
|
+
textClasses = textElementClass + ' ' + defaultTextClasses + ' ' + (localConfig.textClasses ?? globalConfig?.textClasses ?? '')
|
|
104
|
+
arrowSize = localConfig.arrowSize ?? globalConfig?.arrowSize ?? defaultArrowSize
|
|
105
|
+
arrowClasses = localConfig.arrowClasses ?? globalConfig?.arrowClasses ?? ''
|
|
106
|
+
arrowMinOffsetFromTooltipCorner = localConfig.arrowMinOffsetFromTooltipCorner ?? globalConfig?.arrowMinOffsetFromTooltipCorner ?? defaultMinArrowOffsetFromTooltipCorner
|
|
107
|
+
zIndex = localConfig.zIndex ?? globalConfig?.zIndex ?? defaultZIndex
|
|
108
|
+
shouldShow = localConfig.show ?? defaultShouldShow
|
|
46
109
|
}
|
|
47
|
-
let tooltipOffsetFromSource = config?.offsetFromSource ?? defaultTooltipOffsetFromSource
|
|
48
|
-
let tooltipOffsetFromViewport = config?.offsetFromViewport ?? defaultTooltipOffsetFromViewport
|
|
49
|
-
let tooltipMinWidth = config?.minWidth ?? defaultTooltipMinWidth
|
|
50
|
-
let tooltipMaxWidth = config?.maxWidth ?? defaultTooltipMaxWidth
|
|
51
|
-
let tooltipBorderWidth = config?.tooltipBorderWidth ?? defaultTooltipBorderWidth
|
|
52
|
-
let tooltipClasses = tooltipElementClass + ' ' + defaultTooltipClasses + ' ' + config?.tooltipClasses ?? ''
|
|
53
|
-
let textClasses = textElementClass + ' ' + defaultTextClasses + ' ' + config?.textClasses ?? ''
|
|
54
|
-
let arrowSize = config?.arrowSize ?? defaultArrowSize
|
|
55
|
-
let arrowMinOffsetFromTooltipCorner = config?.arrowMinOffsetFromTooltipCorner ?? defaultMinArrowOffsetFromTooltipCorner
|
|
56
110
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
111
|
+
if (tooltipPosition === undefined) tooltipPosition = position ?? globalConfig?.defaultPosition ?? defaultTooltipPosition;
|
|
112
|
+
if (tooltipPositions === undefined) tooltipPositions = {
|
|
113
|
+
left: globalConfig?.positions?.left ?? defaultTooltipPositions.left,
|
|
114
|
+
top: globalConfig?.positions?.top ?? defaultTooltipPositions.top,
|
|
115
|
+
right: globalConfig?.positions?.right ?? defaultTooltipPositions.right,
|
|
116
|
+
bottom: globalConfig?.positions?.bottom ?? defaultTooltipPositions.bottom,
|
|
117
|
+
}
|
|
118
|
+
if (tooltipOffsetFromSource === undefined) tooltipOffsetFromSource = globalConfig?.offsetFromSource ?? defaultTooltipOffsetFromSource
|
|
119
|
+
if (tooltipOffsetFromViewport === undefined) tooltipOffsetFromViewport = globalConfig?.offsetFromViewport ?? defaultTooltipOffsetFromViewport
|
|
120
|
+
if (tooltipMinWidth === undefined) tooltipMinWidth = globalConfig?.minWidth ?? defaultTooltipMinWidth
|
|
121
|
+
if (tooltipMaxWidth === undefined) tooltipMaxWidth = globalConfig?.maxWidth ?? defaultTooltipMaxWidth
|
|
122
|
+
if (tooltipBorderWidth === undefined) tooltipBorderWidth = globalConfig?.tooltipBorderWidth ?? defaultTooltipBorderWidth
|
|
123
|
+
if (tooltipClasses === undefined) tooltipClasses = tooltipElementClass + ' ' + defaultTooltipClasses + ' ' + globalConfig?.tooltipClasses ?? ''
|
|
124
|
+
if (textClasses === undefined) textClasses = textElementClass + ' ' + defaultTextClasses + ' ' + globalConfig?.textClasses ?? ''
|
|
125
|
+
if (arrowSize === undefined) arrowSize = globalConfig?.arrowSize ?? defaultArrowSize
|
|
126
|
+
if (arrowClasses === undefined) arrowClasses = globalConfig?.arrowClasses ?? ''
|
|
127
|
+
if (arrowMinOffsetFromTooltipCorner === undefined) arrowMinOffsetFromTooltipCorner = globalConfig?.arrowMinOffsetFromTooltipCorner ?? defaultMinArrowOffsetFromTooltipCorner
|
|
128
|
+
if (zIndex === undefined) zIndex = globalConfig?.zIndex ?? defaultZIndex
|
|
129
|
+
if (shouldShow === undefined) shouldShow = defaultShouldShow
|
|
130
|
+
}
|
|
61
131
|
|
|
62
|
-
|
|
132
|
+
function getTooltipText(localConfig: string | TooltipLocalConfig) {
|
|
133
|
+
const tooltipText = typeof(localConfig) === 'string' ? localConfig : localConfig.content
|
|
63
134
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const textElement = document.createElement('p')
|
|
68
|
-
textElement.classList.add(...textClasses.split(' '))
|
|
69
|
-
textElement.innerHTML = text
|
|
70
|
-
|
|
71
|
-
// Create Tooltip element
|
|
72
|
-
const tooltipElement = document.createElement('div')
|
|
73
|
-
tooltipElement.classList.add(...tooltipClasses.split(' '))
|
|
74
|
-
tooltipElement.style.borderWidth = `${tooltipBorderWidth}px`
|
|
75
|
-
tooltipElement.appendChild(textElement)
|
|
76
|
-
|
|
77
|
-
// Add listener for showing Tooltip element
|
|
78
|
-
anchorElement.addEventListener('mouseenter', () => {
|
|
79
|
-
const anchorElementRect = anchorElement.getBoundingClientRect()
|
|
80
|
-
|
|
81
|
-
// Mount Tooltip element to body
|
|
82
|
-
const body = document.querySelector('body')
|
|
83
|
-
body?.appendChild(tooltipElement)
|
|
84
|
-
|
|
85
|
-
// Find suitable Tooltip position
|
|
86
|
-
let hasNeededDisplaySpace = false
|
|
87
|
-
let currentTooltipPosition = tooltipPosition
|
|
88
|
-
for (let i = 0; i < 4; i++) {
|
|
89
|
-
currentTooltipPosition = tooltipPositions[tooltipPosition][i]
|
|
90
|
-
|
|
91
|
-
if (currentTooltipPosition === 'left') {
|
|
92
|
-
hasNeededDisplaySpace = tryMountTooltipOnLeft(anchorElementRect)
|
|
93
|
-
} else if (currentTooltipPosition === 'top') {
|
|
94
|
-
hasNeededDisplaySpace = tryMountTooltipOnTop(anchorElementRect)
|
|
95
|
-
} else if (currentTooltipPosition === 'right') {
|
|
96
|
-
hasNeededDisplaySpace = tryMountTooltipOnRight(anchorElementRect)
|
|
97
|
-
} else if (currentTooltipPosition === 'bottom') {
|
|
98
|
-
hasNeededDisplaySpace = tryMountTooltipOnBottom(anchorElementRect)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (hasNeededDisplaySpace) break
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (hasNeededDisplaySpace) {
|
|
105
|
-
drawArrow(anchorElementRect, currentTooltipPosition)
|
|
106
|
-
|
|
107
|
-
tooltipElement.style.opacity = '1'
|
|
108
|
-
handleHideOnScroll(anchorElement, () => hideTooltip())
|
|
109
|
-
}
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
// Add listener for hiding Tooltip element
|
|
113
|
-
anchorElement.addEventListener('mouseleave', () => hideTooltip())
|
|
114
|
-
|
|
115
|
-
// --- Helper functions (placed here because of variables scopes are local (don't wan to use a lot of parameters)) --- //
|
|
116
|
-
function adjustTooltipSettings(bindingValue: TooltipLocalConfig) {
|
|
117
|
-
if (bindingValue.defaultPosition) tooltipPosition = bindingValue.defaultPosition
|
|
118
|
-
if (bindingValue.positions) tooltipPositions = {...tooltipPositions, ...bindingValue.positions}
|
|
119
|
-
if (bindingValue.offsetFromSource) tooltipOffsetFromSource = bindingValue.offsetFromSource
|
|
120
|
-
if (bindingValue.offsetFromViewport) tooltipOffsetFromViewport = bindingValue.offsetFromViewport
|
|
121
|
-
if (bindingValue.minWidth) tooltipMinWidth = bindingValue.minWidth
|
|
122
|
-
if (bindingValue.maxWidth) tooltipMaxWidth = bindingValue.maxWidth
|
|
123
|
-
if (bindingValue.tooltipBorderWidth) tooltipBorderWidth = bindingValue.tooltipBorderWidth
|
|
124
|
-
if (bindingValue.tooltipClasses) tooltipClasses = bindingValue.tooltipClasses
|
|
125
|
-
if (bindingValue.textClasses) textClasses = bindingValue.textClasses
|
|
126
|
-
if (bindingValue.arrowSize) arrowSize = bindingValue.arrowSize
|
|
127
|
-
if (bindingValue.arrowMinOffsetFromTooltipCorner) arrowMinOffsetFromTooltipCorner = bindingValue.arrowMinOffsetFromTooltipCorner
|
|
128
|
-
}
|
|
135
|
+
if (!tooltipText) {
|
|
136
|
+
throw new Error("Please enter valid tooltip value");
|
|
137
|
+
}
|
|
129
138
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const tooltipAvailableMaxWidth = Math.min(anchorElementRect.left - tooltipOffsetFromSource - tooltipOffsetFromViewport, tooltipMaxWidth)
|
|
133
|
-
const isAnchorElementTopLowerThanOffsetFromViewport = anchorElementRect.top >= tooltipOffsetFromViewport
|
|
134
|
-
const isAnchorElementBottomHigherThanOffsetFromViewport = (window.innerHeight - anchorElementRect.bottom) >= tooltipOffsetFromViewport
|
|
139
|
+
return tooltipText
|
|
140
|
+
}
|
|
135
141
|
|
|
136
|
-
|
|
142
|
+
function initTooltip(targetElement: HTMLElement) {
|
|
143
|
+
anchorElement = targetElement
|
|
144
|
+
anchorElement.removeEventListener('mouseenter', onMouseEnter)
|
|
145
|
+
anchorElement.removeEventListener('mouseleave', onMouseLeave)
|
|
137
146
|
|
|
138
|
-
|
|
139
|
-
|
|
147
|
+
createTextElement()
|
|
148
|
+
createTooltipElement()
|
|
140
149
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
let tooltipTop = anchorElementRect.top + (anchorElementRect.height / 2) - (tooltipElementRect.height / 2)
|
|
144
|
-
|
|
145
|
-
if (tooltipTop < tooltipOffsetFromViewport) {
|
|
146
|
-
tooltipTop = tooltipOffsetFromViewport
|
|
147
|
-
} else if (tooltipTop + tooltipElementRect.height > window.innerHeight - tooltipOffsetFromViewport) {
|
|
148
|
-
tooltipTop = window.innerHeight - tooltipOffsetFromViewport - tooltipElementRect.height
|
|
149
|
-
}
|
|
150
|
+
anchorElement.addEventListener('mouseenter', onMouseEnter)
|
|
151
|
+
anchorElement.addEventListener('mouseleave', onMouseLeave)
|
|
150
152
|
|
|
151
|
-
|
|
153
|
+
if (isHovered) {
|
|
154
|
+
anchorElement.dispatchEvent(new Event('mouseleave'))
|
|
155
|
+
anchorElement.dispatchEvent(new Event('mouseenter'))
|
|
156
|
+
}
|
|
157
|
+
}
|
|
152
158
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
159
|
+
function createTextElement() {
|
|
160
|
+
tooltipTextElement = document.createElement('p')
|
|
161
|
+
tooltipTextElement.classList.add(...textClasses.trim().split(' '))
|
|
162
|
+
tooltipTextElement.innerHTML = tooltipText
|
|
163
|
+
}
|
|
156
164
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
165
|
+
function createTooltipElement() {
|
|
166
|
+
tooltipElement = document.createElement('div')
|
|
167
|
+
tooltipElement.classList.add(...tooltipClasses.trim().split(' '))
|
|
168
|
+
tooltipElement.style.borderWidth = `${tooltipBorderWidth}px`
|
|
169
|
+
tooltipElement.appendChild(tooltipTextElement)
|
|
170
|
+
}
|
|
160
171
|
|
|
161
|
-
|
|
162
|
-
|
|
172
|
+
function onMouseEnter() {
|
|
173
|
+
isHovered = true
|
|
163
174
|
|
|
164
|
-
|
|
165
|
-
// Check if Tooltip has enough available horizontal space, top and bottom offset from viewport
|
|
166
|
-
const tooltipAvailableMaxWidth = Math.min(window.innerWidth - (anchorElementRect.right + tooltipOffsetFromSource) - tooltipOffsetFromViewport, tooltipMaxWidth)
|
|
167
|
-
const isAnchorElementTopLowerThanOffsetFromViewport = anchorElementRect.top >= tooltipOffsetFromViewport
|
|
168
|
-
const isAnchorElementBottomHigherThanOffsetFromViewport = (window.innerHeight - anchorElementRect.bottom) >= tooltipOffsetFromViewport
|
|
175
|
+
if (!shouldShow) return
|
|
169
176
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
// Set tooltip maxWidth
|
|
173
|
-
tooltipElement.style.maxWidth = `${tooltipAvailableMaxWidth}px`
|
|
177
|
+
const anchorElementRect = anchorElement.getBoundingClientRect()
|
|
174
178
|
|
|
175
|
-
|
|
176
|
-
|
|
179
|
+
// Mount Tooltip element to body
|
|
180
|
+
const body = document.querySelector('body')
|
|
181
|
+
body?.appendChild(tooltipElement)
|
|
177
182
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
tooltipTop = window.innerHeight - tooltipOffsetFromViewport - tooltipElementRect.height
|
|
184
|
-
}
|
|
183
|
+
// Find suitable Tooltip position
|
|
184
|
+
let hasNeededDisplaySpace = false
|
|
185
|
+
let currentTooltipPosition = tooltipPosition
|
|
186
|
+
for (let i = 0; i < 4; i++) {
|
|
187
|
+
currentTooltipPosition = tooltipPositions[tooltipPosition][i]
|
|
185
188
|
|
|
186
|
-
|
|
189
|
+
if (currentTooltipPosition === 'left') {
|
|
190
|
+
hasNeededDisplaySpace = tryMountTooltipOnLeft(anchorElementRect)
|
|
191
|
+
} else if (currentTooltipPosition === 'top') {
|
|
192
|
+
hasNeededDisplaySpace = tryMountTooltipOnTop(anchorElementRect)
|
|
193
|
+
} else if (currentTooltipPosition === 'right') {
|
|
194
|
+
hasNeededDisplaySpace = tryMountTooltipOnRight(anchorElementRect)
|
|
195
|
+
} else if (currentTooltipPosition === 'bottom') {
|
|
196
|
+
hasNeededDisplaySpace = tryMountTooltipOnBottom(anchorElementRect)
|
|
197
|
+
}
|
|
187
198
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|| anchorElementRect.top > tooltipTop + tooltipElementRect.height - arrowMinOffsetFromTooltipCorner * 2) return false
|
|
199
|
+
if (hasNeededDisplaySpace) break
|
|
200
|
+
}
|
|
191
201
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
tooltipElement.style.left = `${tooltipLeft}px`
|
|
202
|
+
if (hasNeededDisplaySpace) {
|
|
203
|
+
drawArrow(anchorElementRect, currentTooltipPosition)
|
|
195
204
|
|
|
196
|
-
|
|
197
|
-
|
|
205
|
+
tooltipElement.style.opacity = '1'
|
|
206
|
+
tooltipElement.style.zIndex = zIndex.toString()
|
|
198
207
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
208
|
+
handleHideOnScroll(anchorElement, () => hideTooltip())
|
|
209
|
+
handleHideOnResize(anchorElement, () => hideTooltip())
|
|
210
|
+
}
|
|
211
|
+
}
|
|
203
212
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
213
|
+
function onMouseLeave() {
|
|
214
|
+
hideTooltip()
|
|
215
|
+
}
|
|
207
216
|
|
|
208
|
-
|
|
209
|
-
|
|
217
|
+
function tryMountTooltipOnLeft(anchorElementRect: DOMRect) {
|
|
218
|
+
// Check if Tooltip has enough available horizontal space, top and bottom offset from viewport
|
|
219
|
+
const tooltipAvailableMaxWidth = Math.min(anchorElementRect.left - tooltipOffsetFromSource - tooltipOffsetFromViewport, tooltipMaxWidth)
|
|
220
|
+
const isAnchorElementTopLowerThanOffsetFromViewport = anchorElementRect.top >= tooltipOffsetFromViewport
|
|
221
|
+
const isAnchorElementBottomHigherThanOffsetFromViewport = (window.innerHeight - anchorElementRect.bottom) >= tooltipOffsetFromViewport
|
|
210
222
|
|
|
211
|
-
|
|
212
|
-
let tooltipLeft = anchorElementRect.left + (anchorElementRect.width / 2) - (tooltipElementRect.width / 2)
|
|
223
|
+
if (tooltipAvailableMaxWidth < tooltipMinWidth || !isAnchorElementTopLowerThanOffsetFromViewport || !isAnchorElementBottomHigherThanOffsetFromViewport) return false
|
|
213
224
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
} else if (tooltipLeft + tooltipElementRect.width > window.innerWidth - tooltipOffsetFromViewport) {
|
|
217
|
-
tooltipLeft = window.innerWidth - tooltipOffsetFromViewport - tooltipElementRect.width
|
|
218
|
-
}
|
|
225
|
+
// Set Tooltip maxWidth
|
|
226
|
+
tooltipElement.style.maxWidth = `${tooltipAvailableMaxWidth}px`
|
|
219
227
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
228
|
+
// Calculate Tooltip position
|
|
229
|
+
const tooltipElementRect = tooltipElement.getBoundingClientRect()
|
|
230
|
+
let tooltipTop = anchorElementRect.top + (anchorElementRect.height / 2) - (tooltipElementRect.height / 2)
|
|
231
|
+
|
|
232
|
+
if (tooltipTop < tooltipOffsetFromViewport) {
|
|
233
|
+
tooltipTop = tooltipOffsetFromViewport
|
|
234
|
+
} else if (tooltipTop + tooltipElementRect.height > window.innerHeight - tooltipOffsetFromViewport) {
|
|
235
|
+
tooltipTop = window.innerHeight - tooltipOffsetFromViewport - tooltipElementRect.height
|
|
236
|
+
}
|
|
223
237
|
|
|
224
|
-
|
|
225
|
-
tooltipElement.style.top = `${tooltipTop}px`
|
|
226
|
-
tooltipElement.style.left = `${tooltipLeft}px`
|
|
238
|
+
const tooltipLeft = anchorElementRect.left - tooltipOffsetFromSource - tooltipElementRect.width
|
|
227
239
|
|
|
228
|
-
|
|
229
|
-
|
|
240
|
+
// Check if anchor element is directly on right of Tooltip
|
|
241
|
+
if (anchorElementRect.bottom < tooltipTop + arrowMinOffsetFromTooltipCorner * 2
|
|
242
|
+
|| anchorElementRect.top > tooltipTop + tooltipElementRect.height - arrowMinOffsetFromTooltipCorner * 2) return false
|
|
230
243
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
tooltipElement.style.maxWidth = `${tooltipAvailableMaxWidth}px`
|
|
244
|
+
// Set Tooltip position
|
|
245
|
+
tooltipElement.style.top = `${tooltipTop}px`
|
|
246
|
+
tooltipElement.style.left = `${tooltipLeft}px`
|
|
235
247
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
let tooltipTop = anchorElementRect.bottom + tooltipOffsetFromSource
|
|
248
|
+
return true
|
|
249
|
+
}
|
|
239
250
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
251
|
+
function tryMountTooltipOnRight(anchorElementRect: DOMRect) {
|
|
252
|
+
// Check if Tooltip has enough available horizontal space, top and bottom offset from viewport
|
|
253
|
+
const tooltipAvailableMaxWidth = Math.min(window.innerWidth - (anchorElementRect.right + tooltipOffsetFromSource) - tooltipOffsetFromViewport, tooltipMaxWidth)
|
|
254
|
+
const isAnchorElementTopLowerThanOffsetFromViewport = anchorElementRect.top >= tooltipOffsetFromViewport
|
|
255
|
+
const isAnchorElementBottomHigherThanOffsetFromViewport = (window.innerHeight - anchorElementRect.bottom) >= tooltipOffsetFromViewport
|
|
245
256
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
257
|
+
if (tooltipAvailableMaxWidth < tooltipMinWidth || !isAnchorElementTopLowerThanOffsetFromViewport || !isAnchorElementBottomHigherThanOffsetFromViewport) return false
|
|
258
|
+
|
|
259
|
+
// Set tooltip maxWidth
|
|
260
|
+
tooltipElement.style.maxWidth = `${tooltipAvailableMaxWidth}px`
|
|
251
261
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|| anchorElementRect.right < tooltipLeft + arrowMinOffsetFromTooltipCorner * 2) return false
|
|
262
|
+
// Calculate Tooltip position
|
|
263
|
+
const tooltipElementRect = tooltipElement.getBoundingClientRect()
|
|
255
264
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
265
|
+
let tooltipTop = anchorElementRect.top + (anchorElementRect.height / 2) - (tooltipElementRect.height / 2)
|
|
266
|
+
|
|
267
|
+
if (tooltipTop < tooltipOffsetFromViewport) {
|
|
268
|
+
tooltipTop = tooltipOffsetFromViewport
|
|
269
|
+
} else if (tooltipTop + tooltipElementRect.height > window.innerHeight - tooltipOffsetFromViewport) {
|
|
270
|
+
tooltipTop = window.innerHeight - tooltipOffsetFromViewport - tooltipElementRect.height
|
|
271
|
+
}
|
|
259
272
|
|
|
260
|
-
|
|
261
|
-
}
|
|
273
|
+
const tooltipLeft = anchorElementRect.right + tooltipOffsetFromSource
|
|
262
274
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
// Calculate Arrow element size, positions and style/angle classes
|
|
268
|
-
const tooltipElementRect = tooltipElement.getBoundingClientRect()
|
|
269
|
-
const arrowHalfLengthOfLongSide = Math.sin(45 * (180 / Math.PI)) * arrowSize
|
|
270
|
-
|
|
271
|
-
// Arrow top/left 0 is Tooltip top/left 0
|
|
272
|
-
let arrowTop = 0
|
|
273
|
-
let arrowLeft = 0
|
|
274
|
-
|
|
275
|
-
let arrowClassForCorrectAngle = ''
|
|
276
|
-
|
|
277
|
-
switch (currentTooltipPosition) {
|
|
278
|
-
case "left":
|
|
279
|
-
arrowClassForCorrectAngle = '!zt-border-y-transparent !zt-border-r-transparent'
|
|
280
|
-
arrowTop = anchorElementRect.top - tooltipElementRect.top + (anchorElementRect.height / 2) - arrowHalfLengthOfLongSide - tooltipBorderWidth
|
|
281
|
-
arrowLeft = tooltipElementRect.width - tooltipBorderWidth
|
|
282
|
-
break;
|
|
283
|
-
case "top":
|
|
284
|
-
arrowClassForCorrectAngle = '!zt-border-x-transparent !zt-border-b-transparent'
|
|
285
|
-
arrowTop = tooltipElementRect.height - tooltipBorderWidth
|
|
286
|
-
arrowLeft = anchorElementRect.left - tooltipElementRect.left + (anchorElementRect.width / 2) - arrowHalfLengthOfLongSide - tooltipBorderWidth
|
|
287
|
-
break;
|
|
288
|
-
case "right":
|
|
289
|
-
arrowClassForCorrectAngle = '!zt-border-y-transparent !zt-border-l-transparent'
|
|
290
|
-
arrowTop = anchorElementRect.top - tooltipElementRect.top + (anchorElementRect.height / 2) - arrowHalfLengthOfLongSide - tooltipBorderWidth
|
|
291
|
-
arrowLeft = (-arrowSize * 2) - tooltipBorderWidth
|
|
292
|
-
break;
|
|
293
|
-
case "bottom":
|
|
294
|
-
arrowClassForCorrectAngle = '!zt-border-x-transparent !zt-border-t-transparent'
|
|
295
|
-
arrowTop = (-arrowSize * 2) - tooltipBorderWidth
|
|
296
|
-
arrowLeft = anchorElementRect.left - tooltipElementRect.left + (anchorElementRect.width / 2) - arrowHalfLengthOfLongSide - tooltipBorderWidth
|
|
297
|
-
break;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
if (currentTooltipPosition === 'left' || currentTooltipPosition === 'right') {
|
|
301
|
-
if (!isArrowPositionWithinLimits(currentTooltipPosition, tooltipElementRect, arrowTop)) {
|
|
302
|
-
arrowTop = getArrowPositionMinLimit(currentTooltipPosition, tooltipElementRect, arrowTop)
|
|
303
|
-
}
|
|
304
|
-
} else {
|
|
305
|
-
if (!isArrowPositionWithinLimits(currentTooltipPosition, tooltipElementRect, arrowLeft)) {
|
|
306
|
-
arrowLeft = getArrowPositionMinLimit(currentTooltipPosition, tooltipElementRect, arrowLeft)
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// Set Arrow element id, styling/angle
|
|
311
|
-
const arrowClasses = arrowElementClass + ' ' + defaultArrowClasses + ' ' + arrowClassForCorrectAngle + ' ' + config?.arrowClasses ?? ''
|
|
312
|
-
arrowElement.classList.add(...arrowClasses.split(' '))
|
|
313
|
-
|
|
314
|
-
// Set Arrow element size and position
|
|
315
|
-
arrowElement.style.top = `${arrowTop}px`
|
|
316
|
-
arrowElement.style.left = `${arrowLeft}px`
|
|
317
|
-
arrowElement.style.borderWidth = `${arrowSize}px`
|
|
318
|
-
|
|
319
|
-
// Mount Arrow element
|
|
320
|
-
document.querySelector(`.${tooltipElementClass}`)?.appendChild(arrowElement)
|
|
321
|
-
}
|
|
275
|
+
// Check if anchor element is directly on left of Tooltip
|
|
276
|
+
if (anchorElementRect.bottom < tooltipTop + arrowMinOffsetFromTooltipCorner * 2
|
|
277
|
+
|| anchorElementRect.top > tooltipTop + tooltipElementRect.height - arrowMinOffsetFromTooltipCorner * 2) return false
|
|
322
278
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
case "right":
|
|
327
|
-
return arrowPosition > arrowMinOffsetFromTooltipCorner - tooltipBorderWidth
|
|
328
|
-
&& arrowPosition < tooltipElementRect.height + tooltipBorderWidth - arrowMinOffsetFromTooltipCorner - (arrowSize * 2)
|
|
329
|
-
case "top":
|
|
330
|
-
case "bottom":
|
|
331
|
-
return arrowPosition > arrowMinOffsetFromTooltipCorner - tooltipBorderWidth
|
|
332
|
-
&& arrowPosition < tooltipElementRect.width + tooltipBorderWidth - arrowMinOffsetFromTooltipCorner - (arrowSize * 2)
|
|
333
|
-
}
|
|
334
|
-
}
|
|
279
|
+
// Set Tooltip position
|
|
280
|
+
tooltipElement.style.top = `${tooltipTop}px`
|
|
281
|
+
tooltipElement.style.left = `${tooltipLeft}px`
|
|
335
282
|
|
|
336
|
-
|
|
337
|
-
switch (currentTooltipPosition) {
|
|
338
|
-
case "left":
|
|
339
|
-
case "right":
|
|
340
|
-
if (arrowPosition < arrowMinOffsetFromTooltipCorner - tooltipBorderWidth) {
|
|
341
|
-
// Arrow too close to viewport top
|
|
342
|
-
return arrowMinOffsetFromTooltipCorner - tooltipBorderWidth
|
|
343
|
-
} else {
|
|
344
|
-
// Arrow too close to viewport bottom
|
|
345
|
-
return tooltipElementRect.height - tooltipBorderWidth - arrowMinOffsetFromTooltipCorner - (arrowSize * 2)
|
|
346
|
-
}
|
|
347
|
-
case "top":
|
|
348
|
-
case "bottom":
|
|
349
|
-
if (arrowPosition < arrowMinOffsetFromTooltipCorner - tooltipBorderWidth) {
|
|
350
|
-
// Arrow too close to viewport left
|
|
351
|
-
return arrowMinOffsetFromTooltipCorner - tooltipBorderWidth
|
|
352
|
-
} else {
|
|
353
|
-
// Arrow too close to viewport right
|
|
354
|
-
return tooltipElementRect.width - tooltipBorderWidth - arrowMinOffsetFromTooltipCorner - (arrowSize * 2)
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
},
|
|
359
|
-
}
|
|
283
|
+
return true
|
|
360
284
|
}
|
|
361
285
|
|
|
362
|
-
function
|
|
363
|
-
|
|
286
|
+
function tryMountTooltipOnTop(anchorElementRect: DOMRect) {
|
|
287
|
+
// Calculate and set Tooltip width
|
|
288
|
+
const tooltipAvailableMaxWidth = Math.min(window.innerWidth - (tooltipOffsetFromViewport * 2), tooltipMaxWidth)
|
|
289
|
+
tooltipElement.style.maxWidth = `${tooltipAvailableMaxWidth}px`
|
|
290
|
+
|
|
291
|
+
// Calculate Tooltip top position
|
|
292
|
+
const tooltipElementRect = tooltipElement.getBoundingClientRect()
|
|
293
|
+
let tooltipTop = anchorElementRect.top - tooltipOffsetFromSource - tooltipElementRect.height
|
|
294
|
+
|
|
295
|
+
// Check if Tooltip has enough available on top
|
|
296
|
+
if (tooltipTop < tooltipOffsetFromViewport) return false
|
|
364
297
|
|
|
365
|
-
//
|
|
366
|
-
|
|
298
|
+
// Calculate Tooltip left position
|
|
299
|
+
let tooltipLeft = anchorElementRect.left + (anchorElementRect.width / 2) - (tooltipElementRect.width / 2)
|
|
367
300
|
|
|
368
|
-
|
|
301
|
+
if (tooltipLeft < tooltipOffsetFromViewport) {
|
|
302
|
+
tooltipLeft = tooltipOffsetFromViewport
|
|
303
|
+
} else if (tooltipLeft + tooltipElementRect.width > window.innerWidth - tooltipOffsetFromViewport) {
|
|
304
|
+
tooltipLeft = window.innerWidth - tooltipOffsetFromViewport - tooltipElementRect.width
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Check if anchor element is directly on below of Tooltip
|
|
308
|
+
if (anchorElementRect.left > tooltipLeft + tooltipElementRect.width - arrowMinOffsetFromTooltipCorner * 2
|
|
309
|
+
|| anchorElementRect.right < tooltipLeft + arrowMinOffsetFromTooltipCorner * 2) return false
|
|
310
|
+
|
|
311
|
+
// Set Tooltip position
|
|
312
|
+
tooltipElement.style.top = `${tooltipTop}px`
|
|
313
|
+
tooltipElement.style.left = `${tooltipLeft}px`
|
|
314
|
+
|
|
315
|
+
return true
|
|
369
316
|
}
|
|
370
317
|
|
|
371
|
-
function
|
|
372
|
-
|
|
318
|
+
function tryMountTooltipOnBottom(anchorElementRect: DOMRect) {
|
|
319
|
+
// Calculate and set Tooltip width
|
|
320
|
+
const tooltipAvailableMaxWidth = Math.min(window.innerWidth - (tooltipOffsetFromViewport * 2), tooltipMaxWidth)
|
|
321
|
+
tooltipElement.style.maxWidth = `${tooltipAvailableMaxWidth}px`
|
|
322
|
+
|
|
323
|
+
// Calculate Tooltip top position
|
|
324
|
+
const tooltipElementRect = tooltipElement.getBoundingClientRect()
|
|
325
|
+
let tooltipTop = anchorElementRect.bottom + tooltipOffsetFromSource
|
|
373
326
|
|
|
374
|
-
if
|
|
375
|
-
|
|
327
|
+
// Check if Tooltip has enough available on bottom
|
|
328
|
+
if (tooltipTop + tooltipElementRect.height > window.innerHeight - tooltipOffsetFromViewport) return false
|
|
329
|
+
|
|
330
|
+
// Calculate Tooltip left position
|
|
331
|
+
let tooltipLeft = anchorElementRect.left + (anchorElementRect.width / 2) - (tooltipElementRect.width / 2)
|
|
332
|
+
|
|
333
|
+
if (tooltipLeft < tooltipOffsetFromViewport) {
|
|
334
|
+
tooltipLeft = tooltipOffsetFromViewport
|
|
335
|
+
} else if (tooltipLeft + tooltipElementRect.width > window.innerWidth - tooltipOffsetFromViewport) {
|
|
336
|
+
tooltipLeft = window.innerWidth - tooltipOffsetFromViewport - tooltipElementRect.width
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Check if anchor element is directly on top of Tooltip
|
|
340
|
+
if (anchorElementRect.left > tooltipLeft + tooltipElementRect.width - arrowMinOffsetFromTooltipCorner * 2
|
|
341
|
+
|| anchorElementRect.right < tooltipLeft + arrowMinOffsetFromTooltipCorner * 2) return false
|
|
342
|
+
|
|
343
|
+
// Set Tooltip position
|
|
344
|
+
tooltipElement.style.top = `${tooltipTop}px`
|
|
345
|
+
tooltipElement.style.left = `${tooltipLeft}px`
|
|
346
|
+
|
|
347
|
+
return true
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function drawArrow(anchorElementRect: DOMRect, currentTooltipPosition: TooltipPosition) {
|
|
351
|
+
// Create Arrow element
|
|
352
|
+
const arrowElement = document.createElement('div')
|
|
353
|
+
|
|
354
|
+
// Calculate Arrow element size, positions and style/angle classes
|
|
355
|
+
const tooltipElementRect = tooltipElement.getBoundingClientRect()
|
|
356
|
+
const arrowHalfLengthOfLongSide = Math.sin(45 * (180 / Math.PI)) * arrowSize
|
|
357
|
+
|
|
358
|
+
// 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
|
|
359
|
+
const arrowPositionAdjuster = 1;
|
|
360
|
+
|
|
361
|
+
// Arrow top/left 0 is Tooltip top/left 0
|
|
362
|
+
let arrowTop = 0
|
|
363
|
+
let arrowLeft = 0
|
|
364
|
+
|
|
365
|
+
let arrowClassForCorrectAngle = ''
|
|
366
|
+
|
|
367
|
+
switch (currentTooltipPosition) {
|
|
368
|
+
case "left":
|
|
369
|
+
arrowClassForCorrectAngle = '!zt-border-y-transparent !zt-border-r-transparent'
|
|
370
|
+
arrowTop = anchorElementRect.top - tooltipElementRect.top + (anchorElementRect.height / 2) - arrowHalfLengthOfLongSide - tooltipBorderWidth
|
|
371
|
+
arrowLeft = tooltipElementRect.width - tooltipBorderWidth - arrowPositionAdjuster
|
|
372
|
+
break;
|
|
373
|
+
case "top":
|
|
374
|
+
arrowClassForCorrectAngle = '!zt-border-x-transparent !zt-border-b-transparent'
|
|
375
|
+
arrowTop = tooltipElementRect.height - tooltipBorderWidth - arrowPositionAdjuster
|
|
376
|
+
arrowLeft = anchorElementRect.left - tooltipElementRect.left + (anchorElementRect.width / 2) - arrowHalfLengthOfLongSide - tooltipBorderWidth
|
|
377
|
+
break;
|
|
378
|
+
case "right":
|
|
379
|
+
arrowClassForCorrectAngle = '!zt-border-y-transparent !zt-border-l-transparent'
|
|
380
|
+
arrowTop = anchorElementRect.top - tooltipElementRect.top + (anchorElementRect.height / 2) - arrowHalfLengthOfLongSide - tooltipBorderWidth
|
|
381
|
+
arrowLeft = (-arrowSize * 2) - tooltipBorderWidth + arrowPositionAdjuster
|
|
382
|
+
break;
|
|
383
|
+
case "bottom":
|
|
384
|
+
arrowClassForCorrectAngle = '!zt-border-x-transparent !zt-border-t-transparent'
|
|
385
|
+
arrowTop = (-arrowSize * 2) - tooltipBorderWidth + arrowPositionAdjuster
|
|
386
|
+
arrowLeft = anchorElementRect.left - tooltipElementRect.left + (anchorElementRect.width / 2) - arrowHalfLengthOfLongSide - tooltipBorderWidth
|
|
387
|
+
break;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (currentTooltipPosition === 'left' || currentTooltipPosition === 'right') {
|
|
391
|
+
if (!isArrowPositionWithinLimits(currentTooltipPosition, tooltipElementRect, arrowTop)) {
|
|
392
|
+
arrowTop = getArrowPositionMinLimit(currentTooltipPosition, tooltipElementRect, arrowTop)
|
|
393
|
+
}
|
|
376
394
|
} else {
|
|
377
|
-
|
|
395
|
+
if (!isArrowPositionWithinLimits(currentTooltipPosition, tooltipElementRect, arrowLeft)) {
|
|
396
|
+
arrowLeft = getArrowPositionMinLimit(currentTooltipPosition, tooltipElementRect, arrowLeft)
|
|
397
|
+
}
|
|
378
398
|
}
|
|
379
399
|
|
|
380
|
-
|
|
381
|
-
|
|
400
|
+
// Set Arrow element id, styling/angle
|
|
401
|
+
const adjustedArrowClasses = arrowElementClass + ' ' + defaultArrowClasses + ' ' + arrowClassForCorrectAngle + ' ' + arrowClasses
|
|
402
|
+
|
|
403
|
+
arrowElement.classList.add(...adjustedArrowClasses.trim().split(' '))
|
|
404
|
+
|
|
405
|
+
// Set Arrow element size and position
|
|
406
|
+
arrowElement.style.top = `${arrowTop}px`
|
|
407
|
+
arrowElement.style.left = `${arrowLeft}px`
|
|
408
|
+
arrowElement.style.borderWidth = `${arrowSize}px`
|
|
409
|
+
|
|
410
|
+
// Mount Arrow element
|
|
411
|
+
document.querySelector(`.${tooltipElementClass}`)?.appendChild(arrowElement)
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function isArrowPositionWithinLimits(currentTooltipPosition: TooltipPosition, tooltipElementRect: DOMRect, arrowPosition: number) {
|
|
415
|
+
switch (currentTooltipPosition) {
|
|
416
|
+
case "left":
|
|
417
|
+
case "right":
|
|
418
|
+
return arrowPosition > arrowMinOffsetFromTooltipCorner - tooltipBorderWidth
|
|
419
|
+
&& arrowPosition < tooltipElementRect.height + tooltipBorderWidth - arrowMinOffsetFromTooltipCorner - (arrowSize * 2)
|
|
420
|
+
case "top":
|
|
421
|
+
case "bottom":
|
|
422
|
+
return arrowPosition > arrowMinOffsetFromTooltipCorner - tooltipBorderWidth
|
|
423
|
+
&& arrowPosition < tooltipElementRect.width + tooltipBorderWidth - arrowMinOffsetFromTooltipCorner - (arrowSize * 2)
|
|
382
424
|
}
|
|
425
|
+
}
|
|
383
426
|
|
|
384
|
-
|
|
427
|
+
function getArrowPositionMinLimit(currentTooltipPosition: TooltipPosition, tooltipElementRect: DOMRect, arrowPosition: number) {
|
|
428
|
+
switch (currentTooltipPosition) {
|
|
429
|
+
case "left":
|
|
430
|
+
case "right":
|
|
431
|
+
if (arrowPosition < arrowMinOffsetFromTooltipCorner - tooltipBorderWidth) {
|
|
432
|
+
// Arrow too close to viewport top
|
|
433
|
+
return arrowMinOffsetFromTooltipCorner - tooltipBorderWidth
|
|
434
|
+
} else {
|
|
435
|
+
// Arrow too close to viewport bottom
|
|
436
|
+
return tooltipElementRect.height - tooltipBorderWidth - arrowMinOffsetFromTooltipCorner - (arrowSize * 2)
|
|
437
|
+
}
|
|
438
|
+
case "top":
|
|
439
|
+
case "bottom":
|
|
440
|
+
if (arrowPosition < arrowMinOffsetFromTooltipCorner - tooltipBorderWidth) {
|
|
441
|
+
// Arrow too close to viewport left
|
|
442
|
+
return arrowMinOffsetFromTooltipCorner - tooltipBorderWidth
|
|
443
|
+
} else {
|
|
444
|
+
// Arrow too close to viewport right
|
|
445
|
+
return tooltipElementRect.width - tooltipBorderWidth - arrowMinOffsetFromTooltipCorner - (arrowSize * 2)
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
function hideTooltip() {
|
|
451
|
+
const tooltipElement = document.querySelector(`.${tooltipElementClass}`)
|
|
452
|
+
|
|
453
|
+
if (tooltipElement && tooltipElement instanceof HTMLElement) {
|
|
454
|
+
resetResizeReferences()
|
|
455
|
+
|
|
456
|
+
// Remove Arrow element from Tooltip, because it needs to be rebuilt every time Tooltip is showed again
|
|
457
|
+
tooltipElement.querySelector(`.${arrowElementClass}`)?.remove()
|
|
458
|
+
|
|
459
|
+
// Reset position so that old position does not effect new position (when zooming old position could be off screen)
|
|
460
|
+
tooltipElement.style.left = '0'
|
|
461
|
+
tooltipElement.style.top = '0'
|
|
462
|
+
|
|
463
|
+
tooltipElement.remove()
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
isHovered = false
|
|
385
467
|
}
|
|
386
468
|
|
|
387
469
|
export default ZeroTooltip
|