Skip to content

Commit

Permalink
✨(frontend) add multi columns support for editor
Browse files Browse the repository at this point in the history
We add multi columns support for editor,
now you can add columns to your document.
  • Loading branch information
AntoLC committed Jan 2, 2025
1 parent 2491ad7 commit 0005fbd
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 23 deletions.
23 changes: 23 additions & 0 deletions src/frontend/apps/e2e/__tests__/app-impress/doc-editor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -351,4 +351,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 change: 1 addition & 0 deletions src/frontend/apps/impress/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@blocknote/core": "0.22.0",
"@blocknote/mantine": "0.22.0",
"@blocknote/react": "0.22.0",
"@blocknote/xl-multi-column": "0.22.0",
"@gouvfr-lasuite/integration": "1.0.2",
"@hocuspocus/provider": "2.15.0",
"@openfun/cunningham-react": "2.9.4",
Expand Down
Original file line number Diff line number Diff line change
@@ -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 React, { useEffect } from 'react';
import React, { useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import * as Y from 'yjs';

Expand All @@ -16,7 +30,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';

Expand Down Expand Up @@ -120,8 +134,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],
);
Expand Down Expand Up @@ -152,6 +172,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 $css={cssEditor(readOnly)}>
{errorAttachment && (
Expand All @@ -169,7 +201,12 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
formattingToolbar={false}
editable={!readOnly}
theme="light"
slashMenu={false}
>
<SuggestionMenuController
triggerCharacter="/"
getItems={getSlashMenuItems}
/>
<BlockNoteToolbar />
</BlockNoteView>
</Box>
Expand All @@ -195,6 +232,7 @@ export const BlockNoteEditorVersion = ({
},
provider: undefined,
},
schema: blockNoteWithMultiColumn,
},
[initialContent],
);
Expand Down
Original file line number Diff line number Diff line change
@@ -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(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -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) => ({
Expand Down
Original file line number Diff line number Diff line change
@@ -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) {
Expand All @@ -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;
}

Expand Down
10 changes: 10 additions & 0 deletions src/frontend/apps/impress/src/features/docs/doc-editor/types.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { BlockNoteEditor } from '@blocknote/core';

import { blockNoteWithMultiColumn } from './utils';

export interface DocAttachment {
file: string;
}
Expand All @@ -12,3 +16,9 @@ export type HeadingBlock = {
level: number;
};
};

export type DocsBlockNoteEditor = BlockNoteEditor<
typeof blockNoteWithMultiColumn.blockSchema,
typeof blockNoteWithMultiColumn.inlineContentSchema,
typeof blockNoteWithMultiColumn.styleSchema
>;
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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(),
);
Original file line number Diff line number Diff line change
@@ -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 sizeMap: { [key: number]: string } = {
Expand All @@ -17,7 +17,7 @@ export type HeadingsHighlight = {
}[];

interface HeadingProps {
editor: BlockNoteEditor;
editor: DocsBlockNoteEditor;
level: number;
text: string;
headingId: string;
Expand Down
31 changes: 23 additions & 8 deletions src/frontend/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1075,6 +1075,21 @@
y-protocols "^1.0.6"
yjs "^13.6.15"

"@blocknote/xl-multi-column@^0.22.0":
version "0.22.0"
resolved "https://registry.yarnpkg.com/@blocknote/xl-multi-column/-/xl-multi-column-0.22.0.tgz#495a4dc4080c3fb7b2a4d436653502d1abd1d3f6"
integrity sha512-RcrCbH3VPGojB+R5gFLKQ48c2nnr0AqoiAsdpR3w13FvynRY4qVjq3ZVzpHPfKFs0/2D0YNxhQu4fny9roaazQ==
dependencies:
"@blocknote/core" "^0.22.0"
"@blocknote/react" "^0.22.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"

"@cspotcode/source-map-support@^0.8.0":
version "0.8.1"
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1"
Expand Down Expand Up @@ -4736,7 +4751,7 @@
dependencies:
"@types/node" "*"

"@types/node@*", "@types/[email protected]":
"@types/node@*":
version "22.10.3"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.3.tgz#cdc2a89bf6e5d5e593fad08e83f74d7348d5dd10"
integrity sha512-DifAyw4BkrufCILvD3ucnuN8eydUfc/C1GlyrnI+LK6543w5/L3VeVgf05o3B4fqSXP1dKYLOZsKfutpxPzZrw==
Expand Down Expand Up @@ -4798,7 +4813,7 @@
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb"
integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==

"@types/react-dom@*", "@types/[email protected]":
"@types/react-dom@*":
version "18.3.1"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.1.tgz#1e4654c08a9cdcfb6594c780ac59b55aad42fe07"
integrity sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==
Expand Down Expand Up @@ -4943,7 +4958,7 @@
dependencies:
"@types/yargs-parser" "*"

"@typescript-eslint/eslint-plugin@*", "@typescript-eslint/eslint-plugin@8.19.0", "@typescript-eslint/eslint-plugin@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0":
"@typescript-eslint/eslint-plugin@*", "@typescript-eslint/eslint-plugin@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0":
version "8.19.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.19.0.tgz#2b1e1b791e21d5fc27ddc93884db066444f597b5"
integrity sha512-NggSaEZCdSrFddbctrVjkVZvFC6KGfKfNK0CU7mNK/iKHGKbzT4Wmgm08dKpcZECBu9f5FypndoMyRHkdqfT1Q==
Expand All @@ -4958,7 +4973,7 @@
natural-compare "^1.4.0"
ts-api-utils "^1.3.0"

"@typescript-eslint/parser@*", "@typescript-eslint/parser@8.19.0", "@typescript-eslint/parser@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0":
"@typescript-eslint/parser@*", "@typescript-eslint/parser@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0":
version "8.19.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.19.0.tgz#f1512e6e5c491b03aabb2718b95becde22b15292"
integrity sha512-6M8taKyOETY1TKHp0x8ndycipTVgmp4xtg5QpEZzXxDhNvvHOJi5rLRkLr8SK3jTgD5l4fTlvBiRdfsuWydxBw==
Expand Down Expand Up @@ -7048,7 +7063,7 @@ eslint-visitor-keys@^4.2.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45"
integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==

eslint@*, [email protected]:
eslint@*:
version "8.57.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668"
integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==
Expand Down Expand Up @@ -10923,7 +10938,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==
Expand All @@ -10942,7 +10957,7 @@ prosemirror-trailing-node@^3.0.0:
"@remirror/core-constants" "3.0.0"
escape-string-regexp "^4.0.0"

prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transform@^1.10.2, prosemirror-transform@^1.7.3:
prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transform@^1.10.2, prosemirror-transform@^1.7.3, prosemirror-transform@^1.9.0:
version "1.10.2"
resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.10.2.tgz#8ebac4e305b586cd96595aa028118c9191bbf052"
integrity sha512-2iUq0wv2iRoJO/zj5mv8uDUriOHWzXRnOTVgCzSXnktS/2iQRa3UUQwVlkBlYZFtygw6Nh1+X4mGqoYBINn5KQ==
Expand Down Expand Up @@ -12930,7 +12945,7 @@ typed-array-length@^1.0.7:
possible-typed-array-names "^1.0.0"
reflect.getprototypeof "^1.0.6"

typescript@*, typescript@5.7.2, typescript@^5.0.4:
typescript@*, typescript@^5.0.4:
version "5.7.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6"
integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==
Expand Down

0 comments on commit 0005fbd

Please sign in to comment.