import type * as React from 'react' import type { Editor } from '@tiptap/react' import { insertContentEditorMath } from '@admin/utils/editor/insert-content-editor-math' import { insertContentEditorTable } from '@admin/utils/editor/insert-content-editor-table' import { Code, Heading1, Heading2, Heading3, ImagePlus, List, ListOrdered, ListTodo, Minus, Pilcrow, Quote, Sigma, Table } from 'lucide-react' export interface ContentEditorSlashCommand { id: string title: string description: string keywords: string[] Icon: React.ElementType<{ className?: string }> run: (editor: Editor) => boolean } const SLASH_COMMANDS: ContentEditorSlashCommand[] = [ { id: 'paragraph', title: 'Text', description: 'Start with plain paragraph text.', keywords: ['paragraph', 'plain'], Icon: Pilcrow, run: (editor) => editor.chain().focus().setParagraph().run() }, { id: 'heading-1', title: 'Heading 1', description: 'Large section heading.', keywords: ['h1', 'title'], Icon: Heading1, run: (editor) => editor.chain().focus().setHeading({ level: 1 }).run() }, { id: 'heading-2', title: 'Heading 2', description: 'Medium section heading.', keywords: ['h2', 'subtitle'], Icon: Heading2, run: (editor) => editor.chain().focus().setHeading({ level: 2 }).run() }, { id: 'heading-3', title: 'Heading 3', description: 'Small section heading.', keywords: ['h3'], Icon: Heading3, run: (editor) => editor.chain().focus().setHeading({ level: 3 }).run() }, { id: 'bullet-list', title: 'Bullet list', description: 'Create a simple unordered list.', keywords: ['ul', 'unordered'], Icon: List, run: (editor) => editor.chain().focus().toggleBulletList().run() }, { id: 'ordered-list', title: 'Numbered list', description: 'Create an ordered list.', keywords: ['ol', 'numbered'], Icon: ListOrdered, run: (editor) => editor.chain().focus().toggleOrderedList().run() }, { id: 'task-list', title: 'To-do list', description: 'Track tasks with checkboxes.', keywords: ['todo', 'task', 'checkbox'], Icon: ListTodo, run: (editor) => editor.chain().focus().toggleTaskList().run() }, { id: 'blockquote', title: 'Quote', description: 'Capture a callout or quoted section.', keywords: ['blockquote', 'callout'], Icon: Quote, run: (editor) => editor.chain().focus().toggleBlockquote().run() }, { id: 'code-block', title: 'Code block', description: 'Insert a formatted code block.', keywords: ['pre', 'snippet'], Icon: Code, run: (editor) => editor.chain().focus().toggleCodeBlock().run() }, { id: 'media', title: 'Media', description: 'Select an image from the media library.', keywords: ['image', 'photo', 'picture', 'media'], Icon: ImagePlus, run: (editor) => editor.chain().focus().insertContent({ type: 'mediaGalleryPlaceholder' }).run() }, { id: 'table', title: 'Table', description: 'Insert a table with a header row.', keywords: ['grid', 'rows', 'columns'], Icon: Table, run: (editor) => insertContentEditorTable(editor) }, { id: 'math', title: 'Math', description: 'Insert inline LaTeX math.', keywords: ['latex', 'katex', 'equation'], Icon: Sigma, run: (editor) => insertContentEditorMath(editor, 'x') }, { id: 'divider', title: 'Divider', description: 'Separate sections with a horizontal rule.', keywords: ['horizontal', 'rule', 'separator', 'hr'], Icon: Minus, run: (editor) => editor.chain().focus().setHorizontalRule().run() } ] export function getFilteredSlashCommands(query: string): ContentEditorSlashCommand[] { const normalizedQuery = query.trim().toLowerCase() if (!normalizedQuery) return SLASH_COMMANDS return SLASH_COMMANDS.filter((command) => { const searchableText = [command.title, command.description, ...command.keywords] .join(' ') .toLowerCase() return searchableText.includes(normalizedQuery) }) }