113 lines
2.8 KiB
TypeScript
113 lines
2.8 KiB
TypeScript
import { useLayoutEffect, useRef, useState } from "react";
|
|
import { Mark as MarkType } from "../types/Mark";
|
|
|
|
interface MarkProps {
|
|
setHoveredMark: React.Dispatch<React.SetStateAction<string>>;
|
|
hoveredMark: string;
|
|
mark: MarkType;
|
|
width: number;
|
|
height: number;
|
|
icon: React.ReactNode;
|
|
onClick?: () => void;
|
|
}
|
|
|
|
const MainMark = ({
|
|
width,
|
|
height,
|
|
icon,
|
|
mark,
|
|
setHoveredMark,
|
|
hoveredMark,
|
|
onClick,
|
|
}: MarkProps) => {
|
|
const [textWidth, setTextWidth] = useState(0);
|
|
const textRef = useRef(null);
|
|
|
|
useLayoutEffect(() => {
|
|
if (!textRef.current) return;
|
|
const _textWidth = (textRef.current as unknown as SVGSVGElement).getBBox()
|
|
.width;
|
|
setTextWidth(_textWidth);
|
|
}, []);
|
|
|
|
function handleOnMouseEnter(): void {
|
|
setHoveredMark(mark.id);
|
|
}
|
|
|
|
function handleOnMouseLeave(): void {
|
|
setHoveredMark("");
|
|
}
|
|
|
|
return (
|
|
<svg
|
|
onClick={onClick}
|
|
onMouseEnter={handleOnMouseEnter}
|
|
onMouseLeave={handleOnMouseLeave}
|
|
className={`transition-all absolute duration-300 ease-in-out cursor-pointer group`}
|
|
x={mark.x - 150 + 50}
|
|
y={mark.y}
|
|
width={width + 300}
|
|
height={height}
|
|
viewBox={`0 0 ${textWidth + 108} 64`}
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<svg xmlns="http://www.w3.org/2000/svg">
|
|
<g>
|
|
<rect
|
|
x={width / 2}
|
|
y="0"
|
|
width="32"
|
|
height="64"
|
|
fill="white"
|
|
className={`transition-all duration-150 ${
|
|
hoveredMark === mark.id ? "delay-100" : ""
|
|
} ease-in-out w-0 group-hover:w-8`}
|
|
></rect>
|
|
<rect
|
|
x={width / 2}
|
|
y="0"
|
|
rx={32}
|
|
width="100"
|
|
height="64"
|
|
fill="white"
|
|
className={`transition-all duration-300 ease-in-out w-0 group-hover:w-[${
|
|
textWidth + 84
|
|
}]`}
|
|
style={{
|
|
// width: `${true ? `${textWidth + 84}` : 0}`,
|
|
width: `${hoveredMark === mark.id ? `${textWidth + 84}` : 0}`,
|
|
}}
|
|
></rect>
|
|
<text
|
|
className={`${
|
|
hoveredMark === mark.id ? "" : "delay-150"
|
|
} opacity-0 group-hover:opacity-100 duration-200 pointer-events-none
|
|
transition-opacity ease-in-out`}
|
|
ref={textRef}
|
|
x="78"
|
|
y="39"
|
|
fontFamily="Inter"
|
|
fontSize="20"
|
|
fill={"#002347"}
|
|
>
|
|
{mark.label}
|
|
</text>
|
|
</g>
|
|
</svg>
|
|
<rect width="64" height="64" rx="32" fill="white" />
|
|
<rect
|
|
x="3.55566"
|
|
y="3.55566"
|
|
width="56.8889"
|
|
height="56.8889"
|
|
rx="28.4444"
|
|
fill="#002347"
|
|
/>
|
|
<svg>{icon}</svg>
|
|
</svg>
|
|
);
|
|
};
|
|
|
|
export default MainMark;
|