Skip to content

feat: custom styles and custom inline content #418

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 34 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
20f691b
wip custom styles
YousefED Nov 20, 2023
bbaf604
fix
YousefED Nov 20, 2023
2bc1cd9
fix tests
YousefED Nov 20, 2023
5f907c3
simplify PartialInlineContent
YousefED Nov 20, 2023
7d6a75b
custom inline content
YousefED Nov 21, 2023
522c6db
clean nodeconversions test
YousefED Nov 21, 2023
3852fac
streamline tests
YousefED Nov 21, 2023
0c647da
update tests
YousefED Nov 21, 2023
3f86bd4
move schema files
YousefED Nov 21, 2023
b7dfa52
add custom style test
YousefED Nov 21, 2023
a4e7071
inline content + tests
YousefED Nov 21, 2023
de88cb7
misc
YousefED Nov 21, 2023
17651ce
clean imports
YousefED Nov 21, 2023
3989912
fix react tests
YousefED Nov 21, 2023
4b2b249
add react nodeconversions tests
YousefED Nov 21, 2023
d3a282a
move tests and add test for ReactStyles
YousefED Nov 22, 2023
70b97de
fix react tests
YousefED Nov 22, 2023
2aac331
basis of new examples
YousefED Nov 22, 2023
0110217
Merge branch 'feature/new-examples' into feature/custom-inline-content
YousefED Nov 23, 2023
91a5c5a
add react examples
YousefED Nov 23, 2023
b1c8934
fix bug
YousefED Nov 23, 2023
e45c389
misc fixes
YousefED Nov 23, 2023
6fc78c9
wip
YousefED Nov 23, 2023
0442ddc
clean
YousefED Nov 23, 2023
6862008
small cleanup
YousefED Nov 23, 2023
3fd377f
add comments
YousefED Nov 27, 2023
80c644a
move funcs
YousefED Nov 27, 2023
5bb51fd
fix tests
YousefED Nov 27, 2023
bdddbd5
address PR feedback
YousefED Nov 27, 2023
7e02786
Merge branch 'feature/tables' into feature/custom-inline-content
YousefED Nov 27, 2023
3ef4cc1
fix inline content types
YousefED Nov 28, 2023
5a74b58
feat: HTML paste handling (#422)
YousefED Nov 29, 2023
77e887d
Merge remote-tracking branch 'origin/feature/tables' into feature/cus…
YousefED Nov 29, 2023
296085a
fix build
YousefED Nov 29, 2023
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
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
// import logo from './logo.svg'
import { uploadToTmpFilesDotOrg_DEV_ONLY } from "@blocknote/core";
import "@blocknote/core/style.css";
import { BlockNoteView, useBlockNote } from "@blocknote/react";
import "./App.css";

import { uploadToTmpFilesDotOrg_DEV_ONLY } from "@blocknote/core";

type WindowWithProseMirror = Window & typeof globalThis & { ProseMirror: any };

function App() {
export function App() {
const editor = useBlockNote({
onEditorContentChange: (editor) => {
console.log(editor.topLevelBlocks);
},
domAttributes: {
editor: {
class: "editor",
Expand All @@ -23,7 +19,7 @@ function App() {
// Give tests a way to get prosemirror instance
(window as WindowWithProseMirror).ProseMirror = editor?._tiptapEditor;

return <BlockNoteView editor={editor} />;
return <BlockNoteView className="root" editor={editor} />;
}

export default App;
48 changes: 48 additions & 0 deletions examples/editor/examples/Collaboration.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import "@blocknote/core/style.css";
import { BlockNoteView, useBlockNote } from "@blocknote/react";

import { uploadToTmpFilesDotOrg_DEV_ONLY } from "@blocknote/core";

import YPartyKitProvider from "y-partykit/provider";
import * as Y from "yjs";

const doc = new Y.Doc();

const provider = new YPartyKitProvider(
"blocknote-dev.yousefed.partykit.dev",
// use a unique name as a "room" for your application:
"your-project-name",
doc
);

type WindowWithProseMirror = Window & typeof globalThis & { ProseMirror: any };

export function App() {
const editor = useBlockNote({
domAttributes: {
editor: {
class: "editor",
"data-test": "editor",
},
},
collaboration: {
// The Yjs Provider responsible for transporting updates:
provider,
// Where to store BlockNote data in the Y.Doc:
fragment: doc.getXmlFragment("document-storesss"),
// Information (name and color) for this user:
user: {
name: "My Username",
color: "#ff0000",
},
},
uploadFile: uploadToTmpFilesDotOrg_DEV_ONLY,
});

// Give tests a way to get prosemirror instance
(window as WindowWithProseMirror).ProseMirror = editor?._tiptapEditor;

return <BlockNoteView className="root" editor={editor} />;
}

export default App;
90 changes: 90 additions & 0 deletions examples/editor/examples/ReactInlineContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { defaultInlineContentSpecs } from "@blocknote/core";
import "@blocknote/core/style.css";
import {
BlockNoteView,
createReactInlineContentSpec,
useBlockNote,
} from "@blocknote/react";

type WindowWithProseMirror = Window & typeof globalThis & { ProseMirror: any };

const mention = createReactInlineContentSpec(
{
type: "mention",
propSchema: {
user: {
default: "",
},
},
content: "none",
},
{
render: (props) => {
return <span>@{props.inlineContent.props.user}</span>;
},
}
);

const tag = createReactInlineContentSpec(
{
type: "tag",
propSchema: {},
content: "styled",
},
{
render: (props) => {
return (
<span>
#<span ref={props.contentRef}></span>
</span>
);
},
}
);

export function ReactInlineContent() {
const editor = useBlockNote({
inlineContentSpecs: {
mention,
tag,
...defaultInlineContentSpecs,
},
domAttributes: {
editor: {
class: "editor",
"data-test": "editor",
},
},
initialContent: [
{
type: "paragraph",
content: [
"I enjoy working with ",
{
type: "mention",
props: {
user: "Matthew",
},
content: undefined,
} as any,
],
},
{
type: "paragraph",
content: [
"I love ",
{
type: "tag",
// props: {},
content: "BlockNote",
} as any,
],
},
],
});

// Give tests a way to get prosemirror instance
(window as WindowWithProseMirror).ProseMirror = editor?._tiptapEditor;

return <BlockNoteView className="root" editor={editor} />;
}
138 changes: 138 additions & 0 deletions examples/editor/examples/ReactStyles.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import "@blocknote/core/style.css";
import {
BlockNoteView,
FormattingToolbarPositioner,
Toolbar,
ToolbarButton,
createReactStyleSpec,
useActiveStyles,
useBlockNote,
} from "@blocknote/react";

import {
BlockNoteEditor,
DefaultBlockSchema,
DefaultInlineContentSchema,
StyleSchemaFromSpecs,
defaultStyleSpecs,
} from "@blocknote/core";

type WindowWithProseMirror = Window & typeof globalThis & { ProseMirror: any };

const small = createReactStyleSpec(
{
type: "small",
propSchema: "boolean",
},
{
render: (props) => {
return <small ref={props.contentRef}></small>;
},
}
);

const fontSize = createReactStyleSpec(
{
type: "fontSize",
propSchema: "string",
},
{
render: (props) => {
return (
<span ref={props.contentRef} style={{ fontSize: props.value }}></span>
);
},
}
);

const customReactStyles = {
...defaultStyleSpecs,
small,
fontSize,
};

type MyEditorType = BlockNoteEditor<
DefaultBlockSchema,
DefaultInlineContentSchema,
StyleSchemaFromSpecs<typeof customReactStyles>
>;

const CustomFormattingToolbar = (props: { editor: MyEditorType }) => {
const activeStyles = useActiveStyles(props.editor);

return (
<Toolbar>
<ToolbarButton
mainTooltip={"small"}
onClick={() => {
props.editor.toggleStyles({
small: true,
});
}}
isSelected={activeStyles.small}>
Small
</ToolbarButton>
<ToolbarButton
mainTooltip={"font size"}
onClick={() => {
props.editor.toggleStyles({
fontSize: "30px",
});
}}
isSelected={!!activeStyles.fontSize}>
Font size
</ToolbarButton>
</Toolbar>
);
};

export function ReactStyles() {
const editor = useBlockNote(
{
styleSpecs: customReactStyles,
onEditorContentChange: (editor) => {
console.log(editor.topLevelBlocks);
},
domAttributes: {
editor: {
class: "editor",
"data-test": "editor",
},
},
initialContent: [
{
type: "paragraph",
content: [
{
type: "text",
text: "large text",
styles: {
fontSize: "30px",
},
},
{
type: "text",
text: "small text",
styles: {
small: true,
},
},
],
},
],
},
[]
);

// Give tests a way to get prosemirror instance
(window as WindowWithProseMirror).ProseMirror = editor?._tiptapEditor;

return (
<BlockNoteView className="root" editor={editor}>
<FormattingToolbarPositioner
editor={editor}
formattingToolbar={CustomFormattingToolbar}
/>
</BlockNoteView>
);
}
6 changes: 5 additions & 1 deletion examples/editor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@
"dependencies": {
"@blocknote/core": "^0.9.6",
"@blocknote/react": "^0.9.6",
"@mantine/core": "^5.6.1",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react-dom": "^18.2.0",
"react-router-dom": "^6.20.0",
"y-partykit": "^0.0.0-4c022c1",
"yjs": "^13.6.10"
},
"devDependencies": {
"@types/react": "^18.0.25",
Expand Down
9 changes: 9 additions & 0 deletions examples/editor/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,12 @@
margin: 0 calc((100% - 731px) / 2);
height: 100%;
}

body {
margin: 0;
}

.root {
height: 100%;
width: 100%;
}
Loading