1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-13 18:53:59 +02:00

Make onChange prop optional, update examples and docs to treat slate as uncontrolled (#4922)

* Make onChange prop optional, update examples and docs to treat slate as uncontrolled

* Add changeset
This commit is contained in:
Eric Meier
2022-04-03 16:52:32 +01:00
committed by GitHub
parent 08d5a12c91
commit 9892cf0ffb
29 changed files with 207 additions and 246 deletions

View File

@@ -0,0 +1,5 @@
---
'slate-react': patch
---
Make Slate component onChange optional

View File

@@ -66,53 +66,23 @@ declare module 'slate' {
}
```
```typescript
// Also you must annotate `useState<Descendant[]>` and the editor's initial value.
const App = () => {
const initialValue: CustomElement[] = []
const [value, setValue] = useState<Descendant[]>(initialValue)
return (
<Slate value={value} onChange={setValue}>
...
</Slate>
)
}
```
Next we want to create state for `value`:
```jsx
const App = () => {
const [editor] = useState(() => withReact(createEditor()))
// Keep track of state for the value of the editor.
const [value, setValue] = useState([])
return null
}
```
Next up is to render a `<Slate>` context provider.
The provider component keeps track of your Slate editor, its plugins, its value, its selection, and any changes that occur. It **must** be rendered above any `<Editable>` components. But it can also provide the editor state to other components like toolbars, menus, etc. using the `useSlate` hook.
```jsx
const initialValue = []
const App = () => {
const [editor] = useState(() => withReact(createEditor()))
const [value, setValue] = useState([])
// Render the Slate context.
return (
<Slate
editor={editor}
value={value}
onChange={newValue => setValue(newValue)}
/>
)
return <Slate editor={editor} value={initialValue} />
}
```
You can think of the `<Slate>` component as providing a context to every component underneath it.
> As of v0.67 the Slate Provider's "value" prop is now only used as initial state for editor.children. If your code relies on replacing editor.children you should do so by replacing it directly instead of relying on the "value" prop to do this for you. See [Slate PR 4540](https://github.com/ianstormtaylor/slate/pull/4540) for a more in-depth discussion.
> Slate Provider's "value" prop is only used as initial state for editor.children. If your code relies on replacing editor.children you should do so by replacing it directly instead of relying on the "value" prop to do this for you. See [Slate PR 4540](https://github.com/ianstormtaylor/slate/pull/4540) for a more in-depth discussion.
This is a slightly different mental model than things like `<input>` or `<textarea>`, because richtext documents are more complex. You'll often want to include toolbars, or live previews, or other complex components next to your editable content.
@@ -121,16 +91,14 @@ By having a shared context, those other components can execute commands, query t
Okay, so the next step is to render the `<Editable>` component itself:
```jsx
const initialValue = []
const App = () => {
const [editor] = useState(() => withReact(createEditor()))
const [value, setValue] = useState([])
return (
// Add the editable component inside the context.
<Slate
editor={editor}
value={value}
onChange={newValue => setValue(newValue)}
>
<Slate editor={editor} value={initialValue}>
<Editable />
</Slate>
)
@@ -144,22 +112,20 @@ There's only one last step. So far we've been using an empty `[]` array as the i
The value is just plain JSON. Here's one containing a single paragraph block with some text in it:
```jsx
const App = () => {
const [editor] = useState(() => withReact(createEditor()))
// Add the initial value when setting up our state.
const [value, setValue] = useState([
// Add the initial value.
const initialValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
])
]
const App = () => {
const [editor] = useState(() => withReact(createEditor())
const [value, setValue] = useState()
return (
<Slate
editor={editor}
value={value}
onChange={newValue => setValue(newValue)}
>
<Slate editor={editor} value={initialValue}>
<Editable />
</Slate>
)

View File

@@ -9,17 +9,18 @@ Let's use the `onKeyDown` handler to change the editor's content when we press a
Here's our app from earlier:
```jsx
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const [value, setValue] = useState([
const initialValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
])
]
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable />
</Slate>
)
@@ -29,17 +30,18 @@ const App = () => {
Now we add an `onKeyDown` handler:
```jsx
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const [value, setValue] = useState([
const initialValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
])
]
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable
// Define a new handler which prints the key that was pressed.
onKeyDown={event => {
@@ -58,17 +60,18 @@ Now we want to make it actually change the content. For the purposes of our exam
Our `onKeyDown` handler might look like this:
```jsx
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const [value, setValue] = useState([
const initialValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
])
]
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable
onKeyDown={event => {
if (event.key === '&') {

View File

@@ -7,17 +7,18 @@ But that's not all you can do. Slate lets you define any type of custom blocks y
We'll show you how. Let's start with our app from earlier:
```jsx
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const [value, setValue] = useState([
const initialValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
])
]
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable
onKeyDown={event => {
if (event.key === '&') {
@@ -65,14 +66,15 @@ const DefaultElement = props => {
Now, let's add that renderer to our `Editor`:
```jsx
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const [value, setValue] = useState([
const initialValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
])
]
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
// Define a rendering function based on the element passed to `props`. We use
// `useCallback` here to memoize the function for subsequent renders.
@@ -86,7 +88,7 @@ const App = () => {
}, [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable
// Pass in the `renderElement` function.
renderElement={renderElement}
@@ -120,14 +122,15 @@ Okay, but now we'll need a way for the user to actually turn a block into a code
// Import the `Editor` and `Transforms` helpers from Slate.
import { Editor, Transforms } from 'slate'
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const [value, setValue] = useState([
const initialValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
])
]
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const renderElement = useCallback(props => {
switch (props.element.type) {
@@ -139,7 +142,7 @@ const App = () => {
}, [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable
renderElement={renderElement}
onKeyDown={event => {
@@ -177,14 +180,15 @@ Now, if you press ``Ctrl-``` the block your cursor is in should turn into a code
But we forgot one thing. When you hit ``Ctrl-``` again, it should change the code block back into a paragraph. To do that, we'll need to add a bit of logic to change the type we set based on whether any of the currently selected blocks are already a code block:
```jsx
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const [value, setValue] = useState([
const initialValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
])
]
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const renderElement = useCallback(props => {
switch (props.element.type) {
@@ -196,7 +200,7 @@ const App = () => {
}, [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable
renderElement={renderElement}
onKeyDown={event => {

View File

@@ -7,26 +7,27 @@ In this guide, we'll show you how to add custom formatting options, like **bold*
So we start with our app from earlier:
```jsx
const renderElement = (props) => {
const renderElement = props => {
switch (props.element.type) {
case 'code':
return <CodeElement {...props} />
default:
return <DefaultElement {...props} />
}
})
}
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const [value, setValue] = useState([
const initialValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
])
]
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable
renderElement={renderElement}
onKeyDown={event => {
@@ -52,14 +53,15 @@ const App = () => {
And now, we'll edit the `onKeyDown` handler to make it so that when you press `control-B`, it will add a `bold` format to the currently selected text:
```jsx
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const [value, setValue] = useState([
const initialValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
])
]
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const renderElement = useCallback(props => {
switch (props.element.type) {
@@ -71,7 +73,7 @@ const App = () => {
}, [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={value}>
<Editable
renderElement={renderElement}
onKeyDown={event => {
@@ -137,14 +139,15 @@ Pretty familiar, right?
And now, let's tell Slate about that leaf. To do that, we'll pass in the `renderLeaf` prop to our editor.
```jsx
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const [value, setValue] = useState([
const initialValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
])
]
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const renderElement = useCallback(props => {
switch (props.element.type) {
@@ -161,7 +164,7 @@ const App = () => {
}, [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable
renderElement={renderElement}
// Pass in the `renderLeaf` function.

View File

@@ -11,14 +11,15 @@ Let's see how this works.
We'll start with our app from earlier:
```jsx
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const [value, setValue] = useState([
const initialValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
])
]
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const renderElement = useCallback(props => {
switch (props.element.type) {
@@ -34,7 +35,7 @@ const App = () => {
}, [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable
renderElement={renderElement}
renderLeaf={renderLeaf}
@@ -117,14 +118,15 @@ const CustomEditor = {
},
}
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const [value, setValue] = useState([
const initialValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
])
]
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const renderElement = useCallback(props => {
switch (props.element.type) {
@@ -140,7 +142,7 @@ const App = () => {
}, [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable
renderElement={renderElement}
renderLeaf={renderLeaf}
@@ -173,14 +175,15 @@ const App = () => {
Now our commands are clearly defined and you can invoke them from anywhere we have access to our `editor` object. For example, from hypothetical toolbar buttons:
```jsx
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const [value, setValue] = useState([
const initialValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
])
]
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const renderElement = useCallback(props => {
switch (props.element.type) {
@@ -197,7 +200,7 @@ const App = () => {
return (
// Add a toolbar with buttons that call the same methods.
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<div>
<button
onMouseDown={event => {

View File

@@ -7,17 +7,18 @@ In this guide, we'll show you how to add logic to save your Slate content to a d
Let's start with a basic editor:
```jsx
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const [value, setValue] = useState([
const initialValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
])
]
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable />
</Slate>
)
@@ -31,22 +32,21 @@ What we need to do is save the changes you make somewhere. For this example, we'
So, in our `onChange` handler, we need to save the `value` if anything besides the selection was changed:
```jsx
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
const [value, setValue] = useState([
const initialValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
])
]
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
return (
<Slate
editor={editor}
value={value}
value={initialValue}
onChange={value => {
setValue(value)
const isAstChange = editor.operations.some(
op => 'set_selection' !== op.type
)
@@ -71,21 +71,21 @@ But... if you refresh the page, everything is still reset. That's because we nee
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
// Update the initial content to be pulled from Local Storage if it exists.
const [value, setValue] = useState(
const initialValue = useMemo(
JSON.parse(localStorage.getItem('content')) || [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
]
],
[]
)
return (
<Slate
editor={editor}
value={value}
value={initialValue}
onChange={value => {
setValue(value)
const isAstChange = editor.operations.some(
op => 'set_selection' !== op.type
)
@@ -136,16 +136,16 @@ const deserialize = string => {
const App = () => {
const editor = useMemo(() => withReact(createEditor()), [])
// Use our deserializing function to read the data from Local Storage.
const [value, setValue] = useState(
deserialize(localStorage.getItem('content')) || ''
const initialValue = useMemo(
deserialize(localStorage.getItem('content')) || '',
[]
)
return (
<Slate
editor={editor}
value={value}
value={initialValue}
onChange={value => {
setValue(value)
const isAstChange = editor.operations.some(
op => 'set_selection' !== op.type
)
@@ -167,7 +167,7 @@ You can emulate this strategy for any format you like. You can serialize to HTML
> 🤖 Note that even though you _can_ serialize your content however you like, there are tradeoffs. The serialization process has a cost itself, and certain formats may be harder to work with than others. In general we recommend writing your own format only if your use case has a specific need for it. Otherwise, you're often better leaving the data in the format Slate uses.
If you want to update the editor's content in response to events from outside of slate, you need to change the children property directly. The simplest way is to replace the value of editor.children `editor.children = newValue` and trigger a re-rendering (e.g. by calling `setValue(newValue)` in the example above). Alternatively, you can use slate's internal operations to transform the value, for example:
If you want to update the editor's content in response to events from outside of slate, you need to change the children property directly. The simplest way is to replace the value of editor.children `editor.children = newValue` and trigger a re-rendering (e.g. by calling `editor.onChange()` in the example above). Alternatively, you can use slate's internal operations to transform the value, for example:
```javascript
/**

View File

@@ -20,7 +20,7 @@ export const Slate = (props: {
editor: ReactEditor
value: Descendant[]
children: React.ReactNode
onChange: (value: Descendant[]) => void
onChange?: (value: Descendant[]) => void
}) => {
const { editor, children, onChange, value, ...rest } = props
const unmountRef = useRef(false)
@@ -48,7 +48,10 @@ export const Slate = (props: {
} = getSelectorContext(editor)
const onContextChange = useCallback(() => {
if (onChange) {
onChange(editor.children)
}
setContext([editor])
handleSelectorChange(editor)
}, [onChange])

View File

@@ -1,4 +1,4 @@
import React, { useState, useMemo, useCallback } from 'react'
import React, { useMemo, useCallback } from 'react'
import {
Slate,
Editable,
@@ -66,7 +66,6 @@ const initialValue: Descendant[] = [
]
const CheckListsExample = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const renderElement = useCallback(props => <Element {...props} />, [])
const editor = useMemo(
() => withChecklists(withHistory(withReact(createEditor()))),
@@ -74,7 +73,7 @@ const CheckListsExample = () => {
)
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable
renderElement={renderElement}
placeholder="Get to work…"

View File

@@ -10,7 +10,6 @@ import { withHistory } from 'slate-history'
import { css } from '@emotion/css'
const CodeHighlightingExample = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const [language, setLanguage] = useState('html')
const renderLeaf = useCallback(props => <Leaf {...props} />, [])
const editor = useMemo(() => withHistory(withReact(createEditor())), [])
@@ -46,7 +45,7 @@ const CodeHighlightingExample = () => {
)
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<div
contentEditable={false}
style={{ position: 'relative', top: '5px', right: '5px' }}

View File

@@ -1,13 +1,19 @@
import React, { useState, useMemo } from 'react'
import React, { useMemo } from 'react'
import { createEditor, Descendant } from 'slate'
import { Slate, Editable, withReact } from 'slate-react'
import { withHistory } from 'slate-history'
const initialValue: Descendant[] = [
{
type: 'paragraph',
children: [{ text: '' }],
},
]
const PlainTextExample = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const editor = useMemo(() => withHistory(withReact(createEditor())), [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable
placeholder="Type something"
renderPlaceholder={({ children, attributes }) => (
@@ -24,11 +30,4 @@ const PlainTextExample = () => {
)
}
const initialValue: Descendant[] = [
{
type: 'paragraph',
children: [{ text: '' }],
},
]
export default PlainTextExample

View File

@@ -1,4 +1,4 @@
import React, { useState, useMemo } from 'react'
import React, { useMemo } from 'react'
import {
Transforms,
createEditor,
@@ -14,10 +14,9 @@ import {
} from 'slate-react'
const EmbedsExample = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const editor = useMemo(() => withEmbeds(withReact(createEditor())), [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable
renderElement={props => <Element {...props} />}
placeholder="Enter some text..."

View File

@@ -1,4 +1,4 @@
import React, { useState, useCallback, useMemo } from 'react'
import React, { useCallback, useMemo } from 'react'
import { Slate, Editable, withReact } from 'slate-react'
import {
Transforms,
@@ -64,14 +64,13 @@ const withLayout = editor => {
}
const ForcedLayoutExample = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const renderElement = useCallback(props => <Element {...props} />, [])
const editor = useMemo(
() => withLayout(withHistory(withReact(createEditor()))),
[]
)
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable
renderElement={renderElement}
placeholder="Enter a title…"

View File

@@ -1,4 +1,4 @@
import React, { useState, useMemo, useRef, useEffect } from 'react'
import React, { useMemo, useRef, useEffect } from 'react'
import { Slate, Editable, withReact, useSlate, useFocused } from 'slate-react'
import {
Editor,
@@ -14,11 +14,10 @@ import { withHistory } from 'slate-history'
import { Button, Icon, Menu, Portal } from '../components'
const HoveringMenuExample = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const editor = useMemo(() => withHistory(withReact(createEditor())), [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<HoveringToolbar />
<Editable
renderLeaf={props => <Leaf {...props} />}

View File

@@ -1,4 +1,4 @@
import React, { useState, useMemo, useCallback } from 'react'
import React, { useMemo, useCallback } from 'react'
import faker from 'faker'
import { createEditor, Descendant } from 'slate'
import { Slate, Editable, withReact } from 'slate-react'
@@ -22,11 +22,10 @@ for (let h = 0; h < HEADINGS; h++) {
}
const HugeDocumentExample = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const renderElement = useCallback(props => <Element {...props} />, [])
const editor = useMemo(() => withReact(createEditor()), [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable renderElement={renderElement} spellCheck autoFocus />
</Slate>
)

View File

@@ -15,7 +15,6 @@ const HOTKEYS = {
}
const IFrameExample = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const renderElement = useCallback(
({ attributes, children }) => <p {...attributes}>{children}</p>,
[]
@@ -26,7 +25,7 @@ const IFrameExample = () => {
const handleBlur = useCallback(() => ReactEditor.deselect(editor), [editor])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Toolbar>
<MarkButton format="bold" icon="format_bold" />
<MarkButton format="italic" icon="format_italic" />

View File

@@ -1,4 +1,4 @@
import React, { useState, useMemo } from 'react'
import React, { useMemo } from 'react'
import imageExtensions from 'image-extensions'
import isUrl from 'is-url'
import { Transforms, createEditor, Descendant } from 'slate'
@@ -18,14 +18,13 @@ import { Button, Icon, Toolbar } from '../components'
import { ImageElement } from './custom-types'
const ImagesExample = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const editor = useMemo(
() => withImages(withHistory(withReact(createEditor()))),
[]
)
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Toolbar>
<InsertImageButton />
</Toolbar>

View File

@@ -1,4 +1,4 @@
import React, { useState, useMemo } from 'react'
import React, { useMemo } from 'react'
import isUrl from 'is-url'
import { isKeyHotkey } from 'is-hotkey'
import { css } from '@emotion/css'
@@ -61,7 +61,6 @@ const initialValue: Descendant[] = [
},
]
const InlinesExample = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const editor = useMemo(
() => withInlines(withHistory(withReact(createEditor()))),
[]
@@ -92,11 +91,7 @@ const InlinesExample = () => {
}
return (
<SlateReact.Slate
editor={editor}
value={value}
onChange={value => setValue(value)}
>
<SlateReact.Slate editor={editor} value={initialValue}>
<Toolbar>
<AddLinkButton />
<RemoveLinkButton />

View File

@@ -1,7 +1,7 @@
import Prism from 'prismjs'
import React, { useState, useCallback, useMemo } from 'react'
import React, { useCallback, useMemo } from 'react'
import { Slate, Editable, withReact } from 'slate-react'
import { Text, createEditor, Element, Descendant } from 'slate'
import { Text, createEditor, Descendant } from 'slate'
import { withHistory } from 'slate-history'
import { css } from '@emotion/css'
@@ -9,7 +9,6 @@ import { css } from '@emotion/css'
;Prism.languages.markdown=Prism.languages.extend("markup",{}),Prism.languages.insertBefore("markdown","prolog",{blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},code:[{pattern:/^(?: {4}|\t).+/m,alias:"keyword"},{pattern:/``.+?``|`[^`\n]+`/,alias:"keyword"}],title:[{pattern:/\w+.*(?:\r?\n|\r)(?:==+|--+)/,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#+.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])([\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:/(^|[^\\])(\*\*|__)(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,inside:{punctuation:/^\*\*|^__|\*\*$|__$/}},italic:{pattern:/(^|[^\\])([*_])(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,inside:{punctuation:/^[*_]|[*_]$/}},url:{pattern:/!?\[[^\]]+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)| ?\[[^\]\n]*\])/,inside:{variable:{pattern:/(!?\[)[^\]]+(?=\]$)/,lookbehind:!0},string:{pattern:/"(?:\\.|[^"\\])*"(?=\)$)/}}}}),Prism.languages.markdown.bold.inside.url=Prism.util.clone(Prism.languages.markdown.url),Prism.languages.markdown.italic.inside.url=Prism.util.clone(Prism.languages.markdown.url),Prism.languages.markdown.bold.inside.italic=Prism.util.clone(Prism.languages.markdown.italic),Prism.languages.markdown.italic.inside.bold=Prism.util.clone(Prism.languages.markdown.bold); // prettier-ignore
const MarkdownPreviewExample = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const renderLeaf = useCallback(props => <Leaf {...props} />, [])
const editor = useMemo(() => withHistory(withReact(createEditor())), [])
const decorate = useCallback(([node, path]) => {
@@ -51,7 +50,7 @@ const MarkdownPreviewExample = () => {
}, [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable
decorate={decorate}
renderLeaf={renderLeaf}

View File

@@ -1,4 +1,4 @@
import React, { useState, useCallback, useMemo } from 'react'
import React, { useCallback, useMemo } from 'react'
import { Slate, Editable, withReact } from 'slate-react'
import {
Editor,
@@ -26,14 +26,13 @@ const SHORTCUTS = {
}
const MarkdownShortcutsExample = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const renderElement = useCallback(props => <Element {...props} />, [])
const editor = useMemo(
() => withShortcuts(withReact(withHistory(createEditor()))),
[]
)
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable
renderElement={renderElement}
placeholder="Write some markdown..."

View File

@@ -15,7 +15,6 @@ import { MentionElement } from './custom-types'
const MentionExample = () => {
const ref = useRef<HTMLDivElement | null>()
const [value, setValue] = useState<Descendant[]>(initialValue)
const [target, setTarget] = useState<Range | undefined>()
const [index, setIndex] = useState(0)
const [search, setSearch] = useState('')
@@ -73,9 +72,8 @@ const MentionExample = () => {
return (
<Slate
editor={editor}
value={value}
onChange={value => {
setValue(value)
value={initialValue}
onChange={() => {
const { selection } = editor
if (selection && Range.isCollapsed(selection)) {

View File

@@ -1,4 +1,4 @@
import React, { useState, useCallback, useMemo } from 'react'
import React, { useCallback, useMemo } from 'react'
import { jsx } from 'slate-hyperscript'
import { Transforms, createEditor, Descendant } from 'slate'
import { withHistory } from 'slate-history'
@@ -84,7 +84,6 @@ export const deserialize = el => {
}
const PasteHtmlExample = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const renderElement = useCallback(props => <Element {...props} />, [])
const renderLeaf = useCallback(props => <Leaf {...props} />, [])
const editor = useMemo(
@@ -92,7 +91,7 @@ const PasteHtmlExample = () => {
[]
)
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable
renderElement={renderElement}
renderLeaf={renderLeaf}

View File

@@ -1,13 +1,12 @@
import React, { useState, useMemo } from 'react'
import React, { useMemo } from 'react'
import { createEditor, Descendant } from 'slate'
import { Slate, Editable, withReact } from 'slate-react'
import { withHistory } from 'slate-history'
const PlainTextExample = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const editor = useMemo(() => withHistory(withReact(createEditor())), [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable placeholder="Enter some plain text..." />
</Slate>
)

View File

@@ -1,12 +1,11 @@
import React, { useState, useMemo } from 'react'
import { createEditor, Descendant, Element } from 'slate'
import React, { useMemo } from 'react'
import { createEditor, Descendant } from 'slate'
import { Slate, Editable, withReact } from 'slate-react'
const ReadOnlyExample = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const editor = useMemo(() => withReact(createEditor()), [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable readOnly placeholder="Enter some plain text..." />
</Slate>
)

View File

@@ -1,4 +1,4 @@
import React, { useCallback, useMemo, useState } from 'react'
import React, { useCallback, useMemo } from 'react'
import isHotkey from 'is-hotkey'
import { Editable, withReact, useSlate, Slate } from 'slate-react'
import {
@@ -23,13 +23,12 @@ const LIST_TYPES = ['numbered-list', 'bulleted-list']
const TEXT_ALIGN_TYPES = ['left', 'center', 'right', 'justify']
const RichTextExample = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const renderElement = useCallback(props => <Element {...props} />, [])
const renderLeaf = useCallback(props => <Leaf {...props} />, [])
const editor = useMemo(() => withHistory(withReact(createEditor())), [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Toolbar>
<MarkButton format="bold" icon="format_bold" />
<MarkButton format="italic" icon="format_italic" />

View File

@@ -1,4 +1,4 @@
import React, { useState, useMemo } from 'react'
import React, { useMemo } from 'react'
import { createEditor, Descendant } from 'slate'
import { Slate, Editable, withReact } from 'slate-react'
import { withHistory } from 'slate-history'
@@ -49,10 +49,9 @@ const ScrollIntoViewExample = () => {
}
const PlainTextEditor = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const editor = useMemo(() => withHistory(withReact(createEditor())), [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable placeholder="Enter some plain text..." />
</Slate>
)

View File

@@ -7,7 +7,6 @@ import { withHistory } from 'slate-history'
import { Icon, Toolbar } from '../components'
const SearchHighlightingExample = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const [search, setSearch] = useState<string | undefined>()
const editor = useMemo(() => withHistory(withReact(createEditor())), [])
const decorate = useCallback(
@@ -38,7 +37,7 @@ const SearchHighlightingExample = () => {
)
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Toolbar>
<div
className={css`

View File

@@ -1,5 +1,5 @@
import ReactDOM from 'react-dom'
import React, { useState, useMemo, useRef, useEffect } from 'react'
import React, { useMemo, useRef, useEffect } from 'react'
import { createEditor, Descendant } from 'slate'
import { Slate, Editable, withReact } from 'slate-react'
import { withHistory } from 'slate-history'
@@ -28,11 +28,10 @@ const ShadowDOM = () => {
}
const ShadowEditor = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const editor = useMemo(() => withHistory(withReact(createEditor())), [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable placeholder="Enter some plain text..." />
</Slate>
)

View File

@@ -1,4 +1,4 @@
import React, { useState, useCallback, useMemo } from 'react'
import React, { useCallback, useMemo } from 'react'
import { Slate, Editable, withReact } from 'slate-react'
import {
Editor,
@@ -11,7 +11,6 @@ import {
import { withHistory } from 'slate-history'
const TablesExample = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const renderElement = useCallback(props => <Element {...props} />, [])
const renderLeaf = useCallback(props => <Leaf {...props} />, [])
const editor = useMemo(
@@ -19,7 +18,7 @@ const TablesExample = () => {
[]
)
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Slate editor={editor} value={initialValue}>
<Editable renderElement={renderElement} renderLeaf={renderLeaf} />
</Slate>
)