admin管理员组文章数量:1314442
I'm new to lexical.js and don't fully understand how I can listen to different keystroke binations. I want to listen to "Ctrl/Cmd+S" and then fire off a callback (to save data). How can I do that?
With a textarea I can do something like:
const onKeyDown = (event) => {
// "Ctrl" or "Cmd" + "s"
if ((event.ctrlKey || event.metaKey) && event.which === 83) {
// save data
}
}
<textarea onKeyDown={onKeyDown} />
With lexical I've tried to do something like:
const MY_SAVE_COMMAND: LexicalCommand<string> = createCommand('MY_SAVE_COMMAND')
editor.registerCommand<KeyboardEvent>(
MY_SAVE_COMMAND,
(event) => {
console.log('[MY_SAVE_COMMAND] event', event)
return true
},
COMMAND_PRIORITY_HIGH,
)
which does not work. Where do I insert the part where I listen to the keystrokes, or is there a different way of doing this altogether?
I'm new to lexical.js and don't fully understand how I can listen to different keystroke binations. I want to listen to "Ctrl/Cmd+S" and then fire off a callback (to save data). How can I do that?
With a textarea I can do something like:
const onKeyDown = (event) => {
// "Ctrl" or "Cmd" + "s"
if ((event.ctrlKey || event.metaKey) && event.which === 83) {
// save data
}
}
<textarea onKeyDown={onKeyDown} />
With lexical I've tried to do something like:
const MY_SAVE_COMMAND: LexicalCommand<string> = createCommand('MY_SAVE_COMMAND')
editor.registerCommand<KeyboardEvent>(
MY_SAVE_COMMAND,
(event) => {
console.log('[MY_SAVE_COMMAND] event', event)
return true
},
COMMAND_PRIORITY_HIGH,
)
which does not work. Where do I insert the part where I listen to the keystrokes, or is there a different way of doing this altogether?
Share Improve this question asked Feb 3, 2023 at 16:17 caweidmanncaweidmann 4665 silver badges14 bronze badges4 Answers
Reset to default 6Custom mands are more like global event types. Lexical provides a lot out of the box you can listen to, but for things like regular event listeners, what you probably want is to attach the event to the rootElement via editor.registerRootListener
.
You can use a custom plugin to manage attaching and removing this event listener. In the example below, I don't implement onKeyDown
, but you would just like any other normal event handler.
import {useLayoutEffect} from 'react';
import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
function CommandSPlugin() {
const [editor] = useLexicalComposerContext();
useLayoutEffect(() => {
const onKeyDown = () => { /* Your handler logic here */ };
return editor.registerRootListener(
(
rootElement: null | HTMLElement,
prevRootElement: null | HTMLElement,
) => {
if (prevRootElement !== null) {
prevRootElement.removeEventListener('keydown', onKeyDown);
}
if (rootElement !== null) {
rootElement.addEventListener('keydown', onKeyDown);
}
}
);
}, [editor]);
}
// Then later...
const initialConfig = { /* ... */ };
function App() {
return (
<LexicalComposer initialConfig={initialConfig}>
<CommandSPlugin />
<YourEditorHere />
</LexicalComposer>
);
}
Thank you for the answers they helped me a lot. Below the full solution I ended up using. I created a <GlobalEventsPlugin />
with a SAVE_COMMAND
mand which can then be consumed by any plugin:
// GlobalEventsPlugin.tsx
import { useLayoutEffect } from 'react'
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
import { LexicalCommand, createCommand } from 'lexical'
export const SAVE_COMMAND: LexicalCommand<KeyboardEvent> = createCommand('SAVE_COMMAND')
const GlobalEventsPlugin = () => {
const [editor] = useLexicalComposerContext()
useLayoutEffect(() => {
const onKeyDown = (event: KeyboardEvent) => {
// "Ctrl" or "Cmd" + "s"
if ((event.ctrlKey || event.metaKey) && event.which === 83) {
editor.dispatchCommand(SAVE_COMMAND, event)
}
}
return editor.registerRootListener((rootElement: HTMLElement | null, prevRootElement: HTMLElement | null) => {
if (prevRootElement !== null) {
prevRootElement.removeEventListener('keydown', onKeyDown)
}
if (rootElement !== null) {
rootElement.addEventListener('keydown', onKeyDown)
}
})
}, [editor])
return null
}
export default GlobalEventsPlugin
// Editor.tsx
const initialConfig = { /* ... */ }
function App() {
return (
<LexicalComposer initialConfig={initialConfig}>
<GlobalEventsPlugin />
<YourEditorHere />
</LexicalComposer>
)
}
// Any other context that has access to `editor`
editor.registerCommand(
SAVE_COMMAND,
(event) => {
// Do something with `event`, e.g. `event.preventDefault() && saveData()`
},
COMMAND_PRIORITY_HIGH,
)
Custom mands do not have automatic triggers: you must 'dispatch' them.
From the intro in the docs:
Commands are the munication system used to wire everything together in Lexical. Custom mands can be created using
createCommand()
and dispatched to an editor usingeditor.dispatchCommand(mand, payload)
. Lexical dispatches mands internally when key presses are triggered and when other important signals occur. Commands can also be handled usingeditor.registerCommand(handler, priority)
, and ining mands are propagated through all handlers by priority until a handler stops the propagation (in a similar way to event propagation in the browser).
The built-in mands are dispatched in the same way.
If you look at the LexicalEvents.ts
file (referenced frequently in the docs), you can see in the function onKeyDown
how their keyboard-triggered mands are implemented:
function onKeyDown(event: KeyboardEvent, editor: LexicalEditor): void {
...
const {keyCode, shiftKey, ctrlKey, metaKey, altKey} = event;
if (isMoveForward(keyCode, ctrlKey, altKey, metaKey)) {
dispatchCommand(editor, KEY_ARROW_RIGHT_COMMAND, event);
} else if (isMoveToEnd(keyCode, ctrlKey, shiftKey, altKey, metaKey)) {
dispatchCommand(editor, MOVE_TO_END, event);
} ...
It uses helper functions to check the key and some of the modifier keys to determine if a certain bo was used, and, if so, dispatches the relevant mand.
The pattern of including the original event is noted in the docs for dispatchCommand
:
The
payload
s are typed via thecreateCommand(...)
API, but they're usually a DOMevent
for mands dispatched from an event listener.
Note: if you use Ctrl+S
, you'll need to use preventDefault()
to prevent the browser trying to download the page.
There're two mands you can use:
KEY_DOWN_COMMAND
- Triggered on any key down event.MODIFIER_KEY_COMMAND
– Triggered on key press if any modifier key (Cmd/Ctrl/Alt) is also pressed, which makes it a perfect match for shortcuts.
本文标签: javascriptHow can I listen to a keystroke combination with lexicaljsStack Overflow
版权声明:本文标题:javascript - How can I listen to a keystroke combination with lexical.js? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741970929a2407833.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论