返回 presentation-ai
import-toolbar-button.tsx
根目录 / src / components / plate / ui / import-toolbar-button.tsx
1 "use client";
2
3 import { MarkdownPlugin } from "@platejs/markdown";
4 import { type DropdownMenuProps } from "@radix-ui/react-dropdown-menu";
5 import { ArrowUpToLineIcon } from "lucide-react";
6 import { useEditorRef } from "platejs/react";
7 import { getEditorDOMFromHtmlString } from "platejs/static";
8 import * as React from "react";
9 import { useFilePicker } from "use-file-picker";
10
11 import {
12 DropdownMenu,
13 DropdownMenuContent,
14 DropdownMenuGroup,
15 DropdownMenuItem,
16 DropdownMenuTrigger,
17 } from "@/components/plate/ui/dropdown-menu";
18 import { ToolbarButton } from "./toolbar";
19
20 type ImportType = "html" | "markdown";
21
22 export function ImportToolbarButton(props: DropdownMenuProps) {
23 const editor = useEditorRef();
24 const [open, setOpen] = React.useState(false);
25
26 const getFileNodes = (text: string, type: ImportType) => {
27 if (type === "html") {
28 const editorNode = getEditorDOMFromHtmlString(text);
29 const nodes = editor.api.html.deserialize({
30 element: editorNode,
31 });
32
33 return nodes;
34 }
35
36 if (type === "markdown") {
37 return editor.getApi(MarkdownPlugin).markdown.deserialize(text, {
38 withoutMdx: true,
39 });
40 }
41
42 return [];
43 };
44
45 const { openFilePicker: openMdFilePicker } = useFilePicker({
46 accept: [".md", ".mdx"],
47 multiple: false,
48 onFilesSelected: async (data) => {
49 const selectedFile = data.plainFiles?.[0];
50 if (!selectedFile) {
51 return;
52 }
53
54 const text = await selectedFile.text();
55
56 const nodes = getFileNodes(text, "markdown");
57
58 editor.tf.insertNodes(nodes);
59 },
60 });
61
62 const { openFilePicker: openHtmlFilePicker } = useFilePicker({
63 accept: ["text/html"],
64 multiple: false,
65 onFilesSelected: async (data) => {
66 const selectedFile = data.plainFiles?.[0];
67 if (!selectedFile) {
68 return;
69 }
70
71 const text = await selectedFile.text();
72
73 const nodes = getFileNodes(text, "html");
74
75 editor.tf.insertNodes(nodes);
76 },
77 });
78
79 return (
80 <DropdownMenu open={open} onOpenChange={setOpen} modal={false} {...props}>
81 <DropdownMenuTrigger asChild>
82 <ToolbarButton pressed={open} tooltip="Import" isDropdown>
83 <ArrowUpToLineIcon className="size-4" />
84 </ToolbarButton>
85 </DropdownMenuTrigger>
86
87 <DropdownMenuContent align="start">
88 <DropdownMenuGroup>
89 <DropdownMenuItem
90 onSelect={() => {
91 openHtmlFilePicker();
92 }}
93 >
94 Import from HTML
95 </DropdownMenuItem>
96
97 <DropdownMenuItem
98 onSelect={() => {
99 openMdFilePicker();
100 }}
101 >
102 Import from Markdown
103 </DropdownMenuItem>
104 </DropdownMenuGroup>
105 </DropdownMenuContent>
106 </DropdownMenu>
107 );
108 }
109
109 lines Plain Text