Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import {createContext, ReactNode, useContext, useEffect, useRef, useState} from "react";
// Create a context to manage popup state globally
interface PopupContextType {
showPopup: (x: number, y: number, content: React.ReactNode) => void;
hidePopup: () => void;
}
const PopupContext = createContext<PopupContextType | null>(null);
export interface PopupProviderProps {
children: ReactNode;
}
interface PopupState {
isVisible: boolean;
content: ReactNode;
position: {
x: number,
y: number,
};
}
// Provider component to wrap your application
export function PopupProvider(props: PopupProviderProps) {
const [popupState, setPopupState] = useState<PopupState>({
isVisible: false,
content: null,
position: {
x: 0,
y: 0,
},
});
const popupRef = useRef<HTMLDivElement>(null);
function showPopup(x: number, y: number, content: ReactNode) {
setPopupState({
isVisible: true,
content,
position: {
x,
y,
},
});
}
function hidePopup() {
setPopupState(prev => ({...prev, isVisible: false}));
}
// Close popup when clicking outside
useEffect(() => {
const handleClickOutside = (e: MouseEvent) => {
if (popupRef.current && !popupRef.current.contains(e.target as Node)) {
hidePopup();
}
};
if (popupState.isVisible) {
document.addEventListener("mousedown", handleClickOutside);
}
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [popupState.isVisible]);
// noinspection JSUnusedGlobalSymbols
return (
<PopupContext.Provider value={{showPopup, hidePopup}}>
{props.children}
{popupState.isVisible && (
<div
ref={popupRef}
className="fixed border bg-accent border-gray-400 rounded shadow-md p-4 z-50 card"
style={{
left: `${popupState.position.x}px`,
top: `${popupState.position.y}px`,
transform: "translate(-50%, -100%)",
marginTop: "-10px"
}}
>
{popupState.content}
</div>
)}
</PopupContext.Provider>
);
}
// Custom hook to use the popup functionality
// eslint-disable-next-line react-refresh/only-export-components
export function usePopup() {
const context = useContext(PopupContext);
if (!context) {
throw new Error("usePopup must be used within a PopupProvider");
}
return context;
}
|