1 import {COMMAND_PRIORITY_HIGH, FORMAT_TEXT_COMMAND, KEY_ENTER_COMMAND, LexicalEditor} from "lexical";
3 cycleSelectionCalloutFormats,
5 toggleSelectionAsBlockquote,
6 toggleSelectionAsHeading,
7 toggleSelectionAsParagraph
8 } from "../utils/formats";
9 import {HeadingTagType} from "@lexical/rich-text";
11 function headerHandler(editor: LexicalEditor, tag: HeadingTagType): boolean {
12 toggleSelectionAsHeading(editor, tag);
16 function wrapFormatAction(formatAction: (editor: LexicalEditor) => any): ShortcutAction {
17 return (editor: LexicalEditor) => {
23 function toggleInlineCode(editor: LexicalEditor): boolean {
24 editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'code');
28 type ShortcutAction = (editor: LexicalEditor) => boolean;
30 const actionsByKeys: Record<string, ShortcutAction> = {
33 window.$events.emit('editor-save-draft');
37 window.$events.emit('editor-save-page');
40 'ctrl+1': (editor) => headerHandler(editor, 'h1'),
41 'ctrl+2': (editor) => headerHandler(editor, 'h2'),
42 'ctrl+3': (editor) => headerHandler(editor, 'h3'),
43 'ctrl+4': (editor) => headerHandler(editor, 'h4'),
44 'ctrl+5': wrapFormatAction(toggleSelectionAsParagraph),
45 'ctrl+d': wrapFormatAction(toggleSelectionAsParagraph),
46 'ctrl+6': wrapFormatAction(toggleSelectionAsBlockquote),
47 'ctrl+q': wrapFormatAction(toggleSelectionAsBlockquote),
48 'ctrl+7': wrapFormatAction(formatCodeBlock),
49 'ctrl+e': wrapFormatAction(formatCodeBlock),
50 'ctrl+8': toggleInlineCode,
51 'ctrl+shift+e': toggleInlineCode,
52 'ctrl+9': wrapFormatAction(cycleSelectionCalloutFormats),
59 function createKeyDownListener(editor: LexicalEditor): (e: KeyboardEvent) => void {
60 return (event: KeyboardEvent) => {
61 // TODO - Mac Cmd support
62 const combo = `${event.ctrlKey ? 'ctrl+' : ''}${event.shiftKey ? 'shift+' : ''}${event.key}`.toLowerCase();
63 console.log(`pressed: ${combo}`);
64 if (actionsByKeys[combo]) {
65 const handled = actionsByKeys[combo](editor);
67 event.stopPropagation();
68 event.preventDefault();
74 function overrideDefaultCommands(editor: LexicalEditor) {
75 // Prevent default ctrl+enter command
76 editor.registerCommand(KEY_ENTER_COMMAND, (event) => {
77 return event?.ctrlKey ? true : false
78 }, COMMAND_PRIORITY_HIGH);
81 export function registerShortcuts(editor: LexicalEditor) {
82 const listener = createKeyDownListener(editor);
83 overrideDefaultCommands(editor);
85 return editor.registerRootListener((rootElement: null | HTMLElement, prevRootElement: null | HTMLElement) => {
86 // add the listener to the current root element
87 rootElement?.addEventListener('keydown', listener);
88 // remove the listener from the old root element
89 prevRootElement?.removeEventListener('keydown', listener);