1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-26 08:34:28 +02:00

docs: convert examples to typescript (#3766)

* docs: convert examples to typescript

* docs: convert remaining examples

* docs: update next.js

* ci: fix lint

* docs: fix next.js path

* docs: cleanup

* update

Co-authored-by: wendellhu <wendellhu@tencent.com>
This commit is contained in:
Wendell Hu
2020-08-20 00:14:51 +08:00
committed by GitHub
parent 7b2b6df215
commit 912d4b79da
30 changed files with 1598 additions and 1028 deletions

View File

@@ -14,6 +14,7 @@
"jsx": true "jsx": true
} }
}, },
"ignorePatterns": ["**/next-env.d.ts"],
"settings": { "settings": {
"import/extensions": [".js", ".ts", ".jsx", ".tsx"], "import/extensions": [".js", ".ts", ".jsx", ".tsx"],
"react": { "react": {

View File

@@ -60,7 +60,7 @@
"lerna": "^3.19.0", "lerna": "^3.19.0",
"lodash": "^4.17.4", "lodash": "^4.17.4",
"mocha": "^6.2.0", "mocha": "^6.2.0",
"next": "^9.3.5", "next": "^9.4.0",
"npm-run-all": "^4.1.2", "npm-run-all": "^4.1.2",
"prettier": "^1.19.1", "prettier": "^1.19.1",
"prismjs": "^1.5.1", "prismjs": "^1.5.1",

View File

@@ -1,143 +0,0 @@
import React from 'react'
import ReactDOM from 'react-dom'
import { cx, css } from 'emotion'
export const Button = React.forwardRef(
({ className, active, reversed, ...props }, ref) => (
<span
{...props}
ref={ref}
className={cx(
className,
css`
cursor: pointer;
color: ${reversed
? active
? 'white'
: '#aaa'
: active
? 'black'
: '#ccc'};
`
)}
/>
)
)
export const EditorValue = React.forwardRef(
({ className, value, ...props }, ref) => {
const textLines = value.document.nodes
.map(node => node.text)
.toArray()
.join('\n')
return (
<div
ref={ref}
{...props}
className={cx(
className,
css`
margin: 30px -20px 0;
`
)}
>
<div
className={css`
font-size: 14px;
padding: 5px 20px;
color: #404040;
border-top: 2px solid #eeeeee;
background: #f8f8f8;
`}
>
Slate's value as text
</div>
<div
className={css`
color: #404040;
font: 12px monospace;
white-space: pre-wrap;
padding: 10px 20px;
div {
margin: 0 0 0.5em;
}
`}
>
{textLines}
</div>
</div>
)
}
)
export const Icon = React.forwardRef(({ className, ...props }, ref) => (
<span
{...props}
ref={ref}
className={cx(
'material-icons',
className,
css`
font-size: 18px;
vertical-align: text-bottom;
`
)}
/>
))
export const Instruction = React.forwardRef(({ className, ...props }, ref) => (
<div
{...props}
ref={ref}
className={cx(
className,
css`
white-space: pre-wrap;
margin: 0 -20px 10px;
padding: 10px 20px;
font-size: 14px;
background: #f8f8e8;
`
)}
/>
))
export const Menu = React.forwardRef(({ className, ...props }, ref) => (
<div
{...props}
ref={ref}
className={cx(
className,
css`
& > * {
display: inline-block;
}
& > * + * {
margin-left: 15px;
}
`
)}
/>
))
export const Portal = ({ children }) => {
return ReactDOM.createPortal(children, document.body)
}
export const Toolbar = React.forwardRef(({ className, ...props }, ref) => (
<Menu
{...props}
ref={ref}
className={cx(
className,
css`
position: relative;
padding: 1px 18px 17px;
margin: 0 -20px;
border-bottom: 2px solid #eee;
margin-bottom: 20px;
`
)}
/>
))

193
site/components.tsx Normal file
View File

@@ -0,0 +1,193 @@
import React, { Ref, PropsWithChildren } from 'react'
import ReactDOM from 'react-dom'
import { cx, css } from 'emotion'
interface BaseProps {
className: string
[key: string]: unknown
}
type OrNull<T> = T | null
export const Button = React.forwardRef(
(
{
className,
active,
reversed,
...props
}: PropsWithChildren<
{
active: boolean
reversed: boolean
} & BaseProps
>,
ref: Ref<OrNull<HTMLSpanElement>>
) => (
<span
{...props}
ref={ref}
className={cx(
className,
css`
cursor: pointer;
color: ${reversed
? active
? 'white'
: '#aaa'
: active
? 'black'
: '#ccc'};
`
)}
/>
)
)
export const EditorValue = React.forwardRef(
(
{
className,
value,
...props
}: PropsWithChildren<
{
value: any
} & BaseProps
>,
ref: Ref<OrNull<null>>
) => {
const textLines = value.document.nodes
.map(node => node.text)
.toArray()
.join('\n')
return (
<div
ref={ref}
{...props}
className={cx(
className,
css`
margin: 30px -20px 0;
`
)}
>
<div
className={css`
font-size: 14px;
padding: 5px 20px;
color: #404040;
border-top: 2px solid #eeeeee;
background: #f8f8f8;
`}
>
Slate's value as text
</div>
<div
className={css`
color: #404040;
font: 12px monospace;
white-space: pre-wrap;
padding: 10px 20px;
div {
margin: 0 0 0.5em;
}
`}
>
{textLines}
</div>
</div>
)
}
)
export const Icon = React.forwardRef(
(
{ className, ...props }: PropsWithChildren<BaseProps>,
ref: Ref<OrNull<HTMLSpanElement>>
) => (
<span
{...props}
ref={ref}
className={cx(
'material-icons',
className,
css`
font-size: 18px;
vertical-align: text-bottom;
`
)}
/>
)
)
export const Instruction = React.forwardRef(
(
{ className, ...props }: PropsWithChildren<BaseProps>,
ref: Ref<OrNull<HTMLDivElement>>
) => (
<div
{...props}
ref={ref}
className={cx(
className,
css`
white-space: pre-wrap;
margin: 0 -20px 10px;
padding: 10px 20px;
font-size: 14px;
background: #f8f8e8;
`
)}
/>
)
)
export const Menu = React.forwardRef(
(
{ className, ...props }: PropsWithChildren<BaseProps>,
ref: Ref<OrNull<HTMLDivElement>>
) => (
<div
{...props}
ref={ref}
className={cx(
className,
css`
& > * {
display: inline-block;
}
& > * + * {
margin-left: 15px;
}
`
)}
/>
)
)
export const Portal = ({ children }) => {
return ReactDOM.createPortal(children, document.body)
}
export const Toolbar = React.forwardRef(
(
{ className, ...props }: PropsWithChildren<BaseProps>,
ref: Ref<OrNull<HTMLDivElement>>
) => (
<Menu
{...props}
ref={ref}
className={cx(
className,
css`
position: relative;
padding: 1px 18px 17px;
margin: 0 -20px;
border-bottom: 2px solid #eee;
margin-bottom: 20px;
`
)}
/>
)
)

View File

@@ -7,12 +7,12 @@ import {
useReadOnly, useReadOnly,
ReactEditor, ReactEditor,
} from 'slate-react' } from 'slate-react'
import { Editor, Transforms, Range, Point, createEditor } from 'slate' import { Node, Editor, Transforms, Range, Point, createEditor } from 'slate'
import { css } from 'emotion' import { css } from 'emotion'
import { withHistory } from 'slate-history' import { withHistory } from 'slate-history'
const CheckListsExample = () => { const CheckListsExample = () => {
const [value, setValue] = useState(initialValue) const [value, setValue] = useState<Node[]>(initialValue)
const renderElement = useCallback(props => <Element {...props} />, []) const renderElement = useCallback(props => <Element {...props} />, [])
const editor = useMemo( const editor = useMemo(
() => withChecklists(withHistory(withReact(createEditor()))), () => withChecklists(withHistory(withReact(createEditor()))),

View File

@@ -5,12 +5,12 @@ import 'prismjs/components/prism-sql'
import 'prismjs/components/prism-java' import 'prismjs/components/prism-java'
import React, { useState, useCallback, useMemo } from 'react' import React, { useState, useCallback, useMemo } from 'react'
import { Slate, Editable, withReact } from 'slate-react' import { Slate, Editable, withReact } from 'slate-react'
import { Text, createEditor } from 'slate' import { Text, createEditor, Node } from 'slate'
import { withHistory } from 'slate-history' import { withHistory } from 'slate-history'
import { css } from 'emotion' import { css } from 'emotion'
const CodeHighlightingExample = () => { const CodeHighlightingExample = () => {
const [value, setValue] = useState(initialValue) const [value, setValue] = useState<Node[]>(initialValue)
const [language, setLanguage] = useState('html') const [language, setLanguage] = useState('html')
const renderLeaf = useCallback(props => <Leaf {...props} />, []) const renderLeaf = useCallback(props => <Leaf {...props} />, [])
const editor = useMemo(() => withHistory(withReact(createEditor())), []) const editor = useMemo(() => withHistory(withReact(createEditor())), [])

View File

@@ -1,5 +1,5 @@
import React, { useState, useMemo } from 'react' import React, { useState, useMemo } from 'react'
import { Transforms, createEditor } from 'slate' import { Transforms, createEditor, Node } from 'slate'
import { Slate, Editable, useEditor, withReact } from 'slate-react' import { Slate, Editable, useEditor, withReact } from 'slate-react'
import { withHistory } from 'slate-history' import { withHistory } from 'slate-history'
import { css } from 'emotion' import { css } from 'emotion'
@@ -8,7 +8,7 @@ import RichTextEditor from './richtext'
import { Button, Icon, Toolbar } from '../components' import { Button, Icon, Toolbar } from '../components'
const EditableVoidsExample = () => { const EditableVoidsExample = () => {
const [value, setValue] = useState(initialValue) const [value, setValue] = useState<Node[]>(initialValue)
const editor = useMemo( const editor = useMemo(
() => withEditableVoids(withHistory(withReact(createEditor()))), () => withEditableVoids(withHistory(withReact(createEditor()))),
[] []

View File

@@ -1,5 +1,5 @@
import React, { useState, useMemo } from 'react' import React, { useState, useMemo } from 'react'
import { Transforms, createEditor } from 'slate' import { Transforms, createEditor, Node } from 'slate'
import { import {
Slate, Slate,
Editable, Editable,
@@ -11,7 +11,7 @@ import {
} from 'slate-react' } from 'slate-react'
const EmbedsExample = () => { const EmbedsExample = () => {
const [value, setValue] = useState(initialValue) const [value, setValue] = useState<Node[]>(initialValue)
const editor = useMemo(() => withEmbeds(withReact(createEditor())), []) const editor = useMemo(() => withEmbeds(withReact(createEditor())), [])
return ( return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}> <Slate editor={editor} value={value} onChange={value => setValue(value)}>

View File

@@ -34,7 +34,7 @@ const withLayout = editor => {
} }
const ForcedLayoutExample = () => { const ForcedLayoutExample = () => {
const [value, setValue] = useState(initialValue) const [value, setValue] = useState<Node[]>(initialValue)
const renderElement = useCallback(props => <Element {...props} />, []) const renderElement = useCallback(props => <Element {...props} />, [])
const editor = useMemo( const editor = useMemo(
() => withLayout(withHistory(withReact(createEditor()))), () => withLayout(withHistory(withReact(createEditor()))),

View File

@@ -1,6 +1,6 @@
import React, { useState, useMemo, useRef, useEffect } from 'react' import React, { useState, useMemo, useRef, useEffect } from 'react'
import { Slate, Editable, ReactEditor, withReact, useSlate } from 'slate-react' import { Slate, Editable, ReactEditor, withReact, useSlate } from 'slate-react'
import { Editor, Transforms, Text, createEditor } from 'slate' import { Editor, Transforms, Text, createEditor, Node } from 'slate'
import { css } from 'emotion' import { css } from 'emotion'
import { withHistory } from 'slate-history' import { withHistory } from 'slate-history'
@@ -8,7 +8,7 @@ import { Button, Icon, Menu, Portal } from '../components'
import { Range } from 'slate' import { Range } from 'slate'
const HoveringMenuExample = () => { const HoveringMenuExample = () => {
const [value, setValue] = useState(initialValue) const [value, setValue] = useState<Node[]>(initialValue)
const editor = useMemo(() => withHistory(withReact(createEditor())), []) const editor = useMemo(() => withHistory(withReact(createEditor())), [])
return ( return (
@@ -17,7 +17,7 @@ const HoveringMenuExample = () => {
<Editable <Editable
renderLeaf={props => <Leaf {...props} />} renderLeaf={props => <Leaf {...props} />}
placeholder="Enter some text..." placeholder="Enter some text..."
onDOMBeforeInput={event => { onDOMBeforeInput={(event: InputEvent) => {
event.preventDefault() event.preventDefault()
switch (event.inputType) { switch (event.inputType) {
case 'formatBold': case 'formatBold':
@@ -67,7 +67,7 @@ const Leaf = ({ attributes, children, leaf }) => {
} }
const HoveringToolbar = () => { const HoveringToolbar = () => {
const ref = useRef() const ref = useRef<HTMLDivElement | null>()
const editor = useSlate() const editor = useSlate()
useEffect(() => { useEffect(() => {
@@ -91,7 +91,7 @@ const HoveringToolbar = () => {
const domSelection = window.getSelection() const domSelection = window.getSelection()
const domRange = domSelection.getRangeAt(0) const domRange = domSelection.getRangeAt(0)
const rect = domRange.getBoundingClientRect() const rect = domRange.getBoundingClientRect()
el.style.opacity = 1 el.style.opacity = '1'
el.style.top = `${rect.top + window.pageYOffset - el.offsetHeight}px` el.style.top = `${rect.top + window.pageYOffset - el.offsetHeight}px`
el.style.left = `${rect.left + el.style.left = `${rect.left +
window.pageXOffset - window.pageXOffset -

View File

@@ -1,7 +1,7 @@
import React, { useState, useMemo } from 'react' import React, { useState, useMemo } from 'react'
import imageExtensions from 'image-extensions' import imageExtensions from 'image-extensions'
import isUrl from 'is-url' import isUrl from 'is-url'
import { Transforms, createEditor } from 'slate' import { Node, Transforms, createEditor } from 'slate'
import { import {
Slate, Slate,
Editable, Editable,
@@ -16,7 +16,7 @@ import { css } from 'emotion'
import { Button, Icon, Toolbar } from '../components' import { Button, Icon, Toolbar } from '../components'
const ImagesExample = () => { const ImagesExample = () => {
const [value, setValue] = useState(initialValue) const [value, setValue] = useState<Node[]>(initialValue)
const editor = useMemo( const editor = useMemo(
() => withImages(withHistory(withReact(createEditor()))), () => withImages(withHistory(withReact(createEditor()))),
[] []

View File

@@ -1,13 +1,13 @@
import React, { useState, useMemo } from 'react' import React, { useState, useMemo } from 'react'
import isUrl from 'is-url' import isUrl from 'is-url'
import { Slate, Editable, withReact, useSlate } from 'slate-react' import { Slate, Editable, withReact, useSlate } from 'slate-react'
import { Transforms, Editor, Range, createEditor } from 'slate' import { Node, Transforms, Editor, Range, createEditor } from 'slate'
import { withHistory } from 'slate-history' import { withHistory } from 'slate-history'
import { Button, Icon, Toolbar } from '../components' import { Button, Icon, Toolbar } from '../components'
const LinkExample = () => { const LinkExample = () => {
const [value, setValue] = useState(initialValue) const [value, setValue] = useState<Node[]>(initialValue)
const editor = useMemo( const editor = useMemo(
() => withLinks(withHistory(withReact(createEditor()))), () => withLinks(withHistory(withReact(createEditor()))),
[] []

View File

@@ -1,7 +1,7 @@
import Prism from 'prismjs' import Prism from 'prismjs'
import React, { useState, useCallback, useMemo } from 'react' import React, { useState, useCallback, useMemo } from 'react'
import { Slate, Editable, withReact } from 'slate-react' import { Slate, Editable, withReact } from 'slate-react'
import { Text, createEditor } from 'slate' import { Node, Text, createEditor } from 'slate'
import { withHistory } from 'slate-history' import { withHistory } from 'slate-history'
import { css } from 'emotion' import { css } from 'emotion'
@@ -9,7 +9,7 @@ import { css } from 'emotion'
;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 ;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 MarkdownPreviewExample = () => {
const [value, setValue] = useState(initialValue) const [value, setValue] = useState<Node[]>(initialValue)
const renderLeaf = useCallback(props => <Leaf {...props} />, []) const renderLeaf = useCallback(props => <Leaf {...props} />, [])
const editor = useMemo(() => withHistory(withReact(createEditor())), []) const editor = useMemo(() => withHistory(withReact(createEditor())), [])
const decorate = useCallback(([node, path]) => { const decorate = useCallback(([node, path]) => {

View File

@@ -1,6 +1,6 @@
import React, { useState, useCallback, useMemo } from 'react' import React, { useState, useCallback, useMemo } from 'react'
import { Slate, Editable, withReact } from 'slate-react' import { Slate, Editable, withReact } from 'slate-react'
import { Editor, Transforms, Range, Point, createEditor } from 'slate' import { Node, Editor, Transforms, Range, Point, createEditor } from 'slate'
import { withHistory } from 'slate-history' import { withHistory } from 'slate-history'
const SHORTCUTS = { const SHORTCUTS = {
@@ -17,7 +17,7 @@ const SHORTCUTS = {
} }
const MarkdownShortcutsExample = () => { const MarkdownShortcutsExample = () => {
const [value, setValue] = useState(initialValue) const [value, setValue] = useState<Node[]>(initialValue)
const renderElement = useCallback(props => <Element {...props} />, []) const renderElement = useCallback(props => <Element {...props} />, [])
const editor = useMemo( const editor = useMemo(
() => withShortcuts(withReact(withHistory(createEditor()))), () => withShortcuts(withReact(withHistory(createEditor()))),

View File

@@ -1,5 +1,5 @@
import React, { useMemo, useCallback, useRef, useEffect, useState } from 'react' import React, { useMemo, useCallback, useRef, useEffect, useState } from 'react'
import { Editor, Transforms, Range, createEditor } from 'slate' import { Node, Editor, Transforms, Range, createEditor } from 'slate'
import { withHistory } from 'slate-history' import { withHistory } from 'slate-history'
import { import {
Slate, Slate,
@@ -13,9 +13,9 @@ import {
import { Portal } from '../components' import { Portal } from '../components'
const MentionExample = () => { const MentionExample = () => {
const ref = useRef() const ref = useRef<HTMLDivElement | null>()
const [value, setValue] = useState(initialValue) const [value, setValue] = useState<Node[]>(initialValue)
const [target, setTarget] = useState() const [target, setTarget] = useState<Range | undefined>()
const [index, setIndex] = useState(0) const [index, setIndex] = useState(0)
const [search, setSearch] = useState('') const [search, setSearch] = useState('')
const renderElement = useCallback(props => <Element {...props} />, []) const renderElement = useCallback(props => <Element {...props} />, [])

View File

@@ -1,6 +1,6 @@
import React, { useState, useCallback, useMemo } from 'react' import React, { useState, useCallback, useMemo } from 'react'
import { jsx } from 'slate-hyperscript' import { jsx } from 'slate-hyperscript'
import { Transforms, createEditor } from 'slate' import { Node, Transforms, createEditor } from 'slate'
import { withHistory } from 'slate-history' import { withHistory } from 'slate-history'
import { css } from 'emotion' import { css } from 'emotion'
import { import {
@@ -80,7 +80,7 @@ export const deserialize = el => {
} }
const PasteHtmlExample = () => { const PasteHtmlExample = () => {
const [value, setValue] = useState(initialValue) const [value, setValue] = useState<Node[]>(initialValue)
const renderElement = useCallback(props => <Element {...props} />, []) const renderElement = useCallback(props => <Element {...props} />, [])
const renderLeaf = useCallback(props => <Leaf {...props} />, []) const renderLeaf = useCallback(props => <Leaf {...props} />, [])
const editor = useMemo( const editor = useMemo(

View File

@@ -1,10 +1,10 @@
import React, { useState, useMemo } from 'react' import React, { useState, useMemo } from 'react'
import { createEditor } from 'slate' import { Node, createEditor } from 'slate'
import { Slate, Editable, withReact } from 'slate-react' import { Slate, Editable, withReact } from 'slate-react'
import { withHistory } from 'slate-history' import { withHistory } from 'slate-history'
const PlainTextExample = () => { const PlainTextExample = () => {
const [value, setValue] = useState(initialValue) const [value, setValue] = useState<Node[]>(initialValue)
const editor = useMemo(() => withHistory(withReact(createEditor())), []) const editor = useMemo(() => withHistory(withReact(createEditor())), [])
return ( return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}> <Slate editor={editor} value={value} onChange={value => setValue(value)}>

View File

@@ -1,9 +1,9 @@
import React, { useState, useMemo } from 'react' import React, { useState, useMemo } from 'react'
import { createEditor } from 'slate' import { createEditor, Node } from 'slate'
import { Slate, Editable, withReact } from 'slate-react' import { Slate, Editable, withReact } from 'slate-react'
const ReadOnlyExample = () => { const ReadOnlyExample = () => {
const [value, setValue] = useState(initialValue) const [value, setValue] = useState<Node[]>(initialValue)
const editor = useMemo(() => withReact(createEditor()), []) const editor = useMemo(() => withReact(createEditor()), [])
return ( return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}> <Slate editor={editor} value={value} onChange={value => setValue(value)}>

View File

@@ -1,7 +1,7 @@
import React, { useCallback, useMemo, useState } from 'react' import React, { useCallback, useMemo, useState } from 'react'
import isHotkey from 'is-hotkey' import isHotkey from 'is-hotkey'
import { Editable, withReact, useSlate, Slate } from 'slate-react' import { Editable, withReact, useSlate, Slate } from 'slate-react'
import { Editor, Transforms, createEditor } from 'slate' import { Editor, Transforms, createEditor, Node } from 'slate'
import { withHistory } from 'slate-history' import { withHistory } from 'slate-history'
import { Button, Icon, Toolbar } from '../components' import { Button, Icon, Toolbar } from '../components'
@@ -16,7 +16,7 @@ const HOTKEYS = {
const LIST_TYPES = ['numbered-list', 'bulleted-list'] const LIST_TYPES = ['numbered-list', 'bulleted-list']
const RichTextExample = () => { const RichTextExample = () => {
const [value, setValue] = useState(initialValue) const [value, setValue] = useState<Node[]>(initialValue)
const renderElement = useCallback(props => <Element {...props} />, []) const renderElement = useCallback(props => <Element {...props} />, [])
const renderLeaf = useCallback(props => <Leaf {...props} />, []) const renderLeaf = useCallback(props => <Leaf {...props} />, [])
const editor = useMemo(() => withHistory(withReact(createEditor())), []) const editor = useMemo(() => withHistory(withReact(createEditor())), [])
@@ -42,7 +42,7 @@ const RichTextExample = () => {
autoFocus autoFocus
onKeyDown={event => { onKeyDown={event => {
for (const hotkey in HOTKEYS) { for (const hotkey in HOTKEYS) {
if (isHotkey(hotkey, event)) { if (isHotkey(hotkey, event as any)) {
event.preventDefault() event.preventDefault()
const mark = HOTKEYS[hotkey] const mark = HOTKEYS[hotkey]
toggleMark(editor, mark) toggleMark(editor, mark)
@@ -59,7 +59,7 @@ const toggleBlock = (editor, format) => {
const isList = LIST_TYPES.includes(format) const isList = LIST_TYPES.includes(format)
Transforms.unwrapNodes(editor, { Transforms.unwrapNodes(editor, {
match: n => LIST_TYPES.includes(n.type), match: n => LIST_TYPES.includes(n.type as string),
split: true, split: true,
}) })

View File

@@ -1,14 +1,14 @@
import React, { useState, useCallback, useMemo } from 'react' import React, { useState, useCallback, useMemo } from 'react'
import { Slate, Editable, withReact } from 'slate-react' import { Slate, Editable, withReact } from 'slate-react'
import { Text, createEditor } from 'slate' import { Text, Node, createEditor } from 'slate'
import { css } from 'emotion' import { css } from 'emotion'
import { withHistory } from 'slate-history' import { withHistory } from 'slate-history'
import { Icon, Toolbar } from '../components' import { Icon, Toolbar } from '../components'
const SearchHighlightingExample = () => { const SearchHighlightingExample = () => {
const [value, setValue] = useState(initialValue) const [value, setValue] = useState<Node[]>(initialValue)
const [search, setSearch] = useState() const [search, setSearch] = useState<string | undefined>()
const editor = useMemo(() => withHistory(withReact(createEditor())), []) const editor = useMemo(() => withHistory(withReact(createEditor())), [])
const decorate = useCallback( const decorate = useCallback(
([node, path]) => { ([node, path]) => {

View File

@@ -1,10 +1,10 @@
import React, { useState, useCallback, useMemo } from 'react' import React, { useState, useCallback, useMemo } from 'react'
import { Slate, Editable, withReact } from 'slate-react' import { Slate, Editable, withReact } from 'slate-react'
import { Editor, Range, Point, createEditor } from 'slate' import { Editor, Range, Point, Node, createEditor } from 'slate'
import { withHistory } from 'slate-history' import { withHistory } from 'slate-history'
const TablesExample = () => { const TablesExample = () => {
const [value, setValue] = useState(initialValue) const [value, setValue] = useState<Node[]>(initialValue)
const renderElement = useCallback(props => <Element {...props} />, []) const renderElement = useCallback(props => <Element {...props} />, [])
const renderLeaf = useCallback(props => <Leaf {...props} />, []) const renderLeaf = useCallback(props => <Leaf {...props} />, [])
const editor = useMemo( const editor = useMemo(

2
site/next-env.d.ts vendored Normal file
View File

@@ -0,0 +1,2 @@
/// <reference types="next" />
/// <reference types="next/types/global" />

View File

@@ -2,24 +2,6 @@ const fs = require('fs')
const path = require('path') const path = require('path')
module.exports = { module.exports = {
exportPathMap: async (defaultPathMap, config) => {
const { dir } = config
const examples = fs.readdirSync(path.resolve(dir, 'examples'))
const pages = {
'/': { page: '/' },
}
for (const file of examples) {
if (!file.endsWith('.js')) {
continue
}
const example = file.replace('.js', '')
pages[`/examples/${example}`] = { page: '/examples/[example]', example }
}
return pages
},
webpack: config => { webpack: config => {
config.module.rules.push({ config.module.rules.push({
test: /\.js$/, test: /\.js$/,

11
site/pages/api/index.ts Normal file
View File

@@ -0,0 +1,11 @@
import { readdirSync } from 'fs'
import { join } from 'path'
const examplePath = join(process.cwd(), 'examples')
export function getAllExamples() {
const slugs = readdirSync(examplePath)
return slugs
.filter(name => name.match(/.tsx$/))
.map(n => n.replace(/.tsx$/, ''))
}

View File

@@ -1,6 +1,5 @@
import React, { useState } from 'react' import React, { useState, PropsWithChildren, Ref } from 'react'
import { cx, css } from 'emotion' import { cx, css } from 'emotion'
import { useRouter } from 'next/router'
import Head from 'next/head' import Head from 'next/head'
import Link from 'next/link' import Link from 'next/link'
import dynamic from 'next/dynamic' import dynamic from 'next/dynamic'
@@ -27,6 +26,9 @@ import SearchHighlighting from '../../examples/search-highlighting'
import CodeHighlighting from '../../examples/code-highlighting' import CodeHighlighting from '../../examples/code-highlighting'
import Tables from '../../examples/tables' import Tables from '../../examples/tables'
// node
import { getAllExamples } from '../api'
const EXAMPLES = [ const EXAMPLES = [
['Checklists', CheckLists, 'check-lists'], ['Checklists', CheckLists, 'check-lists'],
['Editable Voids', EditableVoids, 'editable-voids'], ['Editable Voids', EditableVoids, 'editable-voids'],
@@ -149,26 +151,39 @@ const TabButton = props => (
/> />
) )
const Tab = React.forwardRef(({ active, href, ...props }, ref) => ( const Tab = React.forwardRef(
<a (
ref={ref} {
href={href} active,
{...props} href,
className={css` ...props
display: inline-block; }: PropsWithChildren<{
margin-bottom: 0.2em; active: boolean
padding: 0.2em 1em; href: string
border-radius: 0.2em; [key: string]: unknown
text-decoration: none; }>,
color: ${active ? 'white' : '#777'}; ref: Ref<HTMLAnchorElement | null>
background: ${active ? '#333' : 'transparent'}; ) => (
<a
ref={ref}
href={href}
{...props}
className={css`
display: inline-block;
margin-bottom: 0.2em;
padding: 0.2em 1em;
border-radius: 0.2em;
text-decoration: none;
color: ${active ? 'white' : '#777'};
background: ${active ? '#333' : 'transparent'};
&:hover { &:hover {
background: #333; background: #333;
} }
`} `}
/> />
)) )
)
const Wrapper = ({ className, ...props }) => ( const Wrapper = ({ className, ...props }) => (
<div <div
@@ -233,12 +248,10 @@ const Warning = props => (
/> />
) )
const ExamplePage = () => { const ExamplePage = ({ example }: { example: string }) => {
const [error, setError] = useState() const [error, setError] = useState<Error | undefined>()
const [stacktrace, setStacktrace] = useState() const [stacktrace, setStacktrace] = useState<string | undefined>()
const [showTabs, setShowTabs] = useState() const [showTabs, setShowTabs] = useState<boolean>()
const router = useRouter()
const { example = router.asPath.replace('/examples/', '') } = router.query
const EXAMPLE = EXAMPLES.find(e => e[2] === example) const EXAMPLE = EXAMPLES.find(e => e[2] === example)
const [name, Component, path] = EXAMPLE const [name, Component, path] = EXAMPLE
return ( return (
@@ -291,7 +304,7 @@ const ExamplePage = () => {
<TabList isVisible={showTabs}> <TabList isVisible={showTabs}>
{EXAMPLES.map(([n, , p]) => ( {EXAMPLES.map(([n, , p]) => (
<Link <Link
key={p} key={p as string}
href="/examples/[example]" href="/examples/[example]"
as={`/examples/${p}`} as={`/examples/${p}`}
passHref passHref
@@ -331,8 +344,29 @@ const NoSsrExamplePage = dynamic(() => Promise.resolve(ExamplePage), {
ssr: false, ssr: false,
}) })
NoSsrExamplePage.getInitialProps = () => { export async function getStaticPaths() {
return {} const paths = getAllExamples()
return {
paths: paths.map(path => ({
params: {
example: path,
},
})),
fallback: false,
}
}
export async function getStaticProps({
params,
}: {
params: { example: string }
}) {
return {
props: {
example: params.example,
},
}
} }
export default NoSsrExamplePage export default NoSsrExamplePage

30
site/tsconfig.json Normal file
View File

@@ -0,0 +1,30 @@
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"downlevelIteration": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
},
"exclude": [
"node_modules"
],
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
]
}

2050
yarn.lock

File diff suppressed because it is too large Load Diff