1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-02-23 00:32:31 +01:00
slate/site/examples/embeds.tsx
Sunny Hirai 08275f68f3
Custom TypeScript Types (#3835)
This PR adds better TypeScript types into Slate and is based on the proposal here: https://github.com/ianstormtaylor/slate/issues/3725

* Extend Slate's types like Element and Text

* Supports type discrimination (ie. if an element has type === "table" then we get a reduced set of properties)

* added custom types

* files

* more extensions

* files

* changed fixtures

* changes eslint file

* changed element.children to descendant

* updated types

* more type changes

* changed a lot of typing, still getting building errors

* extended text type in slate-react

* removed type assertions

* Clean up of custom types and a couple uneeded comments.

* Rename headingElement-true.tsx.tsx to headingElement-true.tsx

* moved basetext and baselement

* Update packages/slate/src/interfaces/text.ts

Co-authored-by: Brent Farese <25846953+BrentFarese@users.noreply.github.com>

* Fix some type issues with core functions.

* Clean up text and element files.

* Convert other types to extended types.

* Change the type of editor.marks to the appropriate type.

* Add version 100.0.0 to package.json

* Revert "Add version 100.0.0 to package.json"

This reverts commit 329e44e43d968700655b1c46f968bfd3147e7339.

* added custom types

* files

* more extensions

* files

* changed fixtures

* changes eslint file

* changed element.children to descendant

* updated types

* more type changes

* changed a lot of typing, still getting building errors

* extended text type in slate-react

* removed type assertions

* Clean up of custom types and a couple uneeded comments.

* Rename headingElement-true.tsx.tsx to headingElement-true.tsx

* moved basetext and baselement

* Update packages/slate/src/interfaces/text.ts

Co-authored-by: Brent Farese <25846953+BrentFarese@users.noreply.github.com>

* Fix some type issues with core functions.

* Clean up text and element files.

* Convert other types to extended types.

* Change the type of editor.marks to the appropriate type.

* Run linter.

* Remove key:string uknown from the base types.

* Clean up types after removing key:string unknown.

* Lint and prettier fixes.

* Implement custom-types

Co-authored-by: mdmjg <mdj308@nyu.edu>

* added custom types to examples

* reset yarn lock

* added ts to fixtures

* examples custom types

* Working fix

* ts-thesunny-try

* Extract interface types.

* Fix minor return type in create-editor.

* Fix the typing issue with Location having compile time CustomTypes

* Extract types for Transforms.

* Update README.

* Fix dependency on slate-history in slate-react

Co-authored-by: mdmjg <mdj308@nyu.edu>
Co-authored-by: Brent Farese <brentfarese@gmail.com>
Co-authored-by: Brent Farese <25846953+BrentFarese@users.noreply.github.com>
Co-authored-by: Tim Buckley <timothypbuckley@gmail.com>
2020-11-24 12:30:06 -08:00

126 lines
2.9 KiB
TypeScript

import React, { useState, useMemo } from 'react'
import { Transforms, createEditor, Node, Element as SlateElement } from 'slate'
import {
Slate,
Editable,
withReact,
useSlateStatic,
ReactEditor,
useFocused,
useSelected,
} from 'slate-react'
const EmbedsExample = () => {
const [value, setValue] = useState<Node[]>(initialValue)
const editor = useMemo(() => withEmbeds(withReact(createEditor())), [])
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Editable
renderElement={props => <Element {...props} />}
placeholder="Enter some text..."
/>
</Slate>
)
}
const withEmbeds = editor => {
const { isVoid } = editor
editor.isVoid = element => (element.type === 'video' ? true : isVoid(element))
return editor
}
const Element = props => {
const { attributes, children, element } = props
switch (element.type) {
case 'video':
return <VideoElement {...props} />
default:
return <p {...attributes}>{children}</p>
}
}
const VideoElement = ({ attributes, children, element }) => {
const editor = useSlateStatic()
const { url } = element
return (
<div {...attributes}>
<div contentEditable={false}>
<div
style={{
padding: '75% 0 0 0',
position: 'relative',
}}
>
<iframe
src={`${url}?title=0&byline=0&portrait=0`}
frameBorder="0"
style={{
position: 'absolute',
top: '0',
left: '0',
width: '100%',
height: '100%',
}}
/>
</div>
<UrlInput
url={url}
onChange={val => {
const path = ReactEditor.findPath(editor, element)
const newProperties: Partial<SlateElement> = {
url: val,
}
Transforms.setNodes(editor, newProperties, { at: path })
}}
/>
</div>
{children}
</div>
)
}
const UrlInput = ({ url, onChange }) => {
const [value, setValue] = React.useState(url)
return (
<input
value={value}
onClick={e => e.stopPropagation()}
style={{
marginTop: '5px',
boxSizing: 'border-box',
}}
onChange={e => {
const newUrl = e.target.value
setValue(newUrl)
onChange(newUrl)
}}
/>
)
}
const initialValue = [
{
children: [
{
text:
'In addition to simple image nodes, you can actually create complex embedded nodes. For example, this one contains an input element that lets you change the video being rendered!',
},
],
},
{
type: 'video',
url: 'https://player.vimeo.com/video/26689853',
children: [{ text: '' }],
},
{
children: [
{
text:
'Try it out! This editor is built to handle Vimeo embeds, but you could handle any type.',
},
],
},
]
export default EmbedsExample