diff --git a/.eslintrc.js b/.eslintrc.js
index 983f7ae31e..dee0b4c119 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -24,6 +24,7 @@ module.exports = {
},
},
},
+ ignorePatterns: ["**/ui/*"],
rules: {
curly: 1,
"import/no-extraneous-dependencies": [
diff --git a/docs/components/pages/landing/hero/DemoEditor.tsx b/docs/components/pages/landing/hero/DemoEditor.tsx
index b57d50203f..acb58ee337 100644
--- a/docs/components/pages/landing/hero/DemoEditor.tsx
+++ b/docs/components/pages/landing/hero/DemoEditor.tsx
@@ -1,7 +1,8 @@
import { uploadToTmpFilesDotOrg_DEV_ONLY } from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import { useCallback, useMemo, useState } from "react";
import YPartyKitProvider from "y-partykit/provider";
import * as Y from "yjs";
diff --git a/docs/package.json b/docs/package.json
index 4970829479..6634864f93 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -11,6 +11,9 @@
"dependencies": {
"@blocknote/core": "^0.12.1",
"@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"@headlessui/react": "^1.7.18",
"@mantine/core": "^7.5.0",
"@next/bundle-analyzer": "^14.1.0",
diff --git a/docs/pages/docs/quickstart.mdx b/docs/pages/docs/quickstart.mdx
index c33ef16616..71b7ea054c 100644
--- a/docs/pages/docs/quickstart.mdx
+++ b/docs/pages/docs/quickstart.mdx
@@ -17,7 +17,7 @@ Getting started with BlockNote is quick and easy. Install the required packages
To install BlockNote with [NPM](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm), run:
```console
-npm install @blocknote/core @blocknote/react
+npm install @blocknote/core @blocknote/react @blocknote/mantine
```
## Creating an Editor
@@ -26,7 +26,7 @@ With the `useCreateBlockNote` hook, we can create a new editor instance, then us
-We also import `@blocknote/react/style.css` to add default styling for the editor and the `Inter` font that BlockNote exports (optional).
+We also import `@blocknote/mantine/style.css` to add default styling for the editor and the `Inter` font that BlockNote exports (optional).
Next.js usage (or other server-side React frameworks)
diff --git a/examples/01-basic/01-minimal/App.tsx b/examples/01-basic/01-minimal/App.tsx
index 55a0cc8e69..c545b7b4dd 100644
--- a/examples/01-basic/01-minimal/App.tsx
+++ b/examples/01-basic/01-minimal/App.tsx
@@ -1,6 +1,7 @@
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
export default function App() {
// Creates a new editor instance.
diff --git a/examples/01-basic/01-minimal/package.json b/examples/01-basic/01-minimal/package.json
index 41993cc9e0..64d0e12aa8 100644
--- a/examples/01-basic/01-minimal/package.json
+++ b/examples/01-basic/01-minimal/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/01-basic/02-block-objects/App.tsx b/examples/01-basic/02-block-objects/App.tsx
index 45cd7c39e6..846df5d180 100644
--- a/examples/01-basic/02-block-objects/App.tsx
+++ b/examples/01-basic/02-block-objects/App.tsx
@@ -1,7 +1,8 @@
import { Block } from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import { useState } from "react";
import "./styles.css";
diff --git a/examples/01-basic/02-block-objects/package.json b/examples/01-basic/02-block-objects/package.json
index 0acac38a6d..81cd70690d 100644
--- a/examples/01-basic/02-block-objects/package.json
+++ b/examples/01-basic/02-block-objects/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/01-basic/03-all-blocks/App.tsx b/examples/01-basic/03-all-blocks/App.tsx
index 19758e6017..ff6e4d05bd 100644
--- a/examples/01-basic/03-all-blocks/App.tsx
+++ b/examples/01-basic/03-all-blocks/App.tsx
@@ -1,6 +1,7 @@
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
export default function App() {
// Creates a new editor instance.
diff --git a/examples/01-basic/03-all-blocks/package.json b/examples/01-basic/03-all-blocks/package.json
index 39561f0b95..efa243f30e 100644
--- a/examples/01-basic/03-all-blocks/package.json
+++ b/examples/01-basic/03-all-blocks/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/01-basic/04-selection-blocks/App.tsx b/examples/01-basic/04-selection-blocks/App.tsx
index 5649a37878..5251754f5a 100644
--- a/examples/01-basic/04-selection-blocks/App.tsx
+++ b/examples/01-basic/04-selection-blocks/App.tsx
@@ -1,7 +1,8 @@
import { Block } from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import { useState } from "react";
import "./styles.css";
diff --git a/examples/01-basic/04-selection-blocks/package.json b/examples/01-basic/04-selection-blocks/package.json
index e087a6d5ff..a541c96eb2 100644
--- a/examples/01-basic/04-selection-blocks/package.json
+++ b/examples/01-basic/04-selection-blocks/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/01-basic/05-block-manipulation/App.tsx b/examples/01-basic/05-block-manipulation/App.tsx
index f961d3527d..412f39c56e 100644
--- a/examples/01-basic/05-block-manipulation/App.tsx
+++ b/examples/01-basic/05-block-manipulation/App.tsx
@@ -1,6 +1,7 @@
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import "./styles.css";
diff --git a/examples/01-basic/05-block-manipulation/package.json b/examples/01-basic/05-block-manipulation/package.json
index 9a0b49bbf6..951063ca7b 100644
--- a/examples/01-basic/05-block-manipulation/package.json
+++ b/examples/01-basic/05-block-manipulation/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/01-basic/06-file-uploading/App.tsx b/examples/01-basic/06-file-uploading/App.tsx
index c7fea399e8..725c2346a9 100644
--- a/examples/01-basic/06-file-uploading/App.tsx
+++ b/examples/01-basic/06-file-uploading/App.tsx
@@ -1,6 +1,7 @@
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
// Uploads a file to tmpfiles.org and returns the URL to the uploaded file.
async function uploadFile(file: File) {
diff --git a/examples/01-basic/06-file-uploading/package.json b/examples/01-basic/06-file-uploading/package.json
index 4d80ea85cb..fc41e7bf39 100644
--- a/examples/01-basic/06-file-uploading/package.json
+++ b/examples/01-basic/06-file-uploading/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/01-basic/07-saving-loading/App.tsx b/examples/01-basic/07-saving-loading/App.tsx
index df8a07b99e..5fe11c206b 100644
--- a/examples/01-basic/07-saving-loading/App.tsx
+++ b/examples/01-basic/07-saving-loading/App.tsx
@@ -1,7 +1,7 @@
import { Block, BlockNoteEditor, PartialBlock } from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import { useEffect, useMemo, useState } from "react";
async function saveToStorage(jsonBlocks: Block[]) {
diff --git a/examples/01-basic/07-saving-loading/package.json b/examples/01-basic/07-saving-loading/package.json
index 927b53a1d9..15446d53a9 100644
--- a/examples/01-basic/07-saving-loading/package.json
+++ b/examples/01-basic/07-saving-loading/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/01-basic/08-shadcn/App.tsx b/examples/01-basic/08-shadcn/App.tsx
index c3bf0fdb2b..754b4a5e94 100644
--- a/examples/01-basic/08-shadcn/App.tsx
+++ b/examples/01-basic/08-shadcn/App.tsx
@@ -1,12 +1,22 @@
import "@blocknote/core/fonts/inter.css";
import { useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
import { BlockNoteView } from "@blocknote/shadcn";
+import "@blocknote/shadcn/style.css";
export default function App() {
// Creates a new editor instance.
const editor = useCreateBlockNote();
// Renders the editor instance using a React component.
- return ;
+ return (
+
+ );
}
diff --git a/examples/01-basic/08-shadcn/README.md b/examples/01-basic/08-shadcn/README.md
index 9e6a3791ae..3056c8f9a5 100644
--- a/examples/01-basic/08-shadcn/README.md
+++ b/examples/01-basic/08-shadcn/README.md
@@ -1,6 +1,6 @@
-# Basic Setup TODO
+# Use with ShadCN
-This example shows the minimal code required to set up a BlockNote editor in React.
+This example shows how you can integrate BlockNote with ShadCN, replacing the default Mantine UI with ShadCN components.
**Relevant Docs:**
diff --git a/examples/01-basic/08-shadcn/index.html b/examples/01-basic/08-shadcn/index.html
index 4a44d67d81..c70c418c1a 100644
--- a/examples/01-basic/08-shadcn/index.html
+++ b/examples/01-basic/08-shadcn/index.html
@@ -5,7 +5,7 @@
- Basic Setup TODO
+ Use with ShadCN
diff --git a/examples/01-basic/08-shadcn/package.json b/examples/01-basic/08-shadcn/package.json
index 0f0acf3a1f..b230f15c03 100644
--- a/examples/01-basic/08-shadcn/package.json
+++ b/examples/01-basic/08-shadcn/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/01-basic/09-ariakit/.bnexample.json b/examples/01-basic/09-ariakit/.bnexample.json
new file mode 100644
index 0000000000..6d4a02dd52
--- /dev/null
+++ b/examples/01-basic/09-ariakit/.bnexample.json
@@ -0,0 +1,6 @@
+{
+ "playground": true,
+ "docs": true,
+ "author": "matthewlipski",
+ "tags": ["Basic"]
+}
diff --git a/examples/01-basic/09-ariakit/App.tsx b/examples/01-basic/09-ariakit/App.tsx
new file mode 100644
index 0000000000..1a86f6b436
--- /dev/null
+++ b/examples/01-basic/09-ariakit/App.tsx
@@ -0,0 +1,12 @@
+import "@blocknote/core/fonts/inter.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/ariakit";
+import "@blocknote/ariakit/style.css";
+
+export default function App() {
+ // Creates a new editor instance.
+ const editor = useCreateBlockNote();
+
+ // Renders the editor instance using a React component.
+ return ;
+}
diff --git a/examples/01-basic/09-ariakit/README.md b/examples/01-basic/09-ariakit/README.md
new file mode 100644
index 0000000000..50d7787e6a
--- /dev/null
+++ b/examples/01-basic/09-ariakit/README.md
@@ -0,0 +1,7 @@
+# Use with Ariakit
+
+This example shows how you can integrate BlockNote with Ariakit, replacing the default Mantine UI with Ariakit components.
+
+**Relevant Docs:**
+
+- [Editor Setup](/docs/editor-basics/setup)
diff --git a/examples/01-basic/09-ariakit/index.html b/examples/01-basic/09-ariakit/index.html
new file mode 100644
index 0000000000..f394c4992a
--- /dev/null
+++ b/examples/01-basic/09-ariakit/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+ Use with Ariakit
+
+
+
+
+
+
diff --git a/packages/shadcn/src/main.tsx b/examples/01-basic/09-ariakit/main.tsx
similarity index 51%
rename from packages/shadcn/src/main.tsx
rename to examples/01-basic/09-ariakit/main.tsx
index 54a23b9d15..f88b490fbd 100644
--- a/packages/shadcn/src/main.tsx
+++ b/examples/01-basic/09-ariakit/main.tsx
@@ -1,14 +1,11 @@
+// AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY
import React from "react";
import { createRoot } from "react-dom/client";
+import App from "./App";
-import { Button } from "./components/ui/button";
-import "./style.css";
const root = createRoot(document.getElementById("root")!);
root.render(
-
+
);
diff --git a/examples/01-basic/09-ariakit/package.json b/examples/01-basic/09-ariakit/package.json
new file mode 100644
index 0000000000..910ef472df
--- /dev/null
+++ b/examples/01-basic/09-ariakit/package.json
@@ -0,0 +1,37 @@
+{
+ "name": "@blocknote/example-ariakit",
+ "description": "AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY",
+ "private": true,
+ "version": "0.12.0",
+ "scripts": {
+ "start": "vite",
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "preview": "vite preview",
+ "lint": "eslint . --max-warnings 0"
+ },
+ "dependencies": {
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ },
+ "devDependencies": {
+ "@types/react": "^18.0.25",
+ "@types/react-dom": "^18.0.9",
+ "@vitejs/plugin-react": "^4.0.4",
+ "eslint": "^8.10.0",
+ "vite": "^4.4.8"
+ },
+ "eslintConfig": {
+ "extends": [
+ "../../../.eslintrc.js"
+ ]
+ },
+ "eslintIgnore": [
+ "dist"
+ ]
+}
\ No newline at end of file
diff --git a/examples/01-basic/09-ariakit/tsconfig.json b/examples/01-basic/09-ariakit/tsconfig.json
new file mode 100644
index 0000000000..1bd8ab3c57
--- /dev/null
+++ b/examples/01-basic/09-ariakit/tsconfig.json
@@ -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": "Node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+ "composite": true
+ },
+ "include": [
+ "."
+ ],
+ "__ADD_FOR_LOCAL_DEV_references": [
+ {
+ "path": "../../../packages/core/"
+ },
+ {
+ "path": "../../../packages/react/"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/examples/01-basic/09-ariakit/vite.config.ts b/examples/01-basic/09-ariakit/vite.config.ts
new file mode 100644
index 0000000000..f62ab20bc2
--- /dev/null
+++ b/examples/01-basic/09-ariakit/vite.config.ts
@@ -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),
+ },
+}));
diff --git a/examples/01-basic/testing/App.tsx b/examples/01-basic/testing/App.tsx
index 5bc1b1c47d..de439b5928 100644
--- a/examples/01-basic/testing/App.tsx
+++ b/examples/01-basic/testing/App.tsx
@@ -1,7 +1,8 @@
import { uploadToTmpFilesDotOrg_DEV_ONLY } from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
export default function App() {
// Creates a new editor instance.
diff --git a/examples/01-basic/testing/package.json b/examples/01-basic/testing/package.json
index 451c22b29e..5109368ec6 100644
--- a/examples/01-basic/testing/package.json
+++ b/examples/01-basic/testing/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/02-ui-components/01-ui-elements-remove/App.tsx b/examples/02-ui-components/01-ui-elements-remove/App.tsx
index 0f67fdc449..b2f9038ab6 100644
--- a/examples/02-ui-components/01-ui-elements-remove/App.tsx
+++ b/examples/02-ui-components/01-ui-elements-remove/App.tsx
@@ -1,6 +1,7 @@
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
export default function App() {
// Creates a new editor instance.
diff --git a/examples/02-ui-components/01-ui-elements-remove/package.json b/examples/02-ui-components/01-ui-elements-remove/package.json
index 01bc2f7fc2..670a9fb53c 100644
--- a/examples/02-ui-components/01-ui-elements-remove/package.json
+++ b/examples/02-ui-components/01-ui-elements-remove/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/02-ui-components/02-formatting-toolbar-buttons/App.tsx b/examples/02-ui-components/02-formatting-toolbar-buttons/App.tsx
index 8f44929e33..779452273d 100644
--- a/examples/02-ui-components/02-formatting-toolbar-buttons/App.tsx
+++ b/examples/02-ui-components/02-formatting-toolbar-buttons/App.tsx
@@ -1,7 +1,6 @@
import "@blocknote/core/fonts/inter.css";
import {
BasicTextStyleButton,
- BlockNoteView,
BlockTypeSelect,
ColorStyleButton,
CreateLinkButton,
@@ -14,7 +13,8 @@ import {
UnnestBlockButton,
useCreateBlockNote,
} from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import { BlueButton } from "./BlueButton";
diff --git a/examples/02-ui-components/02-formatting-toolbar-buttons/BlueButton.tsx b/examples/02-ui-components/02-formatting-toolbar-buttons/BlueButton.tsx
index 4cde53596c..48400a273e 100644
--- a/examples/02-ui-components/02-formatting-toolbar-buttons/BlueButton.tsx
+++ b/examples/02-ui-components/02-formatting-toolbar-buttons/BlueButton.tsx
@@ -1,14 +1,17 @@
import {
- ToolbarButton,
useBlockNoteEditor,
+ useComponentsContext,
useEditorContentOrSelectionChange,
} from "@blocknote/react";
+import "@blocknote/mantine/style.css";
import { useState } from "react";
// Custom Formatting Toolbar Button to toggle blue text & background color.
export function BlueButton() {
const editor = useBlockNoteEditor();
+ const Components = useComponentsContext()!;
+
// Tracks whether the text & background are both blue.
const [isSelected, setIsSelected] = useState(
editor.getActiveStyles().textColor === "blue" &&
@@ -24,7 +27,7 @@ export function BlueButton() {
}, editor);
return (
- {
editor.toggleStyles({
@@ -34,6 +37,6 @@ export function BlueButton() {
}}
isSelected={isSelected}>
Blue
-
+
);
}
diff --git a/examples/02-ui-components/02-formatting-toolbar-buttons/package.json b/examples/02-ui-components/02-formatting-toolbar-buttons/package.json
index e4db1b4ba8..49fbb2416e 100644
--- a/examples/02-ui-components/02-formatting-toolbar-buttons/package.json
+++ b/examples/02-ui-components/02-formatting-toolbar-buttons/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/02-ui-components/03-formatting-toolbar-block-type-items/App.tsx b/examples/02-ui-components/03-formatting-toolbar-block-type-items/App.tsx
index 0ede58d56e..fce0767f09 100644
--- a/examples/02-ui-components/03-formatting-toolbar-block-type-items/App.tsx
+++ b/examples/02-ui-components/03-formatting-toolbar-block-type-items/App.tsx
@@ -1,14 +1,14 @@
import { BlockNoteSchema, defaultBlockSpecs } from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
import {
- BlockNoteView,
+ BlockTypeSelectItem,
FormattingToolbar,
FormattingToolbarController,
- useCreateBlockNote,
blockTypeSelectItems,
- BlockTypeSelectItem,
+ useCreateBlockNote,
} from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import { RiAlertFill } from "react-icons/ri";
import { Alert } from "./Alert";
@@ -56,7 +56,7 @@ export default function App() {
formattingToolbar={() => (
+
{
editor.removeBlocks([props.block]);
}}
/>
-
+
);
}
diff --git a/examples/02-ui-components/04-side-menu-buttons/package.json b/examples/02-ui-components/04-side-menu-buttons/package.json
index c5c820c0cb..ff499b2065 100644
--- a/examples/02-ui-components/04-side-menu-buttons/package.json
+++ b/examples/02-ui-components/04-side-menu-buttons/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.3.1"
diff --git a/examples/02-ui-components/05-side-menu-drag-handle-items/App.tsx b/examples/02-ui-components/05-side-menu-drag-handle-items/App.tsx
index 8652837ae1..9f9cb25f57 100644
--- a/examples/02-ui-components/05-side-menu-drag-handle-items/App.tsx
+++ b/examples/02-ui-components/05-side-menu-drag-handle-items/App.tsx
@@ -1,15 +1,15 @@
import "@blocknote/core/fonts/inter.css";
import {
BlockColorsItem,
- BlockNoteView,
DragHandleMenu,
- DragHandleMenuItem,
RemoveBlockItem,
SideMenu,
SideMenuController,
+ useComponentsContext,
useCreateBlockNote,
} from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
export default function App() {
// Creates a new editor instance.
@@ -34,6 +34,8 @@ export default function App() {
],
});
+ const Components = useComponentsContext()!;
+
// Renders the editor instance.
return (
@@ -46,12 +48,12 @@ export default function App() {
Delete
Colors
{/* Item which resets the hovered block's type. */}
- {
editor.updateBlock(props.block, { type: "paragraph" });
}}>
Reset Type
-
+
)}
/>
diff --git a/examples/02-ui-components/05-side-menu-drag-handle-items/package.json b/examples/02-ui-components/05-side-menu-drag-handle-items/package.json
index 9982ce078e..0b8deb595b 100644
--- a/examples/02-ui-components/05-side-menu-drag-handle-items/package.json
+++ b/examples/02-ui-components/05-side-menu-drag-handle-items/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.3.1"
diff --git a/examples/02-ui-components/06-suggestion-menus-slash-menu-items/App.tsx b/examples/02-ui-components/06-suggestion-menus-slash-menu-items/App.tsx
index bc2900fbec..984cf3d4e1 100644
--- a/examples/02-ui-components/06-suggestion-menus-slash-menu-items/App.tsx
+++ b/examples/02-ui-components/06-suggestion-menus-slash-menu-items/App.tsx
@@ -5,13 +5,13 @@ import {
} from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
import {
- BlockNoteView,
DefaultReactSuggestionItem,
getDefaultReactSlashMenuItems,
SuggestionMenuController,
useCreateBlockNote,
} from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import { HiOutlineGlobeAlt } from "react-icons/hi";
// Custom Slash Menu item to insert a block after the current one.
diff --git a/examples/02-ui-components/06-suggestion-menus-slash-menu-items/package.json b/examples/02-ui-components/06-suggestion-menus-slash-menu-items/package.json
index 87a8b55798..19e88c8643 100644
--- a/examples/02-ui-components/06-suggestion-menus-slash-menu-items/package.json
+++ b/examples/02-ui-components/06-suggestion-menus-slash-menu-items/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.3.1"
diff --git a/examples/02-ui-components/07-suggestion-menus-slash-menu-component/App.tsx b/examples/02-ui-components/07-suggestion-menus-slash-menu-component/App.tsx
index fdf1137fa7..2bd26465f0 100644
--- a/examples/02-ui-components/07-suggestion-menus-slash-menu-component/App.tsx
+++ b/examples/02-ui-components/07-suggestion-menus-slash-menu-component/App.tsx
@@ -1,12 +1,12 @@
import "@blocknote/core/fonts/inter.css";
import {
- BlockNoteView,
DefaultReactSuggestionItem,
SuggestionMenuController,
SuggestionMenuProps,
useCreateBlockNote,
} from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import "./styles.css";
diff --git a/examples/02-ui-components/07-suggestion-menus-slash-menu-component/package.json b/examples/02-ui-components/07-suggestion-menus-slash-menu-component/package.json
index 7eb92b487a..ca1f8ed468 100644
--- a/examples/02-ui-components/07-suggestion-menus-slash-menu-component/package.json
+++ b/examples/02-ui-components/07-suggestion-menus-slash-menu-component/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/02-ui-components/08-custom-ui/App.tsx b/examples/02-ui-components/08-custom-ui/App.tsx
index b447f7aefa..f3bb61a09f 100644
--- a/examples/02-ui-components/08-custom-ui/App.tsx
+++ b/examples/02-ui-components/08-custom-ui/App.tsx
@@ -1,13 +1,13 @@
import { filterSuggestionItems } from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
import {
- BlockNoteView,
getDefaultReactSlashMenuItems,
SideMenuController,
SuggestionMenuController,
useCreateBlockNote,
} from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import { CustomFormattingToolbar } from "./CustomFormattingToolbar";
import { CustomSideMenu } from "./CustomSideMenu";
diff --git a/examples/02-ui-components/08-custom-ui/package.json b/examples/02-ui-components/08-custom-ui/package.json
index 1a7a5bd426..ab13494420 100644
--- a/examples/02-ui-components/08-custom-ui/package.json
+++ b/examples/02-ui-components/08-custom-ui/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"@mantine/core": "^7.5.0",
diff --git a/examples/02-ui-components/link-toolbar-buttons/AlertButton.tsx b/examples/02-ui-components/link-toolbar-buttons/AlertButton.tsx
index 123d856b0e..b393d6077e 100644
--- a/examples/02-ui-components/link-toolbar-buttons/AlertButton.tsx
+++ b/examples/02-ui-components/link-toolbar-buttons/AlertButton.tsx
@@ -1,14 +1,16 @@
-import { LinkToolbarProps, ToolbarButton } from "@blocknote/react";
+import { LinkToolbarProps, useComponentsContext } from "@blocknote/react";
// Custom Link Toolbar button to open a browser alert.
export function AlertButton(props: LinkToolbarProps) {
+ const Components = useComponentsContext()!;
+
return (
- {
window.alert(`Link URL: ${props.url}`);
}}>
Open Alert
-
+
);
}
diff --git a/examples/02-ui-components/link-toolbar-buttons/App.tsx b/examples/02-ui-components/link-toolbar-buttons/App.tsx
index 1e4525bd72..4664d4bf28 100644
--- a/examples/02-ui-components/link-toolbar-buttons/App.tsx
+++ b/examples/02-ui-components/link-toolbar-buttons/App.tsx
@@ -1,11 +1,11 @@
import "@blocknote/core/fonts/inter.css";
import {
- BlockNoteView,
LinkToolbar,
LinkToolbarController,
useCreateBlockNote,
} from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import { AlertButton } from "./AlertButton";
diff --git a/examples/02-ui-components/link-toolbar-buttons/package.json b/examples/02-ui-components/link-toolbar-buttons/package.json
index 470ec0c68f..4f73d483cc 100644
--- a/examples/02-ui-components/link-toolbar-buttons/package.json
+++ b/examples/02-ui-components/link-toolbar-buttons/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/03-theming/01-theming-dom-attributes/App.tsx b/examples/03-theming/01-theming-dom-attributes/App.tsx
index 5f5aa61cc9..7068e12388 100644
--- a/examples/03-theming/01-theming-dom-attributes/App.tsx
+++ b/examples/03-theming/01-theming-dom-attributes/App.tsx
@@ -1,6 +1,7 @@
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import "./styles.css";
diff --git a/examples/03-theming/01-theming-dom-attributes/package.json b/examples/03-theming/01-theming-dom-attributes/package.json
index d747c5a61e..b0d1bce695 100644
--- a/examples/03-theming/01-theming-dom-attributes/package.json
+++ b/examples/03-theming/01-theming-dom-attributes/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/03-theming/02-changing-font/App.tsx b/examples/03-theming/02-changing-font/App.tsx
index e21dd05893..4ef3f9a3dd 100644
--- a/examples/03-theming/02-changing-font/App.tsx
+++ b/examples/03-theming/02-changing-font/App.tsx
@@ -1,6 +1,7 @@
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import "./styles.css";
diff --git a/examples/03-theming/02-changing-font/package.json b/examples/03-theming/02-changing-font/package.json
index ba4a149a7f..47fb985f7b 100644
--- a/examples/03-theming/02-changing-font/package.json
+++ b/examples/03-theming/02-changing-font/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/03-theming/03-theming-css/App.tsx b/examples/03-theming/03-theming-css/App.tsx
index 7a65b64349..493ae7d4ed 100644
--- a/examples/03-theming/03-theming-css/App.tsx
+++ b/examples/03-theming/03-theming-css/App.tsx
@@ -1,6 +1,7 @@
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import "./styles.css";
diff --git a/examples/03-theming/03-theming-css/package.json b/examples/03-theming/03-theming-css/package.json
index ff356edda6..1f5cd62303 100644
--- a/examples/03-theming/03-theming-css/package.json
+++ b/examples/03-theming/03-theming-css/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/03-theming/04-theming-css-variables/App.tsx b/examples/03-theming/04-theming-css-variables/App.tsx
index dcfc1a4a72..ba45053f04 100644
--- a/examples/03-theming/04-theming-css-variables/App.tsx
+++ b/examples/03-theming/04-theming-css-variables/App.tsx
@@ -1,6 +1,7 @@
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import "./styles.css";
diff --git a/examples/03-theming/04-theming-css-variables/package.json b/examples/03-theming/04-theming-css-variables/package.json
index c4a0335626..8a0c9f9822 100644
--- a/examples/03-theming/04-theming-css-variables/package.json
+++ b/examples/03-theming/04-theming-css-variables/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/03-theming/05-theming-css-variables-code/App.tsx b/examples/03-theming/05-theming-css-variables-code/App.tsx
index 0f8e944d32..e26239b446 100644
--- a/examples/03-theming/05-theming-css-variables-code/App.tsx
+++ b/examples/03-theming/05-theming-css-variables-code/App.tsx
@@ -1,12 +1,12 @@
import "@blocknote/core/fonts/inter.css";
import {
- BlockNoteView,
darkDefaultTheme,
lightDefaultTheme,
Theme,
useCreateBlockNote,
} from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
// Base theme
const lightRedTheme = {
diff --git a/examples/03-theming/05-theming-css-variables-code/package.json b/examples/03-theming/05-theming-css-variables-code/package.json
index 27c24dc2a0..ea4f2ab4be 100644
--- a/examples/03-theming/05-theming-css-variables-code/package.json
+++ b/examples/03-theming/05-theming-css-variables-code/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/04-interoperability/01-converting-blocks-to-html/App.tsx b/examples/04-interoperability/01-converting-blocks-to-html/App.tsx
index 698de6f48e..e10fe0c57f 100644
--- a/examples/04-interoperability/01-converting-blocks-to-html/App.tsx
+++ b/examples/04-interoperability/01-converting-blocks-to-html/App.tsx
@@ -1,6 +1,7 @@
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import { useState } from "react";
import "./styles.css";
diff --git a/examples/04-interoperability/01-converting-blocks-to-html/package.json b/examples/04-interoperability/01-converting-blocks-to-html/package.json
index 49508d72f5..4050c9240b 100644
--- a/examples/04-interoperability/01-converting-blocks-to-html/package.json
+++ b/examples/04-interoperability/01-converting-blocks-to-html/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/04-interoperability/02-converting-blocks-from-html/App.tsx b/examples/04-interoperability/02-converting-blocks-from-html/App.tsx
index 98af0279b5..8b53b5ac9c 100644
--- a/examples/04-interoperability/02-converting-blocks-from-html/App.tsx
+++ b/examples/04-interoperability/02-converting-blocks-from-html/App.tsx
@@ -1,6 +1,7 @@
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import { ChangeEvent, useCallback, useEffect } from "react";
import "./styles.css";
diff --git a/examples/04-interoperability/02-converting-blocks-from-html/package.json b/examples/04-interoperability/02-converting-blocks-from-html/package.json
index ec274231e4..028c64d0e4 100644
--- a/examples/04-interoperability/02-converting-blocks-from-html/package.json
+++ b/examples/04-interoperability/02-converting-blocks-from-html/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/04-interoperability/03-converting-blocks-to-md/App.tsx b/examples/04-interoperability/03-converting-blocks-to-md/App.tsx
index 1e020bfae7..c51a3ac92e 100644
--- a/examples/04-interoperability/03-converting-blocks-to-md/App.tsx
+++ b/examples/04-interoperability/03-converting-blocks-to-md/App.tsx
@@ -1,6 +1,7 @@
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import { useState } from "react";
import "./styles.css";
diff --git a/examples/04-interoperability/03-converting-blocks-to-md/package.json b/examples/04-interoperability/03-converting-blocks-to-md/package.json
index b57907e8cc..b543beab0c 100644
--- a/examples/04-interoperability/03-converting-blocks-to-md/package.json
+++ b/examples/04-interoperability/03-converting-blocks-to-md/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/04-interoperability/04-converting-blocks-from-md/App.tsx b/examples/04-interoperability/04-converting-blocks-from-md/App.tsx
index 3015c30f9d..876f5573e9 100644
--- a/examples/04-interoperability/04-converting-blocks-from-md/App.tsx
+++ b/examples/04-interoperability/04-converting-blocks-from-md/App.tsx
@@ -1,6 +1,7 @@
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import { ChangeEvent, useCallback, useEffect } from "react";
const initialMarkdown = "Hello, **world!**";
diff --git a/examples/04-interoperability/04-converting-blocks-from-md/package.json b/examples/04-interoperability/04-converting-blocks-from-md/package.json
index a1e6d389d8..47a5cca23a 100644
--- a/examples/04-interoperability/04-converting-blocks-from-md/package.json
+++ b/examples/04-interoperability/04-converting-blocks-from-md/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/05-custom-schema/01-alert-block/App.tsx b/examples/05-custom-schema/01-alert-block/App.tsx
index 0dda8fbe61..dcaefdfbdf 100644
--- a/examples/05-custom-schema/01-alert-block/App.tsx
+++ b/examples/05-custom-schema/01-alert-block/App.tsx
@@ -6,12 +6,12 @@ import {
} from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
import {
- BlockNoteView,
SuggestionMenuController,
getDefaultReactSlashMenuItems,
useCreateBlockNote,
} from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import { RiAlertFill } from "react-icons/ri";
import { Alert } from "./Alert";
diff --git a/examples/05-custom-schema/01-alert-block/package.json b/examples/05-custom-schema/01-alert-block/package.json
index ed10f99da7..d267e6cc88 100644
--- a/examples/05-custom-schema/01-alert-block/package.json
+++ b/examples/05-custom-schema/01-alert-block/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"@mantine/core": "^7.5.0",
diff --git a/examples/05-custom-schema/02-suggestion-menus-mentions/App.tsx b/examples/05-custom-schema/02-suggestion-menus-mentions/App.tsx
index d3f0463537..e86e4594e9 100644
--- a/examples/05-custom-schema/02-suggestion-menus-mentions/App.tsx
+++ b/examples/05-custom-schema/02-suggestion-menus-mentions/App.tsx
@@ -5,12 +5,12 @@ import {
} from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
import {
- BlockNoteView,
DefaultReactSuggestionItem,
SuggestionMenuController,
useCreateBlockNote,
} from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import { Mention } from "./Mention";
diff --git a/examples/05-custom-schema/02-suggestion-menus-mentions/package.json b/examples/05-custom-schema/02-suggestion-menus-mentions/package.json
index d8c980f452..e5324faf07 100644
--- a/examples/05-custom-schema/02-suggestion-menus-mentions/package.json
+++ b/examples/05-custom-schema/02-suggestion-menus-mentions/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/05-custom-schema/03-font-style/App.tsx b/examples/05-custom-schema/03-font-style/App.tsx
index edb7f96322..0035fc1bbb 100644
--- a/examples/05-custom-schema/03-font-style/App.tsx
+++ b/examples/05-custom-schema/03-font-style/App.tsx
@@ -2,7 +2,6 @@ import { BlockNoteSchema, defaultStyleSpecs } from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
import {
BasicTextStyleButton,
- BlockNoteView,
BlockTypeSelect,
ColorStyleButton,
CreateLinkButton,
@@ -12,12 +11,13 @@ import {
NestBlockButton,
ReplaceImageButton,
TextAlignButton,
- ToolbarButton,
UnnestBlockButton,
useBlockNoteEditor,
+ useComponentsContext,
useCreateBlockNote,
} from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import { RiText } from "react-icons/ri";
import { Font } from "./Font";
@@ -41,10 +41,12 @@ const SetFontStyleButton = () => {
typeof schema.styleSchema
>();
+ const Components = useComponentsContext()!;
+
return (
- }
onClick={() => {
const fontName = prompt("Enter a font name") || "Comic Sans MS";
diff --git a/examples/05-custom-schema/03-font-style/package.json b/examples/05-custom-schema/03-font-style/package.json
index f00fab3dee..29fa2ae516 100644
--- a/examples/05-custom-schema/03-font-style/package.json
+++ b/examples/05-custom-schema/03-font-style/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/05-custom-schema/react-custom-blocks/App.tsx b/examples/05-custom-schema/react-custom-blocks/App.tsx
index 49a541a21c..f92ffb7be6 100644
--- a/examples/05-custom-schema/react-custom-blocks/App.tsx
+++ b/examples/05-custom-schema/react-custom-blocks/App.tsx
@@ -4,12 +4,9 @@ import {
defaultProps,
} from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
-import {
- BlockNoteView,
- createReactBlockSpec,
- useCreateBlockNote,
-} from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { createReactBlockSpec, useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import "./styles.css";
diff --git a/examples/05-custom-schema/react-custom-blocks/package.json b/examples/05-custom-schema/react-custom-blocks/package.json
index c76019d6ce..e4ec269d8b 100644
--- a/examples/05-custom-schema/react-custom-blocks/package.json
+++ b/examples/05-custom-schema/react-custom-blocks/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/05-custom-schema/react-custom-inline-content/App.tsx b/examples/05-custom-schema/react-custom-inline-content/App.tsx
index e321420646..54f0ff7251 100644
--- a/examples/05-custom-schema/react-custom-inline-content/App.tsx
+++ b/examples/05-custom-schema/react-custom-inline-content/App.tsx
@@ -1,11 +1,11 @@
import { BlockNoteSchema, defaultInlineContentSpecs } from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
import {
- BlockNoteView,
createReactInlineContentSpec,
useCreateBlockNote,
} from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
const mention = createReactInlineContentSpec(
{
diff --git a/examples/05-custom-schema/react-custom-inline-content/package.json b/examples/05-custom-schema/react-custom-inline-content/package.json
index 0122e6fd86..00d6e21fd1 100644
--- a/examples/05-custom-schema/react-custom-inline-content/package.json
+++ b/examples/05-custom-schema/react-custom-inline-content/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/05-custom-schema/react-custom-styles/App.tsx b/examples/05-custom-schema/react-custom-styles/App.tsx
index aba31bdeda..f19533c79d 100644
--- a/examples/05-custom-schema/react-custom-styles/App.tsx
+++ b/examples/05-custom-schema/react-custom-styles/App.tsx
@@ -1,17 +1,17 @@
import { BlockNoteSchema, defaultStyleSpecs } from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
import {
- BlockNoteView,
createReactStyleSpec,
FormattingToolbar,
FormattingToolbarController,
FormattingToolbarProps,
- ToolbarButton,
useActiveStyles,
useBlockNoteEditor,
+ useComponentsContext,
useCreateBlockNote,
} from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
const small = createReactStyleSpec(
{
@@ -51,9 +51,11 @@ const CustomFormattingToolbar = (props: FormattingToolbarProps) => {
const editor = useBlockNoteEditor(schema);
const activeStyles = useActiveStyles(editor);
+ const Components = useComponentsContext()!;
+
return (
- {
editor.toggleStyles({
@@ -62,8 +64,8 @@ const CustomFormattingToolbar = (props: FormattingToolbarProps) => {
}}
isSelected={activeStyles.small}>
Small
-
-
+ {
editor.toggleStyles({
@@ -72,7 +74,7 @@ const CustomFormattingToolbar = (props: FormattingToolbarProps) => {
}}
isSelected={!!activeStyles.fontSize}>
Font size
-
+
);
};
diff --git a/examples/05-custom-schema/react-custom-styles/package.json b/examples/05-custom-schema/react-custom-styles/package.json
index 327acc839d..f42a5173bf 100644
--- a/examples/05-custom-schema/react-custom-styles/package.json
+++ b/examples/05-custom-schema/react-custom-styles/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/06-collaboration/01-partykit/App.tsx b/examples/06-collaboration/01-partykit/App.tsx
index 5d0e98fb51..cecfb6767e 100644
--- a/examples/06-collaboration/01-partykit/App.tsx
+++ b/examples/06-collaboration/01-partykit/App.tsx
@@ -1,6 +1,7 @@
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import YPartyKitProvider from "y-partykit/provider";
import * as Y from "yjs";
diff --git a/examples/06-collaboration/01-partykit/package.json b/examples/06-collaboration/01-partykit/package.json
index 983e97f256..36d35456ef 100644
--- a/examples/06-collaboration/01-partykit/package.json
+++ b/examples/06-collaboration/01-partykit/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"y-partykit": "^0.0.25",
diff --git a/examples/06-collaboration/02-liveblocks/App.tsx b/examples/06-collaboration/02-liveblocks/App.tsx
index cc65e59863..854b6b1091 100644
--- a/examples/06-collaboration/02-liveblocks/App.tsx
+++ b/examples/06-collaboration/02-liveblocks/App.tsx
@@ -1,6 +1,7 @@
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import { createClient } from "@liveblocks/client";
import LiveblocksProvider from "@liveblocks/yjs";
import * as Y from "yjs";
diff --git a/examples/06-collaboration/02-liveblocks/package.json b/examples/06-collaboration/02-liveblocks/package.json
index 992c95c466..1369a4bba3 100644
--- a/examples/06-collaboration/02-liveblocks/package.json
+++ b/examples/06-collaboration/02-liveblocks/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"@liveblocks/client": "^1.10.0",
diff --git a/examples/vanilla-js/react-vanilla-custom-blocks/App.tsx b/examples/vanilla-js/react-vanilla-custom-blocks/App.tsx
index 6be9d75827..c0dbb42ce8 100644
--- a/examples/vanilla-js/react-vanilla-custom-blocks/App.tsx
+++ b/examples/vanilla-js/react-vanilla-custom-blocks/App.tsx
@@ -5,8 +5,9 @@ import {
defaultProps,
} from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
import "./styles.css";
diff --git a/examples/vanilla-js/react-vanilla-custom-blocks/package.json b/examples/vanilla-js/react-vanilla-custom-blocks/package.json
index 618db40ffe..02e835fda1 100644
--- a/examples/vanilla-js/react-vanilla-custom-blocks/package.json
+++ b/examples/vanilla-js/react-vanilla-custom-blocks/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/vanilla-js/react-vanilla-custom-inline-content/App.tsx b/examples/vanilla-js/react-vanilla-custom-inline-content/App.tsx
index a090f2aa00..7e81477387 100644
--- a/examples/vanilla-js/react-vanilla-custom-inline-content/App.tsx
+++ b/examples/vanilla-js/react-vanilla-custom-inline-content/App.tsx
@@ -4,8 +4,9 @@ import {
defaultInlineContentSpecs,
} from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
-import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
const mention = createInlineContentSpec(
{
diff --git a/examples/vanilla-js/react-vanilla-custom-inline-content/package.json b/examples/vanilla-js/react-vanilla-custom-inline-content/package.json
index 83d07b6eb4..b8de3757a2 100644
--- a/examples/vanilla-js/react-vanilla-custom-inline-content/package.json
+++ b/examples/vanilla-js/react-vanilla-custom-inline-content/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/examples/vanilla-js/react-vanilla-custom-styles/App.tsx b/examples/vanilla-js/react-vanilla-custom-styles/App.tsx
index ee30b7b8ef..813952cda7 100644
--- a/examples/vanilla-js/react-vanilla-custom-styles/App.tsx
+++ b/examples/vanilla-js/react-vanilla-custom-styles/App.tsx
@@ -5,16 +5,16 @@ import {
} from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
import {
- BlockNoteView,
FormattingToolbar,
FormattingToolbarController,
FormattingToolbarProps,
- ToolbarButton,
useActiveStyles,
useBlockNoteEditor,
+ useComponentsContext,
useCreateBlockNote,
} from "@blocknote/react";
-import "@blocknote/react/style.css";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
const small = createStyleSpec(
{
@@ -63,9 +63,11 @@ const CustomFormattingToolbar = (props: FormattingToolbarProps) => {
const editor = useBlockNoteEditor(schema);
const activeStyles = useActiveStyles(editor);
+ const Components = useComponentsContext()!;
+
return (
- {
editor.toggleStyles({
@@ -74,8 +76,8 @@ const CustomFormattingToolbar = (props: FormattingToolbarProps) => {
}}
isSelected={activeStyles.small}>
Small
-
-
+ {
editor.toggleStyles({
@@ -84,7 +86,7 @@ const CustomFormattingToolbar = (props: FormattingToolbarProps) => {
}}
isSelected={!!activeStyles.fontSize}>
Font size
-
+
);
};
diff --git a/examples/vanilla-js/react-vanilla-custom-styles/package.json b/examples/vanilla-js/react-vanilla-custom-styles/package.json
index d6cb5a2f53..7d01c3f5b2 100644
--- a/examples/vanilla-js/react-vanilla-custom-styles/package.json
+++ b/examples/vanilla-js/react-vanilla-custom-styles/package.json
@@ -11,8 +11,11 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/package-lock.json b/package-lock.json
index 2a71ba0847..153a4fcbbf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -26,8 +26,11 @@
"docs": {
"version": "0.12.2",
"dependencies": {
+ "@blocknote/ariakit": "^0.12.2",
"@blocknote/core": "^0.12.1",
+ "@blocknote/mantine": "^0.12.2",
"@blocknote/react": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"@headlessui/react": "^1.7.18",
"@mantine/core": "^7.5.0",
"@next/bundle-analyzer": "^14.1.0",
@@ -2361,6 +2364,10 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@blocknote/ariakit": {
+ "resolved": "packages/ariakit",
+ "link": true
+ },
"node_modules/@blocknote/core": {
"resolved": "packages/core",
"link": true
@@ -2373,6 +2380,10 @@
"resolved": "playground",
"link": true
},
+ "node_modules/@blocknote/mantine": {
+ "resolved": "packages/mantine",
+ "link": true
+ },
"node_modules/@blocknote/react": {
"resolved": "packages/react",
"link": true
@@ -2934,6 +2945,14 @@
"react-dom": "^16 || ^17 || ^18"
}
},
+ "node_modules/@hookform/resolvers": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.3.4.tgz",
+ "integrity": "sha512-o5cgpGOuJYrd+iMKvkttOclgwRW86EsWJZZRC23prf0uU2i48Htq4PuT73AVb9ionFyZrwYEITuOFGF+BydEtQ==",
+ "peerDependencies": {
+ "react-hook-form": "^7.0.0"
+ }
+ },
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.13",
"dev": true,
@@ -5147,6 +5166,29 @@
}
}
},
+ "node_modules/@radix-ui/react-label": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.0.2.tgz",
+ "integrity": "sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/react-primitive": "1.0.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@radix-ui/react-menu": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.6.tgz",
@@ -5211,6 +5253,67 @@
}
}
},
+ "node_modules/@radix-ui/react-popover": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.0.7.tgz",
+ "integrity": "sha512-shtvVnlsxT6faMnK/a7n0wptwBD23xc1Z5mdrtKLwVEfsEMXodS0r5s0/g5P0hX//EKYZS2sxUjqfzlg52ZSnQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/primitive": "1.0.1",
+ "@radix-ui/react-compose-refs": "1.0.1",
+ "@radix-ui/react-context": "1.0.1",
+ "@radix-ui/react-dismissable-layer": "1.0.5",
+ "@radix-ui/react-focus-guards": "1.0.1",
+ "@radix-ui/react-focus-scope": "1.0.4",
+ "@radix-ui/react-id": "1.0.1",
+ "@radix-ui/react-popper": "1.1.3",
+ "@radix-ui/react-portal": "1.0.4",
+ "@radix-ui/react-presence": "1.0.1",
+ "@radix-ui/react-primitive": "1.0.3",
+ "@radix-ui/react-slot": "1.0.2",
+ "@radix-ui/react-use-controllable-state": "1.0.1",
+ "aria-hidden": "^1.1.1",
+ "react-remove-scroll": "2.5.5"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-popover/node_modules/react-remove-scroll": {
+ "version": "2.5.5",
+ "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz",
+ "integrity": "sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==",
+ "dependencies": {
+ "react-remove-scroll-bar": "^2.3.3",
+ "react-style-singleton": "^2.2.1",
+ "tslib": "^2.1.0",
+ "use-callback-ref": "^1.3.0",
+ "use-sidecar": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@radix-ui/react-popper": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.3.tgz",
@@ -10986,7 +11089,6 @@
},
"node_modules/fraction.js": {
"version": "4.3.7",
- "dev": true,
"license": "MIT",
"engines": {
"node": "*"
@@ -16005,7 +16107,6 @@
},
"node_modules/normalize-range": {
"version": "0.1.2",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -18539,6 +18640,22 @@
"react": ">=16.3.0"
}
},
+ "node_modules/react-hook-form": {
+ "version": "7.51.2",
+ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.51.2.tgz",
+ "integrity": "sha512-y++lwaWjtzDt/XNnyGDQy6goHskFualmDlf+jzEZvjvz6KWDf7EboL7pUvRCzPTJd0EOPpdekYaQLEvvG6m6HA==",
+ "peer": true,
+ "engines": {
+ "node": ">=12.22.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/react-hook-form"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17 || ^18"
+ }
+ },
"node_modules/react-icons": {
"version": "4.12.0",
"license": "MIT",
@@ -20786,11 +20903,11 @@
"license": "MIT"
},
"node_modules/tailwind-merge": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.2.2.tgz",
- "integrity": "sha512-tWANXsnmJzgw6mQ07nE3aCDkCK4QdT3ThPMCzawoYA2Pws7vSTCvz3Vrjg61jVUGfFZPJzxEP+NimbcW+EdaDw==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.3.0.tgz",
+ "integrity": "sha512-vkYrLpIP+lgR0tQCG6AP7zZXCTLc1Lnv/CCRT3BqJ9CZ3ui2++GPaGb1x/ILsINIMSYqqvrpqjUFsMNLlW99EA==",
"dependencies": {
- "@babel/runtime": "^7.24.0"
+ "@babel/runtime": "^7.24.1"
},
"funding": {
"type": "github",
@@ -22956,7 +23073,8 @@
},
"node_modules/zod": {
"version": "3.22.4",
- "license": "MIT",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz",
+ "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
@@ -22969,6 +23087,53 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "packages/ariakit": {
+ "name": "@blocknote/ariakit",
+ "version": "0.12.2",
+ "license": "MPL-2.0",
+ "dependencies": {
+ "@ariakit/react": "^0.4.3",
+ "@blocknote/core": "*",
+ "@blocknote/react": "*",
+ "react": "^18",
+ "react-dom": "^18"
+ },
+ "devDependencies": {
+ "@types/react": "^18.0.25",
+ "@types/react-dom": "^18.0.9",
+ "@vitejs/plugin-react": "^4.0.4",
+ "eslint": "^8.10.0",
+ "prettier": "^2.7.1",
+ "rimraf": "^5.0.5",
+ "rollup-plugin-webpack-stats": "^0.2.2",
+ "typescript": "^5.3.3",
+ "vite": "^4.4.8",
+ "vite-plugin-eslint": "^1.8.1",
+ "vite-plugin-externalize-deps": "^0.7.0"
+ },
+ "peerDependencies": {
+ "react": "^18",
+ "react-dom": "^18"
+ }
+ },
+ "packages/ariakit/node_modules/rimraf": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz",
+ "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^10.3.7"
+ },
+ "bin": {
+ "rimraf": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"packages/core": {
"name": "@blocknote/core",
"version": "0.12.1",
@@ -23081,17 +23246,63 @@
"typescript": "^5.3.3"
}
},
+ "packages/mantine": {
+ "name": "@blocknote/mantine",
+ "version": "0.12.2",
+ "license": "MPL-2.0",
+ "dependencies": {
+ "@blocknote/core": "*",
+ "@blocknote/react": "*",
+ "@mantine/core": "^7.5.0",
+ "@mantine/hooks": "^7.5.0",
+ "@mantine/utils": "^6.0.21",
+ "react": "^18",
+ "react-dom": "^18",
+ "react-icons": "^4.3.1"
+ },
+ "devDependencies": {
+ "@types/react": "^18.0.25",
+ "@types/react-dom": "^18.0.9",
+ "@vitejs/plugin-react": "^4.0.4",
+ "eslint": "^8.10.0",
+ "prettier": "^2.7.1",
+ "rimraf": "^5.0.5",
+ "rollup-plugin-webpack-stats": "^0.2.2",
+ "typescript": "^5.3.3",
+ "vite": "^4.4.8",
+ "vite-plugin-eslint": "^1.8.1",
+ "vite-plugin-externalize-deps": "^0.7.0"
+ },
+ "peerDependencies": {
+ "react": "^18",
+ "react-dom": "^18"
+ }
+ },
+ "packages/mantine/node_modules/rimraf": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz",
+ "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^10.3.7"
+ },
+ "bin": {
+ "rimraf": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"packages/react": {
"name": "@blocknote/react",
"version": "0.12.2",
"license": "MPL-2.0",
"dependencies": {
- "@ariakit/react": "^0.4.3",
"@blocknote/core": "^0.12.1",
"@floating-ui/react": "^0.26.4",
- "@mantine/core": "^7.5.0",
- "@mantine/hooks": "^7.5.0",
- "@mantine/utils": "^6.0.21",
"@tiptap/core": "^2.0.3",
"@tiptap/react": "^2.0.3",
"lodash.merge": "^4.6.2",
@@ -23146,22 +23357,31 @@
"dependencies": {
"@blocknote/core": "*",
"@blocknote/react": "*",
+ "@hookform/resolvers": "^3.3.4",
"@radix-ui/react-dropdown-menu": "^2.0.6",
+ "@radix-ui/react-label": "^2.0.2",
+ "@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-tabs": "^1.0.4",
"@radix-ui/react-toggle": "^1.0.3",
"@radix-ui/react-tooltip": "^1.0.7",
+ "autoprefixer": "^10.4.19",
"class-variance-authority": "^0.7.0",
- "clsx": "^2.1.0",
+ "clsx": "^2.1.1",
"lucide-react": "^0.362.0",
+ "postcss": "^8.4.38",
"react": "^18",
"react-dom": "^18",
- "tailwind-merge": "^2.2.2",
- "tailwindcss-animate": "^1.0.7"
+ "react-hook-form": "^7.51.3",
+ "tailwind-merge": "^2.3.0",
+ "tailwindcss": "^3.4.3",
+ "tailwindcss-animate": "^1.0.7",
+ "zod": "^3.22.4"
},
"devDependencies": {
"@radix-ui/colors": "^3.0.0",
+ "@types/node": "^20.12.7",
"@types/react": "^18.0.25",
"@types/react-dom": "^18.0.9",
"@vitejs/plugin-react": "^4.0.4",
@@ -23172,22 +23392,163 @@
"typescript": "^5.3.3",
"vite": "^4.4.8",
"vite-plugin-eslint": "^1.8.1",
- "vite-plugin-externalize-deps": "^0.7.0",
- "vitest": "^0.34.1"
+ "vite-plugin-externalize-deps": "^0.7.0"
},
"peerDependencies": {
"react": "^18",
"react-dom": "^18"
}
},
+ "packages/shadcn/node_modules/@types/node": {
+ "version": "20.12.7",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz",
+ "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==",
+ "dev": true,
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "packages/shadcn/node_modules/autoprefixer": {
+ "version": "10.4.19",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz",
+ "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/autoprefixer"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "browserslist": "^4.23.0",
+ "caniuse-lite": "^1.0.30001599",
+ "fraction.js": "^4.3.7",
+ "normalize-range": "^0.1.2",
+ "picocolors": "^1.0.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "bin": {
+ "autoprefixer": "bin/autoprefixer"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "packages/shadcn/node_modules/browserslist": {
+ "version": "4.23.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz",
+ "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001587",
+ "electron-to-chromium": "^1.4.668",
+ "node-releases": "^2.0.14",
+ "update-browserslist-db": "^1.0.13"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "packages/shadcn/node_modules/caniuse-lite": {
+ "version": "1.0.30001614",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001614.tgz",
+ "integrity": "sha512-jmZQ1VpmlRwHgdP1/uiKzgiAuGOfLEJsYFP4+GBou/QQ4U6IOJCB4NP1c+1p9RGLpwObcT94jA5/uO+F1vBbog==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ]
+ },
"packages/shadcn/node_modules/clsx": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz",
- "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==",
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
"engines": {
"node": ">=6"
}
},
+ "packages/shadcn/node_modules/electron-to-chromium": {
+ "version": "1.4.751",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.751.tgz",
+ "integrity": "sha512-2DEPi++qa89SMGRhufWTiLmzqyuGmNF3SK4+PQetW1JKiZdEpF4XQonJXJCzyuYSA6mauiMhbyVhqYAP45Hvfw=="
+ },
+ "packages/shadcn/node_modules/postcss": {
+ "version": "8.4.38",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
+ "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "packages/shadcn/node_modules/react-hook-form": {
+ "version": "7.51.3",
+ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.51.3.tgz",
+ "integrity": "sha512-cvJ/wbHdhYx8aviSWh28w9ImjmVsb5Y05n1+FW786vEZQJV5STNM0pW6ujS+oiBecb0ARBxJFyAnXj9+GHXACQ==",
+ "engines": {
+ "node": ">=12.22.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/react-hook-form"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17 || ^18"
+ }
+ },
"packages/shadcn/node_modules/rimraf": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz",
@@ -23206,6 +23567,50 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "packages/shadcn/node_modules/source-map-js": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
+ "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "packages/shadcn/node_modules/tailwindcss": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz",
+ "integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==",
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "arg": "^5.0.2",
+ "chokidar": "^3.5.3",
+ "didyoumean": "^1.2.2",
+ "dlv": "^1.1.3",
+ "fast-glob": "^3.3.0",
+ "glob-parent": "^6.0.2",
+ "is-glob": "^4.0.3",
+ "jiti": "^1.21.0",
+ "lilconfig": "^2.1.0",
+ "micromatch": "^4.0.5",
+ "normalize-path": "^3.0.0",
+ "object-hash": "^3.0.0",
+ "picocolors": "^1.0.0",
+ "postcss": "^8.4.23",
+ "postcss-import": "^15.1.0",
+ "postcss-js": "^4.0.1",
+ "postcss-load-config": "^4.0.1",
+ "postcss-nested": "^6.0.1",
+ "postcss-selector-parser": "^6.0.11",
+ "resolve": "^1.22.2",
+ "sucrase": "^3.32.0"
+ },
+ "bin": {
+ "tailwind": "lib/cli.js",
+ "tailwindcss": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"playground": {
"name": "@blocknote/example-editor",
"version": "0.12.2",
@@ -23258,8 +23663,11 @@
"react-dom": "^18.2.0"
},
"devDependencies": {
+ "@blocknote/ariakit": "^0.12.2",
"@blocknote/core": "^0.12.1",
+ "@blocknote/mantine": "^0.12.2",
"@blocknote/react": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
"@playwright/experimental-ct-react": "^1.42.1",
"@playwright/test": "^1.42.1",
"eslint": "^8.10.0",
diff --git a/packages/ariakit/package.json b/packages/ariakit/package.json
new file mode 100644
index 0000000000..9c8413ec15
--- /dev/null
+++ b/packages/ariakit/package.json
@@ -0,0 +1,83 @@
+{
+ "name": "@blocknote/ariakit",
+ "homepage": "https://github.com/TypeCellOS/BlockNote",
+ "private": false,
+ "license": "MPL-2.0",
+ "version": "0.12.2",
+ "files": [
+ "dist",
+ "types",
+ "src"
+ ],
+ "keywords": [
+ "react",
+ "javascript",
+ "editor",
+ "typescript",
+ "prosemirror",
+ "wysiwyg",
+ "rich-text-editor",
+ "notion",
+ "yjs",
+ "block-based",
+ "tiptap"
+ ],
+ "description": "A \"Notion-style\" block-based extensible text editor built on top of Prosemirror and Tiptap.",
+ "type": "module",
+ "source": "src/index.tsx",
+ "types": "./types/src/index.d.ts",
+ "main": "./dist/blocknote-ariakit.umd.cjs",
+ "module": "./dist/blocknote-ariakit.js",
+ "exports": {
+ ".": {
+ "types": "./types/src/index.d.ts",
+ "import": "./dist/blocknote-ariakit.js",
+ "require": "./dist/blocknote-ariakit.umd.cjs"
+ },
+ "./style.css": {
+ "import": "./dist/style.css",
+ "require": "./dist/style.css"
+ }
+ },
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "build-bundled": "tsc && vite build --config vite.config.bundled.ts && git checkout tmp-releases && rm -rf ../../release && mv ../../release-tmp ../../release",
+ "preview": "vite preview",
+ "lint": "eslint src --max-warnings 0",
+ "clean": "rimraf dist && rimraf types"
+ },
+ "dependencies": {
+ "@ariakit/react": "^0.4.3",
+ "@blocknote/core": "*",
+ "@blocknote/react": "*",
+ "react": "^18",
+ "react-dom": "^18"
+ },
+ "devDependencies": {
+ "@types/react": "^18.0.25",
+ "@types/react-dom": "^18.0.9",
+ "@vitejs/plugin-react": "^4.0.4",
+ "eslint": "^8.10.0",
+ "prettier": "^2.7.1",
+ "rimraf": "^5.0.5",
+ "rollup-plugin-webpack-stats": "^0.2.2",
+ "typescript": "^5.3.3",
+ "vite": "^4.4.8",
+ "vite-plugin-eslint": "^1.8.1",
+ "vite-plugin-externalize-deps": "^0.7.0"
+ },
+ "peerDependencies": {
+ "react": "^18",
+ "react-dom": "^18"
+ },
+ "eslintConfig": {
+ "extends": [
+ "../../.eslintrc.js"
+ ]
+ },
+ "publishConfig": {
+ "access": "public",
+ "registry": "https://registry.npmjs.org/"
+ }
+}
diff --git a/packages/ariakit/src/ariakitStyles.css b/packages/ariakit/src/ariakitStyles.css
new file mode 100644
index 0000000000..7ff878e3b5
--- /dev/null
+++ b/packages/ariakit/src/ariakitStyles.css
@@ -0,0 +1,964 @@
+/* This file contains styles copied directly from Ariakit's website, and is
+responsible for the majority of the styling. */
+
+/* https://ariakit.org/examples/menu-nested */
+.bn-ak-button {
+ --border: rgb(0 0 0/13%);
+ --highlight: rgb(255 255 255/20%);
+ --shadow: rgb(0 0 0/10%);
+ display: flex;
+ height: 2.5rem;
+ user-select: none;
+ align-items: center;
+ justify-content: center;
+ gap: 0.25rem;
+ white-space: nowrap;
+ border-radius: 0.5rem;
+ border-style: none;
+ background-color: hsl(204 20% 100%);
+ padding-left: 1rem;
+ padding-right: 1rem;
+ font-size: 1rem;
+ line-height: 1.5rem;
+ color: hsl(204 4% 0%);
+ text-decoration-line: none;
+ outline-width: 2px;
+ outline-offset: 2px;
+ outline-color: hsl(204 100% 40%);
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 2px 0 var(--highlight),
+ inset 0 -1px 0 var(--shadow),
+ 0 1px 1px var(--shadow);
+ font-weight: 500;
+}
+
+.bn-ak-button:where(.dark, .dark *) {
+ --border: rgb(255 255 255/10%);
+ --highlight: rgb(255 255 255/5%);
+ --shadow: rgb(0 0 0/25%);
+ background-color: hsl(204 20% 100% / 0.05);
+ color: hsl(204 20% 100%);
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 -1px 0 1px var(--shadow),
+ inset 0 1px 0 var(--highlight);
+}
+
+.bn-ak-button:not(:active):hover {
+ --border: rgb(0 0 0/33%);
+}
+
+.bn-ak-button:where(.dark, .dark *):not(:active):hover {
+ --border: rgb(255 255 255/25%);
+}
+
+.bn-ak-button[aria-disabled="true"] {
+ opacity: 0.5;
+}
+
+.bn-ak-button[data-focus-visible] {
+ outline-style: solid;
+}
+
+.bn-ak-button:active,
+.bn-ak-button[data-active] {
+ padding-top: 0.125rem;
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 2px 0 var(--border);
+}
+
+@media (min-width: 640px) {
+ .bn-ak-button {
+ gap: 0.5rem;
+ }
+}
+
+.bn-ak-button:active:where(.dark, .dark *),
+.bn-ak-button[data-active]:where(.dark, .dark *) {
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 1px 1px 1px var(--shadow);
+}
+
+.bn-ak-menu {
+ position: relative;
+ z-index: 50;
+ display: flex;
+ max-height: var(--popover-available-height);
+ min-width: 180px;
+ flex-direction: column;
+ overscroll-behavior: contain;
+ border-radius: 0.5rem;
+ border-width: 1px;
+ border-style: solid;
+ border-color: hsl(204 20% 88%);
+ background-color: hsl(204 20% 100%);
+ padding: 0.5rem;
+ color: hsl(204 4% 0%);
+ box-shadow:
+ 0 10px 15px -3px rgb(0 0 0 / 0.1),
+ 0 4px 6px -4px rgb(0 0 0 / 0.1);
+ outline: none !important;
+ overflow: visible;
+}
+
+.bn-ak-menu:where(.dark, .dark *) {
+ border-color: hsl(204 4% 24%);
+ background-color: hsl(204 4% 16%);
+ color: hsl(204 20% 100%);
+ box-shadow:
+ 0 10px 15px -3px rgb(0 0 0 / 0.25),
+ 0 4px 6px -4px rgb(0 0 0 / 0.1);
+}
+
+.bn-ak-menu-item {
+ display: flex;
+ cursor: default;
+ scroll-margin: 0.5rem;
+ align-items: center;
+ gap: 0.5rem;
+ border-radius: 0.25rem;
+ padding: 0.5rem;
+ outline: none !important;
+}
+
+.bn-ak-menu-item[aria-disabled="true"] {
+ opacity: 0.25;
+}
+
+.bn-ak-menu-item[data-active-item] {
+ background-color: hsl(204 100% 40%);
+ color: hsl(204 20% 100%);
+}
+
+.bn-ak-menu-item:active,
+.bn-ak-menu-item[data-active] {
+ background-color: hsl(204 100% 32%);
+ padding-top: 9px;
+ padding-bottom: 7px;
+}
+
+.bn-ak-menu:not(:focus) .bn-ak-menu-item:not(:focus)[aria-expanded="true"] {
+ background-color: hsl(204 4% 0% / 7.5%);
+ color: currentColor;
+}
+
+.bn-ak-menu:not(:focus)
+.bn-ak-menu-item:not(:focus)[aria-expanded="true"]:where(.dark, .dark *) {
+ background-color: hsl(204 20% 100% / 0.1);
+}
+
+.bn-ak-menu-item .label {
+ flex: 1 1 0%;
+}
+
+/* https://ariakit.org/examples/form-select */
+.bn-ak-button {
+ --border: rgb(0 0 0/13%);
+ --highlight: rgb(255 255 255/20%);
+ --shadow: rgb(0 0 0/10%);
+ display: flex;
+ height: 2.5rem;
+ user-select: none;
+ align-items: center;
+ gap: 0.25rem;
+ white-space: nowrap;
+ border-style: none;
+ background-color: hsl(204 20% 100%);
+ padding-left: 1rem;
+ padding-right: 1rem;
+ font-size: 1rem;
+ line-height: 1.5rem;
+ color: hsl(204 4% 0%);
+ text-decoration-line: none;
+ outline-width: 2px;
+ outline-offset: 2px;
+ outline-color: hsl(204 100% 40%);
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 2px 0 var(--highlight),
+ inset 0 -1px 0 var(--shadow),
+ 0 1px 1px var(--shadow);
+ justify-content: space-between;
+ width: 100%;
+ border-radius: 0.375rem;
+}
+
+.bn-ak-button:where(.dark, .dark *) {
+ --border: rgb(255 255 255/10%);
+ --highlight: rgb(255 255 255/5%);
+ --shadow: rgb(0 0 0/25%);
+ background-color: hsl(204 20% 100% / 0.05);
+ color: hsl(204 20% 100%);
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 -1px 0 1px var(--shadow),
+ inset 0 1px 0 var(--highlight);
+}
+
+.bn-ak-button:not(:active):hover {
+ --border: rgb(0 0 0/33%);
+}
+
+.bn-ak-button:where(.dark, .dark *):not(:active):hover {
+ --border: rgb(255 255 255/25%);
+}
+
+.bn-ak-primary {
+ --border: rgba(0, 0, 0, 0.15);
+ --highlight: rgba(255, 255, 255, 0.25);
+ --shadow: rgba(0, 0, 0, 0.15);
+ background-color: hsl(204 100% 40%);
+ color: hsl(204 20% 100%);
+ justify-content: center;
+}
+
+.bn-ak-primary:hover {
+ --border: rgba(0, 0, 0, 0.35);
+ background-color: hsl(204 100% 35%);
+}
+
+.bn-ak-primary:where(.dark, .dark *) {
+ --border: rgba(255, 255, 255, 0.25);
+ --highlight: rgba(255, 255, 255, 0.1);
+ --shadow: rgba(0, 0, 0, 0.25);
+ background-color: hsl(204 100% 35%);
+}
+
+.bn-ak-primary:hover:where(.dark, .dark *) {
+ --border: rgba(255, 255, 255, 0.45);
+ background-color: hsl(204 100% 40%);
+}
+
+.bn-ak-button[aria-disabled="true"] {
+ opacity: 0.5;
+}
+
+.bn-ak-button[data-focus-visible] {
+ outline-style: solid;
+}
+
+.bn-ak-button:active,
+.bn-ak-button[data-active] {
+ padding-top: 0.125rem;
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 2px 0 var(--border);
+}
+
+@media (min-width: 640px) {
+ .bn-ak-button {
+ gap: 0.5rem;
+ }
+}
+
+.bn-ak-button:active:where(.dark, .dark *),
+.bn-ak-button[data-active]:where(.dark, .dark *) {
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 1px 1px 1px var(--shadow);
+}
+
+.bn-ak-wrapper {
+ display: flex;
+ width: 320px;
+ max-width: 100%;
+ flex-direction: column;
+ gap: 1.5rem;
+ border-radius: 0.5rem;
+ background-color: hsl(204 20% 100%);
+ padding: 1rem;
+ box-shadow:
+ 0 1px 3px 0 rgb(0 0 0 / 0.1),
+ 0 1px 2px -1px rgb(0 0 0 / 0.1);
+}
+
+.bn-ak-label {
+ padding-left: 1rem;
+}
+
+.bn-ak-popover {
+ z-index: 50;
+ display: flex;
+ max-height: min(var(--popover-available-height, 300px), 300px);
+ flex-direction: column;
+ overflow: auto;
+ overscroll-behavior: contain;
+ border-radius: 0.5rem;
+ border-width: 1px;
+ border-style: solid;
+ border-color: hsl(204 20% 88%);
+ background-color: hsl(204 20% 100%);
+ padding: 0.5rem;
+ color: hsl(204 4% 0%);
+ box-shadow:
+ 0 10px 15px -3px rgb(0 0 0 / 0.1),
+ 0 4px 6px -4px rgb(0 0 0 / 0.1);
+}
+
+.bn-ak-popover:where(.dark, .dark *) {
+ border-color: hsl(204 4% 24%);
+ background-color: hsl(204 4% 16%);
+ color: hsl(204 20% 100%);
+ box-shadow:
+ 0 10px 15px -3px rgb(0 0 0 / 0.25),
+ 0 4px 6px -4px rgb(0 0 0 / 0.1);
+}
+
+.bn-ak-select-item {
+ display: flex;
+ cursor: default;
+ scroll-margin: 0.5rem;
+ align-items: center;
+ gap: 0.5rem;
+ border-radius: 0.25rem;
+ padding: 0.5rem;
+ outline: none !important;
+}
+
+.bn-ak-select-item[aria-disabled="true"] {
+ opacity: 0.5;
+}
+
+.bn-ak-select-item[data-active-item] {
+ background-color: hsl(204 100% 40%);
+ color: hsl(204 20% 100%);
+}
+
+.bn-ak-wrapper:where(.dark, .dark *) {
+ background-color: hsl(204 4% 16%);
+ box-shadow:
+ 0 1px 3px 0 rgb(0 0 0 / 0.25),
+ 0 1px 2px -1px rgb(0 0 0 / 0.1);
+}
+
+.bn-ak-field {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+}
+
+.bn-ak-input {
+ height: 2.5rem;
+ width: 100%;
+ border-radius: 0.375rem;
+ border-style: none;
+ background-color: hsl(204 20% 94% / 0.4);
+ padding-left: 1rem;
+ padding-right: 1rem;
+ font-size: 1rem;
+ line-height: 1.5rem;
+ color: hsl(204 4% 0%);
+ box-shadow:
+ inset 0 0 0 1px rgba(0 0 0 / 0.1),
+ inset 0 2px 5px 0 rgba(0 0 0 / 0.05);
+}
+
+.bn-ak-input::placeholder {
+ color: hsl(204 4% 0% / 0.6);
+}
+
+.bn-ak-input:hover {
+ background-color: hsl(204 20% 94%);
+}
+
+.bn-ak-popover:focus-visible,
+.bn-ak-popover[data-focus-visible],
+.bn-ak-input:focus-visible,
+.bn-ak-input[data-focus-visible] {
+ outline: 2px solid hsl(204 100% 40%);
+ outline-offset: -1px;
+}
+
+.bn-ak-input:where(.dark, .dark *) {
+ background-color: hsl(204 4% 10%);
+ color: hsl(204 20% 100%);
+ box-shadow:
+ inset 0 0 0 1px rgba(255 255 255 / 0.12),
+ inset 0 -1px 0 0 rgba(255 255 255 / 0.05),
+ inset 0 2px 5px 0 rgba(0 0 0 / 0.15);
+}
+
+.bn-ak-input:where(.dark, .dark *)::placeholder {
+ color: hsl(204 20% 100% / 46%);
+}
+
+.bn-ak-input:hover:where(.dark, .dark *) {
+ background-color: hsl(204 4% 8%);
+}
+
+.bn-ak-error {
+ width: fit-content;
+ border-radius: 0.375rem;
+ border-width: 1px;
+ border-color: hsl(357 56% 80%);
+ background-color: hsl(357 56% 80% / 0.4);
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+ padding-left: 1rem;
+ padding-right: 1rem;
+ color: hsl(357 100% 30%);
+}
+
+.bn-ak-error:empty {
+ display: none;
+}
+
+.bn-ak-error:where(.dark, .dark *) {
+ border-color: hsl(357 56% 50% / 0.4);
+ background-color: hsl(357 56% 42% / 0.25);
+ color: hsl(357 100% 90%);
+}
+
+.bn-ak-buttons {
+ display: flex;
+ gap: 1rem;
+ padding-top: 1rem;
+}
+
+/* https://ariakit.org/components/menu */
+.bn-ak-button {
+ --border: rgb(0 0 0/13%);
+ --highlight: rgb(255 255 255/20%);
+ --shadow: rgb(0 0 0/10%);
+ display: flex;
+ height: 2.5rem;
+ user-select: none;
+ align-items: center;
+ justify-content: center;
+ gap: 0.25rem;
+ white-space: nowrap;
+ border-radius: 0.5rem;
+ border-style: none;
+ background-color: hsl(204 20% 100%);
+ padding-left: 1rem;
+ padding-right: 1rem;
+ font-size: 1rem;
+ line-height: 1.5rem;
+ color: hsl(204 4% 0%);
+ text-decoration-line: none;
+ outline-width: 2px;
+ outline-offset: 2px;
+ outline-color: hsl(204 100% 40%);
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 2px 0 var(--highlight),
+ inset 0 -1px 0 var(--shadow),
+ 0 1px 1px var(--shadow);
+ font-weight: 500;
+}
+
+.bn-ak-button:where(.dark, .dark *) {
+ --border: rgb(255 255 255/10%);
+ --highlight: rgb(255 255 255/5%);
+ --shadow: rgb(0 0 0/25%);
+ background-color: hsl(204 20% 100% / 0.05);
+ color: hsl(204 20% 100%);
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 -1px 0 1px var(--shadow),
+ inset 0 1px 0 var(--highlight);
+}
+
+.bn-ak-button:not(:active):hover {
+ --border: rgb(0 0 0/33%);
+}
+
+.bn-ak-button:where(.dark, .dark *):not(:active):hover {
+ --border: rgb(255 255 255/25%);
+}
+
+.bn-ak-button[aria-disabled="true"] {
+ opacity: 0.5;
+}
+
+.bn-ak-button[data-focus-visible] {
+ outline-style: solid;
+}
+
+.bn-ak-button:active,
+.bn-ak-button[data-active] {
+ padding-top: 0.125rem;
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 2px 0 var(--border);
+}
+
+@media (min-width: 640px) {
+ .bn-ak-button {
+ gap: 0.5rem;
+ }
+}
+
+.bn-ak-button:active:where(.dark, .dark *),
+.bn-ak-button[data-active]:where(.dark, .dark *) {
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 1px 1px 1px var(--shadow);
+}
+
+.bn-ak-separator {
+ margin-top: 0.5rem;
+ margin-bottom: 0.5rem;
+ height: 0px;
+ width: 100%;
+ border-top-width: 1px;
+ border-color: hsl(204 20% 88%);
+}
+
+.bn-ak-separator:where(.dark, .dark *) {
+ border-color: hsl(204 4% 28%);
+}
+
+.bn-ak-menu {
+ position: relative;
+ z-index: 50;
+ display: flex;
+ /*max-height: var(--popover-available-height);*/
+ min-width: 180px;
+ flex-direction: column;
+ /*overflow: auto;*/
+ overscroll-behavior: contain;
+ border-radius: 0.5rem;
+ border-width: 1px;
+ border-style: solid;
+ border-color: hsl(204 20% 88%);
+ background-color: hsl(204 20% 100%);
+ padding: 0.5rem;
+ color: hsl(204 4% 0%);
+ box-shadow:
+ 0 10px 15px -3px rgb(0 0 0 / 0.1),
+ 0 4px 6px -4px rgb(0 0 0 / 0.1);
+ outline: none !important;
+}
+
+.bn-ak-menu:where(.dark, .dark *) {
+ border-color: hsl(204 4% 24%);
+ background-color: hsl(204 4% 16%);
+ color: hsl(204 20% 100%);
+ box-shadow:
+ 0 10px 15px -3px rgb(0 0 0 / 0.25),
+ 0 4px 6px -4px rgb(0 0 0 / 0.1);
+}
+
+.bn-ak-menu-item {
+ display: flex;
+ cursor: default;
+ scroll-margin: 0.5rem;
+ align-items: center;
+ gap: 0.5rem;
+ border-radius: 0.25rem;
+ padding: 0.5rem;
+ outline: none !important;
+}
+
+.bn-ak-menu-item[aria-disabled="true"] {
+ opacity: 0.25;
+}
+
+.bn-ak-menu-item[data-active-item] {
+ background-color: hsl(204 100% 40%);
+ color: hsl(204 20% 100%);
+}
+
+.bn-ak-menu-item:active,
+.bn-ak-menu-item[data-active] {
+ background-color: hsl(204 100% 32%);
+ padding-top: 9px;
+ padding-bottom: 7px;
+}
+
+/* https://ariakit.org/examples/select-group */
+.bn-ak-button {
+ --border: rgb(0 0 0/13%);
+ --highlight: rgb(255 255 255/20%);
+ --shadow: rgb(0 0 0/10%);
+ display: flex;
+ height: 2.5rem;
+ user-select: none;
+ align-items: center;
+ gap: 0.25rem;
+ white-space: nowrap;
+ border-radius: 0.5rem;
+ border-style: none;
+ background-color: hsl(204 20% 100%);
+ padding-left: 1rem;
+ padding-right: 1rem;
+ font-size: 1rem;
+ line-height: 1.5rem;
+ color: hsl(204 4% 0%);
+ text-decoration-line: none;
+ outline-width: 2px;
+ outline-offset: 2px;
+ outline-color: hsl(204 100% 40%);
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 2px 0 var(--highlight),
+ inset 0 -1px 0 var(--shadow),
+ 0 1px 1px var(--shadow);
+ width: 200px;
+ justify-content: space-between;
+}
+
+.bn-ak-button:where(.dark, .dark *) {
+ --border: rgb(255 255 255/10%);
+ --highlight: rgb(255 255 255/5%);
+ --shadow: rgb(0 0 0/25%);
+ background-color: hsl(204 20% 100% / 0.05);
+ color: hsl(204 20% 100%);
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 -1px 0 1px var(--shadow),
+ inset 0 1px 0 var(--highlight);
+}
+
+.bn-ak-button:not(:active):hover {
+ --border: rgb(0 0 0/33%);
+}
+
+.bn-ak-button:where(.dark, .dark *):not(:active):hover {
+ --border: rgb(255 255 255/25%);
+}
+
+.bn-ak-button[aria-disabled="true"] {
+ opacity: 0.5;
+}
+
+.bn-ak-button[data-focus-visible] {
+ outline-style: solid;
+}
+
+.bn-ak-button:active,
+.bn-ak-button[data-active] {
+ padding-top: 0.125rem;
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 2px 0 var(--border);
+}
+
+@media (min-width: 640px) {
+ .bn-ak-button {
+ gap: 0.5rem;
+ }
+}
+
+.bn-ak-button:active:where(.dark, .dark *),
+.bn-ak-button[data-active]:where(.dark, .dark *) {
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 1px 1px 1px var(--shadow);
+}
+
+.bn-ak-wrapper {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+ padding: 1rem;
+}
+
+.bn-ak-popover {
+ z-index: 50;
+ display: flex;
+ max-height: min(var(--popover-available-height, 300px), 300px);
+ flex-direction: column;
+ overflow: auto;
+ overscroll-behavior: contain;
+ border-radius: 0.5rem;
+ border-width: 1px;
+ border-style: solid;
+ border-color: hsl(204 20% 88%);
+ background-color: hsl(204 20% 100%);
+ padding: 0.5rem;
+ color: hsl(204 4% 0%);
+ box-shadow:
+ 0 10px 15px -3px rgb(0 0 0 / 0.1),
+ 0 4px 6px -4px rgb(0 0 0 / 0.1);
+}
+
+.bn-ak-popover:focus-visible,
+.bn-ak-popover[data-focus-visible] {
+ outline: 2px solid hsl(204 100% 40%);
+ outline-offset: -1px;
+}
+
+.bn-ak-popover:where(.dark, .dark *) {
+ border-color: hsl(204 4% 24%);
+ background-color: hsl(204 4% 16%);
+ color: hsl(204 20% 100%);
+ box-shadow:
+ 0 10px 15px -3px rgb(0 0 0 / 0.25),
+ 0 4px 6px -4px rgb(0 0 0 / 0.1);
+}
+
+.bn-ak-select-item {
+ display: flex;
+ cursor: default;
+ scroll-margin: 0.5rem;
+ align-items: center;
+ gap: 0.5rem;
+ border-radius: 0.25rem;
+ padding: 0.5rem;
+ outline: none !important;
+}
+
+.bn-ak-select-item[aria-disabled="true"] {
+ opacity: 0.5;
+}
+
+.bn-ak-select-item[data-active-item] {
+ background-color: hsl(204 100% 40%);
+ color: hsl(204 20% 100%);
+}
+
+.bn-ak-separator {
+ margin-top: 0.5rem;
+ margin-bottom: 0.5rem;
+ height: 0px;
+ width: 100%;
+ border-top-width: 1px;
+ border-color: hsl(204 20% 88%);
+}
+
+.bn-ak-separator:where(.dark, .dark *) {
+ border-color: hsl(204 4% 28%);
+}
+
+.bn-ak-group-label {
+ cursor: default;
+ padding: 0.5rem;
+ font-size: 0.875rem;
+ line-height: 1.25rem;
+ font-weight: 500;
+ opacity: 0.6;
+}
+
+.bn-ak-group-label + * {
+ scroll-margin-top: 2.5rem;
+}
+
+/* https://ariakit.org/components/tab */
+.bn-ak-wrapper {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+ border-radius: 0.5rem;
+ background-color: hsl(204 20% 100%);
+ padding: 0.5rem;
+ box-shadow:
+ 0 1px 3px 0 rgb(0 0 0 / 0.1),
+ 0 1px 2px -1px rgb(0 0 0 / 0.1);
+}
+
+.bn-ak-wrapper:where(.dark, .dark *) {
+ background-color: hsl(204 4% 16%);
+ box-shadow:
+ 0 1px 3px 0 rgb(0 0 0 / 0.25),
+ 0 1px 2px -1px rgb(0 0 0 / 0.1);
+}
+
+.bn-ak-tab-list {
+ display: flex;
+ gap: 0.5rem;
+}
+
+.bn-ak-tab {
+ display: flex;
+ height: 2.5rem;
+ user-select: none;
+ align-items: center;
+ justify-content: center;
+ gap: 0.5rem;
+ white-space: nowrap;
+ border-radius: 0.25rem;
+ border-style: none;
+ padding-left: 1rem;
+ padding-right: 1rem;
+ font-size: 1rem;
+ line-height: 1.5rem;
+ text-decoration-line: none;
+ outline-width: 2px;
+ outline-offset: 2px;
+ outline-color: hsl(204 100% 40%);
+}
+
+.bn-ak-tab:hover {
+ background-color: hsl(204 4% 0% / 7.5%);
+}
+
+.bn-ak-tab[aria-disabled="true"] {
+ opacity: 0.5;
+}
+
+.bn-ak-tab[aria-selected="true"] {
+ background-color: hsl(204 100% 40%);
+ color: hsl(204 20% 100%);
+}
+
+.bn-ak-tab:hover[aria-selected="true"] {
+ background-color: hsl(204 100% 32%);
+}
+
+.bn-ak-tab[data-focus-visible] {
+ outline-style: solid;
+}
+
+.bn-ak-tab:active,
+.bn-ak-tab[data-active] {
+ padding-top: 0.125rem;
+}
+
+.bn-ak-tab:hover:where(.dark, .dark *) {
+ background-color: hsl(204 20% 100% / 0.1);
+}
+
+.bn-ak-tab[aria-selected="true"]:where(.dark, .dark *) {
+ background-color: hsl(204 100% 40%);
+ color: hsl(204 20% 100%);
+}
+
+.bn-ak-tab:hover[aria-selected="true"]:where(.dark, .dark *) {
+ background-color: hsl(204 100% 32%);
+}
+
+.bn-ak-panels {
+ padding: 0.5rem;
+}
+
+/* https://ariakit.org/components/toolbar */
+.bn-ak-button {
+ --border: rgb(0 0 0/13%);
+ --highlight: rgb(255 255 255/20%);
+ --shadow: rgb(0 0 0/10%);
+ display: flex;
+ height: 2.5rem;
+ user-select: none;
+ align-items: center;
+ justify-content: center;
+ white-space: nowrap;
+ border-style: none;
+ background-color: hsl(204 20% 100%);
+ padding-left: 1rem;
+ padding-right: 1rem;
+ font-size: 1rem;
+ line-height: 1.5rem;
+ color: hsl(204 4% 0%);
+ text-decoration-line: none;
+ outline-width: 2px;
+ outline-offset: 2px;
+ outline-color: hsl(204 100% 40%);
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 2px 0 var(--highlight),
+ inset 0 -1px 0 var(--shadow),
+ 0 1px 1px var(--shadow);
+ scroll-margin-left: 0.25rem;
+ scroll-margin-right: 0.25rem;
+ gap: 0.5rem;
+ border-radius: 0.25rem;
+}
+
+.bn-ak-button:where(.dark, .dark *) {
+ --border: rgb(255 255 255/10%);
+ --highlight: rgb(255 255 255/5%);
+ --shadow: rgb(0 0 0/25%);
+ background-color: hsl(204 20% 100% / 0.05);
+ color: hsl(204 20% 100%);
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 -1px 0 1px var(--shadow),
+ inset 0 1px 0 var(--highlight);
+}
+
+.bn-ak-button:not(:active):hover {
+ --border: rgb(0 0 0/33%);
+}
+
+.bn-ak-button:where(.dark, .dark *):not(:active):hover {
+ --border: rgb(255 255 255/25%);
+}
+
+.bn-ak-button[aria-disabled="true"] {
+ opacity: 0.5;
+}
+
+.bn-ak-button[data-focus-visible] {
+ outline-style: solid;
+}
+
+.bn-ak-button:active,
+.bn-ak-button[data-active] {
+ padding-top: 0.125rem;
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 2px 0 var(--border);
+}
+
+@media (min-width: 640px) {
+ .bn-ak-button {
+ gap: 0.5rem;
+ }
+}
+
+.bn-ak-button:active:where(.dark, .dark *),
+.bn-ak-button[data-active]:where(.dark, .dark *) {
+ box-shadow:
+ inset 0 0 0 1px var(--border),
+ inset 0 1px 1px 1px var(--shadow);
+}
+
+.bn-ak-secondary {
+ background-color: transparent;
+ color: currentColor;
+ box-shadow: none;
+}
+
+.bn-ak-secondary:hover {
+ background-color: hsl(204 4% 0% / 0.05);
+}
+
+.bn-ak-secondary:where(.dark, .dark *) {
+ background-color: transparent;
+ box-shadow: none;
+}
+
+.bn-ak-secondary:hover:where(.dark, .dark *) {
+ background-color: hsl(204 20% 100% / 0.05);
+}
+
+.bn-ak-secondary:active:where(.dark, .dark *),
+.bn-ak-secondary[data-active]:where(.dark, .dark *) {
+ box-shadow: none;
+}
+
+.bn-ak-toolbar {
+ display: flex;
+ max-width: 100%;
+ align-items: center;
+ gap: 0.25rem;
+ overflow-x: auto;
+ border-radius: 0.5rem;
+ background-color: hsl(204 20% 100%);
+ padding: 0.25rem;
+ box-shadow:
+ 0 1px 3px 0 rgb(0 0 0 / 0.1),
+ 0 1px 2px -1px rgb(0 0 0 / 0.1);
+}
+
+.bn-ak-toolbar:where(.dark, .dark *) {
+ background-color: hsl(204 4% 16%);
+ box-shadow:
+ 0 1px 3px 0 rgb(0 0 0 / 0.25),
+ 0 1px 2px -1px rgb(0 0 0 / 0.1);
+}
+
+.bn-ak-separator {
+ height: 2rem;
+ border-right-width: 1px;
+ border-color: hsl(204 20% 88%);
+}
+
+.bn-ak-separator:where(.dark, .dark *) {
+ border-color: hsl(204 4% 28%);
+}
\ No newline at end of file
diff --git a/packages/ariakit/src/index.tsx b/packages/ariakit/src/index.tsx
new file mode 100644
index 0000000000..81da5122d5
--- /dev/null
+++ b/packages/ariakit/src/index.tsx
@@ -0,0 +1,99 @@
+import {
+ BlockNoteViewRaw,
+ Components,
+ ComponentsContext,
+} from "@blocknote/react";
+import { ComponentProps } from "react";
+
+import { Form } from "./input/Form";
+import { TextInput } from "./input/TextInput";
+import {
+ Menu,
+ MenuDivider,
+ MenuDropdown,
+ MenuItem,
+ MenuLabel,
+ MenuTrigger,
+} from "./menu/Menu";
+import { Panel } from "./panel/Panel";
+import { PanelButton } from "./panel/PanelButton";
+import { PanelFileInput } from "./panel/PanelFileInput";
+import { PanelTab } from "./panel/PanelTab";
+import { PanelTextInput } from "./panel/PanelTextInput";
+import { Popover, PopoverContent, PopoverTrigger } from "./popover/Popover";
+import { SideMenu } from "./sideMenu/SideMenu";
+import { SideMenuButton } from "./sideMenu/SideMenuButton";
+import { SuggestionMenu } from "./suggestionMenu/SuggestionMenu";
+import { SuggestionMenuItem } from "./suggestionMenu/SuggestionMenuItem";
+import { SuggestionMenuEmptyItem } from "./suggestionMenu/SuggestionMenuEmptyItem";
+import { SuggestionMenuLabel } from "./suggestionMenu/SuggestionMenuLabel";
+import { SuggestionMenuLoader } from "./suggestionMenu/SuggestionMenuLoader";
+import { TableHandle } from "./tableHandle/TableHandle";
+import { Toolbar } from "./toolbar/Toolbar";
+import { ToolbarButton } from "./toolbar/ToolbarButton";
+import { ToolbarSelect } from "./toolbar/ToolbarSelect";
+
+import "./style.css";
+
+export const components: Components = {
+ FormattingToolbar: {
+ Root: Toolbar,
+ Button: ToolbarButton,
+ Select: ToolbarSelect,
+ },
+ ImagePanel: {
+ Root: Panel,
+ Button: PanelButton,
+ FileInput: PanelFileInput,
+ TabPanel: PanelTab,
+ TextInput: PanelTextInput,
+ },
+ LinkToolbar: {
+ Root: Toolbar,
+ Button: ToolbarButton,
+ },
+ SideMenu: {
+ Root: SideMenu,
+ Button: SideMenuButton,
+ },
+ SuggestionMenu: {
+ Root: SuggestionMenu,
+ Item: SuggestionMenuItem,
+ EmptyItem: SuggestionMenuEmptyItem,
+ Label: SuggestionMenuLabel,
+ Loader: SuggestionMenuLoader,
+ },
+ TableHandle: {
+ Root: TableHandle,
+ },
+ Generic: {
+ Form: {
+ Root: Form,
+ TextInput: TextInput,
+ },
+ Menu: {
+ Root: Menu,
+ Trigger: MenuTrigger,
+ Dropdown: MenuDropdown,
+ Divider: MenuDivider,
+ Label: MenuLabel,
+ Item: MenuItem,
+ },
+ Popover: {
+ Root: Popover,
+ Trigger: PopoverTrigger,
+ Content: PopoverContent,
+ },
+ },
+};
+
+export const BlockNoteView = (
+ // TODO: Fix typing
+ props: ComponentProps>
+) => {
+ return (
+
+
+
+ );
+};
diff --git a/packages/ariakit/src/input/Form.tsx b/packages/ariakit/src/input/Form.tsx
new file mode 100644
index 0000000000..e12de4f09f
--- /dev/null
+++ b/packages/ariakit/src/input/Form.tsx
@@ -0,0 +1,9 @@
+import * as Ariakit from "@ariakit/react";
+
+import { ComponentProps } from "@blocknote/react";
+
+export const Form = (props: ComponentProps["Generic"]["Form"]["Root"]) => {
+ const { children } = props;
+
+ return {children};
+};
diff --git a/packages/ariakit/src/input/TextInput.tsx b/packages/ariakit/src/input/TextInput.tsx
new file mode 100644
index 0000000000..4bcb781049
--- /dev/null
+++ b/packages/ariakit/src/input/TextInput.tsx
@@ -0,0 +1,45 @@
+import * as Ariakit from "@ariakit/react";
+
+import { mergeCSSClasses } from "@blocknote/core";
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const TextInput = forwardRef<
+ HTMLInputElement,
+ ComponentProps["Generic"]["Form"]["TextInput"]
+>((props, ref) => {
+ const {
+ className,
+ name,
+ label,
+ icon,
+ value,
+ autoFocus,
+ placeholder,
+ onKeyDown,
+ onChange,
+ onSubmit,
+ } = props;
+
+ return (
+ <>
+ {props.label && (
+ {label}
+ )}
+
+ >
+ );
+});
diff --git a/packages/ariakit/src/menu/Menu.tsx b/packages/ariakit/src/menu/Menu.tsx
new file mode 100644
index 0000000000..cf2f9dcb83
--- /dev/null
+++ b/packages/ariakit/src/menu/Menu.tsx
@@ -0,0 +1,111 @@
+import * as Ariakit from "@ariakit/react";
+
+import { mergeCSSClasses } from "@blocknote/core";
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const Menu = (props: ComponentProps["Generic"]["Menu"]["Root"]) => {
+ const {
+ children,
+ onOpenChange,
+ position,
+ // sub
+ } = props;
+
+ return (
+
+ {children}
+
+ );
+};
+
+export const MenuDropdown = forwardRef<
+ HTMLDivElement,
+ ComponentProps["Generic"]["Menu"]["Dropdown"]
+>((props, ref) => {
+ const { className, children } = props;
+
+ return (
+
+ {children}
+
+ );
+});
+
+export const MenuItem = forwardRef<
+ HTMLDivElement,
+ ComponentProps["Generic"]["Menu"]["Item"]
+>((props, ref) => {
+ const { className, children, icon, checked, subTrigger, onClick } = props;
+
+ if (subTrigger) {
+ return (
+ }
+ className={mergeCSSClasses("bn-ak-menu-item", className || "")}
+ ref={ref}
+ onClick={onClick}>
+ {icon}
+ {children}
+
+ {checked !== undefined && }
+
+ );
+ }
+ return (
+
+ {icon}
+ {children}
+ {checked !== undefined && }
+
+ );
+});
+
+export const MenuLabel = forwardRef<
+ HTMLDivElement,
+ ComponentProps["Generic"]["Menu"]["Label"]
+>((props, ref) => {
+ const { className, children } = props;
+
+ return (
+
+ {children}
+
+ );
+});
+
+export const MenuTrigger = (
+ props: ComponentProps["Generic"]["Menu"]["Trigger"]
+) => {
+ const { children, sub } = props;
+
+ if (sub) {
+ return children;
+ }
+
+ return ;
+};
+
+export const MenuDivider = forwardRef<
+ HTMLHRElement,
+ ComponentProps["Generic"]["Menu"]["Divider"]
+>((props, ref) => {
+ const { className } = props;
+
+ return (
+
+ );
+});
diff --git a/packages/ariakit/src/panel/Panel.tsx b/packages/ariakit/src/panel/Panel.tsx
new file mode 100644
index 0000000000..553c7b6678
--- /dev/null
+++ b/packages/ariakit/src/panel/Panel.tsx
@@ -0,0 +1,53 @@
+import * as Ariakit from "@ariakit/react";
+
+import { mergeCSSClasses } from "@blocknote/core";
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const Panel = forwardRef<
+ HTMLDivElement,
+ ComponentProps["ImagePanel"]["Root"]
+>((props, ref) => {
+ const {
+ className,
+ tabs,
+ defaultOpenTab,
+ openTab,
+ setOpenTab,
+ // loading,
+ // setLoading,
+ } = props;
+
+ return (
+
+
{
+ if (activeId) {
+ setOpenTab(activeId);
+ }
+ }}>
+ {/*{loading && }*/}
+
+
+ {tabs.map((tab) => (
+
+ {tab.name}
+
+ ))}
+
+
+
+ {tabs.map((tab) => (
+
+ {tab.tabPanel}
+
+ ))}
+
+
+
+ );
+});
diff --git a/packages/ariakit/src/panel/PanelButton.tsx b/packages/ariakit/src/panel/PanelButton.tsx
new file mode 100644
index 0000000000..04c300c18d
--- /dev/null
+++ b/packages/ariakit/src/panel/PanelButton.tsx
@@ -0,0 +1,21 @@
+import * as Ariakit from "@ariakit/react";
+
+import { mergeCSSClasses } from "@blocknote/core";
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const PanelButton = forwardRef<
+ HTMLButtonElement,
+ ComponentProps["ImagePanel"]["Button"]
+>((props, ref) => {
+ const { className, children, onClick } = props;
+
+ return (
+
+ {children}
+
+ );
+});
diff --git a/packages/ariakit/src/panel/PanelFileInput.tsx b/packages/ariakit/src/panel/PanelFileInput.tsx
new file mode 100644
index 0000000000..36df131840
--- /dev/null
+++ b/packages/ariakit/src/panel/PanelFileInput.tsx
@@ -0,0 +1,25 @@
+import * as Ariakit from "@ariakit/react";
+
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const PanelFileInput = forwardRef<
+ HTMLInputElement,
+ ComponentProps["ImagePanel"]["FileInput"]
+>((props, ref) => {
+ const { className, value, placeholder, onChange } = props;
+
+ return (
+
+ onChange?.(e.target.files![0])}
+ placeholder={placeholder}
+ />
+
+ );
+});
diff --git a/packages/ariakit/src/panel/PanelTab.tsx b/packages/ariakit/src/panel/PanelTab.tsx
new file mode 100644
index 0000000000..58ed2aba46
--- /dev/null
+++ b/packages/ariakit/src/panel/PanelTab.tsx
@@ -0,0 +1,15 @@
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const PanelTab = forwardRef<
+ HTMLDivElement,
+ ComponentProps["ImagePanel"]["TabPanel"]
+>((props, ref) => {
+ const { className, children } = props;
+
+ return (
+
+ {children}
+
+ );
+});
diff --git a/packages/ariakit/src/panel/PanelTextInput.tsx b/packages/ariakit/src/panel/PanelTextInput.tsx
new file mode 100644
index 0000000000..3e7f9c2ac4
--- /dev/null
+++ b/packages/ariakit/src/panel/PanelTextInput.tsx
@@ -0,0 +1,27 @@
+import * as Ariakit from "@ariakit/react";
+
+import { mergeCSSClasses } from "@blocknote/core";
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const PanelTextInput = forwardRef<
+ HTMLInputElement,
+ ComponentProps["ImagePanel"]["TextInput"]
+>((props, ref) => {
+ const { className, value, placeholder, onKeyDown, onChange } = props;
+
+ return (
+
+
+
+ );
+});
diff --git a/packages/ariakit/src/popover/Popover.tsx b/packages/ariakit/src/popover/Popover.tsx
new file mode 100644
index 0000000000..71adb6f07f
--- /dev/null
+++ b/packages/ariakit/src/popover/Popover.tsx
@@ -0,0 +1,41 @@
+import * as Ariakit from "@ariakit/react";
+
+import { mergeCSSClasses } from "@blocknote/core";
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const PopoverTrigger = forwardRef<
+ HTMLButtonElement,
+ ComponentProps["Generic"]["Popover"]["Trigger"]
+>((props, ref) => {
+ const { children } = props;
+
+ return ;
+});
+
+export const PopoverContent = forwardRef<
+ HTMLDivElement,
+ ComponentProps["Generic"]["Popover"]["Content"]
+>((props, ref) => {
+ const { className, children } = props;
+
+ return (
+
+ {children}
+
+ );
+});
+
+export const Popover = (
+ props: ComponentProps["Generic"]["Popover"]["Root"]
+) => {
+ const { children, opened, position } = props;
+
+ return (
+
+ {children}
+
+ );
+};
diff --git a/packages/ariakit/src/sideMenu/SideMenu.tsx b/packages/ariakit/src/sideMenu/SideMenu.tsx
new file mode 100644
index 0000000000..742112d71c
--- /dev/null
+++ b/packages/ariakit/src/sideMenu/SideMenu.tsx
@@ -0,0 +1,17 @@
+import * as Ariakit from "@ariakit/react";
+
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const SideMenu = forwardRef<
+ HTMLDivElement,
+ ComponentProps["SideMenu"]["Root"]
+>((props, ref) => {
+ const { className, children } = props;
+
+ return (
+
+ {children}
+
+ );
+});
diff --git a/packages/ariakit/src/sideMenu/SideMenuButton.tsx b/packages/ariakit/src/sideMenu/SideMenuButton.tsx
new file mode 100644
index 0000000000..60ed1b7675
--- /dev/null
+++ b/packages/ariakit/src/sideMenu/SideMenuButton.tsx
@@ -0,0 +1,25 @@
+import * as Ariakit from "@ariakit/react";
+
+import { mergeCSSClasses } from "@blocknote/core";
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const SideMenuButton = forwardRef<
+ HTMLButtonElement,
+ ComponentProps["SideMenu"]["Button"]
+>((props, ref) => {
+ const { className, children, icon, onClick } = props;
+
+ return (
+
+ {icon}
+ {children}
+
+ );
+});
diff --git a/packages/ariakit/src/style.css b/packages/ariakit/src/style.css
new file mode 100644
index 0000000000..974dffbb29
--- /dev/null
+++ b/packages/ariakit/src/style.css
@@ -0,0 +1,125 @@
+@import url("@blocknote/react/style.css");
+
+/* This file contains BlockNote-specific fixes for the styles in
+ ariakitStyles.css. */
+
+@import "./ariakitStyles.css";
+
+.bn-ak-input-wrapper {
+ align-items: center;
+ display: flex;
+ gap: 0.5rem;
+}
+
+.bn-toolbar .bn-ak-button {
+ width: unset;
+}
+
+.bn-toolbar .bn-ak-button[data-selected] {
+ padding-top: 0.125rem;
+ box-shadow: inset 0 0 0 1px var(--border),
+ inset 0 2px 0 var(--border);
+}
+
+.bn-toolbar .bn-ak-button[data-selected]:where(.dark, .dark *) {
+ box-shadow: inset 0 0 0 1px var(--border),
+ inset 0 1px 1px 1px var(--shadow);
+}
+
+.bn-toolbar .bn-ak-popover {
+ gap: 0.5rem;
+}
+
+.bn-tab-panel {
+ align-items: center;
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+}
+
+.bn-file-input {
+ max-width: 100%;
+}
+
+.bn-ak-menu-item[data-hovered] {
+ background-color: hsl(204 100% 40%);
+ color: hsl(204 20% 100%);
+}
+
+.bn-ak-menu-item {
+ display: flex;
+}
+
+.bn-dropdown {
+ overflow: visible;
+}
+
+.bn-suggestion-menu, .bn-color-picker-dropdown {
+ overflow: scroll;
+}
+
+.bn-ak-suggestion-menu-item-body {
+ flex: 1;
+}
+
+.bn-ak-suggestion-menu-item-subtitle {
+ font-size: 0.7rem;
+}
+
+.bn-ak-suggestion-menu-item-section[data-position="left"] {
+ padding: 8px;
+}
+
+.bn-ak-suggestion-menu-item-section[data-position="right"] {
+ --border: rgb(0 0 0/13%);
+ --highlight: rgb(255 255 255/20%);
+ --shadow: rgb(0 0 0/10%);
+ box-shadow: inset 0 0 0 1px var(--border),
+ inset 0 2px 0 var(--highlight),
+ inset 0 -1px 0 var(--shadow),
+ 0 1px 1px var(--shadow);
+ font-size: 0.7rem;
+ border-radius: 4px;
+ padding-inline: 4px;
+}
+
+.bn-side-menu {
+ align-items: center;
+ display: flex;
+ justify-content: center;
+}
+
+.bn-side-menu .bn-ak-button {
+ height: fit-content;
+ padding: 0;
+ width: fit-content;
+}
+
+.bn-panel-popover {
+ background-color: transparent;
+ border: none;
+ box-shadow: none;
+}
+
+.bn-table-handle {
+ height: fit-content;
+ padding: 0;
+ width: fit-content;
+}
+
+.bn-side-menu, .bn-table-handle {
+ color: gray;
+}
+
+.bn-ak-button:where(.dark, .dark *) {
+ color: hsl(204 20% 100%);
+}
+
+.bn-ak-tab, .bn-file-input {
+ background-color: transparent;
+ color: black;
+}
+
+.bn-ak-tab:where(.dark, .dark *), .bn-file-input:where(.dark, .dark *) {
+ color: white;
+}
\ No newline at end of file
diff --git a/packages/ariakit/src/suggestionMenu/SuggestionMenu.tsx b/packages/ariakit/src/suggestionMenu/SuggestionMenu.tsx
new file mode 100644
index 0000000000..4229250989
--- /dev/null
+++ b/packages/ariakit/src/suggestionMenu/SuggestionMenu.tsx
@@ -0,0 +1,20 @@
+import * as Ariakit from "@ariakit/react";
+
+import { mergeCSSClasses } from "@blocknote/core";
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const SuggestionMenu = forwardRef<
+ HTMLDivElement,
+ ComponentProps["SuggestionMenu"]["Root"]
+>((props, ref) => {
+ const { className, children } = props;
+
+ return (
+
+ {children}
+
+ );
+});
diff --git a/packages/ariakit/src/suggestionMenu/SuggestionMenuEmptyItem.tsx b/packages/ariakit/src/suggestionMenu/SuggestionMenuEmptyItem.tsx
new file mode 100644
index 0000000000..9729f0685b
--- /dev/null
+++ b/packages/ariakit/src/suggestionMenu/SuggestionMenuEmptyItem.tsx
@@ -0,0 +1,18 @@
+import { mergeCSSClasses } from "@blocknote/core";
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const SuggestionMenuEmptyItem = forwardRef<
+ HTMLDivElement,
+ ComponentProps["SuggestionMenu"]["EmptyItem"]
+>((props, ref) => {
+ const { className, children } = props;
+
+ return (
+
+ );
+});
diff --git a/packages/ariakit/src/suggestionMenu/SuggestionMenuItem.tsx b/packages/ariakit/src/suggestionMenu/SuggestionMenuItem.tsx
new file mode 100644
index 0000000000..a6cdee6b26
--- /dev/null
+++ b/packages/ariakit/src/suggestionMenu/SuggestionMenuItem.tsx
@@ -0,0 +1,61 @@
+import { mergeCSSClasses } from "@blocknote/core";
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef, useCallback } from "react";
+
+export const SuggestionMenuItem = forwardRef<
+ HTMLDivElement,
+ ComponentProps["SuggestionMenu"]["Item"]
+>((props, ref) => {
+ const {
+ className,
+ title,
+ subtext,
+ // group,
+ icon,
+ badge,
+ // aliases,
+ // onItemClick,
+ isSelected,
+ setSelected,
+ onClick,
+ } = props;
+
+ const handleMouseLeave = useCallback(() => {
+ setSelected?.(false);
+ }, [setSelected]);
+
+ const handleMouseEnter = useCallback(() => {
+ setSelected?.(true);
+ }, [setSelected]);
+
+ return (
+
+ {icon && (
+
+ {icon}
+
+ )}
+
+ {badge && (
+
+ )}
+
+ );
+});
diff --git a/packages/ariakit/src/suggestionMenu/SuggestionMenuLabel.tsx b/packages/ariakit/src/suggestionMenu/SuggestionMenuLabel.tsx
new file mode 100644
index 0000000000..63e77d2cab
--- /dev/null
+++ b/packages/ariakit/src/suggestionMenu/SuggestionMenuLabel.tsx
@@ -0,0 +1,18 @@
+import { mergeCSSClasses } from "@blocknote/core";
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const SuggestionMenuLabel = forwardRef<
+ HTMLDivElement,
+ ComponentProps["SuggestionMenu"]["Label"]
+>((props, ref) => {
+ const { className, children } = props;
+
+ return (
+
+ {children}
+
+ );
+});
diff --git a/packages/ariakit/src/suggestionMenu/SuggestionMenuLoader.tsx b/packages/ariakit/src/suggestionMenu/SuggestionMenuLoader.tsx
new file mode 100644
index 0000000000..0b64e5496f
--- /dev/null
+++ b/packages/ariakit/src/suggestionMenu/SuggestionMenuLoader.tsx
@@ -0,0 +1,16 @@
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const SuggestionMenuLoader = forwardRef<
+ HTMLDivElement,
+ ComponentProps["SuggestionMenu"]["Loader"]
+>((props, ref) => {
+ const { className, children } = props;
+
+ // TODO Test
+ return (
+
+ {children}
+
+ );
+});
diff --git a/packages/ariakit/src/tableHandle/TableHandle.tsx b/packages/ariakit/src/tableHandle/TableHandle.tsx
new file mode 100644
index 0000000000..4c798d6637
--- /dev/null
+++ b/packages/ariakit/src/tableHandle/TableHandle.tsx
@@ -0,0 +1,36 @@
+import * as Ariakit from "@ariakit/react";
+
+import { mergeCSSClasses } from "@blocknote/core";
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const TableHandle = forwardRef<
+ HTMLButtonElement,
+ ComponentProps["TableHandle"]["Root"]
+>((props, ref) => {
+ const {
+ className,
+ children,
+ draggable,
+ onDragStart,
+ onDragEnd,
+ style,
+ ...rest
+ } = props;
+
+ return (
+
+ {children}
+
+ );
+});
diff --git a/packages/ariakit/src/toolbar/Toolbar.tsx b/packages/ariakit/src/toolbar/Toolbar.tsx
new file mode 100644
index 0000000000..c47874b0c9
--- /dev/null
+++ b/packages/ariakit/src/toolbar/Toolbar.tsx
@@ -0,0 +1,24 @@
+import * as Ariakit from "@ariakit/react";
+
+import { mergeCSSClasses } from "@blocknote/core";
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+type ToolbarProps = ComponentProps["FormattingToolbar"]["Root"] &
+ ComponentProps["LinkToolbar"]["Root"];
+
+export const Toolbar = forwardRef(
+ (props, ref) => {
+ const { className, children, onMouseEnter, onMouseLeave } = props;
+
+ return (
+
+ {children}
+
+ );
+ }
+);
diff --git a/packages/ariakit/src/toolbar/ToolbarButton.tsx b/packages/ariakit/src/toolbar/ToolbarButton.tsx
new file mode 100644
index 0000000000..12e03320ff
--- /dev/null
+++ b/packages/ariakit/src/toolbar/ToolbarButton.tsx
@@ -0,0 +1,88 @@
+import * as Ariakit from "@ariakit/react";
+
+import { isSafari, mergeCSSClasses } from "@blocknote/core";
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+type ToolbarButtonProps = ComponentProps["FormattingToolbar"]["Button"] &
+ ComponentProps["LinkToolbar"]["Button"];
+
+/**
+ * Helper for basic buttons that show in the formatting toolbar.
+ */
+// TODO: implement tooltip
+export const ToolbarButton = forwardRef(
+ (props, ref) => {
+ const {
+ className,
+ children,
+ // mainTooltip,
+ // secondaryTooltip,
+ icon,
+ isSelected,
+ isDisabled,
+ onClick,
+ } = props;
+
+ return (
+ {
+ if (isSafari()) {
+ (e.currentTarget as HTMLButtonElement).focus();
+ }
+ }}
+ onClick={onClick}
+ data-selected={isSelected ? "true" : undefined}
+ data-test={
+ props.mainTooltip.slice(0, 1).toLowerCase() +
+ props.mainTooltip.replace(/\s+/g, "").slice(1)
+ }
+ // size={"xs"}
+ disabled={isDisabled || false}
+ ref={ref}>
+ {icon}
+ {children}
+
+ );
+
+ // return (
+ //
+ // {
+ // if (isSafari()) {
+ // (e.currentTarget as HTMLButtonElement).focus();
+ // }
+ // }}
+ // onClick={props.onClick}
+ // data-selected={props.isSelected ? "true" : undefined}
+ // data-test={
+ // props.mainTooltip.slice(0, 1).toLowerCase() +
+ // props.mainTooltip.replace(/\s+/g, "").slice(1)
+ // }
+ // // size={"xs"}
+ // disabled={props.isDisabled || false}
+ // ref={ref}>
+ // }>
+ // {props.icon}
+ // {props.children}
+ //
+ //
+ // {props.mainTooltip}
+ // {props.secondaryTooltip && {props.secondaryTooltip}
}
+ //
+ //
+ // );
+ }
+);
diff --git a/packages/ariakit/src/toolbar/ToolbarSelect.tsx b/packages/ariakit/src/toolbar/ToolbarSelect.tsx
new file mode 100644
index 0000000000..930a281380
--- /dev/null
+++ b/packages/ariakit/src/toolbar/ToolbarSelect.tsx
@@ -0,0 +1,45 @@
+import * as Ariakit from "@ariakit/react";
+
+import { ComponentProps } from "@blocknote/react";
+import { mergeCSSClasses } from "@blocknote/core";
+import { forwardRef } from "react";
+
+export const ToolbarSelect = forwardRef<
+ HTMLDivElement,
+ ComponentProps["FormattingToolbar"]["Select"]
+>((props, ref) => {
+ const { className, items, isDisabled } = props;
+
+ const selectedItem = props.items.filter((p) => p.isSelected)[0];
+
+ const setValue = (value: string) => {
+ items.find((item) => item.text === value)!.onClick?.();
+ };
+
+ return (
+
+ }>
+ {selectedItem.icon} {selectedItem.text}
+
+
+ {items.map((option) => (
+
+ {option.icon}
+ {option.text}
+ {option.text === selectedItem.text && }
+
+ ))}
+
+
+ );
+});
diff --git a/packages/ariakit/tsconfig.json b/packages/ariakit/tsconfig.json
new file mode 100644
index 0000000000..607ad93cfa
--- /dev/null
+++ b/packages/ariakit/tsconfig.json
@@ -0,0 +1,32 @@
+{
+ "compilerOptions": {
+ "target": "ESNext",
+ "useDefineForClassFields": true,
+ "module": "ESNext",
+ "lib": ["ESNext", "DOM"],
+ "moduleResolution": "Node",
+ "jsx": "react-jsx",
+ "strict": true,
+ "sourceMap": true,
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "noEmit": false,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noImplicitReturns": true,
+ "outDir": "dist",
+ "declaration": true,
+ "declarationDir": "types",
+ "composite": true,
+ "skipLibCheck": true,
+ },
+ "include": ["src"],
+ "references": [
+ {
+ "path": "../core"
+ },
+ {
+ "path": "../react"
+ }
+ ]
+}
diff --git a/packages/ariakit/vite.config.ts b/packages/ariakit/vite.config.ts
new file mode 100644
index 0000000000..a50e2823d2
--- /dev/null
+++ b/packages/ariakit/vite.config.ts
@@ -0,0 +1,52 @@
+import react from "@vitejs/plugin-react";
+import * as path from "path";
+import { webpackStats } from "rollup-plugin-webpack-stats";
+import { defineConfig } from "vite";
+import pkg from "./package.json";
+// import eslintPlugin from "vite-plugin-eslint";
+
+// https://vitejs.dev/config/
+export default defineConfig((conf) => ({
+ test: {
+ environment: "jsdom",
+ setupFiles: ["./vitestSetup.ts"],
+ },
+ plugins: [react(), webpackStats()],
+ // used so that vitest resolves the core package from the sources instead of the built version
+ resolve: {
+ alias:
+ conf.command === "build"
+ ? ({} as Record)
+ : ({
+ // load live from sources with live reload working
+ "@blocknote/core": path.resolve(__dirname, "../core/src/"),
+ "@blocknote/react": path.resolve(__dirname, "../react/src/"),
+ } as Record),
+ },
+ build: {
+ sourcemap: true,
+ lib: {
+ entry: path.resolve(__dirname, "src/index.tsx"),
+ name: "blocknote-ariakit",
+ fileName: "blocknote-ariakit",
+ },
+ rollupOptions: {
+ // make sure to externalize deps that shouldn't be bundled
+ // into your library
+ external: Object.keys({
+ ...pkg.dependencies,
+ ...pkg.peerDependencies,
+ ...pkg.devDependencies,
+ }),
+ output: {
+ // Provide global variables to use in the UMD build
+ // for externalized deps
+ globals: {
+ react: "React",
+ "react-dom": "ReactDOM",
+ },
+ interop: "compat", // https://rollupjs.org/migration/#changed-defaults
+ },
+ },
+ },
+}));
diff --git a/packages/core/src/blocks/ImageBlockContent/ImageBlockContent.ts b/packages/core/src/blocks/ImageBlockContent/ImageBlockContent.ts
index 21f8eeeb00..af1e444a99 100644
--- a/packages/core/src/blocks/ImageBlockContent/ImageBlockContent.ts
+++ b/packages/core/src/blocks/ImageBlockContent/ImageBlockContent.ts
@@ -76,7 +76,7 @@ export const renderImage = (
// Text for the add image button.
const addImageButtonText = document.createElement("p");
addImageButtonText.className = "bn-add-image-button-text";
- addImageButtonText.innerText = "Add Image";
+ addImageButtonText.innerText = editor.dictionary.image.add_button;
// Wrapper element for the image, resize handles and caption.
const imageAndCaptionWrapper = document.createElement("div");
diff --git a/packages/core/src/editor/BlockNoteEditor.ts b/packages/core/src/editor/BlockNoteEditor.ts
index 001782123b..9a12f039b4 100644
--- a/packages/core/src/editor/BlockNoteEditor.ts
+++ b/packages/core/src/editor/BlockNoteEditor.ts
@@ -27,10 +27,10 @@ import {
PartialBlock,
} from "../blocks/defaultBlocks";
import { FormattingToolbarProsemirrorPlugin } from "../extensions/FormattingToolbar/FormattingToolbarPlugin";
+import { ImagePanelProsemirrorPlugin } from "../extensions/ImagePanel/ImageToolbarPlugin";
import { LinkToolbarProsemirrorPlugin } from "../extensions/LinkToolbar/LinkToolbarPlugin";
import { SideMenuProsemirrorPlugin } from "../extensions/SideMenu/SideMenuPlugin";
import { SuggestionMenuProseMirrorPlugin } from "../extensions/SuggestionMenu/SuggestionPlugin";
-import { ImagePanelProsemirrorPlugin } from "../extensions/ImagePanel/ImageToolbarPlugin";
import { TableHandlesProsemirrorPlugin } from "../extensions/TableHandles/TableHandlesPlugin";
import { UniqueID } from "../extensions/UniqueID/UniqueID";
import {
@@ -62,6 +62,8 @@ import {
} from "./BlockNoteTipTapEditor";
// CSS
+import { PlaceholderPlugin } from "../extensions/Placeholder/PlaceholderPlugin";
+import { en } from "../i18n/locales";
import "./Block.css";
import "./editor.css";
@@ -150,6 +152,8 @@ export class BlockNoteEditor<
contentComponent: any;
};
public blockCache = new WeakMap>();
+ public readonly dictionary = en;
+
public readonly schema: BlockNoteSchema;
public readonly blockImplementations: BlockSpecs;
@@ -221,6 +225,10 @@ export class BlockNoteEditor<
defaultStyles: true,
schema: options.schema || BlockNoteSchema.create(),
...options,
+ placeholders: {
+ ...this.dictionary.placeholders,
+ ...options.placeholders,
+ },
};
// @ts-ignore
@@ -243,7 +251,6 @@ export class BlockNoteEditor<
const extensions = getBlockNoteExtensions({
editor: this,
- placeholders: newOptions.placeholders,
domAttributes: newOptions.domAttributes || {},
blockSchema: this.schema.blockSchema,
blockSpecs: this.schema.blockSpecs,
@@ -263,6 +270,7 @@ export class BlockNoteEditor<
this.suggestionMenus.plugin,
...(this.imagePanel ? [this.imagePanel.plugin] : []),
...(this.tableHandles ? [this.tableHandles.plugin] : []),
+ PlaceholderPlugin(this, newOptions.placeholders),
];
},
});
diff --git a/packages/core/src/editor/BlockNoteExtensions.ts b/packages/core/src/editor/BlockNoteExtensions.ts
index 2cf41f98f8..a408c00f3e 100644
--- a/packages/core/src/editor/BlockNoteExtensions.ts
+++ b/packages/core/src/editor/BlockNoteExtensions.ts
@@ -14,7 +14,6 @@ import * as Y from "yjs";
import { createCopyToClipboardExtension } from "../api/exporters/copyExtension";
import { createPasteFromClipboardExtension } from "../api/parsers/pasteExtension";
import { BackgroundColorExtension } from "../extensions/BackgroundColor/BackgroundColorExtension";
-import { Placeholder } from "../extensions/Placeholder/PlaceholderExtension";
import { TextAlignmentExtension } from "../extensions/TextAlignment/TextAlignmentExtension";
import { TextColorExtension } from "../extensions/TextColor/TextColorExtension";
import { TrailingNode } from "../extensions/TrailingNode/TrailingNodeExtension";
@@ -39,7 +38,6 @@ export const getBlockNoteExtensions = <
S extends StyleSchema
>(opts: {
editor: BlockNoteEditor;
- placeholders?: Record;
domAttributes: Partial;
blockSchema: BSchema;
blockSpecs: BlockSpecs;
@@ -66,12 +64,6 @@ export const getBlockNoteExtensions = <
Gapcursor,
// DropCursor,
- Placeholder.configure({
- // TODO: This shorthand is kind of ugly
- ...(opts.placeholders !== undefined
- ? { placeholders: opts.placeholders }
- : {}),
- }),
UniqueID.configure({
types: ["blockContainer"],
}),
diff --git a/packages/core/src/extensions/Placeholder/PlaceholderExtension.ts b/packages/core/src/extensions/Placeholder/PlaceholderExtension.ts
deleted file mode 100644
index b25e6d4c5a..0000000000
--- a/packages/core/src/extensions/Placeholder/PlaceholderExtension.ts
+++ /dev/null
@@ -1,124 +0,0 @@
-import { Extension } from "@tiptap/core";
-import { Plugin, PluginKey } from "prosemirror-state";
-import { Decoration, DecorationSet } from "prosemirror-view";
-
-const PLUGIN_KEY = new PluginKey(`blocknote-placeholder`);
-
-/**
- * This is a modified version of the tiptap
- * placeholder plugin, that also sets hasAnchorClass
- *
- * It does not set a data-placeholder (text is currently done in css)
- *
- */
-export interface PlaceholderOptions {
- placeholders: Record;
-}
-
-export const Placeholder = Extension.create({
- name: "placeholder",
-
- addOptions() {
- return {
- placeholders: {
- default: "Enter text or type '/' for commands",
- heading: "Heading",
- bulletListItem: "List",
- numberedListItem: "List",
- },
- };
- },
-
- addProseMirrorPlugins() {
- const placeholders = this.options.placeholders;
- return [
- new Plugin({
- key: PLUGIN_KEY,
- view: () => {
- const styleEl = document.createElement("style");
- document.head.appendChild(styleEl);
- const styleSheet = styleEl.sheet!;
-
- const getBaseSelector = (additionalSelectors = "") =>
- `.bn-block-content${additionalSelectors} .bn-inline-content:has(> .ProseMirror-trailingBreak):before`;
-
- const getSelector = (
- blockType: string | "default",
- mustBeFocused = true
- ) => {
- const mustBeFocusedSelector = mustBeFocused
- ? `[data-is-empty-and-focused]`
- : ``;
-
- if (blockType === "default") {
- return getBaseSelector(mustBeFocusedSelector);
- }
-
- const blockTypeSelector = `[data-content-type="${blockType}"]`;
- return getBaseSelector(mustBeFocusedSelector + blockTypeSelector);
- };
-
- for (const [blockType, placeholder] of Object.entries(placeholders)) {
- const mustBeFocused = blockType === "default";
-
- styleSheet.insertRule(
- `${getSelector(
- blockType,
- mustBeFocused
- )}{ content: ${JSON.stringify(placeholder)}; }`
- );
-
- // For some reason, the placeholders which show when the block is focused
- // take priority over ones which show depending on block type, so we need
- // to make sure the block specific ones are also used when the block is
- // focused.
- if (!mustBeFocused) {
- styleSheet.insertRule(
- `${getSelector(blockType, true)}{ content: ${JSON.stringify(
- placeholder
- )}; }`
- );
- }
- }
-
- return {
- destroy: () => {
- document.head.removeChild(styleEl);
- },
- };
- },
- props: {
- // TODO: maybe also add placeholder for empty document ("e.g.: start writing..")
- decorations: (state) => {
- const { doc, selection } = state;
-
- const active = this.editor.isEditable;
-
- if (!active) {
- return;
- }
-
- if (!selection.empty) {
- return;
- }
-
- const $pos = selection.$anchor;
- const node = $pos.parent;
-
- if (node.content.size > 0) {
- return null;
- }
-
- const before = $pos.before();
-
- const dec = Decoration.node(before, before + node.nodeSize, {
- "data-is-empty-and-focused": "true",
- });
-
- return DecorationSet.create(doc, [dec]);
- },
- },
- }),
- ];
- },
-});
diff --git a/packages/core/src/extensions/Placeholder/PlaceholderPlugin.ts b/packages/core/src/extensions/Placeholder/PlaceholderPlugin.ts
new file mode 100644
index 0000000000..aa7f423126
--- /dev/null
+++ b/packages/core/src/extensions/Placeholder/PlaceholderPlugin.ts
@@ -0,0 +1,95 @@
+import { Plugin, PluginKey } from "prosemirror-state";
+import { Decoration, DecorationSet } from "prosemirror-view";
+import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
+
+const PLUGIN_KEY = new PluginKey(`blocknote-placeholder`);
+
+export const PlaceholderPlugin = (
+ editor: BlockNoteEditor,
+ placeholders: Record
+) => {
+ return new Plugin({
+ key: PLUGIN_KEY,
+ view: () => {
+ const styleEl = document.createElement("style");
+ document.head.appendChild(styleEl);
+ const styleSheet = styleEl.sheet!;
+
+ const getBaseSelector = (additionalSelectors = "") =>
+ `.bn-block-content${additionalSelectors} .bn-inline-content:has(> .ProseMirror-trailingBreak):before`;
+
+ const getSelector = (
+ blockType: string | "default",
+ mustBeFocused = true
+ ) => {
+ const mustBeFocusedSelector = mustBeFocused
+ ? `[data-is-empty-and-focused]`
+ : ``;
+
+ if (blockType === "default") {
+ return getBaseSelector(mustBeFocusedSelector);
+ }
+
+ const blockTypeSelector = `[data-content-type="${blockType}"]`;
+ return getBaseSelector(mustBeFocusedSelector + blockTypeSelector);
+ };
+
+ for (const [blockType, placeholder] of Object.entries(placeholders)) {
+ const mustBeFocused = blockType === "default";
+
+ styleSheet.insertRule(
+ `${getSelector(blockType, mustBeFocused)}{ content: ${JSON.stringify(
+ placeholder
+ )}; }`
+ );
+
+ // For some reason, the placeholders which show when the block is focused
+ // take priority over ones which show depending on block type, so we need
+ // to make sure the block specific ones are also used when the block is
+ // focused.
+ if (!mustBeFocused) {
+ styleSheet.insertRule(
+ `${getSelector(blockType, true)}{ content: ${JSON.stringify(
+ placeholder
+ )}; }`
+ );
+ }
+ }
+
+ return {
+ destroy: () => {
+ document.head.removeChild(styleEl);
+ },
+ };
+ },
+ props: {
+ // TODO: maybe also add placeholder for empty document ("e.g.: start writing..")
+ decorations: (state) => {
+ const { doc, selection } = state;
+
+ if (!editor.isEditable) {
+ return;
+ }
+
+ if (!selection.empty) {
+ return;
+ }
+
+ const $pos = selection.$anchor;
+ const node = $pos.parent;
+
+ if (node.content.size > 0) {
+ return null;
+ }
+
+ const before = $pos.before();
+
+ const dec = Decoration.node(before, before + node.nodeSize, {
+ "data-is-empty-and-focused": "true",
+ });
+
+ return DecorationSet.create(doc, [dec]);
+ },
+ },
+ });
+};
diff --git a/packages/core/src/extensions/SuggestionMenu/DefaultSuggestionItem.ts b/packages/core/src/extensions/SuggestionMenu/DefaultSuggestionItem.ts
index 4505a3aaa9..874c7e318c 100644
--- a/packages/core/src/extensions/SuggestionMenu/DefaultSuggestionItem.ts
+++ b/packages/core/src/extensions/SuggestionMenu/DefaultSuggestionItem.ts
@@ -1,4 +1,7 @@
+import type { Dictionary } from "../../i18n/dictionary";
+
export type DefaultSuggestionItem = {
+ key: keyof Dictionary["slash_menu"];
title: string;
onItemClick: () => void;
subtext?: string;
diff --git a/packages/core/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts b/packages/core/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts
index a56363634e..8805c6a4d6 100644
--- a/packages/core/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts
+++ b/packages/core/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts
@@ -83,95 +83,82 @@ export function getDefaultSlashMenuItems<
if (checkDefaultBlockTypeInSchema("heading", editor)) {
items.push(
{
- title: "Heading 1",
onItemClick: () => {
insertOrUpdateBlock(editor, {
type: "heading",
props: { level: 1 },
});
},
- subtext: "Used for a top-level heading",
badge: formatKeyboardShortcut("Mod-Alt-1"),
- aliases: ["h", "heading1", "h1"],
- group: "Headings",
+ key: "heading",
+ ...editor.dictionary.slash_menu.heading,
},
{
- title: "Heading 2",
onItemClick: () => {
insertOrUpdateBlock(editor, {
type: "heading",
props: { level: 2 },
});
},
- subtext: "Used for key sections",
badge: formatKeyboardShortcut("Mod-Alt-2"),
- aliases: ["h2", "heading2", "subheading"],
- group: "Headings",
+ key: "heading_2",
+ ...editor.dictionary.slash_menu.heading_2,
},
{
- title: "Heading 3",
onItemClick: () => {
insertOrUpdateBlock(editor, {
type: "heading",
props: { level: 3 },
});
},
- subtext: "Used for subsections and group headings",
badge: formatKeyboardShortcut("Mod-Alt-3"),
- aliases: ["h3", "heading3", "subheading"],
- group: "Headings",
+ key: "heading_3",
+ ...editor.dictionary.slash_menu.heading_3,
}
);
}
if (checkDefaultBlockTypeInSchema("numberedListItem", editor)) {
items.push({
- title: "Numbered List",
onItemClick: () => {
insertOrUpdateBlock(editor, {
type: "numberedListItem",
});
},
- subtext: "Used to display a numbered list",
badge: formatKeyboardShortcut("Mod-Shift-7"),
- aliases: ["ol", "li", "list", "numberedlist", "numbered list"],
- group: "Basic blocks",
+ key: "numbered_list",
+ ...editor.dictionary.slash_menu.numbered_list,
});
}
if (checkDefaultBlockTypeInSchema("bulletListItem", editor)) {
items.push({
- title: "Bullet List",
onItemClick: () => {
insertOrUpdateBlock(editor, {
type: "bulletListItem",
});
},
- subtext: "Used to display an unordered list",
badge: formatKeyboardShortcut("Mod-Shift-8"),
- aliases: ["ul", "li", "list", "bulletlist", "bullet list"],
- group: "Basic blocks",
+ key: "bullet_list",
+ ...editor.dictionary.slash_menu.bullet_list,
});
}
if (checkDefaultBlockTypeInSchema("paragraph", editor)) {
items.push({
- title: "Paragraph",
onItemClick: () => {
insertOrUpdateBlock(editor, {
type: "paragraph",
});
},
- subtext: "Used for the body of your document",
badge: formatKeyboardShortcut("Mod-Alt-0"),
- aliases: ["p", "paragraph"],
- group: "Basic blocks",
+ key: "paragraph",
+ ...editor.dictionary.slash_menu.paragraph,
});
}
if (checkDefaultBlockTypeInSchema("table", editor)) {
items.push({
- title: "Table",
onItemClick: () => {
insertOrUpdateBlock(editor, {
type: "table",
@@ -188,16 +175,14 @@ export function getDefaultSlashMenuItems<
},
});
},
- subtext: "Used for for tables",
- aliases: ["table"],
- group: "Advanced",
badge: undefined,
+ key: "table",
+ ...editor.dictionary.slash_menu.table,
});
}
if (checkDefaultBlockTypeInSchema("image", editor)) {
items.push({
- title: "Image",
onItemClick: () => {
const insertedBlock = insertOrUpdateBlock(editor, {
type: "image",
@@ -210,19 +195,8 @@ export function getDefaultSlashMenuItems<
})
);
},
- subtext: "Insert an image",
- aliases: [
- "image",
- "imageUpload",
- "upload",
- "img",
- "picture",
- "media",
- "url",
- "drive",
- "dropbox",
- ],
- group: "Media",
+ key: "image",
+ ...editor.dictionary.slash_menu.image,
});
}
diff --git a/packages/core/src/extensions/TableHandles/TableHandlesPlugin.ts b/packages/core/src/extensions/TableHandles/TableHandlesPlugin.ts
index 8b1918d8e5..ac0be6cda9 100644
--- a/packages/core/src/extensions/TableHandles/TableHandlesPlugin.ts
+++ b/packages/core/src/extensions/TableHandles/TableHandlesPlugin.ts
@@ -350,7 +350,7 @@ export class TableHandlesView<
};
destroy() {
- this.pmView.dom.removeEventListener("mousedown", this.mouseMoveHandler);
+ this.pmView.dom.removeEventListener("mousemove", this.mouseMoveHandler);
document.removeEventListener("dragover", this.dragOverHandler);
document.removeEventListener("drop", this.dropHandler);
diff --git a/packages/core/src/i18n/dictionary.ts b/packages/core/src/i18n/dictionary.ts
new file mode 100644
index 0000000000..c93e6533c5
--- /dev/null
+++ b/packages/core/src/i18n/dictionary.ts
@@ -0,0 +1,17 @@
+// function scramble(dict: any) {
+// const newDict: any = {} as any;
+
+import type { en } from "./locales";
+
+// for (const key in dict) {
+// if (typeof dict[key] === "object") {
+// newDict[key] = scramble(dict[key]);
+// } else {
+// newDict[key] = dict[key].split("").reverse().join("");
+// }
+// }
+
+// return newDict;
+// }
+
+export type Dictionary = typeof en;
diff --git a/packages/core/src/i18n/locales/en.ts b/packages/core/src/i18n/locales/en.ts
new file mode 100644
index 0000000000..3efd049612
--- /dev/null
+++ b/packages/core/src/i18n/locales/en.ts
@@ -0,0 +1,192 @@
+export const en = {
+ slash_menu: {
+ heading: {
+ title: "Heading 1",
+ subtext: "Used for a top-level heading",
+ aliases: ["h", "heading1", "h1"],
+ group: "Headings",
+ },
+ heading_2: {
+ title: "Heading 2",
+ subtext: "Used for key sections",
+ aliases: ["h2", "heading2", "subheading"],
+ group: "Headings",
+ },
+ heading_3: {
+ title: "Heading 3",
+ subtext: "Used for subsections and group headings",
+ aliases: ["h3", "heading3", "subheading"],
+ group: "Headings",
+ },
+ numbered_list: {
+ title: "Numbered List",
+ subtext: "Used to display a numbered list",
+ aliases: ["ol", "li", "list", "numberedlist", "numbered list"],
+ group: "Basic blocks",
+ },
+ bullet_list: {
+ title: "Bullet List",
+ subtext: "Used to display an unordered list",
+ aliases: ["ul", "li", "list", "bulletlist", "bullet list"],
+ group: "Basic blocks",
+ },
+ paragraph: {
+ title: "Paragraph",
+ subtext: "Used for the body of your document",
+ aliases: ["p", "paragraph"],
+ group: "Basic blocks",
+ },
+ table: {
+ title: "Table",
+ subtext: "Used for for tables",
+ aliases: ["table"],
+ group: "Advanced",
+ },
+ image: {
+ title: "Image",
+ subtext: "Insert an image",
+ aliases: [
+ "image",
+ "imageUpload",
+ "upload",
+ "img",
+ "picture",
+ "media",
+ "url",
+ "drive",
+ "dropbox",
+ ],
+ group: "Media",
+ },
+ },
+ placeholders: {
+ default: "Enter text or type '/' for commands",
+ heading: "Heading",
+ bulletListItem: "List",
+ numberedListItem: "List",
+ },
+ image: {
+ add_button: "Add Image",
+ },
+ // from react package:
+ drag_handle: {
+ delete_menuitem: "Delete",
+ colors_menuitem: "Colors",
+ },
+ table_handle: {
+ delete_column_menuitem: "Delete column",
+ delete_row_menuitem: "Delete row",
+ add_left_menuitem: "Add column left",
+ add_right_menuitem: "Add column right",
+ add_above_menuitem: "Add row above",
+ add_below_menuitem: "Add row below",
+ },
+ suggestion_menu: {
+ no_items_title: "No items found",
+ loading: "Loading…",
+ },
+ color_picker: {
+ text_title: "Text",
+ background_title: "Background",
+ colors: {
+ default: "Default",
+ gray: "Gray",
+ brown: "Brown",
+ red: "Red",
+ orange: "Orange",
+ yellow: "Yellow",
+ green: "Green",
+ blue: "Blue",
+ purple: "Purple",
+ pink: "Pink",
+ },
+ },
+
+ formatting_toolbar: {
+ bold: {
+ tooltip: "Bold",
+ secondary_tooltip: "Mod+B",
+ },
+ italic: {
+ tooltip: "Italic",
+ secondary_tooltip: "Mod+I",
+ },
+ underline: {
+ tooltip: "Underline",
+ secondary_tooltip: "Mod+U",
+ },
+ strike: {
+ tooltip: "Strike",
+ secondary_tooltip: "Mod+Shift+X",
+ },
+ code: {
+ tooltip: "Code",
+ secondary_tooltip: "",
+ },
+ colors: {
+ tooltip: "Colors",
+ },
+ link: {
+ tooltip: "Create link",
+ secondary_tooltip: "Mod+K",
+ },
+ image_caption: {
+ tooltip: "Edit caption",
+ input_placeholder: "Edit caption",
+ },
+ image_replace: {
+ tooltip: "Replace image",
+ },
+ nest: {
+ tooltip: "Nest block",
+ secondary_tooltip: "Tab",
+ },
+ unnest: {
+ tooltip: "Unnest block",
+ secondary_tooltip: "Shift+Tab",
+ },
+ align_left: {
+ tooltip: "Align text left",
+ },
+ align_center: {
+ tooltip: "Align text center",
+ },
+ align_right: {
+ tooltip: "Align text right",
+ },
+ align_justify: {
+ tooltip: "Justify text",
+ },
+ },
+ image_panel: {
+ upload: {
+ title: "Upload",
+ file_placeholder: "Upload image",
+ upload_error: "Error: Upload failed",
+ },
+ embed: {
+ title: "Embed",
+ embed_button: "Embed image",
+ url_placeholder: "Enter URL",
+ },
+ },
+ link_toolbar: {
+ delete: {
+ tooltip: "Remove link",
+ },
+ edit: {
+ text: "Edit link",
+ tooltip: "Edit",
+ },
+ open: {
+ tooltip: "Open in new tab",
+ },
+ form: {
+ title_placeholder: "Edit title",
+ url_placeholder: "Edit URL",
+ },
+ },
+ generic: {
+ ctrl_shortcut: "Ctrl",
+ },
+};
diff --git a/packages/core/src/i18n/locales/index.ts b/packages/core/src/i18n/locales/index.ts
new file mode 100644
index 0000000000..fe36955d21
--- /dev/null
+++ b/packages/core/src/i18n/locales/index.ts
@@ -0,0 +1 @@
+export * from "./en";
diff --git a/packages/core/src/i18n/locales/nl.ts b/packages/core/src/i18n/locales/nl.ts
new file mode 100644
index 0000000000..be0cf48363
--- /dev/null
+++ b/packages/core/src/i18n/locales/nl.ts
@@ -0,0 +1,193 @@
+import type { Dictionary } from "../dictionary";
+
+export const nl: Dictionary = {
+ slash_menu: {
+ heading: {
+ title: "Kop 1",
+ subtext: "Gebruikt voor een hoofdkop",
+ aliases: ["h", "kop1", "h1"],
+ group: "Koppen",
+ },
+ heading_2: {
+ title: "Kop 2",
+ subtext: "Gebruikt voor belangrijke secties",
+ aliases: ["h2", "kop2", "subkop"],
+ group: "Koppen",
+ },
+ heading_3: {
+ title: "Kop 3",
+ subtext: "Gebruikt voor subsecties en groepskoppen",
+ aliases: ["h3", "kop3", "subkop"],
+ group: "Koppen",
+ },
+ numbered_list: {
+ title: "Genummerde Lijst",
+ subtext: "Gebruikt om een genummerde lijst weer te geven",
+ aliases: ["ol", "li", "lijst", "genummerdelijst", "genummerde lijst"],
+ group: "Basisblokken",
+ },
+ bullet_list: {
+ title: "Puntenlijst",
+ subtext: "Gebruikt om een ongeordende lijst weer te geven",
+ aliases: ["ul", "li", "lijst", "puntenlijst", "punten lijst"],
+ group: "Basisblokken",
+ },
+ paragraph: {
+ title: "Paragraaf",
+ subtext: "Gebruikt voor de hoofdtekst van uw document",
+ aliases: ["p", "paragraaf"],
+ group: "Basisblokken",
+ },
+ table: {
+ title: "Tabel",
+ subtext: "Gebruikt voor tabellen",
+ aliases: ["tabel"],
+ group: "Geavanceerd",
+ },
+ image: {
+ title: "Afbeelding",
+ subtext: "Voeg een afbeelding in",
+ aliases: [
+ "afbeelding",
+ "imageUpload",
+ "upload",
+ "img",
+ "foto",
+ "media",
+ "url",
+ "drive",
+ "dropbox",
+ ],
+ group: "Media",
+ },
+ },
+ placeholders: {
+ default: "Voer tekst in of type '/' voor commando's",
+ heading: "Kop",
+ bulletListItem: "Lijst",
+ numberedListItem: "Lijst",
+ },
+ image: {
+ add_button: "Afbeelding toevoegen",
+ },
+ // from react package:
+ drag_handle: {
+ delete_menuitem: "Verwijder",
+ colors_menuitem: "Kleuren",
+ },
+ table_handle: {
+ delete_column_menuitem: "Verwijder kolom",
+ delete_row_menuitem: "Verwijder rij",
+ add_left_menuitem: "Voeg kolom links toe",
+ add_right_menuitem: "Voeg kolom rechts toe",
+ add_above_menuitem: "Voeg rij boven toe",
+ add_below_menuitem: "Voeg rij onder toe",
+ },
+ suggestion_menu: {
+ no_items_title: "Geen items gevonden",
+ loading: "Laden…",
+ },
+ color_picker: {
+ text_title: "Tekst",
+ background_title: "Achtergrond",
+ colors: {
+ default: "Standaard",
+ gray: "Grijs",
+ brown: "Bruin",
+ red: "Rood",
+ orange: "Oranje",
+ yellow: "Geel",
+ green: "Groen",
+ blue: "Blauw",
+ purple: "Paars",
+ pink: "Roze",
+ },
+ },
+ formatting_toolbar: {
+ bold: {
+ tooltip: "Vet",
+ secondary_tooltip: "Mod+B",
+ },
+ italic: {
+ tooltip: "Cursief",
+ secondary_tooltip: "Mod+I",
+ },
+ underline: {
+ tooltip: "Onderstrepen",
+ secondary_tooltip: "Mod+U",
+ },
+ strike: {
+ tooltip: "Doorstrepen",
+ secondary_tooltip: "Mod+Shift+X",
+ },
+ code: {
+ tooltip: "Code",
+ secondary_tooltip: "",
+ },
+ colors: {
+ tooltip: "Kleuren",
+ },
+ link: {
+ tooltip: "Maak link",
+ secondary_tooltip: "Mod+K",
+ },
+ image_caption: {
+ tooltip: "Bewerk onderschrift",
+ input_placeholder: "Bewerk onderschrift",
+ },
+ image_replace: {
+ tooltip: "Vervang afbeelding",
+ },
+ nest: {
+ tooltip: "Nest blok",
+ secondary_tooltip: "Tab",
+ },
+ unnest: {
+ tooltip: "Ontnest blok",
+ secondary_tooltip: "Shift+Tab",
+ },
+ align_left: {
+ tooltip: "Tekst links uitlijnen",
+ },
+ align_center: {
+ tooltip: "Tekst centreren",
+ },
+ align_right: {
+ tooltip: "Tekst rechts uitlijnen",
+ },
+ align_justify: {
+ tooltip: "Tekst uitvullen",
+ },
+ },
+ image_panel: {
+ upload: {
+ title: "Upload",
+ file_placeholder: "Upload afbeelding",
+ upload_error: "Fout: Upload mislukt",
+ },
+ embed: {
+ title: "Insluiten",
+ embed_button: "Insluiten afbeelding",
+ url_placeholder: "Voer URL in",
+ },
+ },
+ link_toolbar: {
+ delete: {
+ tooltip: "Verwijder link",
+ },
+ edit: {
+ text: "Bewerk link",
+ tooltip: "Bewerk",
+ },
+ open: {
+ tooltip: "Open in nieuw tabblad",
+ },
+ form: {
+ title_placeholder: "Bewerk titel",
+ url_placeholder: "Bewerk URL",
+ },
+ },
+ generic: {
+ ctrl_shortcut: "Ctrl",
+ },
+};
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index 5a202f72bd..1a70105d11 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -1,3 +1,4 @@
+import * as locales from "./i18n/locales";
export * from "./api/exporters/html/externalHTMLExporter";
export * from "./api/exporters/html/internalHTMLSerializer";
export * from "./api/testUtil";
@@ -25,4 +26,6 @@ export * from "./util/string";
export * from "./api/nodeConversions/nodeConversions";
export * from "./api/testUtil/partialBlockTestUtil";
export * from "./extensions/UniqueID/UniqueID";
+export * from "./i18n/dictionary";
export { UnreachableCaseError } from "./util/typescript";
+export { locales };
diff --git a/packages/core/src/util/browser.ts b/packages/core/src/util/browser.ts
index e5fcf8ac71..9ecdf3250d 100644
--- a/packages/core/src/util/browser.ts
+++ b/packages/core/src/util/browser.ts
@@ -4,11 +4,11 @@ export const isAppleOS = () =>
(/AppleWebKit/.test(navigator.userAgent) &&
/Mobile\/\w+/.test(navigator.userAgent)));
-export function formatKeyboardShortcut(shortcut: string) {
+export function formatKeyboardShortcut(shortcut: string, ctrlText = "Ctrl") {
if (isAppleOS()) {
return shortcut.replace("Mod", "⌘");
} else {
- return shortcut.replace("Mod", "Ctrl");
+ return shortcut.replace("Mod", ctrlText);
}
}
diff --git a/packages/dev-scripts/examples/template-react/package.json.template.tsx b/packages/dev-scripts/examples/template-react/package.json.template.tsx
index 5b391fab85..aa21a45bbc 100644
--- a/packages/dev-scripts/examples/template-react/package.json.template.tsx
+++ b/packages/dev-scripts/examples/template-react/package.json.template.tsx
@@ -13,8 +13,11 @@ const template = (project: Project) => ({
lint: "eslint . --max-warnings 0",
},
dependencies: {
- "@blocknote/core": "^0.12.0",
- "@blocknote/react": "^0.12.0",
+ "@blocknote/core": "^0.12.1",
+ "@blocknote/react": "^0.12.2",
+ "@blocknote/ariakit": "^0.12.2",
+ "@blocknote/mantine": "^0.12.2",
+ "@blocknote/shadcn": "^0.12.2",
react: "^18.2.0",
"react-dom": "^18.2.0",
...(project.config?.dependencies || {}),
diff --git a/packages/mantine/package.json b/packages/mantine/package.json
new file mode 100644
index 0000000000..f656fbff26
--- /dev/null
+++ b/packages/mantine/package.json
@@ -0,0 +1,86 @@
+{
+ "name": "@blocknote/mantine",
+ "homepage": "https://github.com/TypeCellOS/BlockNote",
+ "private": false,
+ "license": "MPL-2.0",
+ "version": "0.12.2",
+ "files": [
+ "dist",
+ "types",
+ "src"
+ ],
+ "keywords": [
+ "react",
+ "javascript",
+ "editor",
+ "typescript",
+ "prosemirror",
+ "wysiwyg",
+ "rich-text-editor",
+ "notion",
+ "yjs",
+ "block-based",
+ "tiptap"
+ ],
+ "description": "A \"Notion-style\" block-based extensible text editor built on top of Prosemirror and Tiptap.",
+ "type": "module",
+ "source": "src/index.tsx",
+ "types": "./types/src/index.d.ts",
+ "main": "./dist/blocknote-mantine.umd.cjs",
+ "module": "./dist/blocknote-mantine.js",
+ "exports": {
+ ".": {
+ "types": "./types/src/index.d.ts",
+ "import": "./dist/blocknote-mantine.js",
+ "require": "./dist/blocknote-mantine.umd.cjs"
+ },
+ "./style.css": {
+ "import": "./dist/style.css",
+ "require": "./dist/style.css"
+ }
+ },
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "build-bundled": "tsc && vite build --config vite.config.bundled.ts && git checkout tmp-releases && rm -rf ../../release && mv ../../release-tmp ../../release",
+ "preview": "vite preview",
+ "lint": "eslint src --max-warnings 0",
+ "clean": "rimraf dist && rimraf types"
+ },
+ "dependencies": {
+ "@blocknote/core": "*",
+ "@blocknote/react": "*",
+ "@mantine/core": "^7.5.0",
+ "@mantine/hooks": "^7.5.0",
+ "@mantine/utils": "^6.0.21",
+ "react": "^18",
+ "react-dom": "^18",
+ "react-icons": "^4.3.1"
+ },
+ "devDependencies": {
+ "@types/react": "^18.0.25",
+ "@types/react-dom": "^18.0.9",
+ "@vitejs/plugin-react": "^4.0.4",
+ "eslint": "^8.10.0",
+ "prettier": "^2.7.1",
+ "rimraf": "^5.0.5",
+ "rollup-plugin-webpack-stats": "^0.2.2",
+ "typescript": "^5.3.3",
+ "vite": "^4.4.8",
+ "vite-plugin-eslint": "^1.8.1",
+ "vite-plugin-externalize-deps": "^0.7.0"
+ },
+ "peerDependencies": {
+ "react": "^18",
+ "react-dom": "^18"
+ },
+ "eslintConfig": {
+ "extends": [
+ "../../.eslintrc.js"
+ ]
+ },
+ "publishConfig": {
+ "access": "public",
+ "registry": "https://registry.npmjs.org/"
+ }
+}
diff --git a/packages/mantine/src/form/TextInput.tsx b/packages/mantine/src/form/TextInput.tsx
new file mode 100644
index 0000000000..db4a76a1c6
--- /dev/null
+++ b/packages/mantine/src/form/TextInput.tsx
@@ -0,0 +1,39 @@
+import * as Mantine from "@mantine/core";
+
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const TextInput = forwardRef<
+ HTMLInputElement,
+ ComponentProps["Generic"]["Form"]["TextInput"]
+>((props, ref) => {
+ const {
+ className,
+ name,
+ label,
+ icon,
+ value,
+ autoFocus,
+ placeholder,
+ onKeyDown,
+ onChange,
+ onSubmit,
+ } = props;
+
+ return (
+
+ );
+});
diff --git a/packages/mantine/src/index.tsx b/packages/mantine/src/index.tsx
new file mode 100644
index 0000000000..285b27397a
--- /dev/null
+++ b/packages/mantine/src/index.tsx
@@ -0,0 +1,110 @@
+import {
+ BlockNoteViewRaw,
+ Components,
+ ComponentsContext,
+} from "@blocknote/react";
+import { MantineProvider } from "@mantine/core";
+import { ComponentProps } from "react";
+
+import { TextInput } from "./form/TextInput";
+import {
+ Menu,
+ MenuDivider,
+ MenuDropdown,
+ MenuItem,
+ MenuLabel,
+ MenuTrigger,
+} from "./menu/Menu";
+import { Panel } from "./panel/Panel";
+import { PanelButton } from "./panel/PanelButton";
+import { PanelFileInput } from "./panel/PanelFileInput";
+import { PanelTab } from "./panel/PanelTab";
+import { PanelTextInput } from "./panel/PanelTextInput";
+import { Popover, PopoverContent, PopoverTrigger } from "./popover/Popover";
+import { SideMenu } from "./sideMenu/SideMenu";
+import { SideMenuButton } from "./sideMenu/SideMenuButton";
+import { SuggestionMenu } from "./suggestionMenu/SuggestionMenu";
+import { SuggestionMenuItem } from "./suggestionMenu/SuggestionMenuItem";
+import { SuggestionMenuEmptyItem } from "./suggestionMenu/SuggestionMenuEmptyItem";
+import { SuggestionMenuLabel } from "./suggestionMenu/SuggestionMenuLabel";
+import { SuggestionMenuLoader } from "./suggestionMenu/SuggestionMenuLoader";
+import { TableHandle } from "./tableHandle/TableHandle";
+import { Toolbar } from "./toolbar/Toolbar";
+import { ToolbarButton } from "./toolbar/ToolbarButton";
+import { ToolbarSelect } from "./toolbar/ToolbarSelect";
+
+import "./style.css";
+
+export const components: Components = {
+ FormattingToolbar: {
+ Root: Toolbar,
+ Button: ToolbarButton,
+ Select: ToolbarSelect,
+ },
+ ImagePanel: {
+ Root: Panel,
+ Button: PanelButton,
+ FileInput: PanelFileInput,
+ TabPanel: PanelTab,
+ TextInput: PanelTextInput,
+ },
+ LinkToolbar: {
+ Root: Toolbar,
+ Button: ToolbarButton,
+ },
+ SideMenu: {
+ Root: SideMenu,
+ Button: SideMenuButton,
+ },
+ SuggestionMenu: {
+ Root: SuggestionMenu,
+ Item: SuggestionMenuItem,
+ EmptyItem: SuggestionMenuEmptyItem,
+ Label: SuggestionMenuLabel,
+ Loader: SuggestionMenuLoader,
+ },
+ TableHandle: {
+ Root: TableHandle,
+ },
+ Generic: {
+ Form: {
+ Root: (props) => {props.children}
,
+ TextInput: TextInput,
+ },
+ Menu: {
+ Root: Menu,
+ Trigger: MenuTrigger,
+ Dropdown: MenuDropdown,
+ Divider: MenuDivider,
+ Label: MenuLabel,
+ Item: MenuItem,
+ },
+ Popover: {
+ Root: Popover,
+ Trigger: PopoverTrigger,
+ Content: PopoverContent,
+ },
+ },
+};
+
+const mantineTheme = {
+ // Removes button press effect
+ activeClassName: "",
+};
+
+export const BlockNoteView = (
+ // TODO: Fix typing
+ props: ComponentProps>
+) => {
+ return (
+
+ {/* `cssVariablesSelector` scopes Mantine CSS variables to only the editor, */}
+ {/* as proposed here: https://github.com/orgs/mantinedev/discussions/5685 */}
+
+
+
+
+ );
+};
diff --git a/packages/react/src/editor/mantineStyles.css b/packages/mantine/src/mantineStyles.css
similarity index 100%
rename from packages/react/src/editor/mantineStyles.css
rename to packages/mantine/src/mantineStyles.css
diff --git a/packages/mantine/src/menu/Menu.tsx b/packages/mantine/src/menu/Menu.tsx
new file mode 100644
index 0000000000..16d14aeea6
--- /dev/null
+++ b/packages/mantine/src/menu/Menu.tsx
@@ -0,0 +1,243 @@
+import * as Mantine from "@mantine/core";
+
+import { ComponentProps } from "@blocknote/react";
+import {
+ createContext,
+ forwardRef,
+ useCallback,
+ useContext,
+ useRef,
+ useState,
+} from "react";
+import { HiChevronRight } from "react-icons/hi";
+
+const SubMenuContext = createContext<
+ | {
+ onTriggerMouseOver: () => void;
+ onTriggerMouseLeave: () => void;
+ onMenuMouseOver: () => void;
+ onMenuMouseLeave: () => void;
+ }
+ | undefined
+>(undefined);
+
+// https://github.com/orgs/mantinedev/discussions/2307
+// Mantine does not officially support sub menus, so we have to use a workaround
+// which uses an unconventional nesting structure:
+//
+// Conventional nesting structure (used by Ariakit/ShadCN):
+//
+//
+// Required structure for Mantine:
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+const SubMenu = forwardRef<
+ HTMLDivElement,
+ ComponentProps["Generic"]["Menu"]["Root"]
+>((props, ref) => {
+ const {
+ children,
+ onOpenChange,
+ position,
+ // sub
+ } = props;
+ const [opened, setOpened] = useState(false);
+
+ const menuCloseTimer = useRef | undefined>();
+
+ const mouseLeave = useCallback(() => {
+ if (menuCloseTimer.current) {
+ clearTimeout(menuCloseTimer.current);
+ }
+ menuCloseTimer.current = setTimeout(() => {
+ setOpened(false);
+ }, 250);
+ }, []);
+
+ const mouseOver = useCallback(() => {
+ if (menuCloseTimer.current) {
+ clearTimeout(menuCloseTimer.current);
+ }
+
+ setOpened(true);
+ }, []);
+
+ return (
+
+
+ onOpenChange?.(false)}
+ onOpen={() => onOpenChange?.(true)}
+ position={position}>
+ {children}
+
+
+
+ );
+});
+
+export const Menu = (props: ComponentProps["Generic"]["Menu"]["Root"]) => {
+ const { children, onOpenChange, position, sub } = props;
+
+ if (sub) {
+ return ;
+ }
+
+ return (
+ onOpenChange?.(false)}
+ onOpen={() => onOpenChange?.(true)}
+ position={position}>
+ {children}
+
+ );
+};
+
+export const MenuItem = forwardRef<
+ HTMLDivElement,
+ ComponentProps["Generic"]["Menu"]["Item"]
+>((props, ref) => {
+ const { className, children, icon, checked, subTrigger, onClick, ...rest } =
+ props;
+
+ const ctx = useContext(SubMenuContext);
+
+ if (subTrigger) {
+ return (
+
+ {children}
+
+
+ );
+ }
+
+ const onMouseLeave = subTrigger ? ctx!.onTriggerMouseLeave : undefined;
+ const onMouseOver = subTrigger ? ctx!.onTriggerMouseOver : undefined;
+
+ return (
+
+ ) : checked === false ? (
+
+ ) : null
+ }
+ onMouseOver={onMouseOver}
+ onMouseLeave={onMouseLeave}
+ onClick={onClick}
+ {...rest}>
+ {children}
+
+ );
+});
+
+export const MenuTrigger = (
+ props: ComponentProps["Generic"]["Menu"]["Trigger"]
+) => {
+ const {
+ children,
+ // sub
+ } = props;
+
+ return {children};
+};
+
+export const MenuDropdown = forwardRef<
+ HTMLDivElement,
+ ComponentProps["Generic"]["Menu"]["Dropdown"]
+>((props, ref) => {
+ const { className, children, sub } = props;
+
+ const ctx = useContext(SubMenuContext);
+
+ return (
+
+ {children}
+
+ );
+});
+
+export const MenuDivider = forwardRef<
+ HTMLDivElement,
+ ComponentProps["Generic"]["Menu"]["Divider"]
+>((props, ref) => {
+ const { className } = props;
+
+ return ;
+});
+
+export const MenuLabel = forwardRef<
+ HTMLDivElement,
+ ComponentProps["Generic"]["Menu"]["Label"]
+>((props, ref) => {
+ const { className, children } = props;
+
+ return (
+
+ {children}
+
+ );
+});
diff --git a/packages/mantine/src/panel/Panel.tsx b/packages/mantine/src/panel/Panel.tsx
new file mode 100644
index 0000000000..78a29f6231
--- /dev/null
+++ b/packages/mantine/src/panel/Panel.tsx
@@ -0,0 +1,47 @@
+import * as Mantine from "@mantine/core";
+
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const Panel = forwardRef<
+ HTMLDivElement,
+ ComponentProps["ImagePanel"]["Root"]
+>((props, ref) => {
+ const {
+ className,
+ tabs,
+ defaultOpenTab,
+ openTab,
+ setOpenTab,
+ loading,
+ // setLoading,
+ } = props;
+
+ return (
+
+
+ {loading && }
+
+
+ {tabs.map((tab) => (
+
+ {tab.name}
+
+ ))}
+
+
+ {tabs.map((tab) => (
+
+ {tab.tabPanel}
+
+ ))}
+
+
+ );
+});
diff --git a/packages/mantine/src/panel/PanelButton.tsx b/packages/mantine/src/panel/PanelButton.tsx
new file mode 100644
index 0000000000..37909ce62a
--- /dev/null
+++ b/packages/mantine/src/panel/PanelButton.tsx
@@ -0,0 +1,22 @@
+import * as Mantine from "@mantine/core";
+
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const PanelButton = forwardRef<
+ HTMLButtonElement,
+ ComponentProps["ImagePanel"]["Button"]
+>((props, ref) => {
+ const { className, children, onClick, ...rest } = props;
+
+ return (
+
+ {children}
+
+ );
+});
diff --git a/packages/mantine/src/panel/PanelFileInput.tsx b/packages/mantine/src/panel/PanelFileInput.tsx
new file mode 100644
index 0000000000..5c38c138a4
--- /dev/null
+++ b/packages/mantine/src/panel/PanelFileInput.tsx
@@ -0,0 +1,23 @@
+import * as Mantine from "@mantine/core";
+
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const PanelFileInput = forwardRef<
+ HTMLButtonElement,
+ ComponentProps["ImagePanel"]["FileInput"]
+>((props, ref) => {
+ const { className, value, placeholder, onChange, ...rest } = props;
+
+ return (
+
+ );
+});
diff --git a/packages/mantine/src/panel/PanelTab.tsx b/packages/mantine/src/panel/PanelTab.tsx
new file mode 100644
index 0000000000..58ed2aba46
--- /dev/null
+++ b/packages/mantine/src/panel/PanelTab.tsx
@@ -0,0 +1,15 @@
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const PanelTab = forwardRef<
+ HTMLDivElement,
+ ComponentProps["ImagePanel"]["TabPanel"]
+>((props, ref) => {
+ const { className, children } = props;
+
+ return (
+
+ {children}
+
+ );
+});
diff --git a/packages/mantine/src/panel/PanelTextInput.tsx b/packages/mantine/src/panel/PanelTextInput.tsx
new file mode 100644
index 0000000000..59f6f9b884
--- /dev/null
+++ b/packages/mantine/src/panel/PanelTextInput.tsx
@@ -0,0 +1,24 @@
+import * as Mantine from "@mantine/core";
+
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const PanelTextInput = forwardRef<
+ HTMLInputElement,
+ ComponentProps["ImagePanel"]["TextInput"]
+>((props, ref) => {
+ const { className, value, placeholder, onKeyDown, onChange } = props;
+
+ return (
+
+ );
+});
diff --git a/packages/mantine/src/popover/Popover.tsx b/packages/mantine/src/popover/Popover.tsx
new file mode 100644
index 0000000000..ccc1a74aeb
--- /dev/null
+++ b/packages/mantine/src/popover/Popover.tsx
@@ -0,0 +1,41 @@
+import * as Mantine from "@mantine/core";
+
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const Popover = (
+ props: ComponentProps["Generic"]["Popover"]["Root"]
+) => {
+ const { children, opened, position } = props;
+
+ return (
+
+ {children}
+
+ );
+};
+
+export const PopoverTrigger = (
+ props: ComponentProps["Generic"]["Popover"]["Trigger"]
+) => {
+ const { children } = props;
+
+ return {children};
+};
+
+export const PopoverContent = forwardRef<
+ HTMLDivElement,
+ ComponentProps["Generic"]["Popover"]["Content"]
+>((props, ref) => {
+ const { className, children } = props;
+
+ return (
+
+ {children}
+
+ );
+});
diff --git a/packages/mantine/src/sideMenu/SideMenu.tsx b/packages/mantine/src/sideMenu/SideMenu.tsx
new file mode 100644
index 0000000000..7a233730d8
--- /dev/null
+++ b/packages/mantine/src/sideMenu/SideMenu.tsx
@@ -0,0 +1,17 @@
+import * as Mantine from "@mantine/core";
+
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const SideMenu = forwardRef<
+ HTMLDivElement,
+ ComponentProps["SideMenu"]["Root"]
+>((props, ref) => {
+ const { className, children } = props;
+
+ return (
+
+ {children}
+
+ );
+});
diff --git a/packages/mantine/src/sideMenu/SideMenuButton.tsx b/packages/mantine/src/sideMenu/SideMenuButton.tsx
new file mode 100644
index 0000000000..329f0baf4f
--- /dev/null
+++ b/packages/mantine/src/sideMenu/SideMenuButton.tsx
@@ -0,0 +1,30 @@
+import * as Mantine from "@mantine/core";
+
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const SideMenuButton = forwardRef<
+ HTMLButtonElement,
+ ComponentProps["SideMenu"]["Button"]
+>((props, ref) => {
+ const { className, children, icon, onClick, ...rest } = props;
+
+ if (icon) {
+ return (
+
+ {icon}
+
+ );
+ }
+
+ return (
+
+ {children}
+
+ );
+});
diff --git a/packages/mantine/src/style.css b/packages/mantine/src/style.css
new file mode 100644
index 0000000000..3f9aa96923
--- /dev/null
+++ b/packages/mantine/src/style.css
@@ -0,0 +1,490 @@
+@import url("@blocknote/react/style.css");
+@import url("./mantineStyles.css");
+
+/* Mantine base styles*/
+
+/* Mantine Badge component base styles */
+.bn-container .mantine-Badge-root {
+ background-color: var(--bn-colors-tooltip-background);
+ color: var(--bn-colors-tooltip-text);
+}
+
+/* Mantine FileInput component base styles */
+.bn-container .mantine-FileInput-input {
+ align-items: center;
+ background-color: var(--bn-colors-menu-background);
+ border: none;
+ border-radius: 4px;
+ color: var(--bn-colors-menu-text);
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+}
+
+.bn-container .mantine-FileInput-input:hover {
+ background-color: var(--bn-colors-hovered-background);
+}
+
+.bn-container .mantine-FileInput-wrapper {
+ border: solid var(--bn-colors-border) 1px;
+ border-radius: 4px;
+}
+
+.bn-container .mantine-InputPlaceholder-placeholder {
+ color: var(--bn-colors-menu-text);
+ font-weight: 600;
+}
+
+/* Mantine Menu component base styles */
+.bn-container .mantine-Menu-dropdown {
+ background-color: var(--bn-colors-menu-background);
+ border: var(--bn-border);
+ border-radius: var(--bn-border-radius-medium);
+ box-shadow: var(--bn-shadow-medium);
+ box-sizing: border-box;
+ color: var(--bn-colors-menu-text);
+ padding: 2px;
+ overflow: auto;
+}
+
+.bn-container .mantine-Menu-label {
+ background-color: var(--bn-colors-menu-background);
+ color: var(--bn-colors-menu-text);
+}
+
+.bn-container .mantine-Menu-item {
+ background-color: var(--bn-colors-menu-background);
+ border: none;
+ border-radius: var(--bn-border-radius-small);
+ color: var(--bn-colors-menu-text);
+}
+
+.bn-container .mantine-Menu-item[data-hovered] {
+ background-color: var(--bn-colors-hovered-background);
+ border: none;
+ color: var(--bn-colors-hovered-text);
+}
+
+/* Mantine Popover component base styles */
+.bn-container .mantine-Popover-dropdown {
+ background-color: transparent;
+ border: none;
+ border-radius: 0;
+ box-shadow: none;
+ padding: 0;
+}
+
+/* Mantine Tabs component base styles */
+.bn-container .mantine-Tabs-root {
+ width: 100%;
+ background-color: var(--bn-colors-menu-background);
+}
+
+.bn-container .mantine-Tabs-list:before {
+ border-color: var(--bn-colors-hovered-background);
+}
+
+.bn-container .mantine-Tabs-tab {
+ color: var(--bn-colors-menu-text);
+ border-color: var(--bn-colors-hovered-background);
+}
+
+.bn-container .mantine-Tabs-tab:hover {
+ background-color: var(--bn-colors-hovered-background);
+ border-color: var(--bn-colors-hovered-background);
+ color: var(--bn-colors-hovered-text);
+}
+
+.bn-container .mantine-Tabs-tab[data-active],
+.bn-container .mantine-Tabs-tab[data-active]:hover {
+ border-color: var(--bn-colors-menu-text);
+ color: var(--bn-colors-menu-text);
+}
+
+.bn-container .mantine-Tabs-panel {
+ padding: 8px;
+}
+
+/* Mantine TextInput component base styles */
+.bn-container .mantine-TextInput-input {
+ background-color: var(--bn-colors-menu-background);
+ border: solid var(--bn-colors-border) 1px;
+ border-radius: 4px;
+ color: var(--bn-colors-menu-text);
+ height: 32px;
+}
+
+/* Mantine Tooltip component base styles */
+.bn-container .mantine-Tooltip-tooltip {
+ background-color: transparent;
+ border: none;
+ border-radius: 0;
+ box-shadow: none;
+ padding: 0;
+}
+
+/* UI element styling */
+
+/* Select styling */
+.bn-select {
+ overflow: auto;
+}
+
+/* Toolbar styling */
+.bn-toolbar {
+ background-color: var(--bn-colors-menu-background);
+ border: var(--bn-border);
+ border-radius: var(--bn-border-radius-medium);
+ box-shadow: var(--bn-shadow-medium);
+ flex-wrap: nowrap;
+ gap: 2px;
+ padding: 2px;
+ width: fit-content;
+}
+
+.bn-toolbar:empty {
+ display: none;
+}
+
+.bn-toolbar .mantine-Button-root,
+.bn-toolbar .mantine-ActionIcon-root {
+ background-color: var(--bn-colors-menu-background);
+ border: none;
+ border-radius: var(--bn-border-radius-small);
+ color: var(--bn-colors-menu-text);
+}
+
+.bn-toolbar .mantine-Button-root:hover,
+.bn-toolbar .mantine-ActionIcon-root:hover {
+ background-color: var(--bn-colors-hovered-background);
+ border: none;
+ color: var(--bn-colors-hovered-text);
+}
+
+.bn-toolbar .mantine-Button-root[data-selected],
+.bn-toolbar .mantine-ActionIcon-root[data-selected] {
+ background-color: var(--bn-colors-selected-background);
+ border: none;
+ color: var(--bn-colors-selected-text);
+}
+
+.bn-toolbar .mantine-Button-root[data-disabled],
+.bn-toolbar .mantine-ActionIcon-root[data-disabled] {
+ background-color: var(--bn-colors-disabled-background);
+ border: none;
+ color: var(--bn-colors-disabled-text);
+}
+
+.bn-toolbar .mantine-Menu-item {
+ font-size: 12px;
+ height: 30px;
+}
+
+.bn-toolbar .mantine-Menu-item:hover {
+ background-color: var(--bn-colors-hovered-background);
+}
+
+.bn-container .bn-form-popover {
+ background-color: var(--bn-colors-menu-background);
+ border: var(--bn-border);
+ border-radius: var(--bn-border-radius-medium);
+ box-shadow: var(--bn-shadow-medium);
+ color: var(--bn-colors-menu-text);
+ gap: 4px;
+ min-width: 145px;
+ padding: 2px;
+}
+
+.bn-form-popover .mantine-TextInput-root,
+.bn-form-popover .mantine-FileInput-root {
+ width: 300px;
+}
+
+.bn-form-popover .mantine-TextInput-wrapper,
+.bn-form-popover .mantine-FileInput-wrapper {
+ padding: 0;
+ border-radius: 4px;
+}
+
+.bn-form-popover .mantine-TextInput-wrapper:hover {
+ background-color: var(--bn-colors-hovered-background);
+}
+
+.bn-form-popover .mantine-TextInput-input,
+.bn-form-popover .mantine-FileInput-input {
+ border: none;
+ font-size: 12px;
+}
+
+.bn-form-popover .mantine-FileInput-input:hover {
+ background-color: var(--bn-colors-hovered-background);
+}
+
+.bn-form-popover .mantine-FileInput-section[data-position="left"] {
+ color: var(--bn-colors-menu-text);
+}
+
+.bn-form-popover .mantine-FileInput-placeholder {
+ color: var(--bn-colors-menu-text);
+}
+
+/* Suggestion Menu styling*/
+
+/*TODO: Make sure there's a clear split between copied Mantine Menu styles and
+ additional BlockNote styles*/
+
+/* Base styles for Suggestion Menus, copied from the Mantine Menu component. */
+/* Unfortunately necessary, as we can't use a Menu.Dropdown component on its
+ own. */
+/* https://github.com/mantinedev/mantine/blob/e3e3bb834de1f2f75a27dbc757dc0a2fc6a6cba8/packages/%40mantine/core/src/components/Menu/Menu.module.css */
+.bn-suggestion-menu {
+ max-height: 100%;
+ position: relative;
+ box-shadow: var(--mantine-shadow-md);
+ border: calc(0.0625rem * var(--mantine-scale)) solid
+ var(--mantine-color-gray-2);
+ border-radius: var(--mantine-radius-default);
+ padding: 4px;
+}
+
+.bn-suggestion-menu-label {
+ color: var(--mantine-color-dimmed);
+ font-weight: 500;
+ font-size: var(--mantine-font-size-xs);
+ padding: calc(var(--mantine-spacing-xs) / 2) var(--mantine-spacing-sm);
+ cursor: default;
+}
+
+.bn-suggestion-menu-item {
+ font-size: var(--mantine-font-size-sm);
+ width: 100%;
+ padding: calc(var(--mantine-spacing-xs) / 1.5) var(--mantine-spacing-sm);
+ border-radius: var(--popover-radius, var(--mantine-radius-default));
+ color: var(--menu-item-color, var(--mantine-color-text));
+ display: flex;
+ align-items: center;
+ user-select: none;
+
+ &:where([data-disabled], :disabled) {
+ color: var(--mantine-color-dimmed);
+ opacity: 0.6;
+ pointer-events: none;
+ }
+
+ &:where([data-hovered]) {
+ }
+}
+
+.bn-mt-suggestion-menu-item-body {
+ flex: 1;
+}
+
+.bn-mt-suggestion-menu-item-section {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ &:where([data-position="left"]) {
+ margin-inline-end: var(--mantine-spacing-xs);
+ }
+
+ &:where([data-position="right"]) {
+ margin-inline-start: var(--mantine-spacing-xs);
+ }
+}
+
+.bn-suggestion-menu {
+ background-color: var(--bn-colors-menu-background);
+ border: var(--bn-border);
+ border-radius: var(--bn-border-radius-medium);
+ box-shadow: var(--bn-shadow-medium);
+ box-sizing: border-box;
+ color: var(--bn-colors-menu-text);
+ overflow-y: auto;
+ padding: 2px;
+}
+
+.bn-suggestion-menu-item {
+ cursor: pointer;
+ height: 52px;
+}
+
+.bn-suggestion-menu-item[data-hovered] {
+ background-color: var(--bn-colors-hovered-background);
+}
+
+.bn-mt-suggestion-menu-item-section {
+ color: var(--bn-colors-tooltip-text);
+}
+
+.bn-mt-suggestion-menu-item-section[data-position="left"] {
+ background-color: var(--bn-colors-tooltip-background);
+ border-radius: var(--bn-border-radius-small);
+ padding: 8px;
+}
+
+.bn-mt-suggestion-menu-item-body {
+ align-items: stretch;
+ color: var(--bn-colors-menu-text);
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ justify-content: flex-start;
+ padding-right: 16px;
+}
+
+.bn-mt-suggestion-menu-item-title {
+ line-height: 20px;
+ font-weight: 500;
+ font-size: 14px;
+ margin: 0;
+ padding: 0;
+}
+
+.bn-mt-suggestion-menu-item-subtitle {
+ line-height: 16px;
+ font-size: 10px;
+ margin: 0;
+ padding: 0;
+}
+
+.bn-suggestion-menu-label {
+ color: var(--bn-colors-hovered-text);
+}
+
+.bn-suggestion-menu-loader {
+ height: 20px;
+ width: 100%;
+}
+
+.bn-suggestion-menu-loader span {
+ background-color: var(--bn-colors-side-menu);
+}
+
+/* Side Menu styling */
+.bn-side-menu {
+ background-color: transparent;
+ overflow: visible;
+}
+
+.bn-side-menu .mantine-Menu-item, .bn-table-handle-menu .mantine-Menu-item {
+ font-size: 12px;
+ height: 30px;
+}
+
+.bn-side-menu .mantine-UnstyledButton-root:not(.mantine-Menu-item) {
+ background-color: transparent;
+}
+
+.bn-side-menu .mantine-UnstyledButton-root:hover {
+ background-color: var(--bn-colors-hovered-background);
+}
+
+.bn-side-menu .mantine-UnstyledButton-root:not(.mantine-Menu-item) svg {
+ background-color: transparent;
+ color: var(--bn-colors-side-menu);
+ height: 22px;
+ width: 22px;
+}
+
+.bn-side-menu > [draggable="true"] {
+ display: flex;
+}
+
+.bn-side-menu .mantine-Menu-dropdown {
+ min-width: 100px;
+ padding: 2px;
+ position: absolute;
+}
+
+/* Image Panel styling*/
+.bn-panel {
+ background-color: var(--bn-colors-menu-background);
+ border: var(--bn-border);
+ border-radius: var(--bn-border-radius-medium);
+ box-shadow: var(--bn-shadow-medium);
+ padding: 2px;
+ width: 500px;
+}
+
+.bn-panel .bn-tab-panel {
+ align-items: center;
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ width: 100%;
+}
+
+.bn-panel .mantine-TextInput-root,
+.bn-panel .mantine-FileInput-root {
+ width: 100%;
+}
+
+.bn-panel .mantine-Button-root {
+ background-color: var(--bn-colors-menu-background);
+ border: solid var(--bn-colors-border) 1px;
+ border-radius: var(--bn-border-radius-small);
+ color: var(--bn-colors-menu-text);
+ height: 32px;
+ width: 60%;
+}
+
+.bn-panel .mantine-Button-root:hover {
+ background-color: var(--bn-colors-hovered-background);
+}
+
+.bn-panel.mantine-Text-root {
+ text-align: center;
+}
+
+/* Table Handle styling */
+.bn-table-handle {
+ align-items: center;
+ background-color: var(--bn-colors-menu-background);
+ border: var(--bn-border);
+ border-radius: var(--bn-border-radius-small);
+ box-shadow: var(--bn-shadow-light);
+ color: var(--bn-colors-side-menu);
+ cursor: pointer;
+ display: flex;
+ justify-content: center;
+ overflow: visible;
+ padding: 0;
+}
+
+.bn-table-handle svg {
+ margin-inline: -4px;
+}
+
+.bn-table-handle:hover,
+.bn-table-handle-dragging {
+ background-color: var(--bn-colors-hovered-background);
+}
+
+/* Drag Handle & Table Handle Menu styling */
+.bn-container .bn-drag-handle-menu {
+ overflow: visible;
+}
+
+/* Tooltip styling */
+.bn-tooltip {
+ background-color: var(--bn-colors-tooltip-background);
+ border: var(--bn-border);
+ border-radius: var(--bn-border-radius-medium);
+ box-shadow: var(--bn-shadow-medium);
+ color: var(--bn-colors-tooltip-text);
+ padding: 4px 10px;
+ text-align: center;
+}
+
+/* Additional menu styles */
+.bn-tick-space {
+ padding: 0;
+ width: 20px;
+}
+
+.bn-mt-sub-menu-item > .mantine-Menu-itemLabel > div:not(.mantine-Menu-dropdown) {
+ align-items: center;
+ display: flex;
+ justify-content: space-between;
+}
diff --git a/packages/mantine/src/suggestionMenu/SuggestionMenu.tsx b/packages/mantine/src/suggestionMenu/SuggestionMenu.tsx
new file mode 100644
index 0000000000..4c0e5a6db7
--- /dev/null
+++ b/packages/mantine/src/suggestionMenu/SuggestionMenu.tsx
@@ -0,0 +1,17 @@
+import * as Mantine from "@mantine/core";
+
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const SuggestionMenu = forwardRef<
+ HTMLDivElement,
+ ComponentProps["SuggestionMenu"]["Root"]
+>((props, ref) => {
+ const { className, children } = props;
+
+ return (
+
+ {children}
+
+ );
+});
diff --git a/packages/mantine/src/suggestionMenu/SuggestionMenuEmptyItem.tsx b/packages/mantine/src/suggestionMenu/SuggestionMenuEmptyItem.tsx
new file mode 100644
index 0000000000..3e88792d86
--- /dev/null
+++ b/packages/mantine/src/suggestionMenu/SuggestionMenuEmptyItem.tsx
@@ -0,0 +1,19 @@
+import * as Mantine from "@mantine/core";
+
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const SuggestionMenuEmptyItem = forwardRef<
+ HTMLDivElement,
+ ComponentProps["SuggestionMenu"]["EmptyItem"]
+>((props, ref) => {
+ const { className, children } = props;
+
+ return (
+
+
+ {children}
+
+
+ );
+});
diff --git a/packages/mantine/src/suggestionMenu/SuggestionMenuItem.tsx b/packages/mantine/src/suggestionMenu/SuggestionMenuItem.tsx
new file mode 100644
index 0000000000..bc622bb073
--- /dev/null
+++ b/packages/mantine/src/suggestionMenu/SuggestionMenuItem.tsx
@@ -0,0 +1,67 @@
+import * as Mantine from "@mantine/core";
+
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef, useCallback } from "react";
+
+export const SuggestionMenuItem = forwardRef<
+ HTMLDivElement,
+ ComponentProps["SuggestionMenu"]["Item"]
+>((props, ref) => {
+ const {
+ className,
+ title,
+ subtext,
+ // group,
+ icon,
+ badge,
+ // aliases,
+ // onItemClick,
+ isSelected,
+ setSelected,
+ onClick,
+ } = props;
+
+ const handleMouseLeave = useCallback(() => {
+ setSelected?.(false);
+ }, [setSelected]);
+
+ const handleMouseEnter = useCallback(() => {
+ setSelected?.(true);
+ }, [setSelected]);
+
+ return (
+
+ {icon && (
+
+ {icon}
+
+ )}
+
+
+ {title}
+
+
+ {subtext}
+
+
+ {badge && (
+
+ {badge}
+
+ )}
+
+ );
+});
diff --git a/packages/mantine/src/suggestionMenu/SuggestionMenuLabel.tsx b/packages/mantine/src/suggestionMenu/SuggestionMenuLabel.tsx
new file mode 100644
index 0000000000..9c7178cc9b
--- /dev/null
+++ b/packages/mantine/src/suggestionMenu/SuggestionMenuLabel.tsx
@@ -0,0 +1,17 @@
+import * as Mantine from "@mantine/core";
+
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const SuggestionMenuLabel = forwardRef<
+ HTMLDivElement,
+ ComponentProps["SuggestionMenu"]["Label"]
+>((props, ref) => {
+ const { className, children } = props;
+
+ return (
+
+ {children}
+
+ );
+});
diff --git a/packages/mantine/src/suggestionMenu/SuggestionMenuLoader.tsx b/packages/mantine/src/suggestionMenu/SuggestionMenuLoader.tsx
new file mode 100644
index 0000000000..c68760f42e
--- /dev/null
+++ b/packages/mantine/src/suggestionMenu/SuggestionMenuLoader.tsx
@@ -0,0 +1,17 @@
+import * as Mantine from "@mantine/core";
+
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const SuggestionMenuLoader = forwardRef<
+ HTMLDivElement,
+ ComponentProps["SuggestionMenu"]["Loader"]
+>((props, ref) => {
+ const { className, children } = props;
+
+ return (
+
+ {children}
+
+ );
+});
diff --git a/packages/mantine/src/tableHandle/TableHandle.tsx b/packages/mantine/src/tableHandle/TableHandle.tsx
new file mode 100644
index 0000000000..08ed50271e
--- /dev/null
+++ b/packages/mantine/src/tableHandle/TableHandle.tsx
@@ -0,0 +1,30 @@
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const TableHandle = forwardRef<
+ HTMLButtonElement,
+ ComponentProps["TableHandle"]["Root"]
+>((props, ref) => {
+ const {
+ className,
+ children,
+ draggable,
+ onDragStart,
+ onDragEnd,
+ style,
+ ...rest
+ } = props;
+
+ return (
+
+ );
+});
diff --git a/packages/mantine/src/toolbar/Toolbar.tsx b/packages/mantine/src/toolbar/Toolbar.tsx
new file mode 100644
index 0000000000..1ab8f33a64
--- /dev/null
+++ b/packages/mantine/src/toolbar/Toolbar.tsx
@@ -0,0 +1,23 @@
+import * as Mantine from "@mantine/core";
+
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+type ToolbarProps = ComponentProps["FormattingToolbar"]["Root"] &
+ ComponentProps["LinkToolbar"]["Root"];
+
+export const Toolbar = forwardRef(
+ (props, ref) => {
+ const { className, children, onMouseEnter, onMouseLeave } = props;
+
+ return (
+
+ {children}
+
+ );
+ }
+);
diff --git a/packages/mantine/src/toolbar/ToolbarButton.tsx b/packages/mantine/src/toolbar/ToolbarButton.tsx
new file mode 100644
index 0000000000..d6a6ccfe5d
--- /dev/null
+++ b/packages/mantine/src/toolbar/ToolbarButton.tsx
@@ -0,0 +1,97 @@
+import * as Mantine from "@mantine/core";
+
+import { isSafari } from "@blocknote/core";
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+
+export const TooltipContent = (props: {
+ mainTooltip: string;
+ secondaryTooltip?: string;
+}) => (
+
+ {props.mainTooltip}
+ {props.secondaryTooltip && (
+ {props.secondaryTooltip}
+ )}
+
+);
+
+type ToolbarButtonProps = ComponentProps["FormattingToolbar"]["Button"] &
+ ComponentProps["LinkToolbar"]["Button"];
+
+/**
+ * Helper for basic buttons that show in the formatting toolbar.
+ */
+export const ToolbarButton = forwardRef(
+ (props, ref) => {
+ const {
+ className,
+ children,
+ mainTooltip,
+ secondaryTooltip,
+ icon,
+ isSelected,
+ isDisabled,
+ onClick,
+ ...rest
+ } = props;
+
+ return (
+
+ }>
+ {/*Creates an ActionIcon instead of a Button if only an icon is provided as content.*/}
+ {children ? (
+ {
+ if (isSafari()) {
+ (e.currentTarget as HTMLButtonElement).focus();
+ }
+ }}
+ onClick={onClick}
+ data-selected={isSelected ? "true" : undefined}
+ data-test={
+ mainTooltip.slice(0, 1).toLowerCase() +
+ mainTooltip.replace(/\s+/g, "").slice(1)
+ }
+ size={"xs"}
+ disabled={isDisabled || false}
+ ref={ref}
+ {...rest}>
+ {children}
+
+ ) : (
+ {
+ if (isSafari()) {
+ (e.currentTarget as HTMLButtonElement).focus();
+ }
+ }}
+ onClick={onClick}
+ data-selected={isSelected ? "true" : undefined}
+ data-test={
+ mainTooltip.slice(0, 1).toLowerCase() +
+ mainTooltip.replace(/\s+/g, "").slice(1)
+ }
+ size={30}
+ disabled={isDisabled || false}
+ ref={ref}
+ {...rest}>
+ {icon}
+
+ )}
+
+ );
+ }
+);
diff --git a/packages/react/src/mantine/toolbar/ToolbarInputsMenuItem.tsx b/packages/mantine/src/toolbar/ToolbarInputsMenuItem.tsx
similarity index 58%
rename from packages/react/src/mantine/toolbar/ToolbarInputsMenuItem.tsx
rename to packages/mantine/src/toolbar/ToolbarInputsMenuItem.tsx
index 16c4b247f6..cfc26e8b41 100644
--- a/packages/react/src/mantine/toolbar/ToolbarInputsMenuItem.tsx
+++ b/packages/mantine/src/toolbar/ToolbarInputsMenuItem.tsx
@@ -1,17 +1,19 @@
-import { Group, TextInput, TextInputProps } from "@mantine/core";
+import * as Mantine from "@mantine/core";
+
import type { IconType } from "react-icons";
+// TODO
export type ToolbarInputsMenuItemProps = {
icon: IconType;
-} & TextInputProps;
+} & Mantine.TextInputProps;
export const ToolbarInputsMenuItem = (props: ToolbarInputsMenuItemProps) => {
const { icon, ...rest } = props;
const Icon = props.icon;
return (
-
- } size={"xs"} {...rest} />
-
+
+ } size={"xs"} {...rest} />
+
);
};
diff --git a/packages/mantine/src/toolbar/ToolbarSelect.tsx b/packages/mantine/src/toolbar/ToolbarSelect.tsx
new file mode 100644
index 0000000000..7f75969dbd
--- /dev/null
+++ b/packages/mantine/src/toolbar/ToolbarSelect.tsx
@@ -0,0 +1,67 @@
+import * as Mantine from "@mantine/core";
+
+import { isSafari } from "@blocknote/core";
+import { ComponentProps } from "@blocknote/react";
+import { forwardRef } from "react";
+import { HiChevronDown } from "react-icons/hi";
+
+// TODO: turn into select
+export const ToolbarSelect = forwardRef<
+ HTMLDivElement,
+ ComponentProps["FormattingToolbar"]["Select"]
+>((props, ref) => {
+ const { className, items, isDisabled } = props;
+
+ const selectedItem = items.filter((p) => p.isSelected)[0];
+
+ if (!selectedItem) {
+ return null;
+ }
+
+ return (
+
+
+ {
+ if (isSafari()) {
+ (e.currentTarget as HTMLButtonElement).focus();
+ }
+ }}
+ leftSection={selectedItem.icon}
+ rightSection={}
+ size={"xs"}
+ variant={"subtle"}
+ disabled={isDisabled}>
+ {selectedItem.text}
+
+
+
+ {items.map((item) => (
+
+ ) : (
+ // Ensures space for tick even if item isn't currently selected.
+
+ )
+ }
+ disabled={item.isDisabled}>
+ {item.text}
+
+ ))}
+
+
+ );
+});
diff --git a/packages/mantine/tsconfig.json b/packages/mantine/tsconfig.json
new file mode 100644
index 0000000000..607ad93cfa
--- /dev/null
+++ b/packages/mantine/tsconfig.json
@@ -0,0 +1,32 @@
+{
+ "compilerOptions": {
+ "target": "ESNext",
+ "useDefineForClassFields": true,
+ "module": "ESNext",
+ "lib": ["ESNext", "DOM"],
+ "moduleResolution": "Node",
+ "jsx": "react-jsx",
+ "strict": true,
+ "sourceMap": true,
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "noEmit": false,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noImplicitReturns": true,
+ "outDir": "dist",
+ "declaration": true,
+ "declarationDir": "types",
+ "composite": true,
+ "skipLibCheck": true,
+ },
+ "include": ["src"],
+ "references": [
+ {
+ "path": "../core"
+ },
+ {
+ "path": "../react"
+ }
+ ]
+}
diff --git a/packages/mantine/vite.config.ts b/packages/mantine/vite.config.ts
new file mode 100644
index 0000000000..0e9e1ed2f5
--- /dev/null
+++ b/packages/mantine/vite.config.ts
@@ -0,0 +1,52 @@
+import react from "@vitejs/plugin-react";
+import * as path from "path";
+import { webpackStats } from "rollup-plugin-webpack-stats";
+import { defineConfig } from "vite";
+import pkg from "./package.json";
+// import eslintPlugin from "vite-plugin-eslint";
+
+// https://vitejs.dev/config/
+export default defineConfig((conf) => ({
+ test: {
+ environment: "jsdom",
+ setupFiles: ["./vitestSetup.ts"],
+ },
+ plugins: [react(), webpackStats()],
+ // used so that vitest resolves the core package from the sources instead of the built version
+ resolve: {
+ alias:
+ conf.command === "build"
+ ? ({} as Record)
+ : ({
+ // load live from sources with live reload working
+ "@blocknote/core": path.resolve(__dirname, "../core/src/"),
+ "@blocknote/react": path.resolve(__dirname, "../react/src/"),
+ } as Record),
+ },
+ build: {
+ sourcemap: true,
+ lib: {
+ entry: path.resolve(__dirname, "src/index.tsx"),
+ name: "blocknote-mantine",
+ fileName: "blocknote-mantine",
+ },
+ rollupOptions: {
+ // make sure to externalize deps that shouldn't be bundled
+ // into your library
+ external: Object.keys({
+ ...pkg.dependencies,
+ ...pkg.peerDependencies,
+ ...pkg.devDependencies,
+ }),
+ output: {
+ // Provide global variables to use in the UMD build
+ // for externalized deps
+ globals: {
+ react: "React",
+ "react-dom": "ReactDOM",
+ },
+ interop: "compat", // https://rollupjs.org/migration/#changed-defaults
+ },
+ },
+ },
+}));
diff --git a/packages/react/package.json b/packages/react/package.json
index e09bd6dfc8..33a1829a6c 100644
--- a/packages/react/package.json
+++ b/packages/react/package.json
@@ -50,12 +50,8 @@
"clean": "rimraf dist && rimraf types"
},
"dependencies": {
- "@ariakit/react": "^0.4.3",
"@blocknote/core": "^0.12.1",
"@floating-ui/react": "^0.26.4",
- "@mantine/core": "^7.5.0",
- "@mantine/hooks": "^7.5.0",
- "@mantine/utils": "^6.0.21",
"@tiptap/core": "^2.0.3",
"@tiptap/react": "^2.0.3",
"lodash.merge": "^4.6.2",
diff --git a/packages/react/src/ariakit/ariakit.css b/packages/react/src/ariakit/ariakit.css
deleted file mode 100644
index 61493d7e06..0000000000
--- a/packages/react/src/ariakit/ariakit.css
+++ /dev/null
@@ -1,399 +0,0 @@
-.button {
- display: flex;
- height: 2.5rem;
- user-select: none;
- align-items: center;
- white-space: nowrap;
- border-style: none;
- background-color: hsl(204 20% 100%);
- padding-left: 1rem;
- padding-right: 1rem;
- font-size: 1rem;
- line-height: 1.5rem;
- color: hsl(204 4% 0%);
- text-decoration-line: none;
- outline-width: 2px;
- outline-offset: 2px;
- outline-color: hsl(204 100% 40%);
- --border: rgba(0, 0, 0, 0.1);
- --highlight: rgba(255, 255, 255, 0.2);
- --shadow: rgba(0, 0, 0, 0.1);
- box-shadow: inset 0 0 0 1px var(--border), inset 0 2px 0 var(--highlight),
- inset 0 -1px 0 var(--shadow), 0 1px 1px var(--shadow);
- scroll-margin-left: 0.25rem;
- scroll-margin-right: 0.25rem;
- gap: 0.5rem;
- border-radius: 0.25rem;
- justify-content: space-between;
- width: auto;
-}
-
-.button:hover {
- background-color: hsl(204 20% 96%);
-}
-
-.button[aria-disabled="true"] {
- opacity: 0.5;
-}
-
-.button[aria-expanded="true"] {
- background-color: hsl(204 20% 96%);
-}
-
-.button[data-focus-visible] {
- outline-style: solid;
-}
-
-.button:active,
-.button[data-active] {
- padding-top: 0.125rem;
- box-shadow: inset 0 0 0 1px var(--border), inset 0 2px 0 var(--border);
-}
-
-:is(.dark .button) {
- background-color: hsl(204 20% 100% / 0.05);
- color: hsl(204 20% 100%);
- --shadow: rgba(0, 0, 0, 0.25);
- --border: rgba(255, 255, 255, 0.1);
- --highlight: rgba(255, 255, 255, 0.05);
- box-shadow: inset 0 0 0 1px var(--border), inset 0 -1px 0 1px var(--shadow),
- inset 0 1px 0 var(--highlight);
-}
-
-:is(.dark .button:hover) {
- background-color: hsl(204 20% 100% / 0.1);
-}
-
-:is(.dark .button)[aria-expanded="true"] {
- background-color: hsl(204 20% 100% / 0.1);
-}
-
-:is(.dark .button:active),
-:is(.dark .button[data-active]) {
- box-shadow: inset 0 0 0 1px var(--border), inset 0 1px 1px 1px var(--shadow);
-}
-
-@media (min-width: 640px) {
- .button {
- gap: 0.5rem;
- }
-}
-
-.secondary {
- background-color: transparent;
- color: currentColor;
- box-shadow: none;
-}
-
-.secondary:hover {
- background-color: hsl(204 4% 0% / 0.05);
-}
-
-:is(.dark .secondary) {
- background-color: transparent;
- box-shadow: none;
-}
-
-:is(.dark .secondary:hover) {
- background-color: hsl(204 20% 100% / 0.05);
-}
-
-:is(.dark .secondary:active),
-:is(.dark .secondary[data-active]) {
- box-shadow: none;
-}
-
-.bn-toolbar {
- display: flex;
- max-width: 100%;
- align-items: center;
- gap: 0.25rem;
- overflow-x: auto;
- border-radius: 0.5rem;
- background-color: hsl(204 20% 100%);
- padding: 0.25rem;
- box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
-}
-
-:is(.dark .bn-toolbar) {
- background-color: hsl(204 4% 16%);
- box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.25), 0 1px 2px -1px rgb(0 0 0 / 0.1);
-}
-
-.separator {
- height: 2rem;
- border-right-width: 1px;
- border-color: hsl(204 20% 88%);
-}
-
-:is(.dark .separator) {
- border-color: hsl(204 4% 28%);
-}
-
-.popover {
- z-index: 50;
- display: flex;
- max-height: min(var(--popover-available-height, 300px), 300px);
- flex-direction: column;
- overflow: auto;
- overscroll-behavior: contain;
- border-radius: 0.5rem;
- border-width: 1px;
- border-style: solid;
- border-color: hsl(204 20% 88%);
- background-color: hsl(204 20% 100%);
- padding: 0.5rem;
- color: hsl(204 4% 0%);
- box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
-}
-
-.popover:focus-visible,
-.popover[data-focus-visible] {
- outline: 2px solid hsl(204 100% 40%);
- outline-offset: -1px;
-}
-
-:is(.dark .popover) {
- border-color: hsl(204 4% 24%);
- background-color: hsl(204 4% 16%);
- color: hsl(204 20% 100%);
- box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.25),
- 0 4px 6px -4px rgb(0 0 0 / 0.1);
-}
-
-.select-item {
- display: flex;
- cursor: default;
- scroll-margin: 0.5rem;
- align-items: center;
- gap: 0.5rem;
- border-radius: 0.25rem;
- padding: 0.5rem;
- outline: none !important;
- padding-right: 2rem;
-}
-
-.select-item[aria-disabled="true"] {
- opacity: 0.5;
-}
-
-.select-item[data-active-item] {
- background-color: hsl(204 100% 40%);
- color: hsl(204 20% 100%);
-}
-
-.input {
- height: 2.5rem;
- width: 100%;
- border-radius: 0.375rem;
- border-style: none;
- background-color: hsl(204 20% 94% / 0.4);
- padding-left: 1rem;
- padding-right: 1rem;
- font-size: 1rem;
- line-height: 1.5rem;
- color: hsl(204 4% 0%);
- box-shadow:
- inset 0 0 0 1px rgba(0 0 0 / 0.1),
- inset 0 2px 5px 0 rgba(0 0 0 / 0.05);
-}
-
-.input::placeholder {
- color: hsl(204 4% 0% / 0.6);
-}
-
-.input:hover {
- background-color: hsl(204 20% 94%);
-}
-
-.input:focus-visible,
-.input[data-focus-visible] {
- outline: 2px solid hsl(204 100% 40%);
- outline-offset: -1px;
-}
-
-:is(.dark .input) {
- background-color: hsl(204 4% 10%);
- color: hsl(204 20% 100%);
- box-shadow:
- inset 0 0 0 1px rgba(255 255 255 / 0.12),
- inset 0 -1px 0 0 rgba(255 255 255 / 0.05),
- inset 0 2px 5px 0 rgba(0 0 0 / 0.15);
-}
-
-:is(.dark .input)::placeholder {
- color: hsl(204 20% 100% / 46%);
-}
-
-:is(.dark .input:hover) {
- background-color: hsl(204 4% 8%);
-}
-
-:is(.dark .bn-image-panel) {
- background-color: hsl(204 4% 16%);
- box-shadow:
- 0 1px 3px 0 rgb(0 0 0 / 0.25),
- 0 1px 2px -1px rgb(0 0 0 / 0.1);
-}
-
-.tab-list {
- display: flex;
- gap: 0.5rem;
-}
-
-.tab {
- display: flex;
- height: 2.5rem;
- user-select: none;
- align-items: center;
- justify-content: center;
- gap: 0.5rem;
- white-space: nowrap;
- border-radius: 0.25rem;
- border-style: none;
- padding-left: 1rem;
- padding-right: 1rem;
- font-size: 1rem;
- line-height: 1.5rem;
- text-decoration-line: none;
- outline-width: 2px;
- outline-offset: 2px;
- outline-color: hsl(204 100% 40%);
-}
-
-.tab:hover {
- background-color: hsl(204 4% 0% / 7.5%);
-}
-
-.tab[aria-disabled="true"] {
- opacity: 0.5;
-}
-
-.tab[aria-selected="true"] {
- background-color: hsl(204 100% 40%);
- color: hsl(204 20% 100%);
-}
-
-.tab:hover[aria-selected="true"] {
- background-color: hsl(204 100% 32%);
-}
-
-.tab[data-focus-visible] {
- outline-style: solid;
-}
-
-.tab:active,
-.tab[data-active] {
- padding-top: 0.125rem;
-}
-
-:is(.dark .tab:hover) {
- background-color: hsl(204 20% 100% / 0.1);
-}
-
-:is(.dark .tab[aria-selected="true"]) {
- background-color: hsl(204 100% 40%);
- color: hsl(204 20% 100%);
-}
-
-:is(.dark .tab:hover[aria-selected="true"]) {
- background-color: hsl(204 100% 32%);
-}
-
-.panel {
- padding: 0.5rem;
-}
-
-.bn-menu {
- position: relative;
- z-index: 50;
- display: flex;
- max-height: var(--popover-available-height);
- min-width: 180px;
- flex-direction: column;
- overscroll-behavior: contain;
- border-radius: 0.5rem;
- border-width: 1px;
- border-style: solid;
- border-color: hsl(204 20% 88%);
- background-color: hsl(204 20% 100%);
- padding: 0.5rem;
- color: hsl(204 4% 0%);
- box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
- outline: none !important;
- overflow: visible;
-}
-
-:is(.dark .bn-menu) {
- border-color: hsl(204 4% 24%);
- background-color: hsl(204 4% 16%);
- color: hsl(204 20% 100%);
- box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.25),
- 0 4px 6px -4px rgb(0 0 0 / 0.1);
-}
-
-.bn-menu-item {
- display: flex;
- cursor: default;
- scroll-margin: 0.5rem;
- align-items: center;
- gap: 0.5rem;
- border-radius: 0.25rem;
- padding: 0.5rem;
- outline: none !important;
-}
-
-.bn-menu-item[aria-disabled="true"] {
- opacity: 0.25;
-}
-
-.bn-menu-item[data-active-item] {
- background-color: hsl(204 100% 40%);
- color: hsl(204 20% 100%);
-}
-
-.bn-menu-item:active,
-.bn-menu-item[data-active] {
- background-color: hsl(204 100% 32%);
- padding-top: 9px;
- padding-bottom: 7px;
-}
-
-.bn-menu:not(:focus) .bn-menu-item:not(:focus)[aria-expanded="true"] {
- background-color: hsl(204 4% 0% / 7.5%);
- color: currentColor;
-}
-
-:is(
- .dark .bn-menu:not(:focus) .bn-menu-item:not(:focus)[aria-expanded="true"]
- ) {
- background-color: hsl(204 20% 100% / 0.1);
-}
-
-.bn-menu-item .label {
- flex: 1 1 0%;
-}
-
-.bn-menu-label {
- cursor: default;
- padding: 0.5rem;
- padding-left: 0.75rem;
- padding-right: 0.75rem;
- font-size: 0.875rem;
- line-height: 1.25rem;
- font-weight: 500;
- opacity: 0.5;
-}
-
-.bn-image-panel {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
- border-radius: 0.5rem;
- background-color: hsl(204 20% 100%);
- padding: 0.5rem;
- box-shadow:
- 0 1px 3px 0 rgb(0 0 0 / 0.1),
- 0 1px 2px -1px rgb(0 0 0 / 0.1);
-}
-
diff --git a/packages/react/src/ariakit/components.tsx b/packages/react/src/ariakit/components.tsx
deleted file mode 100644
index 634cc6ed5a..0000000000
--- a/packages/react/src/ariakit/components.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import { ComponentsContextValue } from "../editor/ComponentsContext";
-import "./ariakit.css";
-import { Form } from "./input/Form";
-import { TextInput } from "./input/TextInput";
-import {
- Menu,
- MenuDivider,
- MenuDropdown,
- MenuItem,
- MenuLabel,
- MenuTrigger,
-} from "./menu/Menu";
-import { Popover, PopoverContent, PopoverTrigger } from "./popover/Popover";
-import { Toolbar } from "./toolbar/Toolbar";
-import { ToolbarButton } from "./toolbar/ToolbarButton";
-import { ToolbarSelect } from "./toolbar/ToolbarSelect";
-
-import { Panel } from "./panel/Panel";
-import { PanelButton } from "./panel/PanelButton";
-import { PanelFileInput } from "./panel/PanelFileInput";
-import { PanelTab } from "./panel/PanelTab";
-import { PanelTextInput } from "./panel/PanelTextInput";
-
-export const ariakitComponents: ComponentsContextValue = {
- Form,
- TextInput,
- Toolbar: Toolbar,
- ToolbarSelect,
- ToolbarButton,
- Menu,
- MenuTrigger,
- MenuDropdown,
- MenuDivider,
- MenuLabel,
- MenuItem,
- Panel,
- PanelButton,
- PanelFileInput,
- PanelTab,
- PanelTextInput,
- Popover,
- PopoverContent,
- PopoverTrigger,
-};
diff --git a/packages/react/src/ariakit/input/Form.tsx b/packages/react/src/ariakit/input/Form.tsx
deleted file mode 100644
index bd7770164a..0000000000
--- a/packages/react/src/ariakit/input/Form.tsx
+++ /dev/null
@@ -1,7 +0,0 @@
-import * as Ariakit from "@ariakit/react";
-
-export const Form = (props: { children: React.ReactNode }) => {
- const { ...rest } = props;
-
- return ;
-};
diff --git a/packages/react/src/ariakit/input/TextInput.tsx b/packages/react/src/ariakit/input/TextInput.tsx
deleted file mode 100644
index cade54c139..0000000000
--- a/packages/react/src/ariakit/input/TextInput.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import * as Ariakit from "@ariakit/react";
-import { TextInputProps } from "../../editor/ComponentsContext";
-
-export const TextInput = (props: TextInputProps) => {
- const { icon, ...rest } = props;
-
- // TODO: support icon
- return (
- <>
- {props.label && (
- {props.label}
- )}
-
- >
- );
-};
diff --git a/packages/react/src/ariakit/menu/Menu.tsx b/packages/react/src/ariakit/menu/Menu.tsx
deleted file mode 100644
index 7050aef418..0000000000
--- a/packages/react/src/ariakit/menu/Menu.tsx
+++ /dev/null
@@ -1,96 +0,0 @@
-import * as Ariakit from "@ariakit/react";
-import { mergeCSSClasses } from "@blocknote/core";
-import { HTMLAttributes, forwardRef } from "react";
-import { MenuItemProps, MenuProps } from "../../editor/ComponentsContext";
-export { MenuSeparator as MenuDivider } from "@ariakit/react";
-
-export const Menu = (props: MenuProps) => {
- const { onOpenChange, position, ...rest } = props;
-
- return (
-
- );
-};
-
-export const MenuDropdown = forwardRef<
- HTMLDivElement,
- HTMLAttributes
->((props, ref) => {
- const { className, children, ...rest } = props;
-
- return (
-
- {children}
-
- );
-});
-
-export const MenuItem = forwardRef(
- (props, ref) => {
- const { className, children, icon, checked, expandArrow, ...rest } = props;
-
- if (expandArrow) {
- return (
-
- {icon}
- {children}
-
- {checked !== undefined && }
-
- );
- }
- return (
-
- {icon}
- {children}
- {checked !== undefined && }
-
- );
- }
-);
-
-export const MenuLabel = forwardRef<
- HTMLDivElement,
- HTMLAttributes
->((props, ref) => {
- const { className, children, ...rest } = props;
-
- return (
-
- {children}
-
- );
-});
-
-export const MenuTrigger = forwardRef<
- HTMLDivElement,
- HTMLAttributes
->((props, ref) => {
- const { className, children, ...rest } = props;
-
- return (
-
- );
-});
diff --git a/packages/react/src/ariakit/panel/Panel.tsx b/packages/react/src/ariakit/panel/Panel.tsx
deleted file mode 100644
index ded7c08241..0000000000
--- a/packages/react/src/ariakit/panel/Panel.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import * as Ariakit from "@ariakit/react";
-
-import { PanelProps } from "../../editor/ComponentsContext";
-
-export const Panel = (props: PanelProps) => {
- return (
-
-
{
- if (activeId) {
- props.setOpenTab(activeId);
- }
- }}>
- {/*{props.loading && }*/}
-
-
- {props.tabs.map((tab) => (
-
- {tab.name}
-
- ))}
-
-
- {props.tabs.map((tab) => (
-
- {tab.tabPanel}
-
- ))}
-
-
- );
-};
diff --git a/packages/react/src/ariakit/panel/PanelButton.tsx b/packages/react/src/ariakit/panel/PanelButton.tsx
deleted file mode 100644
index 9c6a6345bc..0000000000
--- a/packages/react/src/ariakit/panel/PanelButton.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import * as Ariakit from "@ariakit/react";
-
-import { PanelButtonProps } from "../../editor/ComponentsContext";
-import { mergeCSSClasses } from "@blocknote/core";
-
-export const PanelButton = (props: PanelButtonProps) => {
- const { children, className, ...rest } = props;
-
- return (
-
- {children}
-
- );
-};
diff --git a/packages/react/src/ariakit/panel/PanelFileInput.tsx b/packages/react/src/ariakit/panel/PanelFileInput.tsx
deleted file mode 100644
index 96d03c01f7..0000000000
--- a/packages/react/src/ariakit/panel/PanelFileInput.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import * as Ariakit from "@ariakit/react";
-
-import { PanelFileInputProps } from "../../editor/ComponentsContext";
-
-export const PanelFileInput = (props: PanelFileInputProps) => (
-
- props.onChange?.(e.target.files![0])}
- placeholder={props.placeholder}
- />
-
-);
diff --git a/packages/react/src/ariakit/panel/PanelTab.tsx b/packages/react/src/ariakit/panel/PanelTab.tsx
deleted file mode 100644
index dfb92e3fa9..0000000000
--- a/packages/react/src/ariakit/panel/PanelTab.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import { mergeCSSClasses } from "@blocknote/core";
-
-import { PanelTabProps } from "../../editor/ComponentsContext";
-
-export const PanelTab = (props: PanelTabProps) => {
- const { className, children, ...rest } = props;
-
- return (
-
- {children}
-
- );
-};
diff --git a/packages/react/src/ariakit/panel/PanelTextInput.tsx b/packages/react/src/ariakit/panel/PanelTextInput.tsx
deleted file mode 100644
index 3a63326490..0000000000
--- a/packages/react/src/ariakit/panel/PanelTextInput.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import * as Ariakit from "@ariakit/react";
-
-import { PanelTextInputProps } from "../../editor/ComponentsContext";
-
-export const PanelTextInput = (props: PanelTextInputProps) => {
- const { children, ...rest } = props;
-
- return (
-
-
-
- );
-};
diff --git a/packages/react/src/ariakit/popover/Popover.tsx b/packages/react/src/ariakit/popover/Popover.tsx
deleted file mode 100644
index 3e9b3a7390..0000000000
--- a/packages/react/src/ariakit/popover/Popover.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import * as Ariakit from "@ariakit/react";
-import { mergeCSSClasses } from "@blocknote/core";
-import { forwardRef, HTMLAttributes } from "react";
-export {
- PopoverProvider as Popover,
- Popover as PopoverContent,
-} from "@ariakit/react";
-
-export const PopoverTrigger = forwardRef<
- HTMLButtonElement,
- HTMLAttributes
->((props, ref) => {
- const { className, children, ...rest } = props;
-
- return (
-
- );
-});
diff --git a/packages/react/src/ariakit/toolbar/Toolbar.tsx b/packages/react/src/ariakit/toolbar/Toolbar.tsx
deleted file mode 100644
index 15f2fed7c5..0000000000
--- a/packages/react/src/ariakit/toolbar/Toolbar.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import * as Ariakit from "@ariakit/react";
-import { mergeCSSClasses } from "@blocknote/core";
-import { forwardRef, HTMLAttributes } from "react";
-
-export const Toolbar = forwardRef<
- HTMLDivElement,
- HTMLAttributes
->((props, ref) => {
- const { className, children, ...rest } = props;
-
- return (
-
- {children}
-
- );
-});
-
-// export const ToolbarButton = forwardRef(
-//
diff --git a/packages/react/src/ariakit/toolbar/ToolbarButton.tsx b/packages/react/src/ariakit/toolbar/ToolbarButton.tsx
deleted file mode 100644
index 4d36fa80c8..0000000000
--- a/packages/react/src/ariakit/toolbar/ToolbarButton.tsx
+++ /dev/null
@@ -1,70 +0,0 @@
-import * as Ariakit from "@ariakit/react";
-import { isSafari } from "@blocknote/core";
-import { forwardRef } from "react";
-import { ToolbarButtonProps } from "../../editor/ComponentsContext";
-
-/**
- * Helper for basic buttons that show in the formatting toolbar.
- */
-// TODO: implement tooltip
-export const ToolbarButton = forwardRef(
- (props, ref) => {
- return (
- {
- if (isSafari()) {
- (e.currentTarget as HTMLButtonElement).focus();
- }
- }}
- onClick={props.onClick}
- data-selected={props.isSelected ? "true" : undefined}
- data-test={
- props.mainTooltip.slice(0, 1).toLowerCase() +
- props.mainTooltip.replace(/\s+/g, "").slice(1)
- }
- // size={"xs"}
- disabled={props.isDisabled || false}
- ref={ref}>
- {props.icon}
- {props.children}
-
- );
-
- return (
-
- {
- if (isSafari()) {
- (e.currentTarget as HTMLButtonElement).focus();
- }
- }}
- onClick={props.onClick}
- data-selected={props.isSelected ? "true" : undefined}
- data-test={
- props.mainTooltip.slice(0, 1).toLowerCase() +
- props.mainTooltip.replace(/\s+/g, "").slice(1)
- }
- // size={"xs"}
- disabled={props.isDisabled || false}
- ref={ref}>
- }>
- {props.icon}
- {props.children}
-
-
- {props.mainTooltip}
- {props.secondaryTooltip && {props.secondaryTooltip}
}
-
-
- );
- }
-);
diff --git a/packages/react/src/ariakit/toolbar/ToolbarSelect.tsx b/packages/react/src/ariakit/toolbar/ToolbarSelect.tsx
deleted file mode 100644
index e0b4a7065b..0000000000
--- a/packages/react/src/ariakit/toolbar/ToolbarSelect.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import * as Ariakit from "@ariakit/react";
-import { ToolbarSelectProps } from "../../mantine/toolbar/ToolbarSelect";
-
-export function ToolbarSelect(props: ToolbarSelectProps) {
- const selectedItem = props.items.filter((p) => p.isSelected)[0];
-
- const setValue = (value: string) => {
- props.items.find((item) => item.text === value)!.onClick?.();
- };
-
- return (
-
- }>
- {selectedItem.icon && } {selectedItem.text}{" "}
-
-
-
- {props.items.map((option) => (
-
- {option.icon && } {option.text}
-
- ))}
-
-
- );
-}
diff --git a/packages/react/src/components/ColorPicker/ColorPicker.tsx b/packages/react/src/components/ColorPicker/ColorPicker.tsx
index e60617f3e7..5c73c1f4ce 100644
--- a/packages/react/src/components/ColorPicker/ColorPicker.tsx
+++ b/packages/react/src/components/ColorPicker/ColorPicker.tsx
@@ -1,6 +1,20 @@
import { useComponentsContext } from "../../editor/ComponentsContext";
+import { useDictionaryContext } from "../../i18n/dictionary";
import { ColorIcon } from "./ColorIcon";
+const colors = [
+ "default",
+ "gray",
+ "brown",
+ "red",
+ "orange",
+ "yellow",
+ "green",
+ "blue",
+ "purple",
+ "pink",
+] as const;
+
export const ColorPicker = (props: {
onClick?: () => void;
iconSize?: number;
@@ -13,25 +27,16 @@ export const ColorPicker = (props: {
setColor: (color: string) => void;
};
}) => {
- const components = useComponentsContext()!;
-
+ const Components = useComponentsContext()!;
+ const dict = useDictionaryContext();
const TextColorSection = () =>
props.text ? (
<>
- Text
- {[
- "default",
- "gray",
- "brown",
- "red",
- "orange",
- "yellow",
- "green",
- "blue",
- "purple",
- "pink",
- ].map((color) => (
-
+ {dict.color_picker.text_title}
+
+ {colors.map((color) => (
+ {
props.onClick && props.onClick();
props.text!.setColor(color);
@@ -40,8 +45,8 @@ export const ColorPicker = (props: {
icon={}
checked={props.text!.color === color}
key={"text-color-" + color}>
- {color.charAt(0).toUpperCase() + color.slice(1)}
-
+ {dict.color_picker.colors[color]}
+
))}
>
) : null;
@@ -49,20 +54,11 @@ export const ColorPicker = (props: {
const BackgroundColorSection = () =>
props.background ? (
<>
- Background
- {[
- "default",
- "gray",
- "brown",
- "red",
- "orange",
- "yellow",
- "green",
- "blue",
- "purple",
- "pink",
- ].map((color) => (
-
+ {dict.color_picker.background_title}
+
+ {colors.map((color) => (
+ {
props.onClick && props.onClick();
props.background!.setColor(color);
@@ -71,8 +67,8 @@ export const ColorPicker = (props: {
icon={}
key={"background-color-" + color}
checked={props.background!.color === color}>
- {color.charAt(0).toUpperCase() + color.slice(1)}
-
+ {dict.color_picker.colors[color]}
+
))}
>
) : null;
diff --git a/packages/react/src/components/FormattingToolbar/DefaultButtons/BasicTextStyleButton.tsx b/packages/react/src/components/FormattingToolbar/DefaultButtons/BasicTextStyleButton.tsx
index eccc62fec7..f4194be708 100644
--- a/packages/react/src/components/FormattingToolbar/DefaultButtons/BasicTextStyleButton.tsx
+++ b/packages/react/src/components/FormattingToolbar/DefaultButtons/BasicTextStyleButton.tsx
@@ -19,6 +19,7 @@ import { useComponentsContext } from "../../../editor/ComponentsContext";
import { useBlockNoteEditor } from "../../../hooks/useBlockNoteEditor";
import { useEditorContentOrSelectionChange } from "../../../hooks/useEditorContentOrSelectionChange";
import { useSelectedBlocks } from "../../../hooks/useSelectedBlocks";
+import { useDictionaryContext } from "../../../i18n/dictionary";
type BasicTextStyle = "bold" | "italic" | "underline" | "strike" | "code";
@@ -30,14 +31,6 @@ const icons = {
code: RiCodeFill,
} satisfies Record;
-const shortcuts = {
- bold: "Mod+B",
- italic: "Mod+I",
- underline: "Mod+U",
- strike: "Mod+Shift+X",
- code: "",
-} satisfies Record;
-
function checkBasicTextStyleInSchema