"use client";
import * as React from "react";
import {
InlineCombobox,
InlineComboboxContent,
InlineComboboxEmpty,
InlineComboboxGroup,
InlineComboboxInput,
InlineComboboxItem,
} from "@/components/ui/inline-combobox";
import { getMentionOnSelectItem } from "@platejs/mention";
import { MentionInputPlugin, MentionPlugin } from "@platejs/mention/react";
import {
Plate,
PlateContent,
PlateElement,
useFocused,
usePlateEditor,
useSelected,
} from "platejs/react";
import { cn } from "@/lib/utils";
const MENTIONABLES = [
{ key: "0", text: "Aayla Secura" },
{ key: "1", text: "Adi Gallia" },
{ key: "2", text: "Admiral Dodd Rancit" },
{ key: "3", text: "Admiral Firmus Piett" },
{ key: "4", text: "Admiral Gial Ackbar" },
{ key: "5", text: "Admiral Ozzel" },
{ key: "6", text: "Admiral Raddus" },
{ key: "7", text: "Aurra Sing" },
{ key: "8", text: "Boba Fett" },
];
function MentionElement(props: any) {
const selected = useSelected();
const focused = useFocused();
const element = props.element as { value: string };
return (
<PlateElement
{...props}
className={cn(
"inline-block rounded-md bg-muted px-1.5 py-0.5 align-baseline font-medium text-sm",
selected && focused && "ring-2 ring-ring",
)}
attributes={{
...props.attributes,
contentEditable: false,
"data-slate-value": element.value,
draggable: true,
}}
>
{"@"}
{element.value}
{props.children}
</PlateElement>
);
}
const onSelectItem = getMentionOnSelectItem();
function MentionInputElement(props: any) {
const { editor, element } = props;
const [search, setSearch] = React.useState("");
return (
<PlateElement {...props} as="span">
<InlineCombobox
value={search}
element={element}
setValue={setSearch}
showTrigger={false}
trigger="@"
>
<span className="inline-block rounded-md bg-muted px-1.5 py-0.5 align-baseline text-sm ring-ring focus-within:ring-2">
<InlineComboboxInput />
</span>
<InlineComboboxContent className="my-1.5">
<InlineComboboxEmpty>No results</InlineComboboxEmpty>
<InlineComboboxGroup>
{MENTIONABLES.map((item) => (
<InlineComboboxItem
key={item.key}
value={item.text}
onClick={() => onSelectItem(editor, item, search)}
>
{item.text}
</InlineComboboxItem>
))}
</InlineComboboxGroup>
</InlineComboboxContent>
</InlineCombobox>
{props.children}
</PlateElement>
);
}
export default function InlineComboboxDemo() {
const editor = usePlateEditor({
plugins: [
MentionPlugin.configure({
options: {
triggerPreviousCharPattern: /^$|^[\s"']$/,
},
}).withComponent(MentionElement),
MentionInputPlugin.withComponent(MentionInputElement),
],
value: [
{
type: "p",
children: [
{ text: "Type " },
{ text: "@", bold: true },
{ text: " to open the inline combobox and mention someone." },
],
},
],
});
return (
<div className="w-full max-w-xl rounded-lg border bg-background p-2">
<Plate editor={editor}>
<PlateContent
className="min-h-[160px] rounded-md px-3 py-2 text-sm outline-none"
placeholder="Type @ to mention..."
/>
</Plate>
</div>
);
}