diff --git a/examples/editor/examples/basic/App.tsx b/examples/editor/examples/basic/App.tsx
index 6c3213b0dd..0c7ba3ccb4 100644
--- a/examples/editor/examples/basic/App.tsx
+++ b/examples/editor/examples/basic/App.tsx
@@ -1,8 +1,7 @@
+import { uploadToTmpFilesDotOrg_DEV_ONLY } from "@blocknote/core";
import "@blocknote/core/style.css";
import { BlockNoteView, useBlockNote } from "@blocknote/react";
-import { uploadToTmpFilesDotOrg_DEV_ONLY } from "@blocknote/core";
-
type WindowWithProseMirror = Window & typeof globalThis & { ProseMirror: any };
export function App() {
diff --git a/examples/editor/examples/collaboration/App.tsx b/examples/editor/examples/collaboration/App.tsx
index 8bec4b84c9..083cec29ca 100644
--- a/examples/editor/examples/collaboration/App.tsx
+++ b/examples/editor/examples/collaboration/App.tsx
@@ -1,8 +1,7 @@
+import { uploadToTmpFilesDotOrg_DEV_ONLY } from "@blocknote/core";
import "@blocknote/core/style.css";
import { BlockNoteView, useBlockNote } from "@blocknote/react";
-import { uploadToTmpFilesDotOrg_DEV_ONLY } from "@blocknote/core";
-
import YPartyKitProvider from "y-partykit/provider";
import * as Y from "yjs";
diff --git a/examples/editor/examples/react-custom-blocks/App.tsx b/examples/editor/examples/react-custom-blocks/App.tsx
index 43750998a0..16ed570114 100644
--- a/examples/editor/examples/react-custom-blocks/App.tsx
+++ b/examples/editor/examples/react-custom-blocks/App.tsx
@@ -5,6 +5,7 @@ import {
createReactBlockSpec,
useBlockNote,
} from "@blocknote/react";
+import "../vanilla-custom-blocks/style.css";
type WindowWithProseMirror = Window & typeof globalThis & { ProseMirror: any };
@@ -48,14 +49,8 @@ export const alertBlock = createReactBlockSpec(
{
render: (props) => (
+
{"["}
{"{"}
-
+
{"}"}
{"]"}
@@ -119,6 +127,7 @@ export function ReactCustomBlocks() {
blockSpecs: {
...defaultBlockSpecs,
alert: alertBlock,
+ simpleImage: simpleImageBlock,
bracketsParagraph: bracketsParagraphBlock,
},
initialContent: [
@@ -129,6 +138,12 @@ export function ReactCustomBlocks() {
},
content: "Alert",
},
+ {
+ type: "simpleImage",
+ props: {
+ src: "https://t3.ftcdn.net/jpg/02/48/42/64/360_F_248426448_NVKLywWqArG2ADUxDq6QprtIzsF82dMF.jpg",
+ },
+ },
{
type: "bracketsParagraph",
content: "Brackets Paragraph",
diff --git a/examples/editor/examples/react-custom-styles/App.tsx b/examples/editor/examples/react-custom-styles/App.tsx
index 6c82ca2bcf..beee30f385 100644
--- a/examples/editor/examples/react-custom-styles/App.tsx
+++ b/examples/editor/examples/react-custom-styles/App.tsx
@@ -1,22 +1,20 @@
+import {
+ BlockNoteEditor,
+ DefaultBlockSchema,
+ DefaultInlineContentSchema,
+ defaultStyleSpecs,
+} from "@blocknote/core";
import "@blocknote/core/style.css";
import {
BlockNoteView,
+ createReactStyleSpec,
FormattingToolbarPositioner,
Toolbar,
ToolbarButton,
- createReactStyleSpec,
useActiveStyles,
useBlockNote,
} from "@blocknote/react";
-import {
- BlockNoteEditor,
- DefaultBlockSchema,
- DefaultInlineContentSchema,
- StyleSchemaFromSpecs,
- defaultStyleSpecs,
-} from "@blocknote/core";
-
type WindowWithProseMirror = Window & typeof globalThis & { ProseMirror: any };
const small = createReactStyleSpec(
@@ -45,16 +43,13 @@ const fontSize = createReactStyleSpec(
}
);
-const customReactStyles = {
- ...defaultStyleSpecs,
- small,
- fontSize,
-};
-
type MyEditorType = BlockNoteEditor<
DefaultBlockSchema,
DefaultInlineContentSchema,
- StyleSchemaFromSpecs
+ {
+ small: (typeof small)["config"];
+ fontSize: (typeof fontSize)["config"];
+ }
>;
const CustomFormattingToolbar = (props: { editor: MyEditorType }) => {
@@ -86,6 +81,12 @@ const CustomFormattingToolbar = (props: { editor: MyEditorType }) => {
);
};
+const customReactStyles = {
+ ...defaultStyleSpecs,
+ small,
+ fontSize,
+};
+
export function ReactStyles() {
const editor = useBlockNote(
{
diff --git a/examples/editor/examples/vanilla-custom-blocks/App.tsx b/examples/editor/examples/vanilla-custom-blocks/App.tsx
index 2bdfde7ce9..dadb8b9c67 100644
--- a/examples/editor/examples/vanilla-custom-blocks/App.tsx
+++ b/examples/editor/examples/vanilla-custom-blocks/App.tsx
@@ -5,6 +5,7 @@ import {
} from "@blocknote/core";
import "@blocknote/core/style.css";
import { BlockNoteView, useBlockNote } from "@blocknote/react";
+import "./style.css";
type WindowWithProseMirror = Window & typeof globalThis & { ProseMirror: any };
@@ -48,9 +49,7 @@ const alertBlock = createBlockSpec(
{
render: (block, editor) => {
const alert = document.createElement("div");
- Object.entries(alertStyles).forEach(([key, value]) => {
- alert.style[key as any] = value;
- });
+ alert.className = "alert";
alert.style.backgroundColor =
alertTypes[block.props.type].backgroundColor;
@@ -110,16 +109,30 @@ const alertBlock = createBlockSpec(
}
);
-// TODO: use CSS?
-const alertStyles = {
- display: "flex",
- justifyContent: "center",
- alignItems: "center",
- flexGrow: "1",
- height: "48px",
- padding: "4px",
- maxWidth: "100%",
-};
+const simpleImageBlock = createBlockSpec(
+ {
+ type: "simpleImage",
+ propSchema: {
+ src: {
+ default:
+ "https://www.pulsecarshalton.co.uk/wp-content/uploads/2016/08/jk-placeholder-image.jpg",
+ },
+ },
+ content: "none",
+ },
+ {
+ render: (block) => {
+ const image = document.createElement("img");
+ image.className = "simple-image";
+ image.src = block.props.src;
+ image.alt = "placeholder";
+
+ return {
+ dom: image,
+ };
+ },
+ }
+);
const bracketsParagraphBlock = createBlockSpec(
{
@@ -132,9 +145,7 @@ const bracketsParagraphBlock = createBlockSpec(
{
render: () => {
const bracketsParagraph = document.createElement("div");
- Object.entries(bracketsParagraphStyles).forEach(([key, value]) => {
- bracketsParagraph.style[key as any] = value;
- });
+ bracketsParagraph.className = "brackets-paragraph";
const leftBracket = document.createElement("div");
leftBracket.contentEditable = "false";
@@ -146,7 +157,7 @@ const bracketsParagraphBlock = createBlockSpec(
bracketsParagraph.appendChild(leftCurlyBracket);
const inlineContent = document.createElement("div");
- inlineContent.style.flexGrow = "1";
+ inlineContent.className = "inline-content";
bracketsParagraph.appendChild(inlineContent);
@@ -167,17 +178,6 @@ const bracketsParagraphBlock = createBlockSpec(
}
);
-// TODO: use CSS
-const bracketsParagraphStyles = {
- display: "flex",
- justifyContent: "center",
- alignItems: "center",
- flexGrow: "1",
- height: "48px",
- padding: "4px",
- maxWidth: "100%",
-};
-
export function CustomBlocks() {
const editor = useBlockNote({
domAttributes: {
@@ -190,6 +190,7 @@ export function CustomBlocks() {
...defaultBlockSpecs,
alert: alertBlock,
bracketsParagraph: bracketsParagraphBlock,
+ simpleImage: simpleImageBlock,
},
initialContent: [
{
@@ -199,6 +200,12 @@ export function CustomBlocks() {
},
content: ["Alert"],
},
+ {
+ type: "simpleImage",
+ props: {
+ src: "https://t3.ftcdn.net/jpg/02/48/42/64/360_F_248426448_NVKLywWqArG2ADUxDq6QprtIzsF82dMF.jpg",
+ },
+ },
{
type: "bracketsParagraph",
content: "Brackets Paragraph",
diff --git a/examples/editor/examples/vanilla-custom-blocks/style.css b/examples/editor/examples/vanilla-custom-blocks/style.css
new file mode 100644
index 0000000000..38747f13bc
--- /dev/null
+++ b/examples/editor/examples/vanilla-custom-blocks/style.css
@@ -0,0 +1,17 @@
+.alert, .brackets-paragraph {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-grow: 1;
+ height: 48px;
+ padding: 4px;
+ max-width: 100%;
+}
+
+.simple-image {
+ width: 100%;
+}
+
+.inline-content {
+ flex-grow: 1;
+}
\ No newline at end of file
diff --git a/examples/editor/examples/vanilla-custom-styles/App.tsx b/examples/editor/examples/vanilla-custom-styles/App.tsx
new file mode 100644
index 0000000000..ce92919452
--- /dev/null
+++ b/examples/editor/examples/vanilla-custom-styles/App.tsx
@@ -0,0 +1,146 @@
+import {
+ BlockNoteEditor,
+ createStyleSpec,
+ DefaultBlockSchema,
+ DefaultInlineContentSchema,
+ defaultStyleSpecs,
+} from "@blocknote/core";
+import "@blocknote/core/style.css";
+import {
+ BlockNoteView,
+ FormattingToolbarPositioner,
+ Toolbar,
+ ToolbarButton,
+ useActiveStyles,
+ useBlockNote,
+} from "@blocknote/react";
+
+type WindowWithProseMirror = Window & typeof globalThis & { ProseMirror: any };
+
+const small = createStyleSpec(
+ {
+ type: "small",
+ propSchema: "boolean",
+ },
+ {
+ render: () => {
+ const small = document.createElement("small");
+
+ return {
+ dom: small,
+ contentDOM: small,
+ };
+ },
+ }
+);
+
+const fontSize = createStyleSpec(
+ {
+ type: "fontSize",
+ propSchema: "string",
+ },
+ {
+ render: (value) => {
+ const span = document.createElement("span");
+ span.style.fontSize = value;
+
+ return {
+ dom: span,
+ contentDOM: span,
+ };
+ },
+ }
+);
+
+type MyEditorType = BlockNoteEditor<
+ DefaultBlockSchema,
+ DefaultInlineContentSchema,
+ {
+ small: (typeof small)["config"];
+ fontSize: (typeof fontSize)["config"];
+ }
+>;
+
+const CustomFormattingToolbar = (props: { editor: MyEditorType }) => {
+ const activeStyles = useActiveStyles(props.editor);
+
+ return (
+
+ {
+ props.editor.toggleStyles({
+ small: true,
+ });
+ }}
+ isSelected={activeStyles.small}>
+ Small
+
+ {
+ props.editor.toggleStyles({
+ fontSize: "30px",
+ });
+ }}
+ isSelected={!!activeStyles.fontSize}>
+ Font size
+
+
+ );
+};
+
+export function Styles() {
+ const editor = useBlockNote(
+ {
+ styleSpecs: {
+ ...defaultStyleSpecs,
+ small,
+ fontSize,
+ },
+ onEditorContentChange: (editor) => {
+ console.log(editor.topLevelBlocks);
+ },
+ domAttributes: {
+ editor: {
+ class: "editor",
+ "data-test": "editor",
+ },
+ },
+ initialContent: [
+ {
+ type: "paragraph",
+ content: [
+ {
+ type: "text",
+ text: "large text",
+ styles: {
+ fontSize: "30px",
+ },
+ },
+ {
+ type: "text",
+ text: "small text",
+ styles: {
+ small: true,
+ },
+ },
+ ],
+ },
+ ],
+ },
+ []
+ );
+
+ // Give tests a way to get prosemirror instance
+ (window as WindowWithProseMirror).ProseMirror = editor?._tiptapEditor;
+
+ return (
+
+
+
+ );
+}