From 6ec259a0e71174651bae95d4628138bf6fd68742 Mon Sep 17 00:00:00 2001 From: kj_sh604 Date: Sun, 15 Mar 2026 16:19:35 -0400 Subject: refactor: packages/ --- .../dropdownMenu/DropdownMenuContent.tsx | 88 ++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 packages/excalidraw/components/dropdownMenu/DropdownMenuContent.tsx (limited to 'packages/excalidraw/components/dropdownMenu/DropdownMenuContent.tsx') diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenuContent.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenuContent.tsx new file mode 100644 index 0000000..a203124 --- /dev/null +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenuContent.tsx @@ -0,0 +1,88 @@ +import { Island } from "../Island"; +import { useDevice } from "../App"; +import clsx from "clsx"; +import Stack from "../Stack"; +import React, { useEffect, useRef } from "react"; +import { DropdownMenuContentPropsContext } from "./common"; +import { useOutsideClick } from "../../hooks/useOutsideClick"; +import { KEYS } from "../../keys"; +import { EVENT } from "../../constants"; +import { useStable } from "../../hooks/useStable"; + +const MenuContent = ({ + children, + onClickOutside, + className = "", + onSelect, + style, +}: { + children?: React.ReactNode; + onClickOutside?: () => void; + className?: string; + /** + * Called when any menu item is selected (clicked on). + */ + onSelect?: (event: Event) => void; + style?: React.CSSProperties; +}) => { + const device = useDevice(); + const menuRef = useRef(null); + + const callbacksRef = useStable({ onClickOutside }); + + useOutsideClick(menuRef, () => { + callbacksRef.onClickOutside?.(); + }); + + useEffect(() => { + const onKeyDown = (event: KeyboardEvent) => { + if (event.key === KEYS.ESCAPE) { + event.stopImmediatePropagation(); + callbacksRef.onClickOutside?.(); + } + }; + + const option = { + // so that we can stop propagation of the event before it reaches + // event handlers that were bound before this one + capture: true, + }; + + document.addEventListener(EVENT.KEYDOWN, onKeyDown, option); + return () => { + document.removeEventListener(EVENT.KEYDOWN, onKeyDown, option); + }; + }, [callbacksRef]); + + const classNames = clsx(`dropdown-menu ${className}`, { + "dropdown-menu--mobile": device.editor.isMobile, + }).trim(); + + return ( + +
+ {/* the zIndex ensures this menu has higher stacking order, + see https://github.com/excalidraw/excalidraw/pull/1445 */} + {device.editor.isMobile ? ( + {children} + ) : ( + + {children} + + )} +
+
+ ); +}; +MenuContent.displayName = "DropdownMenuContent"; + +export default MenuContent; -- cgit v1.2.3