{
  "name": "react-ui-table-handle",
  "title": "react-ui-table-handle",
  "type": "registry:component",
  "description": "",
  "registryDependencies": [],
  "dependencies": [
    "@egoist/tailwindcss-icons",
    "@iconify-json/lucide",
    "prosekit@^0.22.0"
  ],
  "files": [
    {
      "path": "registry/src/react/ui/table-handle/index.ts",
      "type": "registry:component",
      "target": "components/editor/ui/table-handle/index.ts",
      "content": "export { default as TableHandle } from './table-handle.tsx'\n"
    },
    {
      "path": "registry/src/react/ui/table-handle/table-handle.tsx",
      "type": "registry:component",
      "target": "components/editor/ui/table-handle/table-handle.tsx",
      "content": "'use client'\n\nimport type { Editor } from 'prosekit/core'\nimport type { TableExtension } from 'prosekit/extensions/table'\nimport { useEditorDerivedValue } from 'prosekit/react'\nimport { MenuItem, MenuPopup, MenuPositioner } from 'prosekit/react/menu'\nimport {\n  TableHandleColumnMenuRoot,\n  TableHandleColumnMenuTrigger,\n  TableHandleColumnPopup,\n  TableHandleColumnPositioner,\n  TableHandleDragPreview,\n  TableHandleDropIndicator,\n  TableHandleRoot,\n  TableHandleRowMenuRoot,\n  TableHandleRowMenuTrigger,\n  TableHandleRowPopup,\n  TableHandleRowPositioner,\n} from 'prosekit/react/table-handle'\n\nfunction getTableHandleState(editor: Editor<TableExtension>) {\n  return {\n    addTableColumnBefore: {\n      canExec: editor.commands.addTableColumnBefore.canExec(),\n      command: () => editor.commands.addTableColumnBefore(),\n    },\n    addTableColumnAfter: {\n      canExec: editor.commands.addTableColumnAfter.canExec(),\n      command: () => editor.commands.addTableColumnAfter(),\n    },\n    deleteCellSelection: {\n      canExec: editor.commands.deleteCellSelection.canExec(),\n      command: () => editor.commands.deleteCellSelection(),\n    },\n    deleteTableColumn: {\n      canExec: editor.commands.deleteTableColumn.canExec(),\n      command: () => editor.commands.deleteTableColumn(),\n    },\n    addTableRowAbove: {\n      canExec: editor.commands.addTableRowAbove.canExec(),\n      command: () => editor.commands.addTableRowAbove(),\n    },\n    addTableRowBelow: {\n      canExec: editor.commands.addTableRowBelow.canExec(),\n      command: () => editor.commands.addTableRowBelow(),\n    },\n    deleteTableRow: {\n      canExec: editor.commands.deleteTableRow.canExec(),\n      command: () => editor.commands.deleteTableRow(),\n    },\n    deleteTable: {\n      canExec: editor.commands.deleteTable.canExec(),\n      command: () => editor.commands.deleteTable(),\n    },\n  }\n}\n\ninterface Props {\n  dir?: 'ltr' | 'rtl'\n}\n\nexport default function TableHandle(props: Props) {\n  const state = useEditorDerivedValue(getTableHandleState)\n\n  return (\n    <TableHandleRoot>\n      <TableHandleDragPreview />\n      <TableHandleDropIndicator />\n      <TableHandleColumnPositioner className=\"block overflow-visible w-min h-min z-50 ease-out transition-transform duration-100 motion-reduce:transition-none\">\n        <TableHandleColumnPopup className=\"translate-y-[50%] flex box-border origin-(--transform-origin) transition-[opacity,scale] transition-discrete motion-reduce:transition-none duration-100 data-[state=closed]:duration-150 data-[state=closed]:opacity-0 starting:opacity-0 data-[state=closed]:scale-95 starting:scale-95\">\n          <TableHandleColumnMenuRoot>\n            <TableHandleColumnMenuTrigger className=\"h-4.5 w-6 flex items-center box-border justify-center bg-[canvas] hover:bg-gray-100 dark:hover:bg-gray-800 rounded-sm text-gray-500/50 dark:text-gray-400/50 border border-gray-200 dark:border-gray-800 border-solid p-0 transition-colors overflow-clip\">\n              <div className=\"i-lucide-grip-horizontal size-5 min-h-5 min-w-5 block\"></div>\n            </TableHandleColumnMenuTrigger>\n            <MenuPositioner className=\"block overflow-visible w-min h-min z-50 ease-out transition-transform duration-100 motion-reduce:transition-none\">\n              <MenuPopup className=\"box-border origin-(--transform-origin) transition-[opacity,scale] transition-discrete motion-reduce:transition-none data-[state=closed]:duration-150 data-[state=closed]:opacity-0 starting:opacity-0 data-[state=closed]:scale-95 starting:scale-95 duration-40 rounded-xl border border-gray-200 dark:border-gray-800 shadow-lg bg-[canvas] relative flex flex-col max-h-100 min-w-32 select-none overflow-auto whitespace-nowrap p-1 outline-none\">\n                {state.addTableColumnBefore.canExec && (\n                  <MenuItem\n                    className=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n                    onSelect={state.addTableColumnBefore.command}\n                  >\n                    <span>Insert Left</span>\n                  </MenuItem>\n                )}\n                {state.addTableColumnAfter.canExec && (\n                  <MenuItem\n                    className=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n                    onSelect={state.addTableColumnAfter.command}\n                  >\n                    <span>Insert Right</span>\n                  </MenuItem>\n                )}\n                {state.deleteCellSelection.canExec && (\n                  <MenuItem\n                    className=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n                    onSelect={state.deleteCellSelection.command}\n                  >\n                    <span>Clear Contents</span>\n                    <span className=\"text-xs tracking-widest text-gray-500 dark:text-gray-500\">Del</span>\n                  </MenuItem>\n                )}\n                {state.deleteTableColumn.canExec && (\n                  <MenuItem\n                    className=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n                    onSelect={state.deleteTableColumn.command}\n                  >\n                    <span>Delete Column</span>\n                  </MenuItem>\n                )}\n                {state.deleteTable.canExec && (\n                  <MenuItem\n                    className=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n                    data-danger=\"\"\n                    onSelect={state.deleteTable.command}\n                  >\n                    <span>Delete Table</span>\n                  </MenuItem>\n                )}\n              </MenuPopup>\n            </MenuPositioner>\n          </TableHandleColumnMenuRoot>\n        </TableHandleColumnPopup>\n      </TableHandleColumnPositioner>\n      <TableHandleRowPositioner\n        placement={props.dir === 'rtl' ? 'right' : 'left'}\n        className=\"block overflow-visible w-min h-min z-50 ease-out transition-transform duration-100 motion-reduce:transition-none\"\n      >\n        <TableHandleRowPopup className=\"ltr:translate-x-[50%] rtl:translate-x-[-50%] flex box-border origin-(--transform-origin) transition-[opacity,scale] transition-discrete motion-reduce:transition-none duration-100 data-[state=closed]:duration-150 data-[state=closed]:opacity-0 starting:opacity-0 data-[state=closed]:scale-95 starting:scale-95\">\n          <TableHandleRowMenuRoot>\n            <TableHandleRowMenuTrigger className=\"h-6 w-4.5 flex items-center box-border justify-center bg-[canvas] hover:bg-gray-100 dark:hover:bg-gray-800 rounded-sm text-gray-500/50 dark:text-gray-400/50 border border-gray-200 dark:border-gray-800 border-solid p-0 transition-colors overflow-clip\">\n              <div className=\"i-lucide-grip-vertical size-5 min-h-5 min-w-5 block\"></div>\n            </TableHandleRowMenuTrigger>\n            <MenuPositioner className=\"block overflow-visible w-min h-min z-50 ease-out transition-transform duration-100 motion-reduce:transition-none\">\n              <MenuPopup className=\"box-border origin-(--transform-origin) transition-[opacity,scale] transition-discrete motion-reduce:transition-none data-[state=closed]:duration-150 data-[state=closed]:opacity-0 starting:opacity-0 data-[state=closed]:scale-95 starting:scale-95 duration-40 rounded-xl border border-gray-200 dark:border-gray-800 shadow-lg bg-[canvas] relative flex flex-col max-h-100 min-w-32 select-none overflow-auto whitespace-nowrap p-1 outline-none\">\n                {state.addTableRowAbove.canExec && (\n                  <MenuItem\n                    className=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n                    onSelect={state.addTableRowAbove.command}\n                  >\n                    <span>Insert Above</span>\n                  </MenuItem>\n                )}\n                {state.addTableRowBelow.canExec && (\n                  <MenuItem\n                    className=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n                    onSelect={state.addTableRowBelow.command}\n                  >\n                    <span>Insert Below</span>\n                  </MenuItem>\n                )}\n                {state.deleteCellSelection.canExec && (\n                  <MenuItem\n                    className=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n                    onSelect={state.deleteCellSelection.command}\n                  >\n                    <span>Clear Contents</span>\n                    <span className=\"text-xs tracking-widest text-gray-500 dark:text-gray-500\">Del</span>\n                  </MenuItem>\n                )}\n                {state.deleteTableRow.canExec && (\n                  <MenuItem\n                    className=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n                    onSelect={state.deleteTableRow.command}\n                  >\n                    <span>Delete Row</span>\n                  </MenuItem>\n                )}\n                {state.deleteTable.canExec && (\n                  <MenuItem\n                    className=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n                    data-danger=\"\"\n                    onSelect={state.deleteTable.command}\n                  >\n                    <span>Delete Table</span>\n                  </MenuItem>\n                )}\n              </MenuPopup>\n            </MenuPositioner>\n          </TableHandleRowMenuRoot>\n        </TableHandleRowPopup>\n      </TableHandleRowPositioner>\n    </TableHandleRoot>\n  )\n}\n"
    }
  ],
  "meta": {
    "hasIcons": true,
    "hidden": false,
    "story": "",
    "framework": "react",
    "accumulatedFiles": [
      "registry/src/react/ui/table-handle/index.ts",
      "registry/src/react/ui/table-handle/table-handle.tsx"
    ],
    "internalDependencies": []
  },
  "css": {
    "@plugin @egoist/tailwindcss-icons": {}
  },
  "$schema": "https://ui.shadcn.com/schema/registry-item.json"
}
