import { Accessor, Component, createContext, createEffect, createMemo, createSignal, For, JSX, ParentComponent, splitProps, useContext } from "solid-js"; import { CommandType } from "./command"; import css from "./contextMenu.module.css"; interface ContextMenuType { readonly commands: Accessor; readonly target: Accessor; show(element: HTMLElement): void; hide(): void; } const ContextMenu = createContext() const Root: ParentComponent<{ commands: CommandType[] }> = (props) => { const [target, setTarget] = createSignal(); const context = { commands: createMemo(() => props.commands), target, show(element: HTMLElement) { setTarget(element); }, hide() { setTarget(undefined); }, }; return {props.children} }; const Menu: Component<{ children: (command: CommandType) => JSX.Element }> = (props) => { const context = useContext(ContextMenu)!; const [root, setRoot] = createSignal(); createEffect(() => { const target = context.target(); const menu = root(); if (!menu) { return; } if (target) { menu.showPopover(); } else { menu.hidePopover(); } }); const onToggle = (e: ToggleEvent) => { if (e.newState === 'closed') { context.hide(); } }; const onCommand = (command: CommandType) => (e: PointerEvent) => { context.hide(); command(); }; return { command =>
  • {props.children(command)}
  • }
    ; }; const Handle: ParentComponent> = (props) => { const [local, rest] = splitProps(props, ['children']); const context = useContext(ContextMenu)!; const [handle, setHandle] = createSignal(); return { e.preventDefault(); context.show(handle()!); return false; }}>{local.children}; }; let handleCounter = 0; const createUniqueId = () => `handle-${handleCounter++}` export const Context = { Root, Menu, Handle };