diff options
Diffstat (limited to 'src/lib/Tooltip/LinkedTooltip.svelte')
| -rw-r--r-- | src/lib/Tooltip/LinkedTooltip.svelte | 328 |
1 files changed, 179 insertions, 149 deletions
diff --git a/src/lib/Tooltip/LinkedTooltip.svelte b/src/lib/Tooltip/LinkedTooltip.svelte index 4c90d9af..82147536 100644 --- a/src/lib/Tooltip/LinkedTooltip.svelte +++ b/src/lib/Tooltip/LinkedTooltip.svelte @@ -1,12 +1,12 @@ <script lang="ts"> -import tooltipPosition from '$stores/tooltipPosition'; -import { fade } from 'svelte/transition'; +import tooltipPosition from "$stores/tooltipPosition"; +import { fade } from "svelte/transition"; export let id: string | undefined = undefined; export let pin: string | undefined = undefined; export let content: string; export let disable = false; -export let pinPosition: 'top' | 'bottom' | 'left' | 'right' = 'top'; +export let pinPosition: "top" | "bottom" | "left" | "right" = "top"; export let offset = 10; export let tooltipTransitionTime = 200; export let tooltipHideDelay = 10; @@ -21,178 +21,208 @@ let debounceTimer: number | null = null; let opacity = 0; const createTooltip = () => { - if (!tooltipDiv) { - tooltipDiv = document.createElement('div'); - tooltipDiv.style.position = 'absolute'; - tooltipDiv.style.zIndex = '1000'; - opacity = 0; - tooltipDiv.style.pointerEvents = 'none'; - tooltipDiv.style.whiteSpace = 'nowrap'; - - tooltipDiv.classList.add('card'); - tooltipDiv.classList.add('card-small'); - document.body.appendChild(tooltipDiv); - } + if (!tooltipDiv) { + tooltipDiv = document.createElement("div"); + tooltipDiv.style.position = "absolute"; + tooltipDiv.style.zIndex = "1000"; + opacity = 0; + tooltipDiv.style.pointerEvents = "none"; + tooltipDiv.style.whiteSpace = "nowrap"; + + tooltipDiv.classList.add("card"); + tooltipDiv.classList.add("card-small"); + document.body.appendChild(tooltipDiv); + } }; const updateTooltipPosition = (x: number, y: number) => { - if (tooltipDiv) { - if (pin) { - const pinnedElement = document.getElementById(pin); - - if (pinnedElement) { - const rectangle = pinnedElement.getBoundingClientRect(); - const parentRectangle = pinnedElement.offsetParent?.getBoundingClientRect(); - const tooltipWidth = tooltipDiv.offsetWidth; - const tooltipHeight = tooltipDiv.offsetHeight; - let top = 0; - let left = 0; - - switch (pinPosition) { - case 'top': - if (relative && parentRectangle) { - top = rectangle.top - tooltipHeight - offset - parentRectangle.top; - left = rectangle.left + rectangle.width / 2 - tooltipWidth / 2 - parentRectangle.left; - } else { - top = rectangle.top - tooltipHeight - offset; - left = rectangle.left + rectangle.width / 2 - tooltipWidth / 2; - } - - break; - case 'bottom': - if (relative && parentRectangle) { - top = rectangle.top + rectangle.height + offset - parentRectangle.top; - left = rectangle.left + rectangle.width / 2 - tooltipWidth / 2 - parentRectangle.left; - } else { - top = rectangle.top + rectangle.height + offset; - left = rectangle.left + rectangle.width / 2 - tooltipWidth / 2; - } - - break; - case 'left': - if (relative && parentRectangle) { - top = rectangle.top + rectangle.height / 2 - tooltipHeight / 2 - parentRectangle.top; - left = rectangle.left - tooltipWidth - offset - parentRectangle.left; - } else { - top = rectangle.top + rectangle.height / 2 - tooltipHeight / 2; - left = rectangle.left - tooltipWidth - offset; - } - - break; - case 'right': - if (relative && parentRectangle) { - top = rectangle.top + rectangle.height / 2 - tooltipHeight / 2 - parentRectangle.top; - left = rectangle.left + rectangle.width + offset - parentRectangle.left; - } else { - top = rectangle.top + rectangle.height / 2 - tooltipHeight / 2; - left = rectangle.left + rectangle.width + offset; - } - - break; - } - - if (relative && parentRectangle) { - if (left + parentRectangle.left < 0) left = offset - parentRectangle.left; - if (left + tooltipWidth + parentRectangle.left > window.innerWidth) - left = window.innerWidth - tooltipWidth - offset - parentRectangle.left; - if (top + parentRectangle.top < 0) - top = rectangle.top + rectangle.height + offset - parentRectangle.top; - if (top + tooltipHeight + parentRectangle.top > window.innerHeight) - top = window.innerHeight - tooltipHeight - offset - parentRectangle.top; - } else { - if (left < 0) left = offset; - if (left + tooltipWidth > window.innerWidth) - left = window.innerWidth - tooltipWidth - offset; - if (top < 0) top = rectangle.top + rectangle.height + offset; - if (top + tooltipHeight > window.innerHeight) - top = window.innerHeight - tooltipHeight - offset; - } - - tooltipPosition.set({ - x: left, - y: top + (relative ? 0 : window.scrollY) - }); - - return; - } - } - - const tooltipWidth = tooltipDiv.offsetWidth; - const tooltipHeight = tooltipDiv.offsetHeight; - let top = y - tooltipHeight - offset; - let left = x - tooltipWidth / 2; - - if (left < 0) left = offset; - if (left + tooltipWidth > window.innerWidth) left = window.innerWidth - tooltipWidth - offset; - if (top < 0) top = y + offset; - - tooltipPosition.set({ - x: left, - y: top - }); - } + if (tooltipDiv) { + if (pin) { + const pinnedElement = document.getElementById(pin); + + if (pinnedElement) { + const rectangle = pinnedElement.getBoundingClientRect(); + const parentRectangle = + pinnedElement.offsetParent?.getBoundingClientRect(); + const tooltipWidth = tooltipDiv.offsetWidth; + const tooltipHeight = tooltipDiv.offsetHeight; + let top = 0; + let left = 0; + + switch (pinPosition) { + case "top": + if (relative && parentRectangle) { + top = + rectangle.top - tooltipHeight - offset - parentRectangle.top; + left = + rectangle.left + + rectangle.width / 2 - + tooltipWidth / 2 - + parentRectangle.left; + } else { + top = rectangle.top - tooltipHeight - offset; + left = rectangle.left + rectangle.width / 2 - tooltipWidth / 2; + } + + break; + case "bottom": + if (relative && parentRectangle) { + top = + rectangle.top + rectangle.height + offset - parentRectangle.top; + left = + rectangle.left + + rectangle.width / 2 - + tooltipWidth / 2 - + parentRectangle.left; + } else { + top = rectangle.top + rectangle.height + offset; + left = rectangle.left + rectangle.width / 2 - tooltipWidth / 2; + } + + break; + case "left": + if (relative && parentRectangle) { + top = + rectangle.top + + rectangle.height / 2 - + tooltipHeight / 2 - + parentRectangle.top; + left = + rectangle.left - tooltipWidth - offset - parentRectangle.left; + } else { + top = rectangle.top + rectangle.height / 2 - tooltipHeight / 2; + left = rectangle.left - tooltipWidth - offset; + } + + break; + case "right": + if (relative && parentRectangle) { + top = + rectangle.top + + rectangle.height / 2 - + tooltipHeight / 2 - + parentRectangle.top; + left = + rectangle.left + + rectangle.width + + offset - + parentRectangle.left; + } else { + top = rectangle.top + rectangle.height / 2 - tooltipHeight / 2; + left = rectangle.left + rectangle.width + offset; + } + + break; + } + + if (relative && parentRectangle) { + if (left + parentRectangle.left < 0) + left = offset - parentRectangle.left; + if (left + tooltipWidth + parentRectangle.left > window.innerWidth) + left = + window.innerWidth - tooltipWidth - offset - parentRectangle.left; + if (top + parentRectangle.top < 0) + top = + rectangle.top + rectangle.height + offset - parentRectangle.top; + if (top + tooltipHeight + parentRectangle.top > window.innerHeight) + top = + window.innerHeight - tooltipHeight - offset - parentRectangle.top; + } else { + if (left < 0) left = offset; + if (left + tooltipWidth > window.innerWidth) + left = window.innerWidth - tooltipWidth - offset; + if (top < 0) top = rectangle.top + rectangle.height + offset; + if (top + tooltipHeight > window.innerHeight) + top = window.innerHeight - tooltipHeight - offset; + } + + tooltipPosition.set({ + x: left, + y: top + (relative ? 0 : window.scrollY), + }); + + return; + } + } + + const tooltipWidth = tooltipDiv.offsetWidth; + const tooltipHeight = tooltipDiv.offsetHeight; + let top = y - tooltipHeight - offset; + let left = x - tooltipWidth / 2; + + if (left < 0) left = offset; + if (left + tooltipWidth > window.innerWidth) + left = window.innerWidth - tooltipWidth - offset; + if (top < 0) top = y + offset; + + tooltipPosition.set({ + x: left, + y: top, + }); + } }; const showTooltip = (content: string, x: number, y: number) => { - if (hideTimeout !== null) { - clearTimeout(hideTimeout); + if (hideTimeout !== null) { + clearTimeout(hideTimeout); - hideTimeout = null; - } + hideTimeout = null; + } - createTooltip(); + createTooltip(); - if (tooltipDiv) { - tooltipDiv.innerHTML = content.replace(/\n/g, '<br>'); - tooltipDiv.style.opacity = '0'; + if (tooltipDiv) { + tooltipDiv.innerHTML = content.replace(/\n/g, "<br>"); + tooltipDiv.style.opacity = "0"; - updateTooltipPosition(x, y); - setTimeout(() => { - if (tooltipDiv) { - opacity = 1; - } - }, 10); - } + updateTooltipPosition(x, y); + setTimeout(() => { + if (tooltipDiv) { + opacity = 1; + } + }, 10); + } }; const hideTooltip = () => { - setTimeout(() => { - if (tooltipDiv) { - opacity = 0; - - hideTimeout = window.setTimeout(() => { - if (tooltipDiv) { - document.body.removeChild(tooltipDiv); - - tooltipDiv = null; - } - }, tooltipTransitionTime); - } - }, tooltipHideDelay); + setTimeout(() => { + if (tooltipDiv) { + opacity = 0; + + hideTimeout = window.setTimeout(() => { + if (tooltipDiv) { + document.body.removeChild(tooltipDiv); + + tooltipDiv = null; + } + }, tooltipTransitionTime); + } + }, tooltipHideDelay); }; const handleMouseEnter = (event: MouseEvent) => { - if (disable) return; + if (disable) return; - if (hideTimeout !== null) { - clearTimeout(hideTimeout); + if (hideTimeout !== null) { + clearTimeout(hideTimeout); - hideTimeout = null; - } + hideTimeout = null; + } - if (!tooltipDiv) showTooltip(content, event.pageX, event.pageY); + if (!tooltipDiv) showTooltip(content, event.pageX, event.pageY); }; const handleMouseMove = (event: MouseEvent) => { - if (debounceTimer !== null) clearTimeout(debounceTimer); + if (debounceTimer !== null) clearTimeout(debounceTimer); - debounceTimer = window.setTimeout(() => { - if (tooltipDiv && opacity === 1) updateTooltipPosition(event.pageX, event.pageY); - }, debounceDelay); + debounceTimer = window.setTimeout(() => { + if (tooltipDiv && opacity === 1) + updateTooltipPosition(event.pageX, event.pageY); + }, debounceDelay); }; const handleMouseLeave = () => { - hideTooltip(); + hideTooltip(); }; </script> |