// src/layout/command-palette/useCommandPalette.ts import { useState, useCallback, useRef } from 'react' import type { RegisteredCommand } from '../../plugin/commands' import type { App } from '../../plugin/app' /** * Hook to manage command palette state. * * Features: * - Open/close state management * - Available command filtering from registry * - Centralized command execution with error isolation * * Note: The Cmd/Ctrl+P keyboard shortcut is registered by LayoutCommandsPlugin, * not handled here. This avoids duplicate keyboard handlers and allows the * shortcut to be customizable. */ export function useCommandPalette(app: App) { const [isOpen, setIsOpen] = useState(false) // Cache to prevent re-renders when commands haven't changed const commandsRef = useRef([]) const open = useCallback(() => setIsOpen(true), []) const close = useCallback(() => setIsOpen(false), []) const toggle = useCallback(() => setIsOpen(prev => !prev), []) // Get available commands (filters by checkCallback, etc.) // Uses cached array if content is the same to prevent unnecessary re-renders const getCommands = useCallback((editorContext: { editor: unknown; view: unknown } | null = null): RegisteredCommand[] => { const commands = app.commands.getAvailableCommands(editorContext) // Check if commands have changed by comparing IDs const currentIds = commands.map(c => c.id).join(',') const cachedIds = commandsRef.current.map(c => c.id).join(',') if (currentIds !== cachedIds) { commandsRef.current = commands } return commandsRef.current }, [app.commands]) // Search commands via centralized registry method (includes availability filtering + scoring) const searchCommands = useCallback((query: string, editorContext: { editor: unknown; view: unknown } | null = null): RegisteredCommand[] => { return app.commands.searchCommands(query, editorContext) }, [app.commands]) // Execute command via centralized registry method const executeCommand = useCallback((command: RegisteredCommand, editorContext: { editor: unknown; view: unknown } | null = null): void => { app.commands.executeCommand(command, editorContext) }, [app.commands]) return { isOpen, open, close, toggle, getCommands, searchCommands, executeCommand, } }