Blocknote custom slash menu (#4517)

blocknote v12, cleaned up blockschema & specs, added custom slash menu
This commit is contained in:
brendanlaschke
2024-03-20 08:38:05 +01:00
committed by GitHub
parent 35d41e38c8
commit 017b09ba35
11 changed files with 308 additions and 183 deletions

View File

@ -1,6 +1,5 @@
import { useCallback, useMemo } from 'react';
import { BlockNoteEditor } from '@blocknote/core';
import { useBlockNote } from '@blocknote/react';
import { ClipboardEvent, useCallback, useMemo } from 'react';
import { useCreateBlockNote } from '@blocknote/react';
import styled from '@emotion/styled';
import { isArray, isNonEmptyString } from '@sniptt/guards';
import { useRecoilCallback, useRecoilState } from 'recoil';
@ -8,6 +7,7 @@ import { Key } from 'ts-key-enum';
import { useDebouncedCallback } from 'use-debounce';
import { v4 } from 'uuid';
import { blockSchema } from '@/activities/blocks/schema';
import { useUpsertActivity } from '@/activities/hooks/useUpsertActivity';
import { activityBodyFamilyState } from '@/activities/states/activityBodyFamilyState';
import { activityTitleHasBeenSetFamilyState } from '@/activities/states/activityTitleHasBeenSetFamilyState';
@ -28,8 +28,6 @@ import { FileFolder, useUploadFileMutation } from '~/generated/graphql';
import { isDefined } from '~/utils/isDefined';
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
import { blockSpecs } from '../blocks/blockSpecs';
import { getSlashMenu } from '../blocks/slashMenu';
import { getFileType } from '../files/utils/getFileType';
import '@blocknote/react/style.css';
@ -121,8 +119,6 @@ export const ActivityBodyEditor = ({
canCreateActivityState(),
);
const slashMenuItems = getSlashMenu();
const [uploadFile] = useUploadFileMutation();
const handleUploadAttachment = async (file: File): Promise<string> => {
@ -216,8 +212,8 @@ export const ActivityBodyEditor = ({
const handleBodyChangeDebounced = useDebouncedCallback(handleBodyChange, 500);
const handleEditorChange = (newEditor: BlockNoteEditor) => {
const newStringifiedBody = JSON.stringify(newEditor.topLevelBlocks) ?? '';
const handleEditorChange = () => {
const newStringifiedBody = JSON.stringify(editor.document) ?? '';
setActivityBody(newStringifiedBody);
@ -238,16 +234,11 @@ export const ActivityBodyEditor = ({
}
}, [activity, activityBody]);
const editor: BlockNoteEditor<typeof blockSpecs> | null = useBlockNote({
const editor = useCreateBlockNote({
initialContent: initialBody,
domAttributes: { editor: { class: 'editor' } },
onEditorContentChange: handleEditorChange,
slashMenuItems,
blockSpecs: blockSpecs,
schema: blockSchema,
uploadFile: handleUploadAttachment,
onEditorReady: (editor: BlockNoteEditor) => {
editor.domElement.addEventListener('paste', handleImagePaste);
},
});
const handleImagePaste = async (event: ClipboardEvent) => {
@ -361,7 +352,7 @@ export const ActivityBodyEditor = ({
const newBlockId = v4();
const newBlock = {
id: newBlockId,
type: 'paragraph',
type: 'paragraph' as const,
content: keyboardEvent.key,
};
editor.insertBlocks([newBlock], blockIdentifier, 'after');
@ -387,6 +378,8 @@ export const ActivityBodyEditor = ({
<BlockEditor
onFocus={handleBlockEditorFocus}
onBlur={handlerBlockEditorBlur}
onPaste={handleImagePaste}
onChange={handleEditorChange}
editor={editor}
/>
</StyledBlockNoteStyledContainer>