Skip to content

Commit c2b24e4

Browse files
committed
Merge branch 'main' into new-releases
2 parents 8971bf9 + 0653819 commit c2b24e4

File tree

98 files changed

+3402
-3311
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+3402
-3311
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ blocknote
106106

107107
The codebase is automatically tested using Vitest and Playwright.
108108

109+
# License 📃
110+
111+
BlockNote is licensed under the [MPL 2.0 license](https://fossa.com/blog/open-source-software-licenses-101-mozilla-public-license-2-0/), which allows you to use BlockNote in commercial (and closed-source) applications. If you make changes to the BlockNote source files, you're expected to publish these changes so the wider community can benefit as well.
112+
109113
# Credits ❤️
110114

111115
BlockNote builds directly on two awesome projects; [Prosemirror](https://prosemirror.net/) by Marijn Haverbeke and [Tiptap](https://tiptap.dev/). Consider sponsoring those libraries when using BlockNote: [Prosemirror](https://marijnhaverbeke.nl/fund/), [Tiptap](https://github.com/sponsors/ueberdosis).

examples/vanilla/src/main.tsx

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,12 @@
11
import { BlockNoteEditor } from "@blocknote/core";
22
import "./index.css";
3-
import { blockSideMenuFactory } from "./ui/blockSideMenuFactory";
4-
import { formattingToolbarFactory } from "./ui/formattingToolbarFactory";
5-
import { hyperlinkToolbarFactory } from "./ui/hyperlinkToolbarFactory";
6-
import { slashMenuFactory } from "./ui/slashMenuFactory";
3+
import { addSideMenu } from "./ui/addSideMenu";
4+
import { addFormattingToolbar } from "./ui/addFormattingToolbar";
5+
import { addSlashMenu } from "./ui/addSlashMenu";
6+
import { addHyperlinkToolbar } from "./ui/addHyperlinkToolbar";
77

88
const editor = new BlockNoteEditor({
99
parentElement: document.getElementById("root")!,
10-
uiFactories: {
11-
// Create an example formatting toolbar which just consists of a bold toggle
12-
formattingToolbarFactory,
13-
// Create an example menu for hyperlinks
14-
hyperlinkToolbarFactory,
15-
// Create an example menu for the /-menu
16-
slashMenuFactory: slashMenuFactory,
17-
// Create an example menu for when a block is hovered
18-
blockSideMenuFactory,
19-
},
2010
onEditorContentChange: () => {
2111
console.log(editor.topLevelBlocks);
2212
},
@@ -26,3 +16,8 @@ const editor = new BlockNoteEditor({
2616
});
2717

2818
console.log("editor created", editor);
19+
20+
addSideMenu(editor);
21+
addFormattingToolbar(editor);
22+
addSlashMenu(editor);
23+
addHyperlinkToolbar(editor);
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { BlockNoteEditor } from "@blocknote/core";
2+
import { createButton } from "./util";
3+
4+
export const addFormattingToolbar = (editor: BlockNoteEditor) => {
5+
let element: HTMLElement;
6+
let boldBtn: HTMLAnchorElement;
7+
8+
editor.formattingToolbar.onUpdate((formattingToolbarState) => {
9+
if (!element) {
10+
element = document.createElement("div");
11+
element.style.background = "gray";
12+
element.style.position = "absolute";
13+
element.style.padding = "10px";
14+
element.style.opacity = "0.8";
15+
boldBtn = createButton("set bold", () => {
16+
editor.toggleStyles({ bold: true });
17+
});
18+
element.appendChild(boldBtn);
19+
20+
const linkBtn = createButton("set link", () => {
21+
editor.createLink("https://www.google.com");
22+
});
23+
24+
element.appendChild(boldBtn);
25+
element.appendChild(linkBtn);
26+
element.style.display = "none";
27+
28+
document.getElementById("root")!.appendChild(element);
29+
}
30+
31+
if (formattingToolbarState.show) {
32+
element.style.display = "block";
33+
34+
boldBtn.text =
35+
"bold" in editor.getActiveStyles() ? "unset bold" : "set bold";
36+
element.style.top = formattingToolbarState.referencePos.top + "px";
37+
element.style.left =
38+
formattingToolbarState.referencePos.x - element.offsetWidth + "px";
39+
} else {
40+
element.style.display = "none";
41+
}
42+
});
43+
};
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { BlockNoteEditor } from "@blocknote/core";
2+
import { createButton } from "./util";
3+
4+
export const addHyperlinkToolbar = (editor: BlockNoteEditor) => {
5+
let element: HTMLElement;
6+
7+
editor.hyperlinkToolbar.onUpdate((hyperlinkToolbarState) => {
8+
if (!element) {
9+
element = document.createElement("div");
10+
element.style.background = "gray";
11+
element.style.position = "absolute";
12+
element.style.padding = "10px";
13+
element.style.opacity = "0.8";
14+
15+
let url = hyperlinkToolbarState.url;
16+
let text = hyperlinkToolbarState.text;
17+
18+
const editBtn = createButton("edit", () => {
19+
const newUrl = prompt("new url") || url;
20+
editor.hyperlinkToolbar.editHyperlink(newUrl, text);
21+
});
22+
23+
element.appendChild(editBtn);
24+
25+
const removeBtn = createButton("remove", () => {
26+
editor.hyperlinkToolbar.deleteHyperlink();
27+
});
28+
29+
element.appendChild(editBtn);
30+
element.appendChild(removeBtn);
31+
element.style.display = "none";
32+
33+
document.getElementById("root")!.appendChild(element);
34+
}
35+
36+
if (hyperlinkToolbarState.show) {
37+
element.style.display = "block";
38+
39+
element.style.top = hyperlinkToolbarState.referencePos.top + "px";
40+
element.style.left =
41+
hyperlinkToolbarState.referencePos.x - element.offsetWidth + "px";
42+
} else {
43+
element.style.display = "none";
44+
}
45+
});
46+
};
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { BlockNoteEditor } from "@blocknote/core";
2+
import { createButton } from "./util";
3+
4+
export const addSideMenu = (editor: BlockNoteEditor) => {
5+
let element: HTMLElement;
6+
7+
editor.sideMenu.onUpdate((sideMenuState) => {
8+
if (!element) {
9+
element = document.createElement("div");
10+
element.style.background = "gray";
11+
element.style.position = "absolute";
12+
element.style.padding = "10px";
13+
element.style.opacity = "0.8";
14+
const addBtn = createButton("+", () => {
15+
editor.sideMenu.addBlock();
16+
});
17+
element.appendChild(addBtn);
18+
19+
const dragBtn = createButton("::", () => {
20+
// TODO: render a submenu with a delete option that calls "props.deleteBlock"
21+
});
22+
23+
dragBtn.addEventListener("dragstart", editor.sideMenu.blockDragStart);
24+
dragBtn.addEventListener("dragend", editor.sideMenu.blockDragEnd);
25+
dragBtn.draggable = true;
26+
element.style.display = "none";
27+
element.appendChild(dragBtn);
28+
29+
document.getElementById("root")!.appendChild(element);
30+
}
31+
32+
if (sideMenuState.show) {
33+
element.style.display = "block";
34+
35+
element.style.top = sideMenuState.referencePos.top + "px";
36+
element.style.left =
37+
sideMenuState.referencePos.x - element.offsetWidth + "px";
38+
} else {
39+
element.style.display = "none";
40+
}
41+
});
42+
};
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import {
2+
BaseSlashMenuItem,
3+
BlockNoteEditor,
4+
DefaultBlockSchema,
5+
} from "@blocknote/core";
6+
import { createButton } from "./util";
7+
8+
export const addSlashMenu = (editor: BlockNoteEditor) => {
9+
let element: HTMLElement;
10+
11+
function updateItems(
12+
items: BaseSlashMenuItem<DefaultBlockSchema>[],
13+
onClick: (item: BaseSlashMenuItem<DefaultBlockSchema>) => void,
14+
selected: number
15+
) {
16+
element.innerHTML = "";
17+
const domItems = items.map((val, i) => {
18+
const element = createButton(val.name, () => {
19+
onClick(val);
20+
});
21+
element.style.display = "block";
22+
if (selected === i) {
23+
element.style.fontWeight = "bold";
24+
}
25+
return element;
26+
});
27+
element.append(...domItems);
28+
return domItems;
29+
}
30+
31+
editor.slashMenu.onUpdate((slashMenuState) => {
32+
if (!element) {
33+
element = document.createElement("div");
34+
element.style.background = "gray";
35+
element.style.position = "absolute";
36+
element.style.padding = "10px";
37+
element.style.opacity = "0.8";
38+
element.style.display = "none";
39+
40+
document.getElementById("root")!.appendChild(element);
41+
}
42+
43+
if (slashMenuState.show) {
44+
updateItems(
45+
slashMenuState.filteredItems,
46+
editor.slashMenu.itemCallback,
47+
slashMenuState.keyboardHoveredItemIndex
48+
);
49+
50+
element.style.display = "block";
51+
52+
element.style.top = slashMenuState.referencePos.top + "px";
53+
element.style.left =
54+
slashMenuState.referencePos.x - element.offsetWidth + "px";
55+
} else {
56+
element.style.display = "none";
57+
}
58+
});
59+
};

examples/vanilla/src/ui/blockSideMenuFactory.ts

Lines changed: 0 additions & 48 deletions
This file was deleted.

examples/vanilla/src/ui/formattingToolbarFactory.ts

Lines changed: 0 additions & 48 deletions
This file was deleted.

examples/vanilla/src/ui/hyperlinkToolbarFactory.ts

Lines changed: 0 additions & 53 deletions
This file was deleted.

0 commit comments

Comments
 (0)