|
1 | 1 | <script> |
2 | 2 | import { onMount, onDestroy } from 'svelte'; |
| 3 | + import { formatVariableKey, getMinWidth, isInViewport } from './helpers'; |
| 4 | + import { inverse } from './constants'; |
3 | 5 |
|
4 | 6 | export let content = ''; |
5 | 7 | export let align = 'left'; |
|
14 | 16 | let ref = null; |
15 | 17 | let minWidth = 0; |
16 | 18 | let component = null; |
17 | | -
|
18 | | - const inverse = { |
19 | | - left: 'right', |
20 | | - right: 'left', |
21 | | - top: 'bottom', |
22 | | - bottom: 'top' |
23 | | - }; |
24 | | -
|
25 | | - const isInViewport = () => { |
26 | | - const rect = ref.getBoundingClientRect(); |
27 | | -
|
28 | | - return ( |
29 | | - rect.top >= 0 && |
30 | | - rect.left >= 0 && |
31 | | - rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && |
32 | | - rect.right <= (window.innerWidth || document.documentElement.clientWidth) |
33 | | - ); |
34 | | - }; |
| 19 | + let animationEffect = null; |
| 20 | + let show = false; |
35 | 21 |
|
36 | 22 | onMount(() => { |
| 23 | + const delay = animation ? 200 : 0; |
| 24 | +
|
37 | 25 | if (ref !== null) { |
38 | 26 | if (isComponent && !component) { |
39 | 27 | component = new content.component({ target: ref, props: content.props }); |
40 | 28 | } |
41 | 29 |
|
42 | | - const elementWidth = ref.getBoundingClientRect().width; |
43 | | - const elementStyle = window.getComputedStyle(ref); |
44 | | - const elementPaddingLeft = parseInt(elementStyle.getPropertyValue('padding-left'), 10); |
45 | | - const elementPaddingRight = parseInt(elementStyle.getPropertyValue('padding-right'), 10); |
46 | | - const elementPadding = elementPaddingLeft + elementPaddingRight; |
47 | | - const contentWidth = elementWidth - elementPadding; |
48 | | -
|
49 | | - minWidth = Math.round(Math.min(maxWidth, contentWidth)); |
| 30 | + minWidth = getMinWidth(ref, maxWidth); |
50 | 31 |
|
51 | 32 | if (style && typeof style === 'object') { |
52 | 33 | for (let prop in style) { |
| 34 | + const key = formatVariableKey(prop); |
53 | 35 | const value = style[prop]; |
54 | | - const key = prop |
55 | | - .replace(/-_$/g, '') |
56 | | - .replace(/([a-z0-9])([A-Z])/g, '$1-$2') |
57 | | - .replace(/([A-Z])([A-Z])(?=[a-z])/g, '$1-$2') |
58 | | - .toLowerCase(); |
59 | 36 |
|
60 | 37 | ref.style.setProperty(`--tooltip-${key}`, value); |
61 | 38 | } |
62 | 39 | } |
63 | 40 | } |
64 | 41 |
|
65 | | - if (autoPosition && !isInViewport()) { |
| 42 | + if (autoPosition && !isInViewport(ref)) { |
66 | 43 | position = inverse[position]; |
67 | 44 | } |
68 | 45 |
|
69 | | - ref.classList.add('show'); |
| 46 | + if (animation) { |
| 47 | + animationEffect = animation; |
| 48 | + } |
| 49 | +
|
| 50 | + setTimeout(() => (show = true), delay); |
70 | 51 | }); |
71 | 52 |
|
72 | 53 | onDestroy(() => { |
|
81 | 62 |
|
82 | 63 | <div |
83 | 64 | bind:this={ref} |
84 | | - class="tooltip animation-{animation} {position} {theme}" |
| 65 | + class="tooltip animation-{animationEffect} {position} {theme}" |
| 66 | + class:show |
85 | 67 | class:arrowless={!arrow} |
86 | 68 | style="min-width: {minWidth}px; max-width: {maxWidth}px; text-align: {align};" |
87 | 69 | > |
|
121 | 103 | box-shadow: var(--tooltip-box-shadow); |
122 | 104 | border-radius: var(--tooltip-border-radius); |
123 | 105 | color: var(--tooltip-color); |
| 106 | + opacity: 0; |
124 | 107 | font-family: var(--tooltip-font-family); |
125 | 108 | font-size: var(--tooltip-font-size); |
126 | 109 | font-style: normal; |
|
129 | 112 | padding: var(--tooltip-padding); |
130 | 113 | position: absolute; |
131 | 114 | text-align: left; |
| 115 | + visibility: hidden; |
132 | 116 | white-space: nowrap; |
133 | 117 | z-index: var(--tooltip-z-index); |
134 | 118 | } |
135 | 119 |
|
136 | 120 | .tooltip.show { |
| 121 | + opacity: 1; |
| 122 | + visibility: visible; |
137 | 123 | white-space: normal; |
138 | 124 | } |
139 | 125 |
|
|
210 | 196 |
|
211 | 197 | .tooltip.animation-fade { |
212 | 198 | opacity: 0; |
213 | | - transition: opacity 0.3s ease-in-out; |
| 199 | + transition: opacity 0.25s ease-in-out; |
214 | 200 | } |
215 | 201 |
|
216 | 202 | .tooltip.animation-fade.show { |
|
222 | 208 | .tooltip.top.animation-slide { |
223 | 209 | margin-top: 10px; |
224 | 210 | opacity: 0; |
225 | | - transition: opacity 0.3s ease-in-out, margin 0.3s ease-in-out; |
| 211 | + transition: opacity 0.25s ease-in-out, margin 0.25s ease-in-out; |
226 | 212 | } |
227 | 213 |
|
228 | 214 | .tooltip.top.animation-slide.show { |
|
233 | 219 | .tooltip.bottom.animation-slide { |
234 | 220 | margin-bottom: 20px; |
235 | 221 | opacity: 0; |
236 | | - transition: opacity 0.3s ease-in-out, margin 0.3s ease-in-out; |
| 222 | + transition: opacity 0.25s ease-in-out, margin 0.25s ease-in-out; |
237 | 223 | } |
238 | 224 |
|
239 | 225 | .tooltip.bottom.animation-slide.show { |
|
244 | 230 | .tooltip.right.animation-slide { |
245 | 231 | margin-right: 20px; |
246 | 232 | opacity: 0; |
247 | | - transition: opacity 0.3s ease-in-out, margin 0.3s ease-in-out; |
| 233 | + transition: opacity 0.25s ease-in-out, margin 0.25s ease-in-out; |
248 | 234 | } |
249 | 235 |
|
250 | 236 | .tooltip.right.animation-slide.show { |
|
255 | 241 | .tooltip.left.animation-slide { |
256 | 242 | margin-left: 20px; |
257 | 243 | opacity: 0; |
258 | | - transition: opacity 0.3s ease-in-out, margin 0.3s ease-in-out; |
| 244 | + transition: opacity 0.25s ease-in-out, margin 0.25s ease-in-out; |
259 | 245 | } |
260 | 246 |
|
261 | 247 | .tooltip.left.animation-slide.show { |
|
270 | 256 | opacity: 0; |
271 | 257 | transform: translate(calc(-100% - var(--tooltip-offset-x)), -50%) scale(2, 2); |
272 | 258 | transform-origin: 50% 50%; |
273 | | - transition: opacity 0.3s ease-in-out, filter 0.3s ease-in-out, transform 0.3s ease-in-out; |
| 259 | + transition: opacity 0.25s ease-in-out, filter 0.25s ease-in-out, transform 0.25s ease-in-out; |
274 | 260 | } |
275 | 261 |
|
276 | 262 | .tooltip.left.animation-puff.show { |
|
284 | 270 | opacity: 0; |
285 | 271 | transform: translate(calc(100% + var(--tooltip-offset-x)), -50%) scale(2, 2); |
286 | 272 | transform-origin: 50% 50%; |
287 | | - transition: opacity 0.3s ease-in-out, filter 0.3s ease-in-out, transform 0.3s ease-in-out; |
| 273 | + transition: opacity 0.25s ease-in-out, filter 0.25s ease-in-out, transform 0.25s ease-in-out; |
288 | 274 | } |
289 | 275 |
|
290 | 276 | .tooltip.right.animation-puff.show { |
|
298 | 284 | opacity: 0; |
299 | 285 | transform: translate(-50%, calc(-100% - var(--tooltip-offset-y))) scale(2, 2); |
300 | 286 | transform-origin: 50% 50%; |
301 | | - transition: opacity 0.3s ease-in-out, filter 0.3s ease-in-out, transform 0.3s ease-in-out; |
| 287 | + transition: opacity 0.25s ease-in-out, filter 0.25s ease-in-out, transform 0.25s ease-in-out; |
302 | 288 | } |
303 | 289 |
|
304 | 290 | .tooltip.top.animation-puff.show { |
|
312 | 298 | opacity: 0; |
313 | 299 | transform: translate(-50%, calc(100% + var(--tooltip-offset-y))) scale(2, 2); |
314 | 300 | transform-origin: 50% 50%; |
315 | | - transition: opacity 0.3s ease-in-out, filter 0.3s ease-in-out, transform 0.3s ease-in-out; |
| 301 | + transition: opacity 0.25s ease-in-out, filter 0.25s ease-in-out, transform 0.25s ease-in-out; |
316 | 302 | } |
317 | 303 |
|
318 | 304 | .tooltip.bottom.animation-puff.show { |
|
327 | 313 | opacity: 0; |
328 | 314 | transform: translate(calc(-100% - var(--tooltip-offset-x)), -50%) scale(1.2, 1.2); |
329 | 315 | transform-origin: 50% 50%; |
330 | | - transition: opacity 0.3s ease-in-out, transform 0.3s cubic-bezier(0.5, -1, 0.5, 3); |
| 316 | + transition: opacity 0.25s ease-in-out, transform 0.25s cubic-bezier(0.5, -1, 0.5, 3); |
331 | 317 | } |
332 | 318 |
|
333 | 319 | .tooltip.left.animation-bounce.show { |
|
339 | 325 | opacity: 0; |
340 | 326 | transform: translate(calc(100% + var(--tooltip-offset-x)), -50%) scale(1.2, 1.2); |
341 | 327 | transform-origin: 50% 50%; |
342 | | - transition: opacity 0.3s ease-in-out, transform 0.3s cubic-bezier(0.5, -1, 0.5, 3); |
| 328 | + transition: opacity 0.25s ease-in-out, transform 0.25s cubic-bezier(0.5, -1, 0.5, 3); |
343 | 329 | } |
344 | 330 |
|
345 | 331 | .tooltip.right.animation-bounce.show { |
|
351 | 337 | opacity: 0; |
352 | 338 | transform: translate(-50%, calc(-100% - var(--tooltip-offset-y))) scale(1.2, 1.2); |
353 | 339 | transform-origin: 50% 50%; |
354 | | - transition: opacity 0.3s ease-in-out, transform 0.3s cubic-bezier(0.5, -1, 0.5, 3); |
| 340 | + transition: opacity 0.25s ease-in-out, transform 0.25s cubic-bezier(0.5, -1, 0.5, 3); |
355 | 341 | } |
356 | 342 |
|
357 | 343 | .tooltip.top.animation-bounce.show { |
|
363 | 349 | opacity: 0; |
364 | 350 | transform: translate(-50%, calc(100% + var(--tooltip-offset-y))) scale(1.2, 1.2); |
365 | 351 | transform-origin: 50% 50%; |
366 | | - transition: opacity 0.3s ease-in-out, transform 0.3s cubic-bezier(0.5, -1, 0.5, 3); |
| 352 | + transition: opacity 0.25s ease-in-out, transform 0.25s cubic-bezier(0.5, -1, 0.5, 3); |
367 | 353 | } |
368 | 354 |
|
369 | 355 | .tooltip.bottom.animation-bounce.show { |
|
0 commit comments