From 6ec259a0e71174651bae95d4628138bf6fd68742 Mon Sep 17 00:00:00 2001 From: kj_sh604 Date: Sun, 15 Mar 2026 16:19:35 -0400 Subject: refactor: packages/ --- .../components/dropdownMenu/DropdownMenuItem.tsx | 123 +++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 packages/excalidraw/components/dropdownMenu/DropdownMenuItem.tsx (limited to 'packages/excalidraw/components/dropdownMenu/DropdownMenuItem.tsx') diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenuItem.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenuItem.tsx new file mode 100644 index 0000000..1ff53f8 --- /dev/null +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenuItem.tsx @@ -0,0 +1,123 @@ +import type { JSX } from "react"; +import React, { useEffect, useRef } from "react"; +import { + getDropdownMenuItemClassName, + useHandleDropdownMenuItemClick, +} from "./common"; +import MenuItemContent from "./DropdownMenuItemContent"; +import { useExcalidrawAppState } from "../App"; +import { THEME } from "../../constants"; +import type { ValueOf } from "../../utility-types"; + +const DropdownMenuItem = ({ + icon, + value, + order, + children, + shortcut, + className, + hovered, + selected, + textStyle, + onSelect, + onClick, + ...rest +}: { + icon?: JSX.Element; + value?: string | number | undefined; + order?: number; + onSelect?: (event: Event) => void; + children: React.ReactNode; + shortcut?: string; + hovered?: boolean; + selected?: boolean; + textStyle?: React.CSSProperties; + className?: string; +} & Omit, "onSelect">) => { + const handleClick = useHandleDropdownMenuItemClick(onClick, onSelect); + const ref = useRef(null); + + useEffect(() => { + if (hovered) { + if (order === 0) { + // scroll into the first item differently, so it's visible what is above (i.e. group title) + ref.current?.scrollIntoView({ block: "end" }); + } else { + ref.current?.scrollIntoView({ block: "nearest" }); + } + } + }, [hovered, order]); + + return ( + + ); +}; +DropdownMenuItem.displayName = "DropdownMenuItem"; + +export const DropDownMenuItemBadgeType = { + GREEN: "green", + RED: "red", + BLUE: "blue", +} as const; + +export const DropDownMenuItemBadge = ({ + type = DropDownMenuItemBadgeType.BLUE, + children, +}: { + type?: ValueOf; + children: React.ReactNode; +}) => { + const { theme } = useExcalidrawAppState(); + const style = { + display: "inline-flex", + marginLeft: "auto", + padding: "2px 4px", + borderRadius: 6, + fontSize: 9, + fontFamily: "Cascadia, monospace", + border: theme === THEME.LIGHT ? "1.5px solid white" : "none", + }; + + switch (type) { + case DropDownMenuItemBadgeType.GREEN: + Object.assign(style, { + backgroundColor: "var(--background-color-badge)", + color: "var(--color-badge)", + }); + break; + case DropDownMenuItemBadgeType.RED: + Object.assign(style, { + backgroundColor: "pink", + color: "darkred", + }); + break; + case DropDownMenuItemBadgeType.BLUE: + default: + Object.assign(style, { + background: "var(--color-promo)", + color: "var(--color-surface-lowest)", + }); + } + + return ( +
+ {children} +
+ ); +}; +DropDownMenuItemBadge.displayName = "DropdownMenuItemBadge"; + +DropdownMenuItem.Badge = DropDownMenuItemBadge; + +export default DropdownMenuItem; -- cgit v1.2.3