Skip to content

Commit b67ab62

Browse files
committed
✨(frontend) add multi columns support for editor
We add multi columns support for editor, now you can add columns to your document. Works with export. 📄AGPL feature.
1 parent 1ae831c commit b67ab62

File tree

7 files changed

+114
-13
lines changed

7 files changed

+114
-13
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ and this project adheres to
1313
- ✨(backend) allow masking documents from the list view #1171
1414
- ✨(frontend) subdocs can manage link reach #1190
1515
- ✨(frontend) add duplicate action to doc tree #1175
16+
- ✨(frontend) add multi columns support for editor #1219
1617

1718
### Changed
1819

docs/env.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,10 @@ NODE_ENV=production NEXT_PUBLIC_PUBLISH_AS_MIT=false yarn build
136136

137137
Packages with licences incompatible with the MIT licence:
138138
* `xl-docx-exporter`: [AGPL-3.0](https://github.com/TypeCellOS/BlockNote/blob/main/packages/xl-docx-exporter/LICENSE),
139-
* `xl-pdf-exporter`: [AGPL-3.0](https://github.com/TypeCellOS/BlockNote/blob/main/packages/xl-pdf-exporter/LICENSE)
139+
* `xl-pdf-exporter`: [AGPL-3.0](https://github.com/TypeCellOS/BlockNote/blob/main/packages/xl-pdf-exporter/LICENSE),
140+
* `xl-multi-column`: [AGPL-3.0](https://github.com/TypeCellOS/BlockNote/blob/main/packages/xl-multi-column/LICENSE).
140141

141142
In `.env.development`, `PUBLISH_AS_MIT` is set to `false`, allowing developers to test Docs with all its features.
142143

143-
⚠️ If you run Docs in production with `PUBLISH_AS_MIT` set to `false` make sure you fulfill your [BlockNote licensing](https://github.com/TypeCellOS/BlockNote/blob/main/packages/xl-pdf-exporter/LICENSE) or [subscription](https://www.blocknotejs.org/about#partner-with-us) obligations.
144+
⚠️ If you run Docs in production with `PUBLISH_AS_MIT` set to `false` make sure you fulfill your BlockNote licensing or [subscription](https://www.blocknotejs.org/about#partner-with-us) obligations.
144145

src/frontend/apps/e2e/__tests__/app-impress/doc-export.spec.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,4 +346,69 @@ test.describe('Doc Export', () => {
346346
const pdfData = await pdf(pdfBuffer);
347347
expect(pdfData.text).toContain('Hello World');
348348
});
349+
350+
test('it exports the doc with multi columns', async ({
351+
page,
352+
browserName,
353+
}) => {
354+
const [randomDoc] = await createDoc(
355+
page,
356+
'doc-multi-columns',
357+
browserName,
358+
1,
359+
);
360+
361+
await page.locator('.bn-block-outer').last().fill('/');
362+
363+
await page.getByText('Three Columns', { exact: true }).click();
364+
365+
await page.locator('.bn-block-column').first().fill('Column 1');
366+
await page.locator('.bn-block-column').nth(1).fill('Column 2');
367+
await page.locator('.bn-block-column').last().fill('Column 3');
368+
369+
expect(await page.locator('.bn-block-column').count()).toBe(3);
370+
await expect(
371+
page.locator('.bn-block-column[data-node-type="column"]').first(),
372+
).toHaveText('Column 1');
373+
await expect(
374+
page.locator('.bn-block-column[data-node-type="column"]').nth(1),
375+
).toHaveText('Column 2');
376+
await expect(
377+
page.locator('.bn-block-column[data-node-type="column"]').last(),
378+
).toHaveText('Column 3');
379+
380+
await page
381+
.getByRole('button', {
382+
name: 'download',
383+
exact: true,
384+
})
385+
.click();
386+
387+
await expect(
388+
page.getByRole('button', {
389+
name: 'Download',
390+
exact: true,
391+
}),
392+
).toBeVisible();
393+
394+
const downloadPromise = page.waitForEvent('download', (download) => {
395+
return download.suggestedFilename().includes(`${randomDoc}.pdf`);
396+
});
397+
398+
void page
399+
.getByRole('button', {
400+
name: 'Download',
401+
exact: true,
402+
})
403+
.click();
404+
405+
const download = await downloadPromise;
406+
expect(download.suggestedFilename()).toBe(`${randomDoc}.pdf`);
407+
408+
const pdfBuffer = await cs.toBuffer(await download.createReadStream());
409+
const pdfData = await pdf(pdfBuffer);
410+
expect(pdfData.text).toContain('Column 1');
411+
expect(pdfData.text).toContain('Column 2');
412+
expect(pdfData.text).toContain('Column 3');
413+
});
349414
});

src/frontend/apps/impress/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"@blocknote/mantine": "0.34.0",
2222
"@blocknote/react": "0.34.0",
2323
"@blocknote/xl-docx-exporter": "0.34.0",
24+
"@blocknote/xl-multi-column": "0.34.0",
2425
"@blocknote/xl-pdf-exporter": "0.34.0",
2526
"@dnd-kit/core": "6.3.1",
2627
"@dnd-kit/modifiers": "9.0.0",

src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { codeBlock } from '@blocknote/code-block';
22
import {
33
BlockNoteSchema,
4+
BlockSchemaFromSpecs,
45
defaultBlockSpecs,
56
withPageBreak,
67
} from '@blocknote/core';
@@ -28,15 +29,24 @@ import { randomColor } from '../utils';
2829
import { BlockNoteSuggestionMenu } from './BlockNoteSuggestionMenu';
2930
import { BlockNoteToolbar } from './BlockNoteToolBar/BlockNoteToolbar';
3031
import { CalloutBlock, DividerBlock } from './custom-blocks';
31-
32-
export const blockNoteSchema = withPageBreak(
33-
BlockNoteSchema.create({
34-
blockSpecs: {
35-
...defaultBlockSpecs,
36-
callout: CalloutBlock,
37-
divider: DividerBlock,
38-
},
39-
}),
32+
import XLMultiColumn from './xl-multi-column';
33+
34+
const multiColumnDropCursor = XLMultiColumn?.multiColumnDropCursor;
35+
const multiColumnLocales = XLMultiColumn?.locales;
36+
const withMultiColumn =
37+
XLMultiColumn?.withMultiColumn ||
38+
((schema: BlockSchemaFromSpecs<typeof defaultBlockSpecs>) => schema);
39+
40+
export const blockNoteSchema = withMultiColumn(
41+
withPageBreak(
42+
BlockNoteSchema.create({
43+
blockSpecs: {
44+
...defaultBlockSpecs,
45+
callout: CalloutBlock,
46+
divider: DividerBlock,
47+
},
48+
}),
49+
),
4050
);
4151

4252
interface BlockNoteEditorProps {
@@ -116,7 +126,11 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
116126
},
117127
showCursorLabels: showCursorLabels as 'always' | 'activity',
118128
},
119-
dictionary: locales[lang as keyof typeof locales],
129+
dictionary: {
130+
...locales[lang as keyof typeof locales],
131+
multi_column:
132+
multiColumnLocales?.[lang as keyof typeof multiColumnLocales],
133+
},
120134
tables: {
121135
splitCells: true,
122136
cellBackgroundColor: true,
@@ -125,6 +139,7 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
125139
},
126140
uploadFile,
127141
schema: blockNoteSchema,
142+
dropCursor: multiColumnDropCursor,
128143
},
129144
[collabName, lang, provider, uploadFile],
130145
);

src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteSuggestionMenu.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ import {
1515
getCalloutReactSlashMenuItems,
1616
getDividerReactSlashMenuItems,
1717
} from './custom-blocks';
18+
import XLMultiColumn from './xl-multi-column';
19+
20+
const getMultiColumnSlashMenuItems =
21+
XLMultiColumn?.getMultiColumnSlashMenuItems;
1822

1923
export const BlockNoteSuggestionMenu = () => {
2024
const editor = useBlockNoteEditor<DocsBlockSchema>();
@@ -27,8 +31,9 @@ export const BlockNoteSuggestionMenu = () => {
2731
filterSuggestionItems(
2832
combineByGroup(
2933
getDefaultReactSlashMenuItems(editor),
30-
getPageBreakReactSlashMenuItems(editor),
3134
getCalloutReactSlashMenuItems(editor, t, basicBlocksName),
35+
getMultiColumnSlashMenuItems?.(editor) || [],
36+
getPageBreakReactSlashMenuItems(editor),
3237
getDividerReactSlashMenuItems(editor, t, basicBlocksName),
3338
),
3439
query,
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/**
2+
* To import XL modules you must import from the index file.
3+
* This is to ensure that the XL modules are only loaded when
4+
* the application is not published as MIT.
5+
*/
6+
import * as XLMultiColumn from '@blocknote/xl-multi-column';
7+
8+
let modulesXL = undefined;
9+
if (process.env.NEXT_PUBLIC_PUBLISH_AS_MIT === 'false') {
10+
modulesXL = XLMultiColumn;
11+
}
12+
13+
export default modulesXL as typeof XLMultiColumn;

0 commit comments

Comments
 (0)