import { cn, ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, Drawer, DrawerContent, DrawerDescription, DrawerTitle, DrawerTrigger, useIsMobile, } from "@tensamin/ui"; import { Pin, Clipboard, Pen, Reply, Forward, Trash } from "lucide-react"; import { useMemo, useState } from "react"; import type { ReactElement, ReactNode } from "react"; async function copyText(text: string) { await navigator.clipboard.writeText(text); } type MenuComponents = { Content: (props: { className?: string; children: ReactNode }) => ReactElement; Group: (props: { children: ReactNode }) => ReactElement; Item: (props: { children: ReactNode; className?: string; disabled?: boolean; onClick?: () => void | Promise; variant?: "default" | "destructive"; }) => ReactElement; Separator: (props: { className?: string }) => ReactElement; Sub: (props: { children: ReactNode }) => ReactElement; SubTrigger: (props: { children: ReactNode; onClick?: () => void | Promise; }) => ReactElement; SubContent: (props: { children: ReactNode }) => ReactElement; }; function blurActiveElement() { if (document.activeElement instanceof HTMLElement) { document.activeElement.blur(); } } const desktopMenuComponents: MenuComponents = { Content: ContextMenuContent, Group: ContextMenuGroup, Item: ContextMenuItem, Separator: ContextMenuSeparator, Sub: ContextMenuSub, SubTrigger: ContextMenuSubTrigger, SubContent: ContextMenuSubContent, }; function getMobileMenuComponents({ description, onClose, title, }: { description: string; onClose: () => void; title: string; }): MenuComponents { return { Content: ({ className, children }) => ( {title} {description}
{children}
), Group: ({ children }) =>
{children}
, Item: ({ children, className, disabled, onClick, variant = "default" }) => { async function handleClick() { await onClick?.(); blurActiveElement(); onClose(); } return ( ); }, Separator: ({ className }) => (
), Sub: ({ children }) =>
{children}
, SubTrigger: ({ children, onClick }) => { async function handleClick() { blurActiveElement(); onClose(); await onClick?.(); } return ( ); }, SubContent: ({ children }) =>
{children}
, }; } function ReactionItems({ Item }: { Item: MenuComponents["Item"] }) { return Cool item; } function MessageMenuContent({ components, content, devEnabled, messageId, onAddReaction, showReactionItems = true, }: { components: MenuComponents; content: string; devEnabled: boolean; messageId: number; onAddReaction?: () => void | Promise; showReactionItems?: boolean; }) { const { Content, Group, Item, Separator, Sub, SubContent, SubTrigger } = components; return ( Add Reaction {showReactionItems && ( )}

Pin Message

copyText(content)} >

Copy Raw

Edit Message

Reply

Forward

Delete Message

{devEnabled && ( <> copyText(String(messageId))} >

Copy ID

)}
); } export default function MessageContextMenu({ children, content, messageId, }: { children: ReactElement; content: string; messageId: number; }) { const isMobile = useIsMobile(); const devEnabled = useMemo( () => Number(localStorage.getItem("log_level")) >= 3, [], ); const [mainDrawerOpen, setMainDrawerOpen] = useState(false); const [reactionDrawerOpen, setReactionDrawerOpen] = useState(false); const mainDrawerComponents = useMemo( () => getMobileMenuComponents({ description: "Actions available for this message.", onClose: () => setMainDrawerOpen(false), title: "Message actions", }), [], ); const reactionDrawerComponents = useMemo( () => getMobileMenuComponents({ description: "Choose a reaction to add to this message.", onClose: () => setReactionDrawerOpen(false), title: "Add reaction", }), [], ); if (isMobile) { return ( <> {children} setReactionDrawerOpen(true)} showReactionItems={false} /> Add reaction Choose a reaction to add to this message.
); } return ( ); }