Skip to content

Commit

Permalink
Add an example for using Quill with React
Browse files Browse the repository at this point in the history
  • Loading branch information
luin committed Feb 13, 2024
1 parent 20bfdd9 commit cd3203f
Show file tree
Hide file tree
Showing 13 changed files with 199 additions and 50 deletions.
4 changes: 4 additions & 0 deletions packages/website/src/data/playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ const playground = [
title: 'Custom font and formats',
url: '/playground/custom-formats',
},
{
title: 'Using Quill with React',
url: '/playground/react',
},
];

export default playground;
9 changes: 0 additions & 9 deletions packages/website/src/pages/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -374,9 +374,6 @@ const IndexPage = () => {
events through a simple API. Works consistently and
deterministically with JSON as both input and output.
</span>
<Link className="action-link" href="/docs/quickstart">
View documentation
</Link>
</div>
</div>
<div className="feature columns">
Expand All @@ -388,12 +385,6 @@ const IndexPage = () => {
Experience the same consistent behavior and produced HTML
across platforms.
</span>
<Link
className="action-link"
href="https://github.com/quilljs/quill/#readme"
>
See the Chart
</Link>
</div>
</div>
</div>
Expand Down
24 changes: 10 additions & 14 deletions packages/website/src/pages/playground/[...id].jsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ export async function getStaticProps({ params }) {
}

function Playground({ pack, permalink, title }) {
const { 'externalResources.json': rawResources, ...files } = pack;
const { 'playground.json': raw, ...files } = pack;

let externalResources = [];
let metadata = {};
try {
externalResources = JSON.parse(rawResources);
metadata = JSON.parse(raw);
} catch (err) {}

const [overrides] = useState(() => {
Expand All @@ -72,13 +72,14 @@ function Playground({ pack, permalink, title }) {
<SandpackProvider
key={permalink}
options={{
activeFile: files['index.js']
? 'index.js'
: Object.keys(files)[0],
activeFile:
metadata.activeFile ||
(files['index.js'] ? 'index.js' : Object.keys(files)[0]),
externalResources:
externalResources && externalResources.map(replaceCDN),
metadata.externalResources &&
metadata.externalResources.map(replaceCDN),
}}
template="static"
template={metadata.template}
files={Object.keys(files).reduce((f, name) => {
const fullName = name.startsWith('/') ? name : `/${name}`;
return {
Expand All @@ -87,12 +88,7 @@ function Playground({ pack, permalink, title }) {
};
}, {})}
>
<PlaygroundLayout
permalink={permalink}
title={title}
files={files}
externalResources={externalResources}
>
<PlaygroundLayout permalink={permalink} title={title} files={files}>
<div className={styles.wrapper}>
<div className={styles.editor}>
<SandpackCodeEditor
Expand Down

This file was deleted.

12 changes: 12 additions & 0 deletions packages/website/src/playground/custom-formats/playground.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"template": "static",
"externalResources": [
"{{site.highlightjs}}/highlight.min.js",
"{{site.highlightjs}}/styles/atom-one-dark.min.css",
"{{site.katex}}/katex.min.js",
"{{site.katex}}/katex.min.css",
"{{site.cdn}}/quill.snow.css",
"{{site.cdn}}/quill.bubble.css",
"{{site.cdn}}/quill.js"
]
}
9 changes: 0 additions & 9 deletions packages/website/src/playground/form/externalResources.json

This file was deleted.

12 changes: 12 additions & 0 deletions packages/website/src/playground/form/playground.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"template": "static",
"externalResources": [
"{{site.highlightjs}}/highlight.min.js",
"{{site.highlightjs}}/styles/atom-one-dark.min.css",
"{{site.katex}}/katex.min.js",
"{{site.katex}}/katex.min.css",
"{{site.cdn}}/quill.snow.css",
"{{site.cdn}}/quill.bubble.css",
"{{site.cdn}}/quill.js"
]
}
61 changes: 61 additions & 0 deletions packages/website/src/playground/react/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React, { useRef, useState } from 'react';
import Editor from './Editor';

const Delta = Quill.import('delta');

const App = () => {
const [range, setRange] = useState();
const [lastChange, setLastChange] = useState();
const [readOnly, setReadOnly] = useState(false);

// Use a ref to access the quill instance directly
const quillRef = useRef();

return (
<div>
<Editor
ref={quillRef}
readOnly={readOnly}
defaultValue={new Delta()
.insert('Hello')
.insert('\n', { header: 1 })
.insert('Some ')
.insert('initial', { bold: true })
.insert(' ')
.insert('content', { underline: true })
.insert('\n')}
onSelectionChange={setRange}
onTextChange={setLastChange}
/>
<div class="controls">
<label>
Read Only:{' '}
<input
type="checkbox"
value={readOnly}
onChange={(e) => setReadOnly(e.target.checked)}
/>
</label>
<button
className="controls-right"
type="button"
onClick={() => {
alert(quillRef.current?.getLength());
}}
>
Get Content Length
</button>
</div>
<div className="state">
<div className="state-title">Current Range:</div>
{range ? JSON.stringify(range) : 'Empty'}
</div>
<div className="state">
<div className="state-title">Last Change:</div>
{lastChange ? JSON.stringify(lastChange.ops) : 'Empty'}
</div>
</div>
);
};

export default App;
55 changes: 55 additions & 0 deletions packages/website/src/playground/react/Editor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { forwardRef, useEffect, useLayoutEffect, useRef } from 'react';

// Editor is an uncontrolled React component
const Editor = forwardRef(
({ readOnly, defaultValue, onTextChange, onSelectionChange }, ref) => {
const containerRef = useRef(null);
const defaultValueRef = useRef(defaultValue);
const onTextChangeRef = useRef(onTextChange);
const onSelectionChangeRef = useRef(onSelectionChange);

useLayoutEffect(() => {
onTextChangeRef.current = onTextChange;
onSelectionChangeRef.current = onSelectionChange;
});

useEffect(() => {
ref.current?.enable(!readOnly);
}, [ref, readOnly]);

useEffect(() => {
const container = containerRef.current;
const editorContainer = container.appendChild(
container.ownerDocument.createElement('div'),
);
const quill = new Quill(editorContainer, {
theme: 'snow',
});

ref.current = quill;

if (defaultValueRef.current) {
quill.setContents(defaultValueRef.current);
}

quill.on(Quill.events.TEXT_CHANGE, (...args) => {
onTextChangeRef.current?.(...args);
});

quill.on(Quill.events.SELECTION_CHANGE, (...args) => {
onSelectionChangeRef.current?.(...args);
});

return () => {
ref.current = null;
container.innerHTML = '';
};
}, []);

return <div ref={containerRef}></div>;
},
);

Editor.displayName = 'Editor';

export default Editor;
13 changes: 13 additions & 0 deletions packages/website/src/playground/react/playground.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"template": "react",
"externalResources": [
"{{site.highlightjs}}/highlight.min.js",
"{{site.highlightjs}}/styles/atom-one-dark.min.css",
"{{site.katex}}/katex.min.js",
"{{site.katex}}/katex.min.css",
"{{site.cdn}}/quill.snow.css",
"{{site.cdn}}/quill.bubble.css",
"{{site.cdn}}/quill.js"
],
"activeFile": "App.js"
}
20 changes: 20 additions & 0 deletions packages/website/src/playground/react/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.controls {
display: flex;
border: 1px solid #ccc;
border-top: 0;
padding: 10px;
}

.controls-right {
margin-left: auto;
}

.state {
margin: 10px 0;
font-family: monospace;
}

.state-title {
color: #999;
text-transform: uppercase;
}
9 changes: 0 additions & 9 deletions packages/website/src/playground/snow/externalResources.json

This file was deleted.

12 changes: 12 additions & 0 deletions packages/website/src/playground/snow/playground.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"template": "static",
"externalResources": [
"{{site.highlightjs}}/highlight.min.js",
"{{site.highlightjs}}/styles/atom-one-dark.min.css",
"{{site.katex}}/katex.min.js",
"{{site.katex}}/katex.min.css",
"{{site.cdn}}/quill.snow.css",
"{{site.cdn}}/quill.bubble.css",
"{{site.cdn}}/quill.js"
]
}

0 comments on commit cd3203f

Please sign in to comment.