返回 presentation-ai
emoji-node.tsx
根目录 / src / components / plate / ui / emoji-node.tsx
1 "use client";
2
3 import { EmojiInlineIndexSearch, insertEmoji } from "@platejs/emoji";
4 import { EmojiPlugin } from "@platejs/emoji/react";
5 import {
6 PlateElement,
7 usePluginOption,
8 type PlateElementProps,
9 } from "platejs/react";
10 import * as React from "react";
11
12 import { useDebounce } from "@/components/plate/hooks/use-debounce";
13 import {
14 InlineCombobox,
15 InlineComboboxContent,
16 InlineComboboxEmpty,
17 InlineComboboxGroup,
18 InlineComboboxInput,
19 InlineComboboxItem,
20 } from "./inline-combobox";
21
22 export function EmojiInputElement(props: PlateElementProps) {
23 const { children, editor, element } = props;
24 const data = usePluginOption(EmojiPlugin, "data")!;
25 const [value, setValue] = React.useState("");
26 const debouncedValue = useDebounce(value, 100);
27 const isPending = value !== debouncedValue;
28
29 const filteredEmojis = React.useMemo(() => {
30 if (debouncedValue.trim().length === 0) return [];
31
32 return EmojiInlineIndexSearch.getInstance(data)
33 .search(debouncedValue.replace(/:$/, ""))
34 .get();
35 }, [data, debouncedValue]);
36
37 return (
38 <PlateElement as="span" data-slate-value={element.value} {...props}>
39 <InlineCombobox
40 value={value}
41 element={element}
42 filter={false}
43 setValue={setValue}
44 trigger=":"
45 hideWhenNoValue
46 >
47 <InlineComboboxInput />
48
49 <InlineComboboxContent>
50 {!isPending && <InlineComboboxEmpty>No results</InlineComboboxEmpty>}
51
52 <InlineComboboxGroup>
53 {filteredEmojis.map((emoji) => (
54 <InlineComboboxItem
55 key={emoji.id}
56 value={emoji.name}
57 onClick={() => insertEmoji(editor, emoji)}
58 >
59 {emoji.skins[0]?.native} {emoji.name}
60 </InlineComboboxItem>
61 ))}
62 </InlineComboboxGroup>
63 </InlineComboboxContent>
64 </InlineCombobox>
65
66 {children}
67 </PlateElement>
68 );
69 }
70
70 lines Plain Text