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,12 +1,22 @@
import { BlockNoteEditor } from '@blocknote/core';
import { BlockNoteView } from '@blocknote/react';
import { ClipboardEvent } from 'react';
import { filterSuggestionItems } from '@blocknote/core';
import { BlockNoteView, SuggestionMenuController } from '@blocknote/react';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { blockSchema } from '@/activities/blocks/schema';
import { getSlashMenu } from '@/activities/blocks/slashMenu';
import {
CustomSlashMenu,
SuggestionItem,
} from '@/ui/input/editor/components/CustomSlashMenu';
interface BlockEditorProps {
editor: BlockNoteEditor;
editor: typeof blockSchema.BlockNoteEditor;
onFocus?: () => void;
onBlur?: () => void;
onPaste?: (event: ClipboardEvent) => void;
onChange?: () => void;
}
const StyledEditor = styled.div`
@ -22,7 +32,13 @@ const StyledEditor = styled.div`
}
`;
export const BlockEditor = ({ editor, onFocus, onBlur }: BlockEditorProps) => {
export const BlockEditor = ({
editor,
onFocus,
onBlur,
onChange,
onPaste,
}: BlockEditorProps) => {
const theme = useTheme();
const blockNoteTheme = theme.name === 'light' ? 'light' : 'dark';
@ -34,14 +50,33 @@ export const BlockEditor = ({ editor, onFocus, onBlur }: BlockEditorProps) => {
onBlur?.();
};
const handleChange = () => {
onChange?.();
};
const handlePaste = (event: ClipboardEvent) => {
onPaste?.(event);
};
return (
<StyledEditor>
<BlockNoteView
onFocus={handleFocus}
onBlur={handleBlur}
onPaste={handlePaste}
onChange={handleChange}
editor={editor}
theme={blockNoteTheme}
/>
slashMenu={false}
>
<SuggestionMenuController
triggerCharacter={'/'}
getItems={async (query) =>
filterSuggestionItems<SuggestionItem>(getSlashMenu(editor), query)
}
suggestionMenuComponent={CustomSlashMenu}
/>
</BlockNoteView>
</StyledEditor>
);
};

View File

@ -0,0 +1,42 @@
import { SuggestionMenuProps } from '@blocknote/react';
import styled from '@emotion/styled';
import { IconComponent } from '@/ui/display/icon/types/IconComponent';
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { MenuItemSuggestion } from '@/ui/navigation/menu-item/components/MenuItemSuggestion';
export type SuggestionItem = {
title: string;
onItemClick: () => void;
aliases?: string[];
Icon?: IconComponent;
};
type CustomSlashMenuProps = SuggestionMenuProps<SuggestionItem>;
const StyledSlashMenu = styled.div`
* {
box-sizing: content-box;
}
`;
export const CustomSlashMenu = (props: CustomSlashMenuProps) => {
return (
<StyledSlashMenu>
<DropdownMenu style={{ zIndex: 2001 }}>
<DropdownMenuItemsContainer>
{props.items.map((item, index) => (
<MenuItemSuggestion
key={item.title}
onClick={() => item.onItemClick()}
text={item.title}
LeftIcon={item.Icon}
selected={props.selectedIndex === index}
/>
))}
</DropdownMenuItemsContainer>
</DropdownMenu>
</StyledSlashMenu>
);
};