返回 presentation-ai
suggestion-kit.tsx
根目录 / src / components / plate / plugins / suggestion-kit.tsx
1 "use client";
2
3 import {
4 BaseSuggestionPlugin,
5 type BaseSuggestionConfig,
6 } from "@platejs/suggestion";
7 import {
8 isSlateEditor,
9 isSlateString,
10 type ExtendConfig,
11 type Path,
12 } from "platejs";
13 import { toTPlatePlugin } from "platejs/react";
14
15 import {
16 SuggestionLeaf,
17 SuggestionLineBreak,
18 } from "@/components/plate/ui/suggestion-node";
19 import { discussionPlugin } from "./discussion-kit";
20
21 export type SuggestionConfig = ExtendConfig<
22 BaseSuggestionConfig,
23 {
24 activeId: string | null;
25 hoverId: string | null;
26 uniquePathMap: Map<string, Path>;
27 }
28 >;
29
30 export const suggestionPlugin = toTPlatePlugin<SuggestionConfig>(
31 BaseSuggestionPlugin,
32 ({ editor }) => ({
33 options: {
34 activeId: null,
35 currentUserId: editor.getOption(discussionPlugin, "currentUserId"),
36 hoverId: null,
37 uniquePathMap: new Map(),
38 },
39 }),
40 ).configure({
41 handlers: {
42 // unset active suggestion when clicking outside of suggestion
43 onClick: ({ api, event, setOption, type }) => {
44 let leaf = event.target as HTMLElement;
45 let isSet = false;
46
47 const isBlockLeaf = leaf.dataset.blockSuggestion === "true";
48
49 const unsetActiveSuggestion = () => {
50 setOption("activeId", null);
51 isSet = true;
52 };
53
54 if (!isSlateString(leaf) && !isBlockLeaf) {
55 unsetActiveSuggestion();
56 }
57
58 while (leaf.parentElement && !isSlateEditor(leaf.parentElement)) {
59 const isBlockSuggestion = leaf.dataset.blockSuggestion === "true";
60
61 if (leaf.classList.contains(`slate-${type}`) || isBlockSuggestion) {
62 const suggestionEntry = api.suggestion!.node({
63 isText: !isBlockSuggestion,
64 });
65
66 if (!suggestionEntry) {
67 unsetActiveSuggestion();
68
69 break;
70 }
71
72 const id = api.suggestion!.nodeId(suggestionEntry[0]);
73 setOption("activeId", id ?? null);
74
75 isSet = true;
76
77 break;
78 }
79
80 leaf = leaf.parentElement;
81 }
82
83 if (!isSet) unsetActiveSuggestion();
84 },
85 },
86 render: {
87 belowNodes: (props) =>
88 SuggestionLineBreak(props as Parameters<typeof SuggestionLineBreak>[0]),
89 node: SuggestionLeaf,
90 },
91 });
92
93 export const SuggestionKit = [suggestionPlugin];
94
94 lines Plain Text