Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into feat/editor-select
Browse files Browse the repository at this point in the history
  • Loading branch information
zbeyens committed Nov 26, 2024
2 parents 6f2370a + ed40516 commit 385b27d
Show file tree
Hide file tree
Showing 27 changed files with 1,934 additions and 1,095 deletions.
5 changes: 4 additions & 1 deletion apps/www/content/docs/components/changelog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@ Use the [CLI](https://platejs.org/docs/components/cli) to install the latest ver

### November 26 #16.9

https://github.com/udecode/plate/pull/3809/files
- Add `select-editor`, `tag-element`, `label`, `form`
- Replace `cmdk` dependency with `@udecode/cmdk`. It's a controllable version of `cmdk`.
- `command`: add variants
- `editor`: add `select` variant
- `popover`: add `animate` variant

https://github.com/udecode/plate/pull/3809/files
https://github.com/udecode/plate/pull/3807/files
- `toc-element`: remove `<nav>` tag using `<div>` instead to fix html2canvas issue
- `editor`: remove `role="button"` to fix html2canvas issue

### November 21 #16.8

Expand Down
47 changes: 47 additions & 0 deletions apps/www/content/docs/examples/export.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
title: Export
---

<ComponentPreview name="playground-demo" id="basic-elements" />

<PackageInfo>

## Features

- Export editor content to:
- Client-side export with no server dependencies

</PackageInfo>

## Usage

Install the [Export Toolbar Button](/docs/components/export-toolbar-button) component.

## Examples

### Plate UI

Refer to the preview above.

### Plate Plus

- Server-side PDF export:
- High-quality PDF generation
- Custom fonts and styling
- Headers and footers
- Page numbers
- Font selectable
- Advanced export options:
- Paper size selection
- Margin controls
- Orientation settings
- Compression level
- Enterprise-ready features:
{/* - Batch processing */}
{/* - Watermarking */}
- Custom templates
- Password protection

Try it out with our server-side PDF export:

<ComponentPreviewPro name="export-demo" />
2 changes: 2 additions & 0 deletions apps/www/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,15 @@
"date-fns": "^3.6.0",
"framer-motion": "^11.5.4",
"fzf": "0.5.2",
"html2canvas": "^1.4.1",
"lodash.template": "^4.5.0",
"lucide-react": "0.460.0",
"match-sorter": "6.3.4",
"next": "15.0.3",
"next-contentlayer2": "^0.4.6",
"next-themes": "^0.4.3",
"nuqs": "^2.0.3",
"pdf-lib": "^1.17.1",
"prismjs": "^1.29.0",
"react": "^18.3.1",
"react-day-picker": "^8.10.1",
Expand Down
Binary file removed apps/www/public/ai-selection.png
Binary file not shown.
34 changes: 33 additions & 1 deletion apps/www/public/r/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -1656,6 +1656,37 @@
"registryDependencies": [],
"type": "registry:ui"
},
{
"dependencies": [
"html2canvas",
"pdf-lib"
],
"doc": {
"description": "A toolbar button to export editor content as PDF.",
"docs": [
{
"route": "/docs/export",
"title": "Export"
}
],
"examples": [
"basic-nodes-demo"
],
"label": "New",
"title": "Export Toolbar Button"
},
"files": [
{
"path": "plate-ui/export-toolbar-button.tsx",
"type": "registry:ui"
}
],
"name": "export-toolbar-button",
"registryDependencies": [
"toolbar"
],
"type": "registry:ui"
},
{
"dependencies": [
"@udecode/plate-caption"
Expand Down Expand Up @@ -2075,7 +2106,8 @@
"outdent-toolbar-button",
"table-dropdown-menu",
"toggle-toolbar-button",
"turn-into-dropdown-menu"
"turn-into-dropdown-menu",
"export-toolbar-button"
],
"type": "registry:ui"
},
Expand Down
8 changes: 2 additions & 6 deletions apps/www/public/r/styles/default/editor.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@
"route": "https://pro.platejs.org/docs/components/editor"
}
],
"examples": [
"editor-default",
"editor-disabled",
"editor-full-width"
]
"examples": ["editor-default", "editor-disabled", "editor-full-width"]
},
"files": [
{
Expand All @@ -24,4 +20,4 @@
"name": "editor",
"registryDependencies": [],
"type": "registry:ui"
}
}
33 changes: 33 additions & 0 deletions apps/www/public/r/styles/default/export-toolbar-button.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"dependencies": [
"html2canvas",
"pdf-lib"
],
"doc": {
"description": "A toolbar button to export editor content as PDF.",
"docs": [
{
"route": "/docs/export",
"title": "Export"
}
],
"examples": [
"basic-nodes-demo"
],
"label": "New",
"title": "Export Toolbar Button"
},
"files": [
{
"content": "'use client';\n\nimport React from 'react';\n\nimport type { DropdownMenuProps } from '@radix-ui/react-dropdown-menu';\n\nimport { toDOMNode, useEditorRef } from '@udecode/plate-common/react';\nimport { ArrowDownToLineIcon } from 'lucide-react';\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuTrigger,\n useOpenState,\n} from './dropdown-menu';\nimport { ToolbarButton } from './toolbar';\n\nexport function ExportToolbarButton({ children, ...props }: DropdownMenuProps) {\n const editor = useEditorRef();\n const openState = useOpenState();\n\n const getCanvas = async () => {\n const { default: html2canvas } = await import('html2canvas');\n\n const style = document.createElement('style');\n document.head.append(style);\n style.sheet?.insertRule(\n 'body > div:last-child img { display: inline-block !important; }'\n );\n\n const canvas = await html2canvas(toDOMNode(editor, editor)!);\n style.remove();\n\n return canvas;\n };\n\n const downloadFile = (href: string, filename: string) => {\n const element = document.createElement('a');\n element.setAttribute('href', href);\n element.setAttribute('download', filename);\n element.style.display = 'none';\n document.body.append(element);\n element.click();\n element.remove();\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 downloadFile(pdfBase64, 'plate.pdf');\n };\n\n const exportToImage = async () => {\n const canvas = await getCanvas();\n downloadFile(canvas.toDataURL('image/png'), 'plate.png');\n };\n\n return (\n <DropdownMenu modal={false} {...openState} {...props}>\n <DropdownMenuTrigger asChild>\n <ToolbarButton pressed={openState.open} tooltip=\"Export\" isDropdown>\n <ArrowDownToLineIcon className=\"size-4\" />\n </ToolbarButton>\n </DropdownMenuTrigger>\n\n <DropdownMenuContent align=\"start\">\n <DropdownMenuGroup>\n <DropdownMenuItem onSelect={exportToPdf}>\n Export as PDF\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={exportToImage}>\n Export as Image\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n",
"path": "plate-ui/export-toolbar-button.tsx",
"target": "components/plate-ui/export-toolbar-button.tsx",
"type": "registry:ui"
}
],
"name": "export-toolbar-button",
"registryDependencies": [
"toolbar"
],
"type": "registry:ui"
}
5 changes: 3 additions & 2 deletions apps/www/public/r/styles/default/fixed-toolbar-buttons.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
},
"files": [
{
"content": "'use client';\n\nimport React from 'react';\n\nimport {\n BoldPlugin,\n CodePlugin,\n ItalicPlugin,\n StrikethroughPlugin,\n UnderlinePlugin,\n} from '@udecode/plate-basic-marks/react';\nimport { useEditorReadOnly } from '@udecode/plate-common/react';\nimport {\n FontBackgroundColorPlugin,\n FontColorPlugin,\n} from '@udecode/plate-font/react';\nimport { HighlightPlugin } from '@udecode/plate-highlight/react';\nimport { ListStyleType } from '@udecode/plate-indent-list';\nimport {\n AudioPlugin,\n FilePlugin,\n ImagePlugin,\n VideoPlugin,\n} from '@udecode/plate-media/react';\nimport {\n BaselineIcon,\n BoldIcon,\n Code2Icon,\n HighlighterIcon,\n ItalicIcon,\n PaintBucketIcon,\n StrikethroughIcon,\n UnderlineIcon,\n WandSparklesIcon,\n} from 'lucide-react';\n\nimport { MoreDropdownMenu } from '@/components/plate-ui/more-dropdown-menu';\n\nimport { AIToolbarButton } from './ai-toolbar-button';\nimport { AlignDropdownMenu } from './align-dropdown-menu';\nimport { ColorDropdownMenu } from './color-dropdown-menu';\nimport { CommentToolbarButton } from './comment-toolbar-button';\nimport { EmojiDropdownMenu } from './emoji-dropdown-menu';\nimport { RedoToolbarButton, UndoToolbarButton } from './history-toolbar-button';\nimport { IndentListToolbarButton } from './indent-list-toolbar-button';\nimport { IndentTodoToolbarButton } from './indent-todo-toolbar-button';\nimport { IndentToolbarButton } from './indent-toolbar-button';\nimport { InsertDropdownMenu } from './insert-dropdown-menu';\nimport { LineHeightDropdownMenu } from './line-height-dropdown-menu';\nimport { LinkToolbarButton } from './link-toolbar-button';\nimport { MarkToolbarButton } from './mark-toolbar-button';\nimport { MediaToolbarButton } from './media-toolbar-button';\nimport { ModeDropdownMenu } from './mode-dropdown-menu';\nimport { OutdentToolbarButton } from './outdent-toolbar-button';\nimport { TableDropdownMenu } from './table-dropdown-menu';\nimport { ToggleToolbarButton } from './toggle-toolbar-button';\nimport { ToolbarGroup } from './toolbar';\nimport { TurnIntoDropdownMenu } from './turn-into-dropdown-menu';\n\nexport function FixedToolbarButtons() {\n const readOnly = useEditorReadOnly();\n\n return (\n <div className=\"flex w-full\">\n {!readOnly && (\n <>\n <ToolbarGroup>\n <UndoToolbarButton />\n <RedoToolbarButton />\n </ToolbarGroup>\n\n <ToolbarGroup>\n <AIToolbarButton tooltip=\"AI commands\">\n <WandSparklesIcon />\n </AIToolbarButton>\n </ToolbarGroup>\n\n <ToolbarGroup>\n <InsertDropdownMenu />\n <TurnIntoDropdownMenu />\n </ToolbarGroup>\n\n <ToolbarGroup>\n <MarkToolbarButton nodeType={BoldPlugin.key} tooltip=\"Bold (⌘+B)\">\n <BoldIcon />\n </MarkToolbarButton>\n\n <MarkToolbarButton\n nodeType={ItalicPlugin.key}\n tooltip=\"Italic (⌘+I)\"\n >\n <ItalicIcon />\n </MarkToolbarButton>\n\n <MarkToolbarButton\n nodeType={UnderlinePlugin.key}\n tooltip=\"Underline (⌘+U)\"\n >\n <UnderlineIcon />\n </MarkToolbarButton>\n\n <MarkToolbarButton\n nodeType={StrikethroughPlugin.key}\n tooltip=\"Strikethrough (⌘+⇧+M)\"\n >\n <StrikethroughIcon />\n </MarkToolbarButton>\n\n <MarkToolbarButton nodeType={CodePlugin.key} tooltip=\"Code (⌘+E)\">\n <Code2Icon />\n </MarkToolbarButton>\n\n <ColorDropdownMenu\n nodeType={FontColorPlugin.key}\n tooltip=\"Text color\"\n >\n <BaselineIcon />\n </ColorDropdownMenu>\n\n <ColorDropdownMenu\n nodeType={FontBackgroundColorPlugin.key}\n tooltip=\"Background color\"\n >\n <PaintBucketIcon />\n </ColorDropdownMenu>\n </ToolbarGroup>\n\n <ToolbarGroup>\n <AlignDropdownMenu />\n\n <IndentListToolbarButton nodeType={ListStyleType.Disc} />\n <IndentListToolbarButton nodeType={ListStyleType.Decimal} />\n <IndentTodoToolbarButton />\n <ToggleToolbarButton />\n </ToolbarGroup>\n\n <ToolbarGroup>\n <LinkToolbarButton />\n <TableDropdownMenu />\n <EmojiDropdownMenu />\n </ToolbarGroup>\n\n <ToolbarGroup>\n <MediaToolbarButton nodeType={ImagePlugin.key} />\n <MediaToolbarButton nodeType={VideoPlugin.key} />\n <MediaToolbarButton nodeType={AudioPlugin.key} />\n <MediaToolbarButton nodeType={FilePlugin.key} />\n </ToolbarGroup>\n\n <ToolbarGroup>\n <LineHeightDropdownMenu />\n <OutdentToolbarButton />\n <IndentToolbarButton />\n </ToolbarGroup>\n\n <ToolbarGroup>\n <MoreDropdownMenu />\n </ToolbarGroup>\n </>\n )}\n\n <div className=\"grow\" />\n\n <ToolbarGroup>\n <MarkToolbarButton nodeType={HighlightPlugin.key} tooltip=\"Highlight\">\n <HighlighterIcon />\n </MarkToolbarButton>\n <CommentToolbarButton />\n </ToolbarGroup>\n\n <ToolbarGroup>\n <ModeDropdownMenu />\n </ToolbarGroup>\n </div>\n );\n}\n",
"content": "'use client';\n\nimport React from 'react';\n\nimport {\n BoldPlugin,\n CodePlugin,\n ItalicPlugin,\n StrikethroughPlugin,\n UnderlinePlugin,\n} from '@udecode/plate-basic-marks/react';\nimport { useEditorReadOnly } from '@udecode/plate-common/react';\nimport {\n FontBackgroundColorPlugin,\n FontColorPlugin,\n} from '@udecode/plate-font/react';\nimport { HighlightPlugin } from '@udecode/plate-highlight/react';\nimport { ListStyleType } from '@udecode/plate-indent-list';\nimport {\n AudioPlugin,\n FilePlugin,\n ImagePlugin,\n VideoPlugin,\n} from '@udecode/plate-media/react';\nimport {\n ArrowUpToLineIcon,\n BaselineIcon,\n BoldIcon,\n Code2Icon,\n HighlighterIcon,\n ItalicIcon,\n PaintBucketIcon,\n StrikethroughIcon,\n UnderlineIcon,\n WandSparklesIcon,\n} from 'lucide-react';\n\nimport { MoreDropdownMenu } from '@/components/plate-ui/more-dropdown-menu';\n\nimport { AIToolbarButton } from './ai-toolbar-button';\nimport { AlignDropdownMenu } from './align-dropdown-menu';\nimport { ColorDropdownMenu } from './color-dropdown-menu';\nimport { CommentToolbarButton } from './comment-toolbar-button';\nimport { EmojiDropdownMenu } from './emoji-dropdown-menu';\nimport { ExportToolbarButton } from './export-toolbar-button';\nimport { RedoToolbarButton, UndoToolbarButton } from './history-toolbar-button';\nimport { IndentListToolbarButton } from './indent-list-toolbar-button';\nimport { IndentTodoToolbarButton } from './indent-todo-toolbar-button';\nimport { IndentToolbarButton } from './indent-toolbar-button';\nimport { InsertDropdownMenu } from './insert-dropdown-menu';\nimport { LineHeightDropdownMenu } from './line-height-dropdown-menu';\nimport { LinkToolbarButton } from './link-toolbar-button';\nimport { MarkToolbarButton } from './mark-toolbar-button';\nimport { MediaToolbarButton } from './media-toolbar-button';\nimport { ModeDropdownMenu } from './mode-dropdown-menu';\nimport { OutdentToolbarButton } from './outdent-toolbar-button';\nimport { TableDropdownMenu } from './table-dropdown-menu';\nimport { ToggleToolbarButton } from './toggle-toolbar-button';\nimport { ToolbarGroup } from './toolbar';\nimport { TurnIntoDropdownMenu } from './turn-into-dropdown-menu';\n\nexport function FixedToolbarButtons() {\n const readOnly = useEditorReadOnly();\n\n return (\n <div className=\"flex w-full\">\n {!readOnly && (\n <>\n <ToolbarGroup>\n <UndoToolbarButton />\n <RedoToolbarButton />\n </ToolbarGroup>\n\n <ToolbarGroup>\n <AIToolbarButton tooltip=\"AI commands\">\n <WandSparklesIcon />\n </AIToolbarButton>\n </ToolbarGroup>\n\n <ToolbarGroup>\n <ExportToolbarButton>\n <ArrowUpToLineIcon />\n </ExportToolbarButton>\n </ToolbarGroup>\n\n <ToolbarGroup>\n <InsertDropdownMenu />\n <TurnIntoDropdownMenu />\n </ToolbarGroup>\n\n <ToolbarGroup>\n <MarkToolbarButton nodeType={BoldPlugin.key} tooltip=\"Bold (⌘+B)\">\n <BoldIcon />\n </MarkToolbarButton>\n\n <MarkToolbarButton\n nodeType={ItalicPlugin.key}\n tooltip=\"Italic (⌘+I)\"\n >\n <ItalicIcon />\n </MarkToolbarButton>\n\n <MarkToolbarButton\n nodeType={UnderlinePlugin.key}\n tooltip=\"Underline (⌘+U)\"\n >\n <UnderlineIcon />\n </MarkToolbarButton>\n\n <MarkToolbarButton\n nodeType={StrikethroughPlugin.key}\n tooltip=\"Strikethrough (⌘+⇧+M)\"\n >\n <StrikethroughIcon />\n </MarkToolbarButton>\n\n <MarkToolbarButton nodeType={CodePlugin.key} tooltip=\"Code (⌘+E)\">\n <Code2Icon />\n </MarkToolbarButton>\n\n <ColorDropdownMenu\n nodeType={FontColorPlugin.key}\n tooltip=\"Text color\"\n >\n <BaselineIcon />\n </ColorDropdownMenu>\n\n <ColorDropdownMenu\n nodeType={FontBackgroundColorPlugin.key}\n tooltip=\"Background color\"\n >\n <PaintBucketIcon />\n </ColorDropdownMenu>\n </ToolbarGroup>\n\n <ToolbarGroup>\n <AlignDropdownMenu />\n\n <IndentListToolbarButton nodeType={ListStyleType.Disc} />\n <IndentListToolbarButton nodeType={ListStyleType.Decimal} />\n <IndentTodoToolbarButton />\n <ToggleToolbarButton />\n </ToolbarGroup>\n\n <ToolbarGroup>\n <LinkToolbarButton />\n <TableDropdownMenu />\n <EmojiDropdownMenu />\n </ToolbarGroup>\n\n <ToolbarGroup>\n <MediaToolbarButton nodeType={ImagePlugin.key} />\n <MediaToolbarButton nodeType={VideoPlugin.key} />\n <MediaToolbarButton nodeType={AudioPlugin.key} />\n <MediaToolbarButton nodeType={FilePlugin.key} />\n </ToolbarGroup>\n\n <ToolbarGroup>\n <LineHeightDropdownMenu />\n <OutdentToolbarButton />\n <IndentToolbarButton />\n </ToolbarGroup>\n\n <ToolbarGroup>\n <MoreDropdownMenu />\n </ToolbarGroup>\n </>\n )}\n\n <div className=\"grow\" />\n\n <ToolbarGroup>\n <MarkToolbarButton nodeType={HighlightPlugin.key} tooltip=\"Highlight\">\n <HighlighterIcon />\n </MarkToolbarButton>\n <CommentToolbarButton />\n </ToolbarGroup>\n\n <ToolbarGroup>\n <ModeDropdownMenu />\n </ToolbarGroup>\n </div>\n );\n}\n",
"path": "plate-ui/fixed-toolbar-buttons.tsx",
"target": "components/plate-ui/fixed-toolbar-buttons.tsx",
"type": "registry:ui"
Expand Down Expand Up @@ -42,7 +42,8 @@
"outdent-toolbar-button",
"table-dropdown-menu",
"toggle-toolbar-button",
"turn-into-dropdown-menu"
"turn-into-dropdown-menu",
"export-toolbar-button"
],
"type": "registry:ui"
}
Loading

0 comments on commit 385b27d

Please sign in to comment.