{
  "name": "lit-ui-table-handle",
  "title": "lit-ui-table-handle",
  "type": "registry:component",
  "description": "",
  "registryDependencies": [
    "https://unpkg.com/prosekit-registry/dist/r/lit-ui-editor-context.json"
  ],
  "dependencies": [
    "@egoist/tailwindcss-icons",
    "@iconify-json/lucide",
    "@lit/context",
    "prosekit@^0.22.0"
  ],
  "files": [
    {
      "path": "registry/src/lit/ui/table-handle/index.ts",
      "type": "registry:component",
      "target": "components/editor/ui/table-handle/index.ts",
      "content": "export { registerLitEditorTableHandle } from './table-handle.ts'\n"
    },
    {
      "path": "registry/src/lit/ui/table-handle/table-handle.ts",
      "type": "registry:component",
      "target": "components/editor/ui/table-handle/table-handle.ts",
      "content": "import { ContextConsumer } from '@lit/context'\nimport { html, LitElement, nothing, type PropertyDeclaration, type PropertyValues } from 'lit'\nimport type { Editor } from 'prosekit/core'\nimport { defineUpdateHandler } from 'prosekit/core'\nimport type { TableExtension } from 'prosekit/extensions/table'\nimport {\n  registerMenuItemElement,\n  registerMenuPopupElement,\n  registerMenuPositionerElement,\n} from 'prosekit/lit/menu'\nimport {\n  registerTableHandleColumnMenuRootElement,\n  registerTableHandleColumnMenuTriggerElement,\n  registerTableHandleColumnPopupElement,\n  registerTableHandleColumnPositionerElement,\n  registerTableHandleDragPreviewElement,\n  registerTableHandleDropIndicatorElement,\n  registerTableHandleRootElement,\n  registerTableHandleRowMenuRootElement,\n  registerTableHandleRowMenuTriggerElement,\n  registerTableHandleRowPopupElement,\n  registerTableHandleRowPositionerElement,\n} from 'prosekit/lit/table-handle'\n\nimport { editorContext } from '../editor-context.ts'\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\nclass LitTableHandle extends LitElement {\n  static override properties = {\n    dir: { type: String } satisfies PropertyDeclaration<'ltr' | 'rtl'>,\n  }\n\n  override dir: string = ''\n\n  private editorConsumer = new ContextConsumer(this, {\n    context: editorContext,\n    subscribe: true,\n  })\n\n  private removeUpdateExtension?: VoidFunction\n  private attachedEditor?: Editor\n\n  override createRenderRoot() {\n    return this\n  }\n\n  override connectedCallback() {\n    super.connectedCallback()\n    this.classList.add('contents')\n    this.attachEditorListener()\n  }\n\n  override disconnectedCallback() {\n    this.detachEditorListener()\n    super.disconnectedCallback()\n  }\n\n  override updated(changedProperties: PropertyValues) {\n    super.updated(changedProperties)\n    this.attachEditorListener()\n  }\n\n  private attachEditorListener() {\n    const editor = this.editorConsumer.value\n    if (editor === this.attachedEditor) return\n\n    this.detachEditorListener()\n    this.attachedEditor = editor\n\n    if (!editor) return\n\n    this.removeUpdateExtension = editor.use(defineUpdateHandler(() => this.requestUpdate()))\n  }\n\n  private detachEditorListener() {\n    this.removeUpdateExtension?.()\n    this.removeUpdateExtension = undefined\n    this.attachedEditor = undefined\n  }\n\n  override render() {\n    const editor = this.editorConsumer.value as Editor<TableExtension> | undefined\n    if (!editor) {\n      return nothing\n    }\n\n    const state = getTableHandleState(editor)\n    const placement = this.dir === 'rtl' ? 'right' : 'left'\n\n    return html`<prosekit-table-handle-root .editor=${editor}>\n      <prosekit-table-handle-drag-preview .editor=${editor}></prosekit-table-handle-drag-preview>\n      <prosekit-table-handle-drop-indicator\n        .editor=${editor}\n      ></prosekit-table-handle-drop-indicator>\n      <prosekit-table-handle-column-positioner\n        .editor=${editor}\n        class=\"block overflow-visible w-min h-min z-50 ease-out transition-transform duration-100 motion-reduce:transition-none\"\n      >\n        <prosekit-table-handle-column-popup class=\"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          <prosekit-table-handle-column-menu-root>\n            <prosekit-table-handle-column-menu-trigger\n              .editor=${editor}\n              class=\"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            >\n              <div class=\"i-lucide-grip-horizontal size-5 min-h-5 min-w-5 block\"></div>\n            </prosekit-table-handle-column-menu-trigger>\n            <prosekit-menu-positioner class=\"block overflow-visible w-min h-min z-50 ease-out transition-transform duration-100 motion-reduce:transition-none\">\n              <prosekit-menu-popup class=\"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                ${\n                  state.addTableColumnBefore.canExec\n                    ? html`<prosekit-menu-item\n                        class=\"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                        @select=${state.addTableColumnBefore.command}\n                      >\n                        <span>Insert Left</span>\n                      </prosekit-menu-item>`\n                    : nothing\n                }\n                ${\n                  state.addTableColumnAfter.canExec\n                    ? html`<prosekit-menu-item\n                        class=\"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                        @select=${state.addTableColumnAfter.command}\n                      >\n                        <span>Insert Right</span>\n                      </prosekit-menu-item>`\n                    : nothing\n                }\n                ${\n                  state.deleteCellSelection.canExec\n                    ? html`<prosekit-menu-item\n                        class=\"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                        @select=${state.deleteCellSelection.command}\n                      >\n                        <span>Clear Contents</span>\n                        <span class=\"text-xs tracking-widest text-gray-500 dark:text-gray-500\">Del</span>\n                      </prosekit-menu-item>`\n                    : nothing\n                }\n                ${\n                  state.deleteTableColumn.canExec\n                    ? html`<prosekit-menu-item\n                        class=\"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                        @select=${state.deleteTableColumn.command}\n                      >\n                        <span>Delete Column</span>\n                      </prosekit-menu-item>`\n                    : nothing\n                }\n                ${\n                  state.deleteTable.canExec\n                    ? html`<prosekit-menu-item\n                        class=\"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                        @select=${state.deleteTable.command}\n                      >\n                        <span>Delete Table</span>\n                      </prosekit-menu-item>`\n                    : nothing\n                }\n              </prosekit-menu-popup>\n            </prosekit-menu-positioner>\n          </prosekit-table-handle-column-menu-root>\n        </prosekit-table-handle-column-popup>\n      </prosekit-table-handle-column-positioner>\n      <prosekit-table-handle-row-positioner\n        .editor=${editor}\n        .placement=${placement}\n        class=\"block overflow-visible w-min h-min z-50 ease-out transition-transform duration-100 motion-reduce:transition-none\"\n      >\n        <prosekit-table-handle-row-popup class=\"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          <prosekit-table-handle-row-menu-root>\n            <prosekit-table-handle-row-menu-trigger\n              .editor=${editor}\n              class=\"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            >\n              <div class=\"i-lucide-grip-vertical size-5 min-h-5 min-w-5 block\"></div>\n            </prosekit-table-handle-row-menu-trigger>\n            <prosekit-menu-positioner class=\"block overflow-visible w-min h-min z-50 ease-out transition-transform duration-100 motion-reduce:transition-none\">\n              <prosekit-menu-popup class=\"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                ${\n                  state.addTableRowAbove.canExec\n                    ? html`<prosekit-menu-item\n                        class=\"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                        @select=${state.addTableRowAbove.command}\n                      >\n                        <span>Insert Above</span>\n                      </prosekit-menu-item>`\n                    : nothing\n                }\n                ${\n                  state.addTableRowBelow.canExec\n                    ? html`<prosekit-menu-item\n                        class=\"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                        @select=${state.addTableRowBelow.command}\n                      >\n                        <span>Insert Below</span>\n                      </prosekit-menu-item>`\n                    : nothing\n                }\n                ${\n                  state.deleteCellSelection.canExec\n                    ? html`<prosekit-menu-item\n                        class=\"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                        @select=${state.deleteCellSelection.command}\n                      >\n                        <span>Clear Contents</span>\n                        <span class=\"text-xs tracking-widest text-gray-500 dark:text-gray-500\">Del</span>\n                      </prosekit-menu-item>`\n                    : nothing\n                }\n                ${\n                  state.deleteTableRow.canExec\n                    ? html`<prosekit-menu-item\n                        class=\"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                        @select=${state.deleteTableRow.command}\n                      >\n                        <span>Delete Row</span>\n                      </prosekit-menu-item>`\n                    : nothing\n                }\n                ${\n                  state.deleteTable.canExec\n                    ? html`<prosekit-menu-item\n                        class=\"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                        @select=${state.deleteTable.command}\n                      >\n                        <span>Delete Table</span>\n                      </prosekit-menu-item>`\n                    : nothing\n                }\n              </prosekit-menu-popup>\n            </prosekit-menu-positioner>\n          </prosekit-table-handle-row-menu-root>\n        </prosekit-table-handle-row-popup>\n      </prosekit-table-handle-row-positioner>\n    </prosekit-table-handle-root>`\n  }\n}\n\nexport function registerLitEditorTableHandle() {\n  registerMenuItemElement()\n  registerMenuPopupElement()\n  registerMenuPositionerElement()\n  registerTableHandleColumnMenuRootElement()\n  registerTableHandleColumnMenuTriggerElement()\n  registerTableHandleColumnPopupElement()\n  registerTableHandleColumnPositionerElement()\n  registerTableHandleDragPreviewElement()\n  registerTableHandleDropIndicatorElement()\n  registerTableHandleRootElement()\n  registerTableHandleRowMenuRootElement()\n  registerTableHandleRowMenuTriggerElement()\n  registerTableHandleRowPopupElement()\n  registerTableHandleRowPositionerElement()\n\n  if (customElements.get('lit-editor-table-handle')) return\n  customElements.define('lit-editor-table-handle', LitTableHandle)\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'lit-editor-table-handle': LitTableHandle\n  }\n}\n"
    }
  ],
  "meta": {
    "hasIcons": true,
    "hidden": false,
    "story": "",
    "framework": "lit",
    "accumulatedFiles": [
      "registry/src/lit/ui/editor-context.ts",
      "registry/src/lit/ui/table-handle/index.ts",
      "registry/src/lit/ui/table-handle/table-handle.ts"
    ],
    "internalDependencies": [
      "lit-ui-editor-context"
    ]
  },
  "css": {
    "@plugin @egoist/tailwindcss-icons": {}
  },
  "$schema": "https://ui.shadcn.com/schema/registry-item.json"
}
