123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- import "./Tooltip.scss";
- import React, { useEffect } from "react";
- export const getTooltipDiv = () => {
- const existingDiv = document.querySelector<HTMLDivElement>(
- ".excalidraw-tooltip",
- );
- if (existingDiv) {
- return existingDiv;
- }
- const div = document.createElement("div");
- document.body.appendChild(div);
- div.classList.add("excalidraw-tooltip");
- return div;
- };
- export const updateTooltipPosition = (
- tooltip: HTMLDivElement,
- item: {
- left: number;
- top: number;
- width: number;
- height: number;
- },
- position: "bottom" | "top" = "bottom",
- ) => {
- const tooltipRect = tooltip.getBoundingClientRect();
- const viewportWidth = window.innerWidth;
- const viewportHeight = window.innerHeight;
- const margin = 5;
- let left = item.left + item.width / 2 - tooltipRect.width / 2;
- if (left < 0) {
- left = margin;
- } else if (left + tooltipRect.width >= viewportWidth) {
- left = viewportWidth - tooltipRect.width - margin;
- }
- let top: number;
- if (position === "bottom") {
- top = item.top + item.height + margin;
- if (top + tooltipRect.height >= viewportHeight) {
- top = item.top - tooltipRect.height - margin;
- }
- } else {
- top = item.top - tooltipRect.height - margin;
- if (top < 0) {
- top = item.top + item.height + margin;
- }
- }
- Object.assign(tooltip.style, {
- top: `${top}px`,
- left: `${left}px`,
- });
- };
- const updateTooltip = (
- item: HTMLDivElement,
- tooltip: HTMLDivElement,
- label: string,
- long: boolean,
- ) => {
- tooltip.classList.add("excalidraw-tooltip--visible");
- tooltip.style.minWidth = long ? "50ch" : "10ch";
- tooltip.style.maxWidth = long ? "50ch" : "15ch";
- tooltip.textContent = label;
- const itemRect = item.getBoundingClientRect();
- updateTooltipPosition(tooltip, itemRect);
- };
- type TooltipProps = {
- children: React.ReactNode;
- label: string;
- long?: boolean;
- style?: React.CSSProperties;
- };
- export const Tooltip = ({
- children,
- label,
- long = false,
- style,
- }: TooltipProps) => {
- useEffect(() => {
- return () =>
- getTooltipDiv().classList.remove("excalidraw-tooltip--visible");
- }, []);
- return (
- <div
- className="excalidraw-tooltip-wrapper"
- onPointerEnter={(event) =>
- updateTooltip(
- event.currentTarget as HTMLDivElement,
- getTooltipDiv(),
- label,
- long,
- )
- }
- onPointerLeave={() =>
- getTooltipDiv().classList.remove("excalidraw-tooltip--visible")
- }
- style={style}
- >
- {children}
- </div>
- );
- };
|