Skip to content

Commit

Permalink
Basic tiptap RichTextField
Browse files Browse the repository at this point in the history
  • Loading branch information
howlettt committed Sep 25, 2022
1 parent 2890881 commit fc44374
Show file tree
Hide file tree
Showing 17 changed files with 774 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import RichTextField, {
RichTextFieldStandardToolBar,
RichTextFieldTiptapEditor,
} from '@mui/lab/RichTextField';
import Stack from '@mui/material/Stack';
import Underline from '@tiptap/extension-underline';
import { useEditor } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import * as React from 'react';

export default function TiptapRichTextField() {
const [value, setValue] = React.useState('');
const [editor, setEditor] = React.useState(new RichTextFieldTiptapEditor(null));

const tiptapEditor = useEditor({
extensions: [
StarterKit.configure({
blockquote: false,
code: false,
codeBlock: false,
dropcursor: false,
gapcursor: false,
heading: false,
horizontalRule: false,
strike: false,
}),
Underline,
],
});

React.useEffect(() => {
setEditor(new RichTextFieldTiptapEditor(tiptapEditor));
}, [tiptapEditor]);

return (
<Stack alignItems="center" direction="column" spacing={2}>
<RichTextField
label="Type here"
editor={editor}
onChange={setValue}
variant="filled"
value={value}
>
<RichTextFieldStandardToolBar />
</RichTextField>
<div>{value}</div>
</Stack>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import RichTextField, {
RichTextFieldStandardToolBar,
RichTextFieldTiptapEditor,
} from '@mui/lab/RichTextField';
import Stack from '@mui/material/Stack';
import Underline from '@tiptap/extension-underline';
import { useEditor } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import * as React from 'react';

export default function TiptapRichTextField() {
const [value, setValue] = React.useState('');
const [editor, setEditor] = React.useState(new RichTextFieldTiptapEditor(null));

const tiptapEditor = useEditor({
extensions: [
StarterKit.configure({
blockquote: false,
code: false,
codeBlock: false,
dropcursor: false,
gapcursor: false,
heading: false,
horizontalRule: false,
strike: false,
}),
Underline,
],
});

React.useEffect(() => {
setEditor(new RichTextFieldTiptapEditor(tiptapEditor));
}, [tiptapEditor]);

return (
<Stack alignItems="center" direction="column" spacing={2}>
<RichTextField
label="Type here"
editor={editor}
onChange={setValue}
variant="filled"
value={value}
>
<RichTextFieldStandardToolBar />
</RichTextField>
<div>{value}</div>
</Stack>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<RichTextField
label="Type here"
editor={editor}
onChange={setValue}
variant="filled"
value={value}
>
<RichTextFieldStandardToolBar />
</RichTextField>
<div>{value}</div>
19 changes: 19 additions & 0 deletions docs/data/material/components/rich-text-field/rich-text-field.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
product: material-ui
title: React RichTextField component
components: RichTextField
githubLabel: 'component: rich text field'
packageName: '@mui/lab'
---

# Rich Text Field

<p class="description">Text field component that supports advanced text editing like formatting</p>

{{"component": "modules/components/ComponentLinkHeader.js"}}

## Tiptap

A rich text field using [tiptap](https://tiptap.dev)

{{"demo": "TiptapRichTextField.js"}}
1 change: 1 addition & 0 deletions docs/data/material/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ const pages = [
subheader: 'lab',
children: [
{ pathname: '/material-ui/about-the-lab', title: 'About the lab 🧪' },
{ pathname: '/material-ui/react-rich-text-field' },
{ pathname: '/material-ui/react-masonry' },
{ pathname: '/material-ui/react-timeline' },
{ pathname: '/material-ui/react-tree-view' },
Expand Down
3 changes: 3 additions & 0 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@
"@mui/x-date-pickers": "^5.0.1",
"@mui/x-date-pickers-pro": "^5.0.1",
"@mui/x-license-pro": "^5.17.0",
"@tiptap/extension-underline": "^2.0.0-beta.196",
"@tiptap/react": "^2.0.0-beta.196",
"@tiptap/starter-kit": "^2.0.0-beta.196",
"@trendmicro/react-interpolate": "^0.5.5",
"@types/autosuggest-highlight": "^3.2.0",
"@types/css-mediaquery": "^0.1.1",
Expand Down
11 changes: 11 additions & 0 deletions docs/pages/material-ui/react-rich-text-field.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as React from 'react';
import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs';
import {
demos,
docs,
demoComponents,
} from 'docs/data/material/components/rich-text-field/rich-text-field.md?@mui/markdown';

export default function Page() {
return <MarkdownDocs demos={demos} docs={docs} demoComponents={demoComponents} />;
}
1 change: 1 addition & 0 deletions docs/translations/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@
"MUI X": "MUI X",
"lab": "Lab",
"/material-ui/about-the-lab": "About the lab 🧪",
"/material-ui/react-rich-text-field": "Rich text field",
"/material-ui/react-masonry": "Masonry",
"/material-ui/react-timeline": "Timeline",
"/material-ui/react-tree-view": "Tree view",
Expand Down
1 change: 1 addition & 0 deletions packages/mui-lab/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"@emotion/react": "^11.5.0",
"@emotion/styled": "^11.3.0",
"@mui/material": "^5.0.0",
"@mui/icons-material": "^5.4.1",
"@types/react": "^17.0.0 || ^18.0.0",
"react": "^17.0.0 || ^18.0.0",
"react-dom": "^17.0.0 || ^18.0.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import '@tiptap/extension-underline';
import { Editor, EditorContent } from '@tiptap/react';
import '@tiptap/starter-kit';
import * as React from 'react';
import RichTextFieldEditor, {
RichTextFieldEditorEvent,
RichTextFieldEditorTextStyle,
} from '../RichTextFieldEditor';

export default class RichTextFieldTiptapEditor implements RichTextFieldEditor {
private editor: Editor | null;

get hasContent(): boolean {
return this.editor !== null && !this.editor.isEmpty;
}

constructor(editor: Editor | null) {
this.editor = editor;
}

public clearStyles() {
this.editor?.chain().focus().unsetAllMarks().clearNodes().run();
}

public focus() {
this.editor?.chain().focus();
}

public getValue() {
return this.editor?.getHTML() ?? '';
}

public off(event: RichTextFieldEditorEvent, callback: () => void) {
switch (event) {
case RichTextFieldEditorEvent.change:
this.editor?.off('update', callback);
break;
default:
throw new Error(`Unsupported event ${event}`);
}
}

public on(event: RichTextFieldEditorEvent, callback: () => void) {
switch (event) {
case RichTextFieldEditorEvent.change:
this.editor?.on('update', callback);
break;
default:
throw new Error(`Unsupported event ${event}`);
}
}

public render() {
return <EditorContent editor={this.editor} />;
}

public toggleStyle(style: RichTextFieldEditorTextStyle) {
switch (style) {
case RichTextFieldEditorTextStyle.bold:
this.editor?.chain().focus().toggleBold().run();
break;
case RichTextFieldEditorTextStyle.bulletList:
this.editor?.chain().focus().toggleBulletList().run();
break;
case RichTextFieldEditorTextStyle.italic:
this.editor?.chain().focus().toggleItalic().run();
break;
case RichTextFieldEditorTextStyle.orderedList:
this.editor?.chain().focus().toggleOrderedList().run();
break;
case RichTextFieldEditorTextStyle.underline:
this.editor?.chain().focus().toggleUnderline().run();
break;
default:
throw new Error(`Unsupported style ${style}`);
}
}
}
Loading

0 comments on commit fc44374

Please sign in to comment.