'use client'; import * as React from 'react'; import type { PlateElementProps } from 'platejs/react'; import { SlashInputPlugin } from '@platejs/slash-command/react'; import { ChevronRightIcon, Code2Icon, FileCodeIcon, Heading1Icon, Heading2Icon, Heading3Icon, InfoIcon, ListIcon, ListOrderedIcon, MinusIcon, PilcrowIcon, QuoteIcon, RadicalIcon, SquareIcon, TableIcon, } from 'lucide-react'; import { KEYS } from 'platejs'; import { PlateElement, useEditorRef } from 'platejs/react'; import { InlineCombobox, InlineComboboxContent, InlineComboboxEmpty, InlineComboboxGroup, InlineComboboxGroupLabel, InlineComboboxInput, InlineComboboxItem, } from '@/components/ui/inline-combobox'; import { insertBlock, insertInlineElement } from '@/components/editor/transforms'; interface SlashCommandItem { icon: React.ReactNode; keywords: string[]; label: string; value: string; onSelect: (editor: any) => void; } const slashCommandGroups: { heading: string; items: SlashCommandItem[] }[] = [ { heading: 'Basic Blocks', items: [ { icon: , keywords: ['paragraph', 'text', 'plain'], label: 'Text', value: 'text', onSelect: (editor) => insertBlock(editor, KEYS.p), }, { icon: , keywords: ['title', 'h1', 'heading'], label: 'Heading 1', value: 'heading1', onSelect: (editor) => insertBlock(editor, 'h1'), }, { icon: , keywords: ['subtitle', 'h2', 'heading'], label: 'Heading 2', value: 'heading2', onSelect: (editor) => insertBlock(editor, 'h2'), }, { icon: , keywords: ['subtitle', 'h3', 'heading'], label: 'Heading 3', value: 'heading3', onSelect: (editor) => insertBlock(editor, 'h3'), }, { icon: , keywords: ['citation', 'blockquote'], label: 'Quote', value: 'quote', onSelect: (editor) => insertBlock(editor, KEYS.blockquote), }, { icon: , keywords: ['divider', 'separator', 'line'], label: 'Divider', value: 'divider', onSelect: (editor) => insertBlock(editor, KEYS.hr), }, ], }, { heading: 'Lists', items: [ { icon: , keywords: ['unordered', 'ul', 'bullet'], label: 'Bulleted list', value: 'bulleted-list', onSelect: (editor) => insertBlock(editor, KEYS.ul), }, { icon: , keywords: ['ordered', 'ol', 'numbered'], label: 'Numbered list', value: 'numbered-list', onSelect: (editor) => insertBlock(editor, KEYS.ol), }, { icon: , keywords: ['checklist', 'task', 'checkbox', 'todo'], label: 'To-do list', value: 'todo-list', onSelect: (editor) => insertBlock(editor, KEYS.listTodo), }, ], }, { heading: 'Advanced', items: [ { icon: , keywords: ['table', 'grid'], label: 'Table', value: 'table', onSelect: (editor) => insertBlock(editor, KEYS.table), }, { icon: , keywords: ['code', 'codeblock', 'snippet'], label: 'Code block', value: 'code-block', onSelect: (editor) => insertBlock(editor, KEYS.codeBlock), }, { icon: , keywords: ['callout', 'note', 'info', 'warning', 'tip'], label: 'Callout', value: 'callout', onSelect: (editor) => insertBlock(editor, KEYS.callout), }, { icon: , keywords: ['toggle', 'collapsible', 'expand'], label: 'Toggle', value: 'toggle', onSelect: (editor) => insertBlock(editor, KEYS.toggle), }, { icon: , keywords: ['equation', 'math', 'formula', 'latex'], label: 'Equation', value: 'equation', onSelect: (editor) => insertInlineElement(editor, KEYS.equation), }, ], }, { heading: 'Inline', items: [ { icon: , keywords: ['link', 'url', 'href'], label: 'Link', value: 'link', onSelect: (editor) => insertInlineElement(editor, KEYS.link), }, ], }, ]; export function SlashInputElement({ children, ...props }: PlateElementProps) { const editor = useEditorRef(); return ( No results found. {slashCommandGroups.map(({ heading, items }) => ( {heading} {items.map(({ icon, keywords, label, value, onSelect }) => ( { onSelect(editor); editor.tf.focus(); }} > {icon} {label} ))} ))} {children} ); }