memos/web/src/components/MemoEditor/Editor/CommandSuggestions.tsx
Johnny 5925e3cfc1 chore(web): simplify command system and improve editor UX (#5242)
Streamlines the command suggestion interface and fixes list auto-completion behavior:

- Remove command descriptions for cleaner suggestion popup UI
- Replace PaperclipIcon with FileIcon for semantic accuracy
- Fix list auto-completion to avoid extra newline when exiting list mode
- Add explanatory comments for cursor offset positions
- Improve dependency array in useListAutoCompletion hook

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-09 13:09:50 +08:00

59 lines
2 KiB
TypeScript

import { observer } from "mobx-react-lite";
import OverflowTip from "@/components/kit/OverflowTip";
import { EditorRefActions } from ".";
import { Command } from "../types/command";
import { SuggestionsPopup } from "./SuggestionsPopup";
import { useSuggestions } from "./useSuggestions";
interface CommandSuggestionsProps {
editorRef: React.RefObject<HTMLTextAreaElement>;
editorActions: React.ForwardedRef<EditorRefActions>;
commands: Command[];
}
/**
* Command suggestions popup that appears when typing "/" in the editor.
* Shows available editor commands like formatting options, insertions, etc.
*
* Usage:
* - Type "/" to trigger
* - Continue typing to filter commands
* - Use Arrow keys to navigate, Enter/Tab to select
*/
const CommandSuggestions = observer(({ editorRef, editorActions, commands }: CommandSuggestionsProps) => {
const { position, suggestions, selectedIndex, isVisible, handleItemSelect } = useSuggestions({
editorRef,
editorActions,
triggerChar: "/",
items: commands,
filterItems: (items, searchQuery) => {
if (!searchQuery) return items;
// Filter commands by prefix match for intuitive searching
return items.filter((cmd) => cmd.name.toLowerCase().startsWith(searchQuery));
},
onAutocomplete: (cmd, word, index, actions) => {
// Replace the trigger word with the command output
actions.removeText(index, word.length);
actions.insertText(cmd.run());
// Position cursor if command specifies an offset
if (cmd.cursorOffset) {
actions.setCursorPosition(actions.getCursorPosition() + cmd.cursorOffset);
}
},
});
if (!isVisible || !position) return null;
return (
<SuggestionsPopup
position={position}
suggestions={suggestions}
selectedIndex={selectedIndex}
onItemSelect={handleItemSelect}
getItemKey={(cmd) => cmd.name}
renderItem={(cmd) => <OverflowTip>/{cmd.name}</OverflowTip>}
/>
);
});
export default CommandSuggestions;