83 lines
1.9 KiB
JavaScript
83 lines
1.9 KiB
JavaScript
import React, { useEffect, useMemo, useRef, useState } from "react";
|
|
import { useDispatch, useSelector } from "react-redux";
|
|
import {
|
|
closePopup,
|
|
openPopup,
|
|
togglePopup,
|
|
} from "../../slices/localVariablesSlice";
|
|
|
|
const HoverPopup = ({
|
|
id,
|
|
title,
|
|
content,
|
|
children,
|
|
className,
|
|
Mode = "hover",
|
|
}) => {
|
|
const dispatch = useDispatch();
|
|
const visible = useSelector((s) => s.localVariables.popups[id] || false);
|
|
|
|
const triggerRef = useRef(null);
|
|
const popupRef = useRef(null);
|
|
|
|
const handleMouseEnter = () => {
|
|
if (Mode === "hover") dispatch(openPopup(id));
|
|
};
|
|
|
|
const handleMouseLeave = () => {
|
|
if (Mode === "hover") dispatch(closePopup(id));
|
|
};
|
|
|
|
const handleClick = (e) => {
|
|
if (Mode === "click") {
|
|
e.stopPropagation();
|
|
dispatch(togglePopup(id));
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (Mode !== "click" || !visible) return;
|
|
|
|
const handleOutside = (e) => {
|
|
if (
|
|
!popupRef.current?.contains(e.target) &&
|
|
!triggerRef.current?.contains(e.target)
|
|
) {
|
|
dispatch(closePopup(id));
|
|
}
|
|
};
|
|
|
|
document.addEventListener("click", handleOutside);
|
|
return () => document.removeEventListener("click", handleOutside);
|
|
}, [visible, Mode, id]);
|
|
|
|
return (
|
|
<div className="d-inline-block position-relative">
|
|
<div
|
|
ref={triggerRef}
|
|
onMouseEnter={handleMouseEnter}
|
|
onMouseLeave={handleMouseLeave}
|
|
onClick={handleClick}
|
|
style={{ cursor: "pointer" }}
|
|
>
|
|
{children}
|
|
</div>
|
|
|
|
{visible && (
|
|
<div
|
|
ref={popupRef}
|
|
className={`bg-white border w-max rounded shadow-sm p-3 position-absolute top-100 mt-2 start-50 translate-middle-x ${className}`}
|
|
style={{ zIndex: 1000 }}
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
{title && <h6 className="fw-semibold mb-2">{title}</h6>}
|
|
|
|
<div>{content}</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default HoverPopup;
|