✨(frontend) add divider blocks to the editor
Add a custom block to add a divider in the editor.
This commit is contained in:
@@ -27,12 +27,13 @@ import { randomColor } from '../utils';
|
|||||||
|
|
||||||
import { BlockNoteSuggestionMenu } from './BlockNoteSuggestionMenu';
|
import { BlockNoteSuggestionMenu } from './BlockNoteSuggestionMenu';
|
||||||
import { BlockNoteToolbar } from './BlockNoteToolBar/BlockNoteToolbar';
|
import { BlockNoteToolbar } from './BlockNoteToolBar/BlockNoteToolbar';
|
||||||
import { QuoteBlock } from './custom-blocks';
|
import { DividerBlock, QuoteBlock } from './custom-blocks';
|
||||||
|
|
||||||
export const blockNoteSchema = withPageBreak(
|
export const blockNoteSchema = withPageBreak(
|
||||||
BlockNoteSchema.create({
|
BlockNoteSchema.create({
|
||||||
blockSpecs: {
|
blockSpecs: {
|
||||||
...defaultBlockSpecs,
|
...defaultBlockSpecs,
|
||||||
|
divider: DividerBlock,
|
||||||
quote: QuoteBlock,
|
quote: QuoteBlock,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -11,7 +11,10 @@ import { useTranslation } from 'react-i18next';
|
|||||||
|
|
||||||
import { DocsBlockSchema } from '../types';
|
import { DocsBlockSchema } from '../types';
|
||||||
|
|
||||||
import { getQuoteReactSlashMenuItems } from './custom-blocks';
|
import {
|
||||||
|
getDividerReactSlashMenuItems,
|
||||||
|
getQuoteReactSlashMenuItems,
|
||||||
|
} from './custom-blocks';
|
||||||
|
|
||||||
export const BlockNoteSuggestionMenu = () => {
|
export const BlockNoteSuggestionMenu = () => {
|
||||||
const editor = useBlockNoteEditor<DocsBlockSchema>();
|
const editor = useBlockNoteEditor<DocsBlockSchema>();
|
||||||
@@ -26,6 +29,7 @@ export const BlockNoteSuggestionMenu = () => {
|
|||||||
getDefaultReactSlashMenuItems(editor),
|
getDefaultReactSlashMenuItems(editor),
|
||||||
getPageBreakReactSlashMenuItems(editor),
|
getPageBreakReactSlashMenuItems(editor),
|
||||||
getQuoteReactSlashMenuItems(editor, t, basicBlocksName),
|
getQuoteReactSlashMenuItems(editor, t, basicBlocksName),
|
||||||
|
getDividerReactSlashMenuItems(editor, t, basicBlocksName),
|
||||||
),
|
),
|
||||||
query,
|
query,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import { insertOrUpdateBlock } from '@blocknote/core';
|
||||||
|
import { createReactBlockSpec } from '@blocknote/react';
|
||||||
|
import { TFunction } from 'i18next';
|
||||||
|
|
||||||
|
import { Box, Text } from '@/components';
|
||||||
|
import { useCunninghamTheme } from '@/cunningham';
|
||||||
|
|
||||||
|
import { DocsBlockNoteEditor } from '../../types';
|
||||||
|
|
||||||
|
export const DividerBlock = createReactBlockSpec(
|
||||||
|
{
|
||||||
|
type: 'divider',
|
||||||
|
propSchema: {},
|
||||||
|
content: 'none',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
render: () => {
|
||||||
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||||
|
const { colorsTokens } = useCunninghamTheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
as="hr"
|
||||||
|
$width="100%"
|
||||||
|
$background={colorsTokens()['greyscale-300']}
|
||||||
|
$margin="1rem 0"
|
||||||
|
$css={`border: 1px solid ${colorsTokens()['greyscale-300']};`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
export const getDividerReactSlashMenuItems = (
|
||||||
|
editor: DocsBlockNoteEditor,
|
||||||
|
t: TFunction<'translation', undefined>,
|
||||||
|
group: string,
|
||||||
|
) => [
|
||||||
|
{
|
||||||
|
title: t('Divider'),
|
||||||
|
onItemClick: () => {
|
||||||
|
insertOrUpdateBlock(editor, {
|
||||||
|
type: 'divider',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
aliases: ['divider', 'hr', 'horizontal rule', 'line', 'separator'],
|
||||||
|
group,
|
||||||
|
icon: (
|
||||||
|
<Text $isMaterialIcon $size="18px">
|
||||||
|
remove
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
subtext: t('Add a horizontal line'),
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -13,7 +13,6 @@ export const QuoteBlock = createReactBlockSpec(
|
|||||||
type: 'quote',
|
type: 'quote',
|
||||||
propSchema: {
|
propSchema: {
|
||||||
textAlignment: defaultProps.textAlignment,
|
textAlignment: defaultProps.textAlignment,
|
||||||
textColor: defaultProps.textColor,
|
|
||||||
},
|
},
|
||||||
content: 'inline',
|
content: 'inline',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
|
export * from './DividerBlock';
|
||||||
export * from './QuoteBlock';
|
export * from './QuoteBlock';
|
||||||
|
|||||||
@@ -10,10 +10,6 @@ export const cssEditor = (readonly: boolean) => css`
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bn-side-menu[data-block-type='quote'] {
|
|
||||||
height: 46px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.collaboration-cursor-custom__base {
|
.collaboration-cursor-custom__base {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
@@ -49,6 +45,9 @@ export const cssEditor = (readonly: boolean) => css`
|
|||||||
clip-path: polygon(0 0, 100% 0%, 100% 100%, 0% 100%);
|
clip-path: polygon(0 0, 100% 0%, 100% 100%, 0% 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Side menu
|
||||||
|
*/
|
||||||
.bn-side-menu[data-block-type='heading'][data-level='1'] {
|
.bn-side-menu[data-block-type='heading'][data-level='1'] {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
}
|
}
|
||||||
@@ -58,6 +57,13 @@ export const cssEditor = (readonly: boolean) => css`
|
|||||||
.bn-side-menu[data-block-type='heading'][data-level='3'] {
|
.bn-side-menu[data-block-type='heading'][data-level='3'] {
|
||||||
height: 35px;
|
height: 35px;
|
||||||
}
|
}
|
||||||
|
.bn-side-menu[data-block-type='quote'] {
|
||||||
|
height: 46px;
|
||||||
|
}
|
||||||
|
.bn-side-menu[data-block-type='divider'] {
|
||||||
|
height: 38px;
|
||||||
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 1.875rem;
|
font-size: 1.875rem;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user