{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "export-toolbar-button",
  "title": "Export Toolbar Button",
  "description": "A toolbar button for exporting editor content in various formats (HTML, PDF, Image, Markdown).",
  "dependencies": [
    "@platejs/docx-io",
    "@platejs/markdown",
    "html2canvas-pro",
    "pdf-lib",
    "lucide-react"
  ],
  "registryDependencies": [
    "https://platejs.org/r/docx-export-kit.json",
    "dropdown-menu",
    "https://platejs.org/r/toolbar.json",
    "https://platejs.org/r/editor-base-kit.json"
  ],
  "files": [
    {
      "path": "src/registry/ui/export-toolbar-button.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\n\nimport type { DropdownMenuProps } from '@radix-ui/react-dropdown-menu';\n\nimport { exportToDocx } from '@platejs/docx-io';\nimport { MarkdownPlugin } from '@platejs/markdown';\nimport { ArrowDownToLineIcon } from 'lucide-react';\nimport type { SlatePlugin } from 'platejs';\nimport { createSlateEditor } from 'platejs';\nimport { useEditorRef } from 'platejs/react';\nimport { serializeHtml } from 'platejs/static';\n\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuGroup,\n  DropdownMenuItem,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { BaseEditorKit } from '@/registry/components/editor/editor-base-kit';\n\nimport { EditorStatic } from './editor-static';\nimport { ToolbarButton } from './toolbar';\nimport { DocxExportKit } from '@/registry/components/editor/plugins/docx-export-kit';\n\nconst siteUrl = 'https://platejs.org';\n\nexport function ExportToolbarButton(props: DropdownMenuProps) {\n  const editor = useEditorRef();\n  const [open, setOpen] = React.useState(false);\n\n  const getCanvas = async () => {\n    const { default: html2canvas } = await import('html2canvas-pro');\n\n    const style = document.createElement('style');\n    document.head.append(style);\n\n    const canvas = await html2canvas(editor.api.toDOMNode(editor)!, {\n      onclone: (document: Document) => {\n        const editorElement = document.querySelector(\n          '[contenteditable=\"true\"]'\n        );\n        if (editorElement) {\n          Array.from(editorElement.querySelectorAll('*')).forEach((element) => {\n            const existingStyle = element.getAttribute('style') || '';\n            element.setAttribute(\n              'style',\n              `${existingStyle}; font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif !important`\n            );\n          });\n        }\n      },\n    });\n    style.remove();\n\n    return canvas;\n  };\n\n  const downloadFile = async (url: string, filename: string) => {\n    const response = await fetch(url);\n\n    const blob = await response.blob();\n    const blobUrl = window.URL.createObjectURL(blob);\n\n    const link = document.createElement('a');\n    link.href = blobUrl;\n    link.download = filename;\n    document.body.append(link);\n    link.click();\n    link.remove();\n\n    // Clean up the blob URL\n    window.URL.revokeObjectURL(blobUrl);\n  };\n\n  const exportToPdf = async () => {\n    const canvas = await getCanvas();\n\n    const PDFLib = await import('pdf-lib');\n    const pdfDoc = await PDFLib.PDFDocument.create();\n    const page = pdfDoc.addPage([canvas.width, canvas.height]);\n    const imageEmbed = await pdfDoc.embedPng(canvas.toDataURL('PNG'));\n    const { height, width } = imageEmbed.scale(1);\n    page.drawImage(imageEmbed, {\n      height,\n      width,\n      x: 0,\n      y: 0,\n    });\n    const pdfBase64 = await pdfDoc.saveAsBase64({ dataUri: true });\n\n    await downloadFile(pdfBase64, 'plate.pdf');\n  };\n\n  const exportToImage = async () => {\n    const canvas = await getCanvas();\n    await downloadFile(canvas.toDataURL('image/png'), 'plate.png');\n  };\n\n  const exportToHtml = async () => {\n    const editorStatic = createSlateEditor({\n      plugins: BaseEditorKit,\n      value: editor.children,\n    });\n\n    const editorHtml = await serializeHtml(editorStatic, {\n      editorComponent: EditorStatic,\n      props: { style: { padding: '0 calc(50% - 350px)', paddingBottom: '' } },\n    });\n\n    const tailwindCss = `<link rel=\"stylesheet\" href=\"${siteUrl}/tailwind.css\">`;\n    const katexCss = `<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/katex@0.16.18/dist/katex.css\" integrity=\"sha384-9PvLvaiSKCPkFKB1ZsEoTjgnJn+O3KvEwtsz37/XrkYft3DTk2gHdYvd9oWgW3tV\" crossorigin=\"anonymous\">`;\n\n    const html = `<!DOCTYPE html>\n    <html lang=\"en\">\n      <head>\n        <meta charset=\"utf-8\" />\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n        <meta name=\"color-scheme\" content=\"light dark\" />\n        <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n        <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin />\n        <link\n          href=\"https://fonts.googleapis.com/css2?family=Inter:wght@400..700&family=JetBrains+Mono:wght@400..700&display=swap\"\n          rel=\"stylesheet\"\n        />\n        ${tailwindCss}\n        ${katexCss}\n        <style>\n          :root {\n            --font-sans: 'Inter', 'Inter Fallback';\n            --font-mono: 'JetBrains Mono', 'JetBrains Mono Fallback';\n          }\n        </style>\n      </head>\n      <body>\n        ${editorHtml}\n      </body>\n    </html>`;\n\n    const url = `data:text/html;charset=utf-8,${encodeURIComponent(html)}`;\n\n    await downloadFile(url, 'plate.html');\n  };\n\n  const exportToMarkdown = async () => {\n    const md = editor.getApi(MarkdownPlugin).markdown.serialize();\n    const url = `data:text/markdown;charset=utf-8,${encodeURIComponent(md)}`;\n    await downloadFile(url, 'plate.md');\n  };\n\n  const exportToWord = async () => {\n    const blob = await exportToDocx(editor.children, {\n      editorPlugins: [...BaseEditorKit, ...DocxExportKit] as SlatePlugin[],\n    });\n\n    const url = URL.createObjectURL(blob);\n    const link = document.createElement('a');\n    link.href = url;\n    link.download = 'plate.docx';\n    document.body.append(link);\n    link.click();\n    link.remove();\n    URL.revokeObjectURL(url);\n  };\n\n  return (\n    <DropdownMenu open={open} onOpenChange={setOpen} modal={false} {...props}>\n      <DropdownMenuTrigger asChild>\n        <ToolbarButton pressed={open} tooltip=\"Export\" isDropdown>\n          <ArrowDownToLineIcon className=\"size-4\" />\n        </ToolbarButton>\n      </DropdownMenuTrigger>\n\n      <DropdownMenuContent align=\"start\">\n        <DropdownMenuGroup>\n          <DropdownMenuItem onSelect={exportToHtml}>\n            Export as HTML\n          </DropdownMenuItem>\n          <DropdownMenuItem onSelect={exportToPdf}>\n            Export as PDF\n          </DropdownMenuItem>\n          <DropdownMenuItem onSelect={exportToImage}>\n            Export as Image\n          </DropdownMenuItem>\n          <DropdownMenuItem onSelect={exportToMarkdown}>\n            Export as Markdown\n          </DropdownMenuItem>\n          <DropdownMenuItem onSelect={exportToWord}>\n            Export as Word\n          </DropdownMenuItem>\n        </DropdownMenuGroup>\n      </DropdownMenuContent>\n    </DropdownMenu>\n  );\n}\n",
      "type": "registry:ui"
    }
  ],
  "meta": {
    "docs": [
      {
        "route": "/docs/export",
        "title": "Export"
      }
    ],
    "examples": [
      "basic-nodes-demo"
    ],
    "label": "New"
  },
  "type": "registry:ui"
}