Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions examples/02-backend/04-rendering-static-documents/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@ This example has the HTML hard-coded, but shows at least how the document will b
export default function App() {
// This HTML is generated by the ServerBlockNoteEditor.blocksToFullHTML method
const html = `<div class="bn-block-group" data-node-type="blockGroup">
<div class="bn-block-outer" data-node-type="blockOuter" data-id="1" data-text-color="yellow" data-background-color="blue">
<div class="bn-block" data-node-type="blockContainer" data-id="1" data-text-color="yellow" data-background-color="blue">
<div class="bn-block-content" data-content-type="heading" data-text-alignment="right" data-level="2">
<div class="bn-block-outer" data-node-type="blockOuter" data-id="1">
<div class="bn-block" data-node-type="blockContainer" data-id="1">
<div class="bn-block-content" data-content-type="heading" data-background-color="blue" data-text-color="yellow" data-text-alignment="right" data-level="2">
<h2 class="bn-inline-content">
<strong><u>Heading </u></strong><em><s>2</s></em>
</h2>
</div>
<div class="bn-block-group" data-node-type="blockGroup">
<div class="bn-block-outer" data-node-type="blockOuter" data-id="2" data-background-color="red">
<div class="bn-block" data-node-type="blockContainer" data-id="2" data-background-color="red">
<div class="bn-block-content" data-content-type="paragraph">
<div class="bn-block-outer" data-node-type="blockOuter" data-id="2">
<div class="bn-block" data-node-type="blockContainer" data-id="2">
<div class="bn-block-content" data-content-type="paragraph" data-background-color="red">
<p class="bn-inline-content">Paragraph</p>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"playground": true,
"docs": false,
"author": "matthewlipski",
"tags": ["Intermediate", "Blocks", "Custom Schemas"]
}
8 changes: 8 additions & 0 deletions examples/06-custom-schema/08-non-editable-block/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Non-Editable Block

In this example, we create a custom block which renders a simple HTML paragraph with placeholder text. The block has no editable content.

**Relevant Docs:**

- [Custom Blocks](/docs/features/custom-schemas/custom-blocks)
- [Editor Setup](/docs/getting-started/editor-setup)
14 changes: 14 additions & 0 deletions examples/06-custom-schema/08-non-editable-block/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Non-Editable Block</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
</script>
</head>
<body>
<div id="root"></div>
<script type="module" src="./main.tsx"></script>
</body>
</html>
11 changes: 11 additions & 0 deletions examples/06-custom-schema/08-non-editable-block/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY
import React from "react";
import { createRoot } from "react-dom/client";
import App from "./src/App.jsx";

const root = createRoot(document.getElementById("root")!);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
31 changes: 31 additions & 0 deletions examples/06-custom-schema/08-non-editable-block/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "@blocknote/example-custom-schema-non-editable-block",
"description": "AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY",
"type": "module",
"private": true,
"version": "0.12.4",
"scripts": {
"start": "vite",
"dev": "vite",
"build:prod": "tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"@blocknote/ariakit": "latest",
"@blocknote/core": "latest",
"@blocknote/mantine": "latest",
"@blocknote/react": "latest",
"@blocknote/shadcn": "latest",
"@mantine/core": "^8.3.11",
"@mantine/hooks": "^8.3.11",
"@mantine/utils": "^6.0.22",
"react": "^19.2.3",
"react-dom": "^19.2.3"
},
"devDependencies": {
"@types/react": "^19.2.3",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^6.0.1",
"vite": "^8.0.8"
}
}
38 changes: 38 additions & 0 deletions examples/06-custom-schema/08-non-editable-block/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { BlockNoteSchema } from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";
import { useCreateBlockNote } from "@blocknote/react";

import { createNonEditableBlock } from "./NonEditableBlock";

// Our schema with block specs, which contain the configs and implementations for
// blocks that we want our editor to use.
const schema = BlockNoteSchema.create().extend({
blockSpecs: {
// Creates an instance of the Non-Editable block and adds it to the schema.
nonEditable: createNonEditableBlock(),
},
});

export default function App() {
// Creates a new editor instance.
const editor = useCreateBlockNote({
schema,
initialContent: [
{
type: "paragraph",
content: "Welcome to this demo!",
},
{
type: "nonEditable",
},
{
type: "paragraph",
},
],
});

// Renders the editor instance.
return <BlockNoteView editor={editor} />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { createReactBlockSpec } from "@blocknote/react";

// The Non-Editable block.
export const createNonEditableBlock = createReactBlockSpec(
{
type: "nonEditable",
propSchema: {},
content: "none",
},
{
render: () => <p>This is a non-editable block.</p>,
},
);
36 changes: 36 additions & 0 deletions examples/06-custom-schema/08-non-editable-block/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"__comment": "AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY",
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"lib": [
"DOM",
"DOM.Iterable",
"ESNext"
],
"allowJs": false,
"skipLibCheck": true,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"composite": true
},
"include": [
"."
],
"__ADD_FOR_LOCAL_DEV_references": [
{
"path": "../../../packages/core/"
},
{
"path": "../../../packages/react/"
}
]
}
32 changes: 32 additions & 0 deletions examples/06-custom-schema/08-non-editable-block/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY
import react from "@vitejs/plugin-react";
import * as fs from "fs";
import * as path from "path";
import { defineConfig } from "vite";
// import eslintPlugin from "vite-plugin-eslint";
// https://vitejs.dev/config/
export default defineConfig((conf) => ({
plugins: [react()],
optimizeDeps: {},
build: {
sourcemap: true,
},
resolve: {
alias:
conf.command === "build" ||
!fs.existsSync(path.resolve(__dirname, "../../packages/core/src"))
? {}
: ({
// Comment out the lines below to load a built version of blocknote
// or, keep as is to load live from sources with live reload working
"@blocknote/core": path.resolve(
__dirname,
"../../packages/core/src/"
),
"@blocknote/react": path.resolve(
__dirname,
"../../packages/react/src/"
),
} as any),
},
}));
47 changes: 38 additions & 9 deletions packages/core/src/blocks/Table/TableExtension.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import { callOrReturn, Extension, getExtensionField } from "@tiptap/core";
import { columnResizing, goToNextCell, tableEditing } from "prosemirror-tables";
import { TextSelection } from "prosemirror-state";
import {
columnResizing,
goToNextCell,
isInTable,
moveCellForward,
nextCell,
selectionCell,
tableEditing,
} from "prosemirror-tables";

export const RESIZE_MIN_WIDTH = 35;
export const EMPTY_CELL_WIDTH = 120;
Expand All @@ -24,19 +33,39 @@ export const TableExtension = Extension.create({

addKeyboardShortcuts() {
return {
// Makes enter create a new line within the cell.
// Moves the selection to the cell below.
Enter: () => {
if (
this.editor.state.selection.empty &&
this.editor.state.selection.$head.parent.type.name ===
"tableParagraph"
this.editor.state.selection.$head.parent.type.name !==
"tableParagraph"
) {
this.editor.commands.insertContent({ type: "hardBreak" });

return true;
return false;
}

return false;
return this.editor.commands.command(({ state, dispatch }) => {
if (!isInTable(state)) {
return false;
}

const $cell = selectionCell(state);
const $nextCell = nextCell($cell, "vert", 1);

if (!$nextCell) {
return false;
}

if (dispatch) {
dispatch(
state.tr
.setSelection(
TextSelection.between($nextCell, moveCellForward($nextCell)),
)
.scrollIntoView(),
);
}

return true;
});
},
// Ensures that backspace won't delete the table if the text cursor is at
// the start of a cell and the selection is empty.
Expand Down
Loading