Skip to content

docs: Proposal for editor basics docs changes #594

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions docs/api/og.tsx → docs/api/og.tsx.bak
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { ImageResponse } from "@vercel/og";
import React from "react";

export const config = {
runtime: "edge",
};

const font = fetch(
new URL("../docs/public/fonts/Gilroy-Regular.ttf", import.meta.url)
new URL("../../assets/fonts/Gilroy-Regular.ttf", import.meta.url),
).then((res) => res.arrayBuffer());

export default async function handler(request: { url: string }) {
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"docs:build": "next build",
"start": "next start",
"lint": "next lint"
},
Expand Down
2 changes: 1 addition & 1 deletion docs/pages/docs/_meta.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{

"index": "Introduction",
"quickstart": "Quickstart",
"editor-basics": "Editor Basics",
"editor-api": "Editor API",
"styling-theming": "Styling & Theming",
"ui-components": "UI Components",
Expand Down
110 changes: 53 additions & 57 deletions docs/pages/docs/advanced/vanilla-js.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import { Callout } from "nextra/components";
BlockNote is mainly designed as a quick and easy drop-in block-based editor for React apps, but can also be used in vanilla JavaScript apps. However, this does involve writing your own UI elements.

<Callout type={"warning"}>
We recommend using BlockNote with React so you can use the built-in UI components. This document will explain how you can use BlockNote without React, and write your own components, but this is not recommended as you'll lose the great out-of-the-box experience that BlockNote offers.
We recommend using BlockNote with React so you can use the built-in UI
components. This document will explain how you can use BlockNote without
React, and write your own components, but this is not recommended as you'll
lose the great out-of-the-box experience that BlockNote offers.
</Callout>

## Installing with NPM
Expand All @@ -25,19 +28,14 @@ npm install @blocknote/core

## Creating an editor

TODO: AFAIK there is actually just no way of doing this anymore

This is how to create a new BlockNote editor:

``` typescript
```typescript
import { BlockNoteEditor } from "@blocknote/core";

const editor = BlockNoteEditor.create({
element: document.getElementById("root")!, // element to append the editor to
onEditorContentChange: ({) => {
console.log(editor.getJSON());
}
});
const editor = BlockNoteEditor.create();

editor.mount(document.getElementById("root")); // element to append the editor to
```

Now, you'll have a plain BlockNote instance on your page. However, it's missing some menus and other UI elements.
Expand Down Expand Up @@ -70,60 +68,58 @@ Let's look at how you could add the [Side Menu]() to your editor:
import { BlockNoteEditor } from "@blocknote/core";

const editor = BlockNoteEditor.create({
element: document.getElementById("root")!
element: document.getElementById("root")!,
});

export function createButton(text: string, onClick?: () => void) {
const element = document.createElement("a");
element.href = "#";
element.text = text;
element.style.margin = "10px";

if (onClick) {
element.addEventListener("click", (e) => {
onClick();
e.preventDefault();
});
}

return element;
const element = document.createElement("a");
element.href = "#";
element.text = text;
element.style.margin = "10px";

if (onClick) {
element.addEventListener("click", (e) => {
onClick();
e.preventDefault();
});
}

return element;
}

let element: HTMLElement;

editor.sideMenu.onUpdate((sideMenuState) => {
if (!element) {
element = document.createElement("div");
element.style.background = "gray";
element.style.position = "absolute";
element.style.padding = "10px";
element.style.opacity = "0.8";
const addBtn = createButton("+", () => {
editor.sideMenu.addBlock();
});
element.appendChild(addBtn);

const dragBtn = createButton("::", () => {});

dragBtn.addEventListener("dragstart", editor.sideMenu.blockDragStart);
dragBtn.addEventListener("dragend", editor.sideMenu.blockDragEnd);
dragBtn.draggable = true;
element.style.display = "none";
element.appendChild(dragBtn);

document.getElementById("root")!.appendChild(element);
}

if (sideMenuState.show) {
element.style.display = "block";

element.style.top = sideMenuState.referencePos.top + "px";
element.style.left =
sideMenuState.referencePos.x - element.offsetWidth + "px";
} else {
element.style.display = "none";
}
if (!element) {
element = document.createElement("div");
element.style.background = "gray";
element.style.position = "absolute";
element.style.padding = "10px";
element.style.opacity = "0.8";
const addBtn = createButton("+", () => {
editor.sideMenu.addBlock();
});
element.appendChild(addBtn);

const dragBtn = createButton("::", () => {});

dragBtn.addEventListener("dragstart", editor.sideMenu.blockDragStart);
dragBtn.addEventListener("dragend", editor.sideMenu.blockDragEnd);
dragBtn.draggable = true;
element.style.display = "none";
element.appendChild(dragBtn);

document.getElementById("root")!.appendChild(element);
}

if (sideMenuState.show) {
element.style.display = "block";

element.style.top = sideMenuState.referencePos.top + "px";
element.style.left =
sideMenuState.referencePos.x - element.offsetWidth + "px";
} else {
element.style.display = "none";
}
});
```

TODO: Bring back vanilla example?
2 changes: 1 addition & 1 deletion docs/pages/docs/custom-schemas.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: Learn how to create custom schemas for your BlockNote editor

# Custom Schemas (advanced)

By default, BlockNote documents support different kind of blocks, inline content and text styles. See xxxx.
By default, BlockNote documents support different kind of blocks, inline content and text styles (see [default schema](/docs/editor-basics/default-schema)).
However, you can extend BlockNote and create custom schemas to support your own blocks, inline content and text styles.

## Custom Blocks
Expand Down
21 changes: 8 additions & 13 deletions docs/pages/docs/custom-schemas/custom-styles.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,14 @@ function createReactStyleSpec(
Let's look at our custom font style from the demo, and go over each field to explain how it works:

```typescript
const Mention = createReactStyleSpec(
export const Font = createReactStyleSpec(
{
type: "mention",
propSchema: {
user: {
default: "Unknown",
},
},
content: "none",
} as const,
type: "font",
propSchema: "string",
},
{
render: (props) => (
...
<span style={{ fontFamily: props.value }} ref={props.contentRef} />
),
}
);
Expand All @@ -57,7 +52,7 @@ Defines the identifier of the custom style.

The `PropSchema` specifies whether the style can only be toggled (`"boolean"`), or whether it can take a string value (`"string"`). Having a string value is useful for e.g. setting a color on the style.

_In the font style demo, we set this to `"string"` so we can store the font name._
_In the font style demo, we set this to `"string"` so we can store the font family._

#### Style Implementation (`ReactCustomStyleImplementation`)

Expand All @@ -78,9 +73,9 @@ This is your React component which defines how your custom style should be rende

`value:` The string value of the style, this is only available if your style config contains `propSchema: "string"`.

`contentRef:` A React `ref` you can use to mark which element in your style is editable.
`contentRef:` A React `ref` to mark the editable element.

_Note that since styles are applied to text, you must set `contentRef` somewhere in you component, and should also return an HTML inline element._
_Note that in contrast to Custom Blocks and Inline Content, the `render` function of Custom Styles cannot access React Context or other state. They should be plain React functions analogous to the example._

### Adding Custom Style to the Editor

Expand Down
10 changes: 9 additions & 1 deletion docs/pages/docs/editor-api.mdx
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
hello
# Editor API

BlockNote exposes an API to interact with the editor and its contents from code.
These methods are directly available on the `BlockNoteEditor` object you created when instantiating your editor.

- [Manipulating Blocks](/docs/editor-api/manipulating-blocks.md) explains how to read / update Blocks in the document.
- [Manipulating Inline Content](/docs/editor-api/manipulating-inline-content.md) explains how to update / read data from selected text.
- [Cursors & Selections](/docs/editor-api/cursor-selections) explains methods related to cursor positions and selections.
- [Markdown & HTML](/docs/converting-blocks) explains how to convert the document to and from Markdown and HTML.
5 changes: 1 addition & 4 deletions docs/pages/docs/editor-api/_meta.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
{
"editor":"",
"blocks": "",
"default-blocks":"",
"manipulating-blocks":"",
"block-content":"",
"manipulating-inline-content":"",
"cursor-selections":"",
"converting-blocks":""
}
Loading