Skip to content

Commit dc0988e

Browse files
committed
✨(frontend) create editor shortcuts hook
We created the editor shortcuts hook to handle the shortcuts for the editor. We implemented the following shortcuts: - "@" to open the interlinking inline content
1 parent 5ed6abd commit dc0988e

File tree

6 files changed

+62
-8
lines changed

6 files changed

+62
-8
lines changed

src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx

+2-3
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@ import { Box, TextErrors } from '@/components';
1919
import { Doc } from '@/docs/doc-management';
2020
import { useAuth } from '@/features/auth';
2121

22-
import { useUploadFile } from '../hook';
23-
import { useHeadings } from '../hook/useHeadings';
24-
import useSaveDoc from '../hook/useSaveDoc';
22+
import { useHeadings, useSaveDoc, useShortcuts, useUploadFile } from '../hook';
2523
import { useEditorStore } from '../stores';
2624
import { cssEditor } from '../styles';
2725
import { randomColor } from '../utils';
@@ -129,6 +127,7 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
129127
[collabName, lang, provider, uploadFile],
130128
);
131129
useHeadings(editor);
130+
useShortcuts(editor);
132131

133132
useEffect(() => {
134133
setEditor(editor);

src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking/InterlinkingSearchInlineContent.tsx

+12-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ export const InterlinkingSearchInlineContent = createReactInlineContentSpec(
1313
{
1414
type: 'interlinkingSearchInline',
1515
propSchema: {
16+
trigger: {
17+
default: '/',
18+
values: ['/', '@'],
19+
},
1620
disabled: {
1721
default: false,
1822
values: [true, false],
@@ -26,7 +30,13 @@ export const InterlinkingSearchInlineContent = createReactInlineContentSpec(
2630
return null;
2731
}
2832

29-
return <SearchPage {...props} contentRef={props.contentRef} />;
33+
return (
34+
<SearchPage
35+
{...props}
36+
trigger={props.inlineContent.props.trigger}
37+
contentRef={props.contentRef}
38+
/>
39+
);
3040
},
3141
},
3242
);
@@ -45,6 +55,7 @@ export const getInterlinkinghMenuItems = (
4555
type: 'interlinkingSearchInline',
4656
props: {
4757
disabled: false,
58+
trigger: '/',
4859
},
4960
},
5061
]);

src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking/SearchPage.tsx

+8-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const inputStyle = css`
3939
`;
4040

4141
type SearchPageProps = {
42+
trigger: string;
4243
updateInlineContent: (
4344
update: PartialCustomInlineContentFromConfig<
4445
{
@@ -47,6 +48,9 @@ type SearchPageProps = {
4748
disabled: {
4849
default: boolean;
4950
};
51+
trigger: {
52+
default: string;
53+
};
5054
};
5155
content: 'styled';
5256
},
@@ -58,6 +62,7 @@ type SearchPageProps = {
5862

5963
export const SearchPage = ({
6064
contentRef,
65+
trigger,
6166
updateInlineContent,
6267
}: SearchPageProps) => {
6368
const { colorsTokens } = useCunninghamTheme();
@@ -99,7 +104,7 @@ export const SearchPage = ({
99104
tabIndex={-1} // Ensure the span is focusable
100105
>
101106
{' '}
102-
/
107+
{trigger}
103108
<Box
104109
as="input"
105110
$padding={{ left: '3px' }}
@@ -118,6 +123,7 @@ export const SearchPage = ({
118123
type: 'interlinkingSearchInline',
119124
props: {
120125
disabled: true,
126+
trigger,
121127
},
122128
});
123129

@@ -174,6 +180,7 @@ export const SearchPage = ({
174180
type: 'interlinkingSearchInline',
175181
props: {
176182
disabled: true,
183+
trigger,
177184
},
178185
});
179186

Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1+
export * from './useHeadings';
12
export * from './useSaveDoc';
3+
export * from './useShortcuts';
24
export * from './useUploadFile';

src/frontend/apps/impress/src/features/docs/doc-editor/hook/useSaveDoc.tsx

+1-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { toBase64 } from '../utils';
1010

1111
const SAVE_INTERVAL = 60000;
1212

13-
const useSaveDoc = (docId: string, yDoc: Y.Doc, canSave: boolean) => {
13+
export const useSaveDoc = (docId: string, yDoc: Y.Doc, canSave: boolean) => {
1414
const { mutate: updateDoc } = useUpdateDoc({
1515
listInvalideQueries: [KEY_LIST_DOC_VERSIONS],
1616
onSuccess: () => {
@@ -92,5 +92,3 @@ const useSaveDoc = (docId: string, yDoc: Y.Doc, canSave: boolean) => {
9292
};
9393
}, [router.events, saveDoc]);
9494
};
95-
96-
export default useSaveDoc;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { useEffect } from 'react';
2+
3+
import { DocsBlockNoteEditor } from '../types';
4+
5+
export const useShortcuts = (editor: DocsBlockNoteEditor) => {
6+
useEffect(() => {
7+
const handleKeyDown = (event: KeyboardEvent) => {
8+
if (event.key === '@' && editor?.isFocused()) {
9+
const selection = window.getSelection();
10+
const previousChar = selection?.anchorNode?.textContent?.charAt(
11+
selection.anchorOffset - 1,
12+
);
13+
14+
if (previousChar !== ' ') {
15+
return;
16+
}
17+
18+
event.preventDefault();
19+
editor.insertInlineContent([
20+
{
21+
type: 'interlinkingSearchInline',
22+
props: {
23+
disabled: false,
24+
trigger: '@',
25+
},
26+
},
27+
]);
28+
}
29+
};
30+
31+
window.addEventListener('keydown', handleKeyDown);
32+
33+
return () => {
34+
window.removeEventListener('keydown', handleKeyDown);
35+
};
36+
}, [editor]);
37+
};

0 commit comments

Comments
 (0)