Lexical: support hotkeys in autosuggest plugin
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
parent
4557fb98b6
commit
0255b85e18
1 changed files with 71 additions and 6 deletions
|
@ -14,7 +14,11 @@ import {
|
||||||
$isRangeSelection,
|
$isRangeSelection,
|
||||||
$isTextNode,
|
$isTextNode,
|
||||||
COMMAND_PRIORITY_LOW,
|
COMMAND_PRIORITY_LOW,
|
||||||
|
KEY_ARROW_DOWN_COMMAND,
|
||||||
|
KEY_ARROW_UP_COMMAND,
|
||||||
|
KEY_ENTER_COMMAND,
|
||||||
KEY_ESCAPE_COMMAND,
|
KEY_ESCAPE_COMMAND,
|
||||||
|
KEY_TAB_COMMAND,
|
||||||
LexicalEditor,
|
LexicalEditor,
|
||||||
RangeSelection,
|
RangeSelection,
|
||||||
} from 'lexical';
|
} from 'lexical';
|
||||||
|
@ -288,19 +292,24 @@ const AutosuggestPlugin = ({
|
||||||
|
|
||||||
const [editor] = useLexicalComposerContext();
|
const [editor] = useLexicalComposerContext();
|
||||||
const [resolution, setResolution] = useState<Resolution | null>(null);
|
const [resolution, setResolution] = useState<Resolution | null>(null);
|
||||||
const [selectedSuggestion] = useState(0);
|
const [selectedSuggestion, setSelectedSuggestion] = useState(0);
|
||||||
const anchorElementRef = useMenuAnchorRef(
|
const anchorElementRef = useMenuAnchorRef(
|
||||||
resolution,
|
resolution,
|
||||||
setResolution,
|
setResolution,
|
||||||
);
|
);
|
||||||
|
|
||||||
const onSelectSuggestion: React.MouseEventHandler<HTMLDivElement> = (e) => {
|
const handleSelectSuggestion: React.MouseEventHandler<HTMLDivElement> = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const suggestion = suggestions.get(e.currentTarget.getAttribute('data-index') as any) as AutoSuggestion;
|
const index = e.currentTarget.getAttribute('data-index');
|
||||||
|
|
||||||
|
return onSelectSuggestion(index);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSelectSuggestion = (index: any) => {
|
||||||
|
const suggestion = suggestions.get(index) as AutoSuggestion;
|
||||||
|
|
||||||
editor.update(() => {
|
editor.update(() => {
|
||||||
|
|
||||||
dispatch((dispatch, getState) => {
|
dispatch((dispatch, getState) => {
|
||||||
const state = editor.getEditorState();
|
const state = editor.getEditorState();
|
||||||
const node = (state._selection as RangeSelection)?.anchor?.getNode();
|
const node = (state._selection as RangeSelection)?.anchor?.getNode();
|
||||||
|
@ -385,7 +394,7 @@ const AutosuggestPlugin = ({
|
||||||
'px-4 py-2.5 text-sm text-gray-700 dark:text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800 focus:bg-gray-100 dark:focus:bg-primary-800 group': true,
|
'px-4 py-2.5 text-sm text-gray-700 dark:text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800 focus:bg-gray-100 dark:focus:bg-primary-800 group': true,
|
||||||
'bg-gray-100 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-800': i === selectedSuggestion,
|
'bg-gray-100 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-800': i === selectedSuggestion,
|
||||||
})}
|
})}
|
||||||
onMouseDown={onSelectSuggestion}
|
onMouseDown={handleSelectSuggestion}
|
||||||
>
|
>
|
||||||
{inner}
|
{inner}
|
||||||
</div>
|
</div>
|
||||||
|
@ -466,6 +475,62 @@ const AutosuggestPlugin = ({
|
||||||
}, [resolution, suggestionsHidden, suggestions.isEmpty()]);
|
}, [resolution, suggestionsHidden, suggestions.isEmpty()]);
|
||||||
|
|
||||||
useEffect(() => mergeRegister(
|
useEffect(() => mergeRegister(
|
||||||
|
editor.registerCommand<KeyboardEvent>(
|
||||||
|
KEY_ARROW_UP_COMMAND,
|
||||||
|
(payload) => {
|
||||||
|
const event = payload;
|
||||||
|
if (suggestions !== null && suggestions.size && selectedSuggestion !== null) {
|
||||||
|
const newSelectedSuggestion = selectedSuggestion !== 0 ? selectedSuggestion - 1 : suggestions.size - 1;
|
||||||
|
setSelectedSuggestion(newSelectedSuggestion);
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
COMMAND_PRIORITY_LOW,
|
||||||
|
),
|
||||||
|
editor.registerCommand<KeyboardEvent>(
|
||||||
|
KEY_ARROW_DOWN_COMMAND,
|
||||||
|
(payload) => {
|
||||||
|
const event = payload;
|
||||||
|
if (suggestions !== null && suggestions.size && selectedSuggestion !== null) {
|
||||||
|
const newSelectedSuggestion = selectedSuggestion !== suggestions.size - 1 ? selectedSuggestion + 1 : 0;
|
||||||
|
setSelectedSuggestion(newSelectedSuggestion);
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
COMMAND_PRIORITY_LOW,
|
||||||
|
),
|
||||||
|
editor.registerCommand<KeyboardEvent>(
|
||||||
|
KEY_TAB_COMMAND,
|
||||||
|
(payload) => {
|
||||||
|
const event = payload;
|
||||||
|
if (suggestions !== null && suggestions.size && selectedSuggestion !== null) {
|
||||||
|
const newSelectedSuggestion = event.shiftKey
|
||||||
|
? (selectedSuggestion !== 0 ? selectedSuggestion - 1 : suggestions.size - 1)
|
||||||
|
: (selectedSuggestion !== suggestions.size - 1 ? selectedSuggestion + 1 : 0);
|
||||||
|
setSelectedSuggestion(newSelectedSuggestion);
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
COMMAND_PRIORITY_LOW,
|
||||||
|
),
|
||||||
|
editor.registerCommand<KeyboardEvent>(
|
||||||
|
KEY_ENTER_COMMAND,
|
||||||
|
(payload) => {
|
||||||
|
const event = payload;
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
onSelectSuggestion(selectedSuggestion);
|
||||||
|
setResolution(null);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
COMMAND_PRIORITY_LOW,
|
||||||
|
),
|
||||||
editor.registerCommand<KeyboardEvent>(
|
editor.registerCommand<KeyboardEvent>(
|
||||||
KEY_ESCAPE_COMMAND,
|
KEY_ESCAPE_COMMAND,
|
||||||
(payload) => {
|
(payload) => {
|
||||||
|
@ -477,7 +542,7 @@ const AutosuggestPlugin = ({
|
||||||
},
|
},
|
||||||
COMMAND_PRIORITY_LOW,
|
COMMAND_PRIORITY_LOW,
|
||||||
),
|
),
|
||||||
), [editor]);
|
), [editor, selectedSuggestion]);
|
||||||
|
|
||||||
return resolution === null || editor === null ? null : (
|
return resolution === null || editor === null ? null : (
|
||||||
<LexicalPopoverMenu
|
<LexicalPopoverMenu
|
||||||
|
|
Loading…
Reference in a new issue