import type { FC } from 'react' import { useEffect, useMemo } from 'react' import { Command } from 'cmdk' import { useTranslation } from 'react-i18next' import type { ActionItem } from './actions/types' import { slashCommandRegistry } from './actions/commands/registry' type Props = { actions: Record onCommandSelect: (commandKey: string) => void searchFilter?: string commandValue?: string onCommandValueChange?: (value: string) => void originalQuery?: string } const CommandSelector: FC = ({ actions, onCommandSelect, searchFilter, commandValue, onCommandValueChange, originalQuery }) => { const { t } = useTranslation() // Check if we're in slash command mode const isSlashMode = originalQuery?.trim().startsWith('/') || false // Get slash commands from registry const slashCommands = useMemo(() => { if (!isSlashMode) return [] const allCommands = slashCommandRegistry.getAllCommands() const filter = searchFilter?.toLowerCase() || '' // searchFilter already has '/' removed return allCommands.filter((cmd) => { if (!filter) return true return cmd.name.toLowerCase().includes(filter) }).map(cmd => ({ key: `/${cmd.name}`, shortcut: `/${cmd.name}`, title: cmd.name, description: cmd.description, })) }, [isSlashMode, searchFilter]) const filteredActions = useMemo(() => { if (isSlashMode) return [] return Object.values(actions).filter((action) => { // Exclude slash action when in @ mode if (action.key === '/') return false if (!searchFilter) return true const filterLower = searchFilter.toLowerCase() return action.shortcut.toLowerCase().includes(filterLower) }) }, [actions, searchFilter, isSlashMode]) const allItems = isSlashMode ? slashCommands : filteredActions useEffect(() => { if (allItems.length > 0 && onCommandValueChange) { const currentValueExists = allItems.some(item => item.shortcut === commandValue) if (!currentValueExists) onCommandValueChange(allItems[0].shortcut) } }, [searchFilter, allItems.length]) if (allItems.length === 0) { return (
{t('app.gotoAnything.noMatchingCommands')}
{t('app.gotoAnything.tryDifferentSearch')}
) } return (
{isSlashMode ? t('app.gotoAnything.groups.commands') : t('app.gotoAnything.selectSearchType')}
{allItems.map(item => ( onCommandSelect(item.shortcut)} > {item.shortcut} {isSlashMode ? ( (() => { const slashKeyMap: Record = { '/theme': 'app.gotoAnything.actions.themeCategoryDesc', '/language': 'app.gotoAnything.actions.languageChangeDesc', '/account': 'app.gotoAnything.actions.accountDesc', '/feedback': 'app.gotoAnything.actions.feedbackDesc', '/doc': 'app.gotoAnything.actions.docDesc', '/community': 'app.gotoAnything.actions.communityDesc', } return t(slashKeyMap[item.key] || item.description) })() ) : ( (() => { const keyMap: Record = { '@app': 'app.gotoAnything.actions.searchApplicationsDesc', '@plugin': 'app.gotoAnything.actions.searchPluginsDesc', '@knowledge': 'app.gotoAnything.actions.searchKnowledgeBasesDesc', '@node': 'app.gotoAnything.actions.searchWorkflowNodesDesc', } return t(keyMap[item.key]) })() )} ))}
) } export default CommandSelector