Skip to content

Commit 18ebf15

Browse files
committed
Merge branch 'main' into new-releases
2 parents d172057 + 0a81db3 commit 18ebf15

File tree

17 files changed

+206
-59
lines changed

17 files changed

+206
-59
lines changed

packages/core/src/BlockNoteEditor.ts

+19-7
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ export type BlockNoteEditorOptions<BSchema extends BlockSchema> = {
140140
};
141141

142142
// tiptap options, undocumented
143-
_tiptapOptions: any;
143+
_tiptapOptions: Partial<EditorOptions>;
144144
};
145145

146146
const blockNoteTipTapOptions = {
@@ -228,10 +228,11 @@ export class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {
228228
},
229229
]);
230230

231-
const tiptapOptions: EditorOptions = {
231+
const tiptapOptions: Partial<EditorOptions> = {
232232
...blockNoteTipTapOptions,
233233
...newOptions._tiptapOptions,
234234
onBeforeCreate(editor) {
235+
newOptions._tiptapOptions?.onBeforeCreate?.(editor);
235236
if (!initialContent) {
236237
// when using collaboration
237238
return;
@@ -250,7 +251,8 @@ export class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {
250251
);
251252
editor.editor.options.content = root.toJSON();
252253
},
253-
onCreate: () => {
254+
onCreate: (editor) => {
255+
newOptions._tiptapOptions?.onCreate?.(editor);
254256
// We need to wait for the TipTap editor to init before we can set the
255257
// initial content, as the schema may contain custom blocks which need
256258
// it to render.
@@ -261,7 +263,8 @@ export class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {
261263
newOptions.onEditorReady?.(this);
262264
this.ready = true;
263265
},
264-
onUpdate: () => {
266+
onUpdate: (editor) => {
267+
newOptions._tiptapOptions?.onUpdate?.(editor);
265268
// This seems to be necessary due to a bug in TipTap:
266269
// https://github.com/ueberdosis/tiptap/issues/2583
267270
if (!this.ready) {
@@ -270,7 +273,8 @@ export class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {
270273

271274
newOptions.onEditorContentChange?.(this);
272275
},
273-
onSelectionUpdate: () => {
276+
onSelectionUpdate: (editor) => {
277+
newOptions._tiptapOptions?.onSelectionUpdate?.(editor);
274278
// This seems to be necessary due to a bug in TipTap:
275279
// https://github.com/ueberdosis/tiptap/issues/2583
276280
if (!this.ready) {
@@ -279,17 +283,25 @@ export class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {
279283

280284
newOptions.onTextCursorPositionChange?.(this);
281285
},
282-
editable: options.editable === undefined ? true : options.editable,
286+
editable:
287+
options.editable !== undefined
288+
? options.editable
289+
: newOptions._tiptapOptions?.editable !== undefined
290+
? newOptions._tiptapOptions?.editable
291+
: true,
283292
extensions:
284293
newOptions.enableBlockNoteExtensions === false
285-
? newOptions._tiptapOptions?.extensions
294+
? newOptions._tiptapOptions?.extensions || []
286295
: [...(newOptions._tiptapOptions?.extensions || []), ...extensions],
287296
editorProps: {
297+
...newOptions._tiptapOptions?.editorProps,
288298
attributes: {
299+
...newOptions._tiptapOptions?.editorProps?.attributes,
289300
...newOptions.domAttributes?.editor,
290301
class: mergeCSSClasses(
291302
styles.bnEditor,
292303
styles.bnRoot,
304+
newOptions.domAttributes?.editor?.class || "",
293305
newOptions.defaultStyles ? styles.defaultStyles : "",
294306
newOptions.domAttributes?.editor?.class || ""
295307
),

packages/core/src/api/nodeConversions/nodeConversions.ts

-13
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
BlockSchema,
66
PartialBlock,
77
} from "../../extensions/Blocks/api/blockTypes";
8-
import { defaultProps } from "../../extensions/Blocks/api/defaultProps";
98
import {
109
ColorStyle,
1110
InlineContent,
@@ -394,18 +393,6 @@ export function nodeToBlock<BSchema extends BlockSchema>(
394393
if (attr in propSchema) {
395394
props[attr] = value;
396395
}
397-
// Block ids are stored as node attributes the same way props are, so we
398-
// need to ensure we don't attempt to read block ids as props.
399-
400-
// the second check is for the backgroundColor & textColor props.
401-
// Since we want them to be inherited by child blocks, we can't put them on the blockContent node,
402-
// and instead have to put them on the blockContainer node.
403-
// The blockContainer node is the same for all block types, but some custom blocks might not use backgroundColor & textColor,
404-
// so these 2 props are technically unexpected but we shouldn't log a warning.
405-
// (this is a bit hacky)
406-
else if (attr !== "id" && !(attr in defaultProps)) {
407-
console.warn("Block has an unrecognized attribute: " + attr);
408-
}
409396
}
410397

411398
const blockSpec = blockSchema[blockInfo.contentType.name];

packages/core/src/extensions/Blocks/nodes/Block.module.css

+1-4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ BASIC STYLES
2323
padding: 3px 0;
2424
flex-grow: 1;
2525
transition: font-size 0.2s;
26+
width: 100%;
2627
/*
2728
because the content elements are display: block
2829
we use flex to position them next to list markers
@@ -287,10 +288,6 @@ NESTED BLOCKS
287288
cursor: ew-resize;
288289
}
289290

290-
[data-content-type="image"] .imageWrapper:hover .resizeHandle {
291-
display: block;
292-
}
293-
294291
[data-content-type="image"] .caption {
295292
font-size: 0.8em
296293
}

packages/core/src/extensions/Blocks/nodes/BlockContent/ImageBlockContent/ImageBlockContent.ts

+30
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,34 @@ const renderImage = (
225225
);
226226
};
227227

228+
// Shows the resize handles when hovering over the image with the cursor.
229+
const imageMouseEnterHandler = () => {
230+
if (editor.isEditable) {
231+
leftResizeHandle.style.display = "block";
232+
rightResizeHandle.style.display = "block";
233+
} else {
234+
leftResizeHandle.style.display = "none";
235+
rightResizeHandle.style.display = "none";
236+
}
237+
};
238+
// Hides the resize handles when the cursor leaves the image, unless the
239+
// cursor moves to one of the resize handles.
240+
const imageMouseLeaveHandler = (event: MouseEvent) => {
241+
if (
242+
event.relatedTarget === leftResizeHandle ||
243+
event.relatedTarget === rightResizeHandle
244+
) {
245+
return;
246+
}
247+
248+
if (resizeParams) {
249+
return;
250+
}
251+
252+
leftResizeHandle.style.display = "none";
253+
rightResizeHandle.style.display = "none";
254+
};
255+
228256
// Sets the resize params, allowing the user to begin resizing the image by
229257
// moving the cursor left or right.
230258
const leftResizeHandleMouseDownHandler = (event: MouseEvent) => {
@@ -266,6 +294,8 @@ const renderImage = (
266294
window.addEventListener("mouseup", windowMouseUpHandler);
267295
addImageButton.addEventListener("mousedown", addImageButtonMouseDownHandler);
268296
addImageButton.addEventListener("click", addImageButtonClickHandler);
297+
image.addEventListener("mouseenter", imageMouseEnterHandler);
298+
image.addEventListener("mouseleave", imageMouseLeaveHandler);
269299
leftResizeHandle.addEventListener(
270300
"mousedown",
271301
leftResizeHandleMouseDownHandler

packages/core/src/extensions/SideMenu/SideMenuPlugin.ts

+11
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ export class SideMenuView<BSchema extends BlockSchema> implements PluginView {
265265
// Makes menu scroll with the page.
266266
document.addEventListener("scroll", this.onScroll);
267267

268+
// Unfreezes the menu whenever the user clicks anywhere.
269+
document.body.addEventListener("mousedown", this.onMouseDown, true);
268270
// Hides and unfreezes the menu whenever the user presses a key.
269271
document.body.addEventListener("keydown", this.onKeyDown, true);
270272
}
@@ -347,6 +349,14 @@ export class SideMenuView<BSchema extends BlockSchema> implements PluginView {
347349
this.menuFrozen = false;
348350
};
349351

352+
onMouseDown = (_event: MouseEvent) => {
353+
if (this.sideMenuState && !this.sideMenuState.show) {
354+
this.sideMenuState.show = true;
355+
this.updateSideMenu(this.sideMenuState);
356+
}
357+
this.menuFrozen = false;
358+
};
359+
350360
onMouseMove = (event: MouseEvent) => {
351361
if (this.menuFrozen) {
352362
return;
@@ -479,6 +489,7 @@ export class SideMenuView<BSchema extends BlockSchema> implements PluginView {
479489
this.pmView.dom.removeEventListener("dragstart", this.onDragStart);
480490
document.body.removeEventListener("drop", this.onDrop, true);
481491
document.removeEventListener("scroll", this.onScroll);
492+
document.body.removeEventListener("mousedown", this.onMouseDown, true);
482493
document.body.removeEventListener("keydown", this.onKeyDown, true);
483494
}
484495

packages/react/src/BlockNoteTheme.ts

+13-4
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ export type ComponentStyles = Partial<{
3939
// Menu to edit hyperlinks (in Formatting Toolbar & Hyperlink Toolbar)
4040
EditHyperlinkMenu: CSSObject;
4141
Editor: CSSObject;
42+
// Used in the Image Toolbar
43+
FileInput: CSSObject;
44+
Tabs: CSSObject;
45+
TextInput: CSSObject;
4246
// Wraps Formatting Toolbar & Hyperlink Toolbar
4347
Toolbar: CSSObject;
4448
// Appears on hover for Formatting Toolbar
@@ -129,10 +133,13 @@ export const blockNoteToMantineTheme = (theme: Theme): MantineThemeOverride => {
129133
},
130134
Tabs: {
131135
styles: () => ({
132-
root: {
133-
width: "100%",
134-
backgroundColor: theme.colors.menu.background,
135-
},
136+
root: _.merge<CSSObject, CSSObject>(
137+
{
138+
width: "100%",
139+
backgroundColor: theme.colors.menu.background,
140+
},
141+
theme.componentStyles?.(theme).Tabs || {}
142+
),
136143
tabsList: {
137144
borderColor: theme.colors.hovered.background,
138145
},
@@ -166,6 +173,7 @@ export const blockNoteToMantineTheme = (theme: Theme): MantineThemeOverride => {
166173
},
167174
FileInput: {
168175
styles: () => ({
176+
root: theme.componentStyles?.(theme).FileInput || {},
169177
input: {
170178
color: theme.colors.menu.text,
171179
backgroundColor: theme.colors.menu.background,
@@ -191,6 +199,7 @@ export const blockNoteToMantineTheme = (theme: Theme): MantineThemeOverride => {
191199
},
192200
TextInput: {
193201
styles: () => ({
202+
root: theme.componentStyles?.(theme).TextInput || {},
194203
input: {
195204
color: theme.colors.menu.text,
196205
backgroundColor: theme.colors.menu.background,

packages/website/docs/.vitepress/config.ts

+4
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,10 @@ const EXAMPLES_SIDEBAR = [
133133
text: "Saving & Loading",
134134
link: "/examples/saving-loading",
135135
},
136+
{
137+
text: "Changing Font",
138+
link: "/examples/changing-font",
139+
},
136140
],
137141
},
138142
{

packages/website/docs/docs/block-types.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ img {
262262
::: info
263263
While custom blocks open a lot of doors for what you can do with BlockNote, we're still working on the API and there are a few limitations for the kinds of blocks you can create.
264264

265-
We'd love to hear your feedback on Github or in our Discord community!
265+
We'd love to hear your feedback on GitHub or in our Discord community!
266266
:::
267267

268268
### Creating a Custom Block Type

packages/website/docs/docs/image-toolbar.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,18 @@ You can use the provided `uploadToTempFilesOrg` function to as a starting point,
3535
::: sandbox {template=react-ts}
3636

3737
```typescript-vue /App.tsx
38-
import { BlockNoteEditor, uploadToTmpFilesOrg } from "@blocknote/core";
38+
import {
39+
BlockNoteEditor,
40+
uploadToTmpFilesDotOrg_DEV_ONLY,
41+
} from "@blocknote/core";
3942
import { BlockNoteView, useBlockNote } from "@blocknote/react";
4043
import "@blocknote/core/style.css";
4144

4245
export default function App() {
4346
// Creates a new editor instance.
4447
const editor: BlockNoteEditor = useBlockNote({
4548
// Sets the example file upload handler.
46-
uploadFile: uploadToTmpFilesOrg,
49+
uploadFile: uploadToTmpFilesDotOrg_DEV_ONLY,
4750
});
4851

4952
return <BlockNoteView editor={editor} theme={"{{ getTheme(isDark) }}"} />;

packages/website/docs/docs/slash-menu.md

-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ export default function App() {
7777
// Renders the editor instance.
7878
return <BlockNoteView editor={editor} theme={"{{ getTheme(isDark) }}"} />;
7979
}
80-
8180
```
8281

8382
```css-vue /styles.css [hidden]

packages/website/docs/docs/theming.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ import "@blocknote/core/style.css";
3737

3838
// Custom red light theme
3939
const lightRedTheme = {
40-
type: "light",
4140
colors: {
4241
editor: {
4342
text: "#222222",
@@ -75,7 +74,6 @@ const lightRedTheme = {
7574
// Custom red dark theme
7675
const darkRedTheme = {
7776
...lightRedTheme,
78-
type: "dark",
7977
colors: {
8078
...lightRedTheme.colors,
8179
editor: {
@@ -247,6 +245,12 @@ There are a number of components that you can override styles for:
247245

248246
`Editor:` The editor itself, excluding menus & toolbars.
249247

248+
`FileInput:` Component used for file inputs in the Image Toolbar.
249+
250+
`Tabs:` Component used for tabs in the Image Toolbar.
251+
252+
`TextInput:` Component used for text inputs in the Image Toolbar.
253+
250254
`Toolbar:` Component used for the [Formatting Toolbar](/docs/formatting-toolbar), Hyperlink Toolbar, and [Image Toolbar](/docs/image-toolbar).
251255

252256
`Tooltip:` Component for the tooltip that appears on hover, for Formatting Toolbar & Hyperlink Toolbar buttons.

packages/website/docs/docs/ui-elements.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ export default function App() {
116116

117117
// Renders the editor instance.
118118
return (
119-
<BlockNoteView editor={editor} theme={"light"}>
119+
<BlockNoteView editor={editor} theme={"{{ getTheme(isDark) }}"}>
120120
<FormattingToolbarPositioner editor={editor} />
121121
<HyperlinkToolbarPositioner editor={editor} />
122122
<SlashMenuPositioner editor={editor} />

0 commit comments

Comments
 (0)