From 726eb6018cff5e577ac1d1ff31acb8d8648d8b79 Mon Sep 17 00:00:00 2001 From: Martin Wacker Date: Fri, 26 Sep 2025 16:30:47 +0000 Subject: [PATCH] feat: context menu contextData --- frontend/src/components/ContextMenu.tsx | 50 +++++++++------- frontend/src/components/table/BodyCell.jsx | 16 ++++- frontend/src/components/table/DataRow.jsx | 10 ++++ frontend/src/containers/Browser/Browser.jsx | 65 ++++++++++++--------- 4 files changed, 91 insertions(+), 50 deletions(-) diff --git a/frontend/src/components/ContextMenu.tsx b/frontend/src/components/ContextMenu.tsx index 2a2b6c23..bfef1cf2 100644 --- a/frontend/src/components/ContextMenu.tsx +++ b/frontend/src/components/ContextMenu.tsx @@ -49,36 +49,44 @@ interface ContextMenuOption { onClick?: (contextData: { posX: number; posY: number }) => void; } + interface ContextMenuProps { target: React.RefObject; - options: () => ContextMenuOption[]; + options: (contextData?: any) => ContextMenuOption[]; } const ContextMenu: React.FC = ({ target, options }) => { - const [contextData, setContextData] = useState({ + const [menuState, setMenuState] = useState({ visible: false, posX: 0, posY: 0, + contextData: undefined, }); const contextRef = useRef(null); useEffect(() => { const contextMenuEventHandler = (event: MouseEvent) => { const targetElement = target.current; + let contextData = undefined; + // Try to get context data from a custom property on the event + if ((event as any).contextData) { + contextData = (event as any).contextData; + } if (targetElement && targetElement.contains(event.target as Node)) { event.preventDefault(); setTimeout(() => { - setContextData({ + setMenuState({ visible: true, posX: event.clientX, posY: event.clientY, + contextData, }); }, 0); } else if ( contextRef.current && (contextRef.current as HTMLElement).contains(event.target as Node) ) { - setContextData({ ...contextData, visible: false }); + setMenuState({ ...menuState, visible: false }); } }; @@ -87,7 +95,7 @@ const ContextMenu: React.FC = ({ target, options }) => { contextRef.current && !(contextRef.current as HTMLElement).contains(event.target as Node) ) { - setContextData({ ...contextData, visible: false }); + setMenuState({ ...menuState, visible: false }); } }; @@ -97,36 +105,36 @@ const ContextMenu: React.FC = ({ target, options }) => { document.removeEventListener('contextmenu', contextMenuEventHandler); document.removeEventListener('click', offClickHandler); }; - }, [contextData, target]); + }, [menuState, target]); useLayoutEffect(() => { if (!contextRef?.current) return; const element = contextRef.current as HTMLElement; - if (contextData.posX + element.offsetWidth > window.innerWidth) { - setContextData({ - ...contextData, - posX: contextData.posX - element.offsetWidth, + if (menuState.posX + element.offsetWidth > window.innerWidth) { + setMenuState({ + ...menuState, + posX: menuState.posX - element.offsetWidth, }); } - if (contextData.posY + element.offsetHeight > window.innerHeight) { - setContextData({ - ...contextData, - posY: contextData.posY - element.offsetHeight, + if (menuState.posY + element.offsetHeight > window.innerHeight) { + setMenuState({ + ...menuState, + posY: menuState.posY - element.offsetHeight, }); } - }, [contextData]); + }, [menuState]); return ( - {options().map((option, idx) => ( + {options(menuState.contextData).map((option, idx) => ( {option.separator &&
}