(frontend) add multi columns support for editor

We add multi columns support for editor,
now you can add columns to your document.
This commit is contained in:
Anthony LC
2025-01-28 16:16:54 +01:00
parent b93b43abe8
commit ef77889d25
11 changed files with 114 additions and 16 deletions
+4
View File
@@ -24,6 +24,10 @@ and this project adheres to
## [2.0.1] - 2025-01-17
## Added
✨(frontend) add multi columns support for editor #533
## Fixed
-🐛(frontend) share modal is shown when you don't have the abilities #557
@@ -366,4 +366,27 @@ test.describe('Doc Editor', () => {
await expect(editor.getByText('Bonjour le monde')).toBeVisible();
});
test('it checks the multi columns', async ({ page, browserName }) => {
await createDoc(page, 'doc-multi-columns', browserName, 1);
await page.locator('.bn-block-outer').last().fill('/');
await page.getByText('Three Columns', { exact: true }).click();
await page.locator('.bn-block-column').first().fill('Column 1');
await page.locator('.bn-block-column').nth(1).fill('Column 2');
await page.locator('.bn-block-column').last().fill('Column 3');
expect(await page.locator('.bn-block-column').count()).toBe(3);
await expect(
page.locator('.bn-block-column[data-node-type="column"]').first(),
).toHaveText('Column 1');
await expect(
page.locator('.bn-block-column[data-node-type="column"]').nth(1),
).toHaveText('Column 2');
await expect(
page.locator('.bn-block-column[data-node-type="column"]').last(),
).toHaveText('Column 3');
});
});
+1
View File
@@ -18,6 +18,7 @@
"@blocknote/core": "0.21.0",
"@blocknote/mantine": "0.21.0",
"@blocknote/react": "0.21.0",
"@blocknote/xl-multi-column": "0.21.0",
"@blocknote/xl-docx-exporter": "0.21.0",
"@blocknote/xl-pdf-exporter": "0.21.0",
"@gouvfr-lasuite/integration": "1.0.2",
@@ -1,10 +1,24 @@
import { Dictionary, locales } from '@blocknote/core';
import {
Dictionary,
combineByGroup,
filterSuggestionItems,
locales,
} from '@blocknote/core';
import '@blocknote/core/fonts/inter.css';
import { BlockNoteView } from '@blocknote/mantine';
import '@blocknote/mantine/style.css';
import { useCreateBlockNote } from '@blocknote/react';
import {
SuggestionMenuController,
getDefaultReactSlashMenuItems,
useCreateBlockNote,
} from '@blocknote/react';
import {
getMultiColumnSlashMenuItems,
multiColumnDropCursor,
locales as multiColumnLocales,
} from '@blocknote/xl-multi-column';
import { HocuspocusProvider } from '@hocuspocus/provider';
import { useEffect } from 'react';
import { useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { css } from 'styled-components';
import * as Y from 'yjs';
@@ -17,7 +31,7 @@ import { useUploadFile } from '../hook';
import { useHeadings } from '../hook/useHeadings';
import useSaveDoc from '../hook/useSaveDoc';
import { useEditorStore } from '../stores';
import { randomColor } from '../utils';
import { blockNoteWithMultiColumn, randomColor } from '../utils';
import { BlockNoteToolbar } from './BlockNoteToolbar';
@@ -163,8 +177,14 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
return cursor;
},
},
dictionary: locales[lang as keyof typeof locales] as Dictionary,
dictionary: {
...(locales[lang as keyof typeof locales] as Dictionary),
multi_column:
multiColumnLocales[lang as keyof typeof multiColumnLocales],
},
uploadFile,
schema: blockNoteWithMultiColumn,
dropCursor: multiColumnDropCursor,
},
[collabName, lang, provider, uploadFile],
);
@@ -178,6 +198,18 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
};
}, [setEditor, editor]);
const getSlashMenuItems = useMemo(() => {
// eslint-disable-next-line @typescript-eslint/require-await
return async (query: string) =>
filterSuggestionItems(
combineByGroup(
getDefaultReactSlashMenuItems(editor),
getMultiColumnSlashMenuItems(editor),
),
query,
);
}, [editor]);
return (
<Box
$padding={{ top: 'md' }}
@@ -199,7 +231,12 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
formattingToolbar={false}
editable={!readOnly}
theme="light"
slashMenu={false}
>
<SuggestionMenuController
triggerCharacter="/"
getItems={getSlashMenuItems}
/>
<BlockNoteToolbar />
</BlockNoteView>
</Box>
@@ -225,6 +262,7 @@ export const BlockNoteEditorVersion = ({
},
provider: undefined,
},
schema: blockNoteWithMultiColumn,
},
[initialContent],
);
@@ -1,9 +1,9 @@
import { BlockNoteEditor } from '@blocknote/core';
import { useEffect } from 'react';
import { useHeadingStore } from '../stores';
import { DocsBlockNoteEditor } from '../types';
export const useHeadings = (editor: BlockNoteEditor) => {
export const useHeadings = (editor: DocsBlockNoteEditor) => {
const { setHeadings, resetHeadings } = useHeadingStore();
useEffect(() => {
@@ -1,9 +1,10 @@
import { BlockNoteEditor } from '@blocknote/core';
import { create } from 'zustand';
import { DocsBlockNoteEditor } from '../types';
export interface UseEditorstore {
editor?: BlockNoteEditor;
setEditor: (editor: BlockNoteEditor | undefined) => void;
editor?: DocsBlockNoteEditor;
setEditor: (editor: DocsBlockNoteEditor | undefined) => void;
}
export const useEditorStore = create<UseEditorstore>((set) => ({
@@ -1,7 +1,6 @@
import { BlockNoteEditor } from '@blocknote/core';
import { create } from 'zustand';
import { HeadingBlock } from '../types';
import { DocsBlockNoteEditor, HeadingBlock } from '../types';
const recursiveTextContent = (content: HeadingBlock['content']): string => {
if (!content) {
@@ -21,7 +20,7 @@ const recursiveTextContent = (content: HeadingBlock['content']): string => {
export interface UseHeadingStore {
headings: HeadingBlock[];
setHeadings: (editor: BlockNoteEditor) => void;
setHeadings: (editor: DocsBlockNoteEditor) => void;
resetHeadings: () => void;
}
@@ -1,3 +1,7 @@
import { BlockNoteEditor } from '@blocknote/core';
import { blockNoteWithMultiColumn } from './utils';
export interface DocAttachment {
file: string;
}
@@ -12,3 +16,9 @@ export type HeadingBlock = {
level: number;
};
};
export type DocsBlockNoteEditor = BlockNoteEditor<
typeof blockNoteWithMultiColumn.blockSchema,
typeof blockNoteWithMultiColumn.inlineContentSchema,
typeof blockNoteWithMultiColumn.styleSchema
>;
@@ -1,3 +1,6 @@
import { BlockNoteSchema } from '@blocknote/core';
import { withMultiColumn } from '@blocknote/xl-multi-column';
export const randomColor = () => {
const randomInt = (min: number, max: number) => {
return Math.floor(Math.random() * (max - min + 1)) + min;
@@ -25,3 +28,7 @@ function hslToHex(h: number, s: number, l: number) {
export const toBase64 = (str: Uint8Array) =>
Buffer.from(str).toString('base64');
export const blockNoteWithMultiColumn = withMultiColumn(
BlockNoteSchema.create(),
);
@@ -1,8 +1,8 @@
import { BlockNoteEditor } from '@blocknote/core';
import { useState } from 'react';
import { BoxButton, Text } from '@/components';
import { useCunninghamTheme } from '@/cunningham';
import { DocsBlockNoteEditor } from '@/features/docs/doc-editor';
import { useResponsiveStore } from '@/stores';
const leftPaddingMap: { [key: number]: string } = {
@@ -17,7 +17,7 @@ export type HeadingsHighlight = {
}[];
interface HeadingProps {
editor: BlockNoteEditor;
editor: DocsBlockNoteEditor;
level: number;
text: string;
headingId: string;
+16 -1
View File
@@ -1146,6 +1146,21 @@
docx "^9.0.2"
sharp "^0.33.5"
"@blocknote/[email protected]":
version "0.21.0"
resolved "https://registry.yarnpkg.com/@blocknote/xl-multi-column/-/xl-multi-column-0.21.0.tgz#913bf07d6fb2c5445a6e4a375646997035e351e2"
integrity sha512-nWRZCP14pcbbA4F274kBL4UXI6RNmxZRKynsqACBPC/B3bns8GDh0GWMEPz/KN/6kuOkm/bYHHCkglDlEIEF1Q==
dependencies:
"@blocknote/core" "^0.21.0"
"@blocknote/react" "^0.21.0"
"@tiptap/core" "^2.7.1"
prosemirror-model "^1.23.0"
prosemirror-state "^1.4.3"
prosemirror-tables "^1.3.7"
prosemirror-transform "^1.9.0"
prosemirror-view "^1.33.7"
react-icons "^5.2.1"
"@blocknote/[email protected]":
version "0.21.0"
resolved "https://registry.yarnpkg.com/@blocknote/xl-pdf-exporter/-/xl-pdf-exporter-0.21.0.tgz#6e05b20ba331cdd17162f7d42678bdfc54e9914f"
@@ -11478,7 +11493,7 @@ prosemirror-state@^1.0.0, prosemirror-state@^1.2.2, prosemirror-state@^1.4.3:
prosemirror-transform "^1.0.0"
prosemirror-view "^1.27.0"
prosemirror-tables@^1.6.1:
prosemirror-tables@^1.3.7, prosemirror-tables@^1.6.1:
version "1.6.2"
resolved "https://registry.yarnpkg.com/prosemirror-tables/-/prosemirror-tables-1.6.2.tgz#cec9e9ac6ecf81d67147c19ab39125d56c8351ae"
integrity sha512-97dKocVLrEVTQjZ4GBLdrrMw7Gv3no8H8yMwf5IRM9OoHrzbWpcH5jJxYgNQIRCtdIqwDctT1HdMHrGTiwp1dQ==