Skip to content

Commit

Permalink
Add Javascript Examples Support (#5722)
Browse files Browse the repository at this point in the history
* chore: moved all ts files for examples to examples/ts

* add: tsc to eject js and jsx output

* example: add js transpiled examples

* example: update example site to show both js and ts code

* chore: fix yarn lint

* fix(example): getAllExamplesPath
  • Loading branch information
RavenColEvol authored Sep 26, 2024
1 parent ee2c454 commit 01dc30b
Show file tree
Hide file tree
Showing 58 changed files with 4,262 additions and 47 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"test:integration-local": "run-p -r serve playwright",
"test:mocha": "mocha --require ./config/babel/register.cjs ./packages/{slate,slate-history,slate-hyperscript}/test/**/*.{js,ts}",
"test:jest": "jest --config jest.config.js",
"tsc:examples": "tsc --project ./site/tsconfig.example.json",
"watch": "yarn build:rollup --watch",
"playwright": "playwright test"
},
Expand Down
20 changes: 10 additions & 10 deletions site/examples/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

This directory contains a set of examples that give you an idea for how you might use Slate to implement your own editor. Take a look around!

- [**Plain text**](./plaintext.tsx) — showing the most basic case: a glorified `<textarea>`.
- [**Rich text**](./richtext.tsx) — showing the features you'd expect from a basic editor.
- [**Forced Layout**](./forced-layout.tsx) - showing how to use constraints to enforce a document structure.
- [**Markdown Shortcuts**](./markdown-shortcuts.tsx) — showing how to add key handlers for Markdown-like shortcuts.
- [**Inlines**](./inlines.tsx) — showing how wrap text in inline nodes with associated data.
- [**Images**](./images.tsx) — showing how to use void (text-less) nodes to add images.
- [**Hovering toolbar**](./hovering-toolbar.tsx) — showing how a hovering toolbar can be implemented.
- [**Tables**](./tables.tsx) — showing how to nest blocks to render more advanced components.
- [**Paste HTML**](./paste-html.tsx) — showing how to use an HTML serializer to handle pasted HTML.
- [**Code Highlighting**](./code-highlighting.tsx) — showing how to use decorations to dynamically format text.
- [**Plain text**](./ts/plaintext.tsx) — showing the most basic case: a glorified `<textarea>`.
- [**Rich text**](./ts/richtext.tsx) — showing the features you'd expect from a basic editor.
- [**Forced Layout**](./ts/forced-layout.tsx) - showing how to use constraints to enforce a document structure.
- [**Markdown Shortcuts**](./ts/markdown-shortcuts.tsx) — showing how to add key handlers for Markdown-like shortcuts.
- [**Inlines**](./ts/inlines.tsx) — showing how wrap text in inline nodes with associated data.
- [**Images**](./ts/images.tsx) — showing how to use void (text-less) nodes to add images.
- [**Hovering toolbar**](./ts/hovering-toolbar.tsx) — showing how a hovering toolbar can be implemented.
- [**Tables**](./ts/tables.tsx) — showing how to nest blocks to render more advanced components.
- [**Paste HTML**](./ts/paste-html.tsx) — showing how to use an HTML serializer to handle pasted HTML.
- [**Code Highlighting**](./ts/code-highlighting.tsx) — showing how to use decorations to dynamically format text.
- ...and more!

If you have an idea for an example that shows a common use case, pull request it!
Expand Down
176 changes: 176 additions & 0 deletions site/examples/js/check-lists.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
import React, { useMemo, useCallback } from 'react'
import {
Slate,
Editable,
withReact,
useSlateStatic,
useReadOnly,
ReactEditor,
} from 'slate-react'
import {
Editor,
Transforms,
Range,
Point,
createEditor,
Element as SlateElement,
} from 'slate'
import { css } from '@emotion/css'
import { withHistory } from 'slate-history'

const initialValue = [
{
type: 'paragraph',
children: [
{
text: 'With Slate you can build complex block types that have their own embedded content and behaviors, like rendering checkboxes inside check list items!',
},
],
},
{
type: 'check-list-item',
checked: true,
children: [{ text: 'Slide to the left.' }],
},
{
type: 'check-list-item',
checked: true,
children: [{ text: 'Slide to the right.' }],
},
{
type: 'check-list-item',
checked: false,
children: [{ text: 'Criss-cross.' }],
},
{
type: 'check-list-item',
checked: true,
children: [{ text: 'Criss-cross!' }],
},
{
type: 'check-list-item',
checked: false,
children: [{ text: 'Cha cha real smooth…' }],
},
{
type: 'check-list-item',
checked: false,
children: [{ text: "Let's go to work!" }],
},
{
type: 'paragraph',
children: [{ text: 'Try it out for yourself!' }],
},
]
const CheckListsExample = () => {
const renderElement = useCallback(props => <Element {...props} />, [])
const editor = useMemo(
() => withChecklists(withHistory(withReact(createEditor()))),
[]
)
return (
<Slate editor={editor} initialValue={initialValue}>
<Editable
renderElement={renderElement}
placeholder="Get to work…"
spellCheck
autoFocus
/>
</Slate>
)
}
const withChecklists = editor => {
const { deleteBackward } = editor
editor.deleteBackward = (...args) => {
const { selection } = editor
if (selection && Range.isCollapsed(selection)) {
const [match] = Editor.nodes(editor, {
match: n =>
!Editor.isEditor(n) &&
SlateElement.isElement(n) &&
n.type === 'check-list-item',
})
if (match) {
const [, path] = match
const start = Editor.start(editor, path)
if (Point.equals(selection.anchor, start)) {
const newProperties = {
type: 'paragraph',
}
Transforms.setNodes(editor, newProperties, {
match: n =>
!Editor.isEditor(n) &&
SlateElement.isElement(n) &&
n.type === 'check-list-item',
})
return
}
}
}
deleteBackward(...args)
}
return editor
}
const Element = props => {
const { attributes, children, element } = props
switch (element.type) {
case 'check-list-item':
return <CheckListItemElement {...props} />
default:
return <p {...attributes}>{children}</p>
}
}
const CheckListItemElement = ({ attributes, children, element }) => {
const editor = useSlateStatic()
const readOnly = useReadOnly()
const { checked } = element
return (
<div
{...attributes}
className={css`
display: flex;
flex-direction: row;
align-items: center;
& + & {
margin-top: 0;
}
`}
>
<span
contentEditable={false}
className={css`
margin-right: 0.75em;
`}
>
<input
type="checkbox"
checked={checked}
onChange={event => {
const path = ReactEditor.findPath(editor, element)
const newProperties = {
checked: event.target.checked,
}
Transforms.setNodes(editor, newProperties, { at: path })
}}
/>
</span>
<span
contentEditable={!readOnly}
suppressContentEditableWarning
className={css`
flex: 1;
opacity: ${checked ? 0.666 : 1};
text-decoration: ${!checked ? 'none' : 'line-through'};
&:focus {
outline: none;
}
`}
>
{children}
</span>
</div>
)
}
export default CheckListsExample
Loading

0 comments on commit 01dc30b

Please sign in to comment.