Skip to content

✨(frontend) add multi columns support for editor #533

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
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 @@ -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 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.21.0",
"@blocknote/mantine": "0.21.0",
"@blocknote/react": "0.21.0",
"@blocknote/xl-multi-column": "0.21.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it took us a while to review this PR, maybe update this deps to the latest version now (0.25.1)

"@blocknote/xl-docx-exporter": "0.21.0",
"@blocknote/xl-pdf-exporter": "0.21.0",
"@gouvfr-lasuite/integration": "1.0.2",
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 { useEffect } from 'react';
import { useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { css } from 'styled-components';
import * as Y from 'yjs';
Expand All @@ -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';

Expand Down Expand Up @@ -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],
);
Expand All @@ -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' }}
Expand All @@ -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>
Expand All @@ -225,6 +262,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 leftPaddingMap: { [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
17 changes: 16 additions & 1 deletion src/frontend/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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==
Expand Down
Loading