UNPKG

astro

Version:

Astro is a modern site builder with web best practices, performance, and DX front-of-mind.

71 lines (70 loc) • 2.66 kB
export function createHighlight(rect, icon, additionalAttributes) { const highlight = document.createElement("astro-dev-toolbar-highlight"); if (icon) highlight.icon = icon; if (additionalAttributes) { for (const [key, value] of Object.entries(additionalAttributes)) { highlight.setAttribute(key, value); } } highlight.tabIndex = 0; if (rect.width === 0 || rect.height === 0) { highlight.style.display = "none"; } else { positionHighlight(highlight, rect); } return highlight; } // Figures out the element's position, based on it's parents. export function getElementsPositionInDocument(el) { let isFixed = false; let current = el; while (current instanceof Element) { // all the way up the tree. We are only doing so when the app initializes, so the cost is one-time // If perf becomes an issue we'll want to refactor this somehow so that it reads this info in a rAF let style = getComputedStyle(current); if (style.position === "fixed") { isFixed = true; } current = current.parentNode; } return { isFixed }; } export function positionHighlight(highlight, rect) { highlight.style.display = "block"; // If the highlight is fixed, don't position based on scroll const scrollY = highlight.style.position === "fixed" ? 0 : window.scrollY; // Make a highlight that is 10px bigger than the element on all sides highlight.style.top = `${Math.max(rect.top + scrollY - 10, 0)}px`; highlight.style.left = `${Math.max(rect.left + window.scrollX - 10, 0)}px`; highlight.style.width = `${rect.width + 15}px`; highlight.style.height = `${rect.height + 15}px`; } export function attachTooltipToHighlight(highlight, tooltip, originalElement) { highlight.shadowRoot.append(tooltip); ["mouseover", "focus"].forEach((event) => { highlight.addEventListener(event, () => { tooltip.dataset.show = "true"; const originalRect = originalElement.getBoundingClientRect(); const dialogRect = tooltip.getBoundingClientRect(); // Prevent the tooltip from being off the screen if (originalRect.top < dialogRect.height) { // Not enough space above, show below tooltip.style.top = `${originalRect.height + 15}px`; } else { tooltip.style.top = `-${tooltip.offsetHeight}px`; } if (dialogRect.right > document.documentElement.clientWidth) { // Not enough space on the right, align to the right tooltip.style.right = "0px"; } else if (dialogRect.left < 0) { // Not enough space on the left, align to the left tooltip.style.left = "0px"; } }); }); ["mouseout", "blur"].forEach((event) => { highlight.addEventListener(event, () => { tooltip.dataset.show = "false"; }); }); }