import { type Component, createSignal, For, createEffect } from "solid-js"; import { Heading1, Heading2, Heading3, List, ListTodo, Type, Code, Quote } from "lucide-solid"; import { cn } from "@/lib/utils"; export interface CommandItem { title: string; description: string; icon: any; command: (props: { editor: any; range: any }) => void; } export const getSuggestionItems = ({ query }: { query: string }): CommandItem[] => { return [ { title: "Text", description: "Just start typing with plain text.", icon: Type, command: ({ editor, range }: { editor: any, range: any }) => { editor.chain().focus().deleteRange(range).setNode("paragraph").run(); }, }, { title: "Heading 1", description: "Big section heading.", icon: Heading1, command: ({ editor, range }: { editor: any, range: any }) => { editor.chain().focus().deleteRange(range).setNode("heading", { level: 1 }).run(); }, }, { title: "Heading 2", description: "Medium section heading.", icon: Heading2, command: ({ editor, range }: { editor: any, range: any }) => { editor.chain().focus().deleteRange(range).setNode("heading", { level: 2 }).run(); }, }, { title: "Heading 3", description: "Small section heading.", icon: Heading3, command: ({ editor, range }: { editor: any, range: any }) => { editor.chain().focus().deleteRange(range).setNode("heading", { level: 3 }).run(); }, }, { title: "Bullet List", description: "Create a simple bulleted list.", icon: List, command: ({ editor, range }: { editor: any, range: any }) => { editor.chain().focus().deleteRange(range).toggleBulletList().run(); }, }, { title: "Task List", description: "Track tasks with a checklist.", icon: ListTodo, command: ({ editor, range }: { editor: any, range: any }) => { editor.chain().focus().deleteRange(range).toggleTaskList().run(); }, }, { title: "Code Block", description: "Capture a code snippet.", icon: Code, command: ({ editor, range }: { editor: any, range: any }) => { editor.chain().focus().deleteRange(range).toggleCodeBlock().run(); }, }, { title: "Blockquote", description: "Capture a quote.", icon: Quote, command: ({ editor, range }: { editor: any, range: any }) => { editor.chain().focus().deleteRange(range).toggleBlockquote().run(); }, }, ].filter(item => item.title.toLowerCase().startsWith(query.toLowerCase())); }; export const SlashMenu: Component<{ items: CommandItem[]; command: (item: CommandItem) => void; editor: any; ref: (handlers: { onKeyDown: (e: KeyboardEvent) => boolean }) => void; }> = (props) => { const [selectedIndex, setSelectedIndex] = createSignal(0); // Auto-select the first item when the list changes (filtering) createEffect(() => { // We track props.items. When it changes, we reset. props.items; setSelectedIndex(0); }); const selectItem = (index: number) => { const item = props.items[index]; if (item) { props.command(item); } }; // Expose handlers to the parent via the ref prop props.ref({ onKeyDown: (e: KeyboardEvent) => { if (e.key === "ArrowUp") { setSelectedIndex((prev) => (prev + props.items.length - 1) % props.items.length); return true; } if (e.key === "ArrowDown") { setSelectedIndex((prev) => (prev + 1) % props.items.length); return true; } if (e.key === "Enter") { selectItem(selectedIndex()); return true; } return false; } }); return (