返回 presentation-ai
mention-node.tsx
根目录 / src / components / plate / ui / mention-node.tsx
1 "use client";
2
3 import { getMentionOnSelectItem } from "@platejs/mention";
4 import {
5 IS_APPLE,
6 KEYS,
7 type TComboboxInputElement,
8 type TMentionElement,
9 } from "platejs";
10 import {
11 PlateElement,
12 useFocused,
13 useReadOnly,
14 useSelected,
15 type PlateElementProps,
16 } from "platejs/react";
17 import * as React from "react";
18
19 import { useMounted } from "@/components/plate/hooks/use-mounted";
20 import { cn } from "@/lib/utils";
21 import {
22 InlineCombobox,
23 InlineComboboxContent,
24 InlineComboboxEmpty,
25 InlineComboboxGroup,
26 InlineComboboxInput,
27 InlineComboboxItem,
28 } from "./inline-combobox";
29
30 export function MentionElement(
31 props: PlateElementProps<TMentionElement> & {
32 prefix?: string;
33 },
34 ) {
35 const element = props.element;
36 const selected = useSelected();
37 const focused = useFocused();
38 const mounted = useMounted();
39 const readOnly = useReadOnly();
40
41 return (
42 <PlateElement
43 {...props}
44 className={cn(
45 "inline-block rounded-md bg-muted px-1.5 py-0.5 align-baseline text-sm font-medium",
46 !readOnly && "cursor-pointer",
47 selected && focused && "ring-2 ring-ring",
48 element.children[0]![KEYS.bold] === true && "font-bold",
49 element.children[0]![KEYS.italic] === true && "italic",
50 element.children[0]![KEYS.underline] === true && "underline",
51 )}
52 attributes={{
53 ...props.attributes,
54 contentEditable: false,
55 "data-slate-value": element.value,
56 draggable: true,
57 }}
58 >
59 {mounted && IS_APPLE ? (
60 // Mac OS IME https://github.com/ianstormtaylor/slate/issues/3490
61 <React.Fragment>
62 {props.children}
63 {props.prefix}
64 {element.value}
65 </React.Fragment>
66 ) : (
67 // Others like Android https://github.com/ianstormtaylor/slate/pull/5360
68 <React.Fragment>
69 {props.prefix}
70 {element.value}
71 {props.children}
72 </React.Fragment>
73 )}
74 </PlateElement>
75 );
76 }
77
78 const onSelectItem = getMentionOnSelectItem();
79
80 export function MentionInputElement(
81 props: PlateElementProps<TComboboxInputElement>,
82 ) {
83 const { editor, element } = props;
84 const [search, setSearch] = React.useState("");
85
86 return (
87 <PlateElement {...props} as="span" data-slate-value={element.value}>
88 <InlineCombobox
89 value={search}
90 element={element}
91 setValue={setSearch}
92 showTrigger={false}
93 trigger="@"
94 >
95 <span className="inline-block rounded-md bg-muted px-1.5 py-0.5 align-baseline text-sm ring-ring focus-within:ring-2">
96 <InlineComboboxInput />
97 </span>
98
99 <InlineComboboxContent className="my-1.5">
100 <InlineComboboxEmpty>No results</InlineComboboxEmpty>
101
102 <InlineComboboxGroup>
103 {MENTIONABLES.map((item) => (
104 <InlineComboboxItem
105 key={item.key}
106 value={item.text}
107 onClick={() => onSelectItem(editor, item, search)}
108 >
109 {item.text}
110 </InlineComboboxItem>
111 ))}
112 </InlineComboboxGroup>
113 </InlineComboboxContent>
114 </InlineCombobox>
115
116 {props.children}
117 </PlateElement>
118 );
119 }
120
121 const MENTIONABLES = [
122 { key: "0", text: "Aayla Secura" },
123 { key: "1", text: "Adi Gallia" },
124 {
125 key: "2",
126 text: "Admiral Dodd Rancit",
127 },
128 {
129 key: "3",
130 text: "Admiral Firmus Piett",
131 },
132 {
133 key: "4",
134 text: "Admiral Gial Ackbar",
135 },
136 { key: "5", text: "Admiral Ozzel" },
137 { key: "6", text: "Admiral Raddus" },
138 {
139 key: "7",
140 text: "Admiral Terrinald Screed",
141 },
142 { key: "8", text: "Admiral Trench" },
143 {
144 key: "9",
145 text: "Admiral U.O. Statura",
146 },
147 { key: "10", text: "Agen Kolar" },
148 { key: "11", text: "Agent Kallus" },
149 {
150 key: "12",
151 text: "Aiolin and Morit Astarte",
152 },
153 { key: "13", text: "Aks Moe" },
154 { key: "14", text: "Almec" },
155 { key: "15", text: "Alton Kastle" },
156 { key: "16", text: "Amee" },
157 { key: "17", text: "AP-5" },
158 { key: "18", text: "Armitage Hux" },
159 { key: "19", text: "Artoo" },
160 { key: "20", text: "Arvel Crynyd" },
161 { key: "21", text: "Asajj Ventress" },
162 { key: "22", text: "Aurra Sing" },
163 { key: "23", text: "AZI-3" },
164 { key: "24", text: "Bala-Tik" },
165 { key: "25", text: "Barada" },
166 { key: "26", text: "Bargwill Tomder" },
167 { key: "27", text: "Baron Papanoida" },
168 { key: "28", text: "Barriss Offee" },
169 { key: "29", text: "Baze Malbus" },
170 { key: "30", text: "Bazine Netal" },
171 { key: "31", text: "BB-8" },
172 { key: "32", text: "BB-9E" },
173 { key: "33", text: "Ben Quadinaros" },
174 { key: "34", text: "Berch Teller" },
175 { key: "35", text: "Beru Lars" },
176 { key: "36", text: "Bib Fortuna" },
177 {
178 key: "37",
179 text: "Biggs Darklighter",
180 },
181 { key: "38", text: "Black Krrsantan" },
182 { key: "39", text: "Bo-Katan Kryze" },
183 { key: "40", text: "Boba Fett" },
184 { key: "41", text: "Bobbajo" },
185 { key: "42", text: "Bodhi Rook" },
186 { key: "43", text: "Borvo the Hutt" },
187 { key: "44", text: "Boss Nass" },
188 { key: "45", text: "Bossk" },
189 {
190 key: "46",
191 text: "Breha Antilles-Organa",
192 },
193 { key: "47", text: "Bren Derlin" },
194 { key: "48", text: "Brendol Hux" },
195 { key: "49", text: "BT-1" },
196 ];
197
197 lines Plain Text