🔥(frontend) remove Quote custom block
Last Blocknote upgrade included a Quote block, better to use their built-in one.
This commit is contained in:
@@ -235,7 +235,7 @@ test.describe('Doc Export', () => {
|
|||||||
// Trigger slash menu to show menu
|
// Trigger slash menu to show menu
|
||||||
await editor.click();
|
await editor.click();
|
||||||
await editor.fill('/');
|
await editor.fill('/');
|
||||||
await page.getByText('Add a quote block').click();
|
await page.getByText('Quote or excerpt').click();
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
editor.locator('.bn-block-content[data-content-type="quote"]'),
|
editor.locator('.bn-block-content[data-content-type="quote"]'),
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
BlockNoteSchema,
|
BlockNoteSchema,
|
||||||
Dictionary,
|
|
||||||
defaultBlockSpecs,
|
defaultBlockSpecs,
|
||||||
locales,
|
|
||||||
withPageBreak,
|
withPageBreak,
|
||||||
} from '@blocknote/core';
|
} from '@blocknote/core';
|
||||||
import '@blocknote/core/fonts/inter.css';
|
import '@blocknote/core/fonts/inter.css';
|
||||||
|
import * as locales from '@blocknote/core/locales';
|
||||||
import { BlockNoteView } from '@blocknote/mantine';
|
import { BlockNoteView } from '@blocknote/mantine';
|
||||||
import '@blocknote/mantine/style.css';
|
import '@blocknote/mantine/style.css';
|
||||||
import { useCreateBlockNote } from '@blocknote/react';
|
import { useCreateBlockNote } from '@blocknote/react';
|
||||||
@@ -27,14 +26,13 @@ import { randomColor } from '../utils';
|
|||||||
|
|
||||||
import { BlockNoteSuggestionMenu } from './BlockNoteSuggestionMenu';
|
import { BlockNoteSuggestionMenu } from './BlockNoteSuggestionMenu';
|
||||||
import { BlockNoteToolbar } from './BlockNoteToolBar/BlockNoteToolbar';
|
import { BlockNoteToolbar } from './BlockNoteToolBar/BlockNoteToolbar';
|
||||||
import { DividerBlock, QuoteBlock } from './custom-blocks';
|
import { DividerBlock } from './custom-blocks';
|
||||||
|
|
||||||
export const blockNoteSchema = withPageBreak(
|
export const blockNoteSchema = withPageBreak(
|
||||||
BlockNoteSchema.create({
|
BlockNoteSchema.create({
|
||||||
blockSpecs: {
|
blockSpecs: {
|
||||||
...defaultBlockSpecs,
|
...defaultBlockSpecs,
|
||||||
divider: DividerBlock,
|
divider: DividerBlock,
|
||||||
quote: QuoteBlock,
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -112,7 +110,7 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
|
|||||||
},
|
},
|
||||||
showCursorLabels: showCursorLabels as 'always' | 'activity',
|
showCursorLabels: showCursorLabels as 'always' | 'activity',
|
||||||
},
|
},
|
||||||
dictionary: locales[lang as keyof typeof locales] as Dictionary,
|
dictionary: locales[lang as keyof typeof locales],
|
||||||
uploadFile,
|
uploadFile,
|
||||||
schema: blockNoteSchema,
|
schema: blockNoteSchema,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,10 +11,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
|
|
||||||
import { DocsBlockSchema } from '../types';
|
import { DocsBlockSchema } from '../types';
|
||||||
|
|
||||||
import {
|
import { getDividerReactSlashMenuItems } from './custom-blocks';
|
||||||
getDividerReactSlashMenuItems,
|
|
||||||
getQuoteReactSlashMenuItems,
|
|
||||||
} from './custom-blocks';
|
|
||||||
|
|
||||||
export const BlockNoteSuggestionMenu = () => {
|
export const BlockNoteSuggestionMenu = () => {
|
||||||
const editor = useBlockNoteEditor<DocsBlockSchema>();
|
const editor = useBlockNoteEditor<DocsBlockSchema>();
|
||||||
@@ -28,7 +25,6 @@ export const BlockNoteSuggestionMenu = () => {
|
|||||||
combineByGroup(
|
combineByGroup(
|
||||||
getDefaultReactSlashMenuItems(editor),
|
getDefaultReactSlashMenuItems(editor),
|
||||||
getPageBreakReactSlashMenuItems(editor),
|
getPageBreakReactSlashMenuItems(editor),
|
||||||
getQuoteReactSlashMenuItems(editor, t, basicBlocksName),
|
|
||||||
getDividerReactSlashMenuItems(editor, t, basicBlocksName),
|
getDividerReactSlashMenuItems(editor, t, basicBlocksName),
|
||||||
),
|
),
|
||||||
query,
|
query,
|
||||||
|
|||||||
@@ -6,12 +6,9 @@ import {
|
|||||||
useDictionary,
|
useDictionary,
|
||||||
} from '@blocknote/react';
|
} from '@blocknote/react';
|
||||||
import React, { JSX, useCallback, useMemo, useState } from 'react';
|
import React, { JSX, useCallback, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
import { useConfig } from '@/core/config/api';
|
import { useConfig } from '@/core/config/api';
|
||||||
|
|
||||||
import { getQuoteFormattingToolbarItems } from '../custom-blocks';
|
|
||||||
|
|
||||||
import { AIGroupButton } from './AIButton';
|
import { AIGroupButton } from './AIButton';
|
||||||
import { FileDownloadButton } from './FileDownloadButton';
|
import { FileDownloadButton } from './FileDownloadButton';
|
||||||
import { MarkdownButton } from './MarkdownButton';
|
import { MarkdownButton } from './MarkdownButton';
|
||||||
@@ -21,13 +18,11 @@ export const BlockNoteToolbar = () => {
|
|||||||
const dict = useDictionary();
|
const dict = useDictionary();
|
||||||
const [confirmOpen, setIsConfirmOpen] = useState(false);
|
const [confirmOpen, setIsConfirmOpen] = useState(false);
|
||||||
const [onConfirm, setOnConfirm] = useState<() => void | Promise<void>>();
|
const [onConfirm, setOnConfirm] = useState<() => void | Promise<void>>();
|
||||||
const { t } = useTranslation();
|
|
||||||
const { data: conf } = useConfig();
|
const { data: conf } = useConfig();
|
||||||
|
|
||||||
const toolbarItems = useMemo(() => {
|
const toolbarItems = useMemo(() => {
|
||||||
const toolbarItems = getFormattingToolbarItems([
|
const toolbarItems = getFormattingToolbarItems([
|
||||||
...blockTypeSelectItems(dict),
|
...blockTypeSelectItems(dict),
|
||||||
getQuoteFormattingToolbarItems(t),
|
|
||||||
]);
|
]);
|
||||||
const fileDownloadButtonIndex = toolbarItems.findIndex(
|
const fileDownloadButtonIndex = toolbarItems.findIndex(
|
||||||
(item) =>
|
(item) =>
|
||||||
@@ -51,7 +46,7 @@ export const BlockNoteToolbar = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return toolbarItems as JSX.Element[];
|
return toolbarItems as JSX.Element[];
|
||||||
}, [dict, t]);
|
}, [dict]);
|
||||||
|
|
||||||
const formattingToolbar = useCallback(() => {
|
const formattingToolbar = useCallback(() => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
import { defaultProps, insertOrUpdateBlock } from '@blocknote/core';
|
|
||||||
import { BlockTypeSelectItem, createReactBlockSpec } from '@blocknote/react';
|
|
||||||
import { TFunction } from 'i18next';
|
|
||||||
|
|
||||||
import { Box, Icon } from '@/components';
|
|
||||||
import { useCunninghamTheme } from '@/cunningham';
|
|
||||||
|
|
||||||
import { DocsBlockNoteEditor } from '../../types';
|
|
||||||
|
|
||||||
export const QuoteBlock = createReactBlockSpec(
|
|
||||||
{
|
|
||||||
type: 'quote',
|
|
||||||
propSchema: {
|
|
||||||
textAlignment: defaultProps.textAlignment,
|
|
||||||
},
|
|
||||||
content: 'inline',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
render: (props) => {
|
|
||||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
||||||
const { colorsTokens } = useCunninghamTheme();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box
|
|
||||||
as="blockquote"
|
|
||||||
className="inline-content"
|
|
||||||
$margin="0 0 1rem 0"
|
|
||||||
$padding="0.5rem 1rem"
|
|
||||||
style={{
|
|
||||||
borderLeft: `4px solid ${colorsTokens['greyscale-300']}`,
|
|
||||||
fontStyle: 'italic',
|
|
||||||
flexGrow: 1,
|
|
||||||
}}
|
|
||||||
$color="var(--c--theme--colors--greyscale-500)"
|
|
||||||
ref={props.contentRef}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
export const getQuoteReactSlashMenuItems = (
|
|
||||||
editor: DocsBlockNoteEditor,
|
|
||||||
t: TFunction<'translation', undefined>,
|
|
||||||
group: string,
|
|
||||||
) => [
|
|
||||||
{
|
|
||||||
title: t('Quote'),
|
|
||||||
onItemClick: () => {
|
|
||||||
insertOrUpdateBlock(editor, {
|
|
||||||
type: 'quote',
|
|
||||||
});
|
|
||||||
},
|
|
||||||
aliases: ['quote', 'blockquote', 'citation'],
|
|
||||||
group,
|
|
||||||
icon: <Icon iconName="format_quote" $size="18px" />,
|
|
||||||
subtext: t('Add a quote block'),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const getQuoteFormattingToolbarItems = (
|
|
||||||
t: TFunction<'translation', undefined>,
|
|
||||||
): BlockTypeSelectItem => ({
|
|
||||||
name: t('Quote'),
|
|
||||||
type: 'quote',
|
|
||||||
icon: () => <Icon iconName="format_quote" $size="16px" />,
|
|
||||||
isSelected: (block) => block.type === 'quote',
|
|
||||||
});
|
|
||||||
@@ -1,2 +1 @@
|
|||||||
export * from './DividerBlock';
|
export * from './DividerBlock';
|
||||||
export * from './QuoteBlock';
|
|
||||||
|
|||||||
@@ -57,9 +57,6 @@ 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'] {
|
.bn-side-menu[data-block-type='divider'] {
|
||||||
height: 38px;
|
height: 38px;
|
||||||
}
|
}
|
||||||
@@ -84,11 +81,19 @@ export const cssEditor = (readonly: boolean) => css`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.bn-editor {
|
& .bn-editor {
|
||||||
color: var(--c--theme--colors--greyscale-700);
|
color: var(--c--theme--colors--greyscale-700);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quotes
|
||||||
|
*/
|
||||||
|
blockquote {
|
||||||
|
border-left: 4px solid var(--c--theme--colors--greyscale-300);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.bn-block-outer:not(:first-child) {
|
& .bn-block-outer:not(:first-child) {
|
||||||
&:has(h1) {
|
&:has(h1) {
|
||||||
margin-top: 32px;
|
margin-top: 32px;
|
||||||
}
|
}
|
||||||
@@ -105,12 +110,6 @@ export const cssEditor = (readonly: boolean) => css`
|
|||||||
padding: 2px;
|
padding: 2px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
& .bn-inline-content {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.bn-block-content[data-content-type='checkListItem'] > div {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (width <= 768px) {
|
@media screen and (width <= 768px) {
|
||||||
& .bn-editor {
|
& .bn-editor {
|
||||||
|
|||||||
Reference in New Issue
Block a user