Skip to content

Commit fab8721

Browse files
committed
Merge branch 'main' into releases
2 parents 1d4d4ff + 1d8f3d9 commit fab8721

File tree

10 files changed

+490
-27
lines changed

10 files changed

+490
-27
lines changed

README.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@ See our homepage @ [https://www.blocknotejs.org](https://www.blocknotejs.org/) o
3434
[![npm version](https://badge.fury.io/js/%40blocknote%2Freact.svg)](https://badge.fury.io/js/%40blocknote%2Freact)
3535

3636
```typescript
37-
import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
37+
import { useCreateBlockNote } from "@blocknote/react";
38+
import { BlockNoteView } from "@blocknote/mantine";
3839
import "@blocknote/core/fonts/inter.css";
39-
import "@blocknote/react/style.css";
40+
import "@blocknote/mantine/style.css";
4041

4142
function App() {
4243
const editor = useCreateBlockNote();
@@ -95,6 +96,9 @@ Directory structure:
9596
blocknote
9697
├── packages/core - The core of the editor
9798
├── packages/react - The main library for use in React apps
99+
├── packages/mantine - Mantine (default) implementation of BlockNote UI
100+
├── packages/ariakit - AriaKit implementation of BlockNote UI
101+
├── packages/shadcn - ShadCN / Tailwind / Radix implementation of BlockNote UI
98102
├── examples - Example apps
99103
├── playground - App to browse the example apps (https://playground.blocknotejs.org)
100104
└── tests - Playwright end to end tests

docs/pages/docs/advanced/nextjs.mdx

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ Make sure to use BlockNote in a [Client Component](https://nextjs.org/docs/getti
1212

1313
```typescript jsx
1414
"use client"; // this registers <Editor> as a Client Component
15-
import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
1615
import "@blocknote/core/fonts/inter.css";
17-
import "@blocknote/react/style.css";
16+
import { useCreateBlockNote } from "@blocknote/react";
17+
import { BlockNoteView } from "@blocknote/mantine";
18+
import "@blocknote/mantine/style.css";
1819

1920
// Our <Editor> component we can reuse later
2021
export default function Editor() {

examples/02-ui-components/05-side-menu-drag-handle-items/App.tsx

+3-9
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ import {
55
RemoveBlockItem,
66
SideMenu,
77
SideMenuController,
8-
useComponentsContext,
98
useCreateBlockNote,
109
} from "@blocknote/react";
1110
import { BlockNoteView } from "@blocknote/mantine";
1211
import "@blocknote/mantine/style.css";
1312

13+
import { ResetBlockTypeItem } from "./ResetBlockTypeItem";
14+
1415
export default function App() {
1516
// Creates a new editor instance.
1617
const editor = useCreateBlockNote({
@@ -34,8 +35,6 @@ export default function App() {
3435
],
3536
});
3637

37-
const Components = useComponentsContext()!;
38-
3938
// Renders the editor instance.
4039
return (
4140
<BlockNoteView editor={editor} sideMenu={false}>
@@ -48,12 +47,7 @@ export default function App() {
4847
<RemoveBlockItem {...props}>Delete</RemoveBlockItem>
4948
<BlockColorsItem {...props}>Colors</BlockColorsItem>
5049
{/* Item which resets the hovered block's type. */}
51-
<Components.Generic.Menu.Item
52-
onClick={() => {
53-
editor.updateBlock(props.block, { type: "paragraph" });
54-
}}>
55-
Reset Type
56-
</Components.Generic.Menu.Item>
50+
<ResetBlockTypeItem {...props}>Reset Type</ResetBlockTypeItem>
5751
</DragHandleMenu>
5852
)}
5953
/>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import {
2+
DragHandleMenuProps,
3+
useBlockNoteEditor,
4+
useComponentsContext,
5+
} from "@blocknote/react";
6+
7+
export function ResetBlockTypeItem(props: DragHandleMenuProps) {
8+
const editor = useBlockNoteEditor();
9+
10+
const Components = useComponentsContext()!;
11+
12+
return (
13+
<Components.Generic.Menu.Item
14+
onClick={() => {
15+
editor.updateBlock(props.block, { type: "paragraph" });
16+
}}>
17+
Reset Type
18+
</Components.Generic.Menu.Item>
19+
);
20+
}

packages/core/src/editor/BlockNoteExtensions.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export const getBlockNoteExtensions = <
6868
UniqueID.configure({
6969
types: ["blockContainer"],
7070
}),
71-
HardBreak,
71+
HardBreak.extend({ priority: 10 }),
7272
// Comments,
7373

7474
// basics:

packages/core/src/extensions/NonEditableBlocks/NonEditableBlockPlugin.ts

+43-12
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,58 @@
1-
import { Plugin, PluginKey } from "prosemirror-state";
1+
import { Plugin, PluginKey, TextSelection } from "prosemirror-state";
22

33
const PLUGIN_KEY = new PluginKey("non-editable-block");
4-
// Prevent typing for blocks without inline content, as this would otherwise
5-
// convert them into paragraph blocks.
4+
// By default, typing with a node selection active will cause ProseMirror to
5+
// replace the node with one that contains editable content. This plugin blocks
6+
// this behaviour without also blocking things like keyboard shortcuts:
7+
//
8+
// - Lets through key presses that do not include alphanumeric characters. This
9+
// includes things like backspace/delete/home/end/etc.
10+
// - Lets through any key presses that include ctrl/meta keys. These will be
11+
// shortcuts of some kind like ctrl+C/mod+C.
12+
// - Special case for Enter key which creates a new paragraph block below and
13+
// sets the selection to it. This is just to bring the UX closer to Notion
14+
//
15+
// While a more elegant solution would probably process transactions instead of
16+
// keystrokes, this brings us most of the way to Notion's UX without much added
17+
// complexity.
618
export const NonEditableBlockPlugin = () => {
719
return new Plugin({
820
key: PLUGIN_KEY,
921
props: {
1022
handleKeyDown: (view, event) => {
1123
// Checks for node selection
1224
if ("node" in view.state.selection) {
13-
// Checks if key input will insert a character - we want to block this
14-
// as it will convert the block into a paragraph.
15-
if (
16-
event.key.length === 1 &&
17-
!event.ctrlKey &&
18-
!event.altKey &&
19-
!event.metaKey &&
20-
!event.shiftKey
21-
) {
25+
// Checks if key press uses ctrl/meta modifier
26+
if (event.ctrlKey || event.metaKey) {
27+
return false;
28+
}
29+
// Checks if key press is alphanumeric
30+
if (event.key.length === 1) {
2231
event.preventDefault();
32+
33+
return true;
34+
}
35+
// Checks if key press is Enter
36+
if (event.key === "Enter") {
37+
const tr = view.state.tr;
38+
view.dispatch(
39+
tr
40+
.insert(
41+
view.state.tr.selection.$to.after(),
42+
view.state.schema.nodes["paragraph"].create()
43+
)
44+
.setSelection(
45+
new TextSelection(
46+
tr.doc.resolve(view.state.tr.selection.$to.after() + 1)
47+
)
48+
)
49+
);
50+
51+
return true;
2352
}
2453
}
54+
55+
return false;
2556
},
2657
},
2758
});

packages/core/src/i18n/locales/fr.ts

+196
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
export const fr = {
2+
slash_menu: {
3+
heading: {
4+
title: "Titre 1",
5+
subtext: "Utilisé pour un titre de premier niveau",
6+
aliases: ["h", "titre1", "h1"],
7+
group: "Titres",
8+
},
9+
heading_2: {
10+
title: "Titre 2",
11+
subtext: "Utilisé pour les sections clés",
12+
aliases: ["h2", "titre2", "sous-titre"],
13+
group: "Titres",
14+
},
15+
heading_3: {
16+
title: "Titre 3",
17+
subtext: "Utilisé pour les sous-sections et les titres de groupe",
18+
aliases: ["h3", "titre3", "sous-titre"],
19+
group: "Titres",
20+
},
21+
numbered_list: {
22+
title: "Liste Numérotée",
23+
subtext: "Utilisé pour afficher une liste numérotée",
24+
aliases: ["ol", "li", "liste", "listenumérotée", "liste numérotée"],
25+
group: "Blocs de base",
26+
},
27+
bullet_list: {
28+
title: "Liste à Puces",
29+
subtext: "Utilisé pour afficher une liste non ordonnée",
30+
aliases: ["ul", "li", "liste", "listeàpuces", "liste à puces"],
31+
group: "Blocs de base",
32+
},
33+
paragraph: {
34+
title: "Paragraphe",
35+
subtext: "Utilisé pour le corps de votre document",
36+
aliases: ["p", "paragraphe"],
37+
group: "Blocs de base",
38+
},
39+
table: {
40+
title: "Tableau",
41+
subtext: "Utilisé pour les tableaux",
42+
aliases: ["tableau"],
43+
group: "Avancé",
44+
},
45+
image: {
46+
title: "Image",
47+
subtext: "Insérer une image",
48+
aliases: [
49+
"image",
50+
"uploadImage",
51+
"télécharger",
52+
"img",
53+
"photo",
54+
"média",
55+
"url",
56+
"drive",
57+
"dropbox",
58+
],
59+
group: "Médias",
60+
},
61+
},
62+
placeholders: {
63+
default: "Entrez du texte ou tapez '/' pour les commandes",
64+
heading: "Titre",
65+
bulletListItem: "Liste",
66+
numberedListItem: "Liste",
67+
},
68+
image: {
69+
add_button: "Ajouter une Image",
70+
},
71+
// from react package:
72+
side_menu: {
73+
add_block_label: "Ajouter un bloc",
74+
drag_handle_label: "Ouvrir le menu du bloc",
75+
},
76+
drag_handle: {
77+
delete_menuitem: "Supprimer",
78+
colors_menuitem: "Couleurs",
79+
},
80+
table_handle: {
81+
delete_column_menuitem: "Supprimer la colonne",
82+
delete_row_menuitem: "Supprimer la ligne",
83+
add_left_menuitem: "Ajouter une colonne à gauche",
84+
add_right_menuitem: "Ajouter une colonne à droite",
85+
add_above_menuitem: "Ajouter une ligne au-dessus",
86+
add_below_menuitem: "Ajouter une ligne en dessous",
87+
},
88+
suggestion_menu: {
89+
no_items_title: "Aucun élément trouvé",
90+
loading: "Chargement…",
91+
},
92+
color_picker: {
93+
text_title: "Texte",
94+
background_title: "Fond",
95+
colors: {
96+
default: "Défaut",
97+
gray: "Gris",
98+
brown: "Marron",
99+
red: "Rouge",
100+
orange: "Orange",
101+
yellow: "Jaune",
102+
green: "Vert",
103+
blue: "Bleu",
104+
purple: "Violet",
105+
pink: "Rose",
106+
},
107+
},
108+
109+
formatting_toolbar: {
110+
bold: {
111+
tooltip: "Gras",
112+
secondary_tooltip: "Mod+B",
113+
},
114+
italic: {
115+
tooltip: "Italique",
116+
secondary_tooltip: "Mod+I",
117+
},
118+
underline: {
119+
tooltip: "Souligner",
120+
secondary_tooltip: "Mod+U",
121+
},
122+
strike: {
123+
tooltip: "Barré",
124+
secondary_tooltip: "Mod+Shift+X",
125+
},
126+
code: {
127+
tooltip: "Code",
128+
secondary_tooltip: "",
129+
},
130+
colors: {
131+
tooltip: "Couleurs",
132+
},
133+
link: {
134+
tooltip: "Créer un lien",
135+
secondary_tooltip: "Mod+K",
136+
},
137+
image_caption: {
138+
tooltip: "Modifier la légende",
139+
input_placeholder: "Modifier la légende",
140+
},
141+
image_replace: {
142+
tooltip: "Remplacer l'image",
143+
},
144+
nest: {
145+
tooltip: "Emboîter le bloc",
146+
secondary_tooltip: "Tab",
147+
},
148+
unnest: {
149+
tooltip: "Démboîter le bloc",
150+
secondary_tooltip: "Shift+Tab",
151+
},
152+
align_left: {
153+
tooltip: "Aligner le texte à gauche",
154+
},
155+
align_center: {
156+
tooltip: "Aligner le texte au centre",
157+
},
158+
align_right: {
159+
tooltip: "Aligner le texte à droite",
160+
},
161+
align_justify: {
162+
tooltip: "Justifier le texte",
163+
},
164+
},
165+
image_panel: {
166+
upload: {
167+
title: "Télécharger",
168+
file_placeholder: "Télécharger l'image",
169+
upload_error: "Erreur : Échec du téléchargement",
170+
},
171+
embed: {
172+
title: "Intégrer",
173+
embed_button: "Intégrer l'image",
174+
url_placeholder: "Entrez l'URL",
175+
},
176+
},
177+
link_toolbar: {
178+
delete: {
179+
tooltip: "Supprimer le lien",
180+
},
181+
edit: {
182+
text: "Modifier le lien",
183+
tooltip: "Modifier",
184+
},
185+
open: {
186+
tooltip: "Ouvrir dans un nouvel onglet",
187+
},
188+
form: {
189+
title_placeholder: "Modifier le titre",
190+
url_placeholder: "Modifier l'URL",
191+
},
192+
},
193+
generic: {
194+
ctrl_shortcut: "Ctrl",
195+
},
196+
};
+2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
export * from "./en";
22
export * from "./nl";
3+
export * from "./zh";
4+
export * from "./fr";

0 commit comments

Comments
 (0)