mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-09-08 22:20:41 +02:00
Next (#3093)
* remove some key usage from core, refactor Operations.apply * undeprecate some methods * convert more key usage to paths * update deprecations * convert selection commands to use all paths * refactor word boundary selection logic * convert many at-range commands to use paths * convert wrapBlock and wrapInline to not use keys * cleanup * remove chainability from editor * simplify commands, queries and middleware * convert deleteAtRange * remove key usage from schema, deprecate *ByKey methods * migrate *ByKey tests, remove index from *ByPath signatures * rename at-current-range tests * deprecate mode key usage, migrate more tests away from keys * deprecate range and point methods which rely on keys to work * refactor insertBlock, without fixing warnings * add pathRef/pointRef, fix insertBlock/Inline deprecations, work on insertFragment * refactor insertFragment * get rich-text example rendering * fix lint * refactor query files, fix more tests * remove unused queries, refactor others * deprecate splitDescendantsByPath * merge master * add typescript, convert slate, slate-hyperscript, slate-plain-serializer * add Point, Path, Range, Annotation tests * add Annotation, Change, Element, Fragment, Mark, Range, Selection, Value interfaces tests * add Operation and Text tests * add Node tests * get operations and normalization tests working for slate * get *AtPath command tests passing * rename *AtPath command tests * rename * get *AtPoint tests working * rename * rename * add value queries tests * add element, mark and path queries tests * convert most on-selection tests * convert on-selection commands * rename * get addMarks and delete commands working * rename * rename * rename * refactor value.positions(), work on delete tests * progress on delete tests * more delete work * finish delete tests * start converting to at-based commands * restructure query tests * restructure operations tests * more work converting to multi-purpose commands * lots of progress on converting to at-based commands * add unwrapNodes * remove setValue * more progress * refactor node commands to use consistent matching logic * cleanup, get non-fragment commands passing * remove annotations and isAtomic * rename surround/pluck to cover/uncover * add location concept, change at-path to from-path for iterables * refactor batches * add location-based queries * refactor hanging logic * more location query work * renaming * use getMatch more * add split to wrap/unwrap * flip levels/ancestors ordering * switch splitNodes to use levels * change split to always:false by default * fix tests * add more queries tests * fixing more delete logic * add more splitNodes tests * get rest of delete tests passing * fix location-based logic in some commands * cleanup * get previous packages tests passing again * add slate-history package * start slate-schema work * start of react working * rendering fixes * get rich and plain text examples working * get image example working with hooks and dropping * refactor onDrop to be internal * inline more event handlers * refactor lots of event-related logic * change rendering to use render props * delete unused stuff * cleanup dom utils * remove unused deps * remove unnecessary packages, add placeholder * remove slate-react-placeholder package * remove unused dep * remove unnecessary tests, fix readonly example * convert checklists example * switch to next from webpack * get link example working * convert more examples * preserve keys, memoized leafs/texts, fix node lookup * fix to always useLayoutEffect for ordering * fix annotations to be maps, memoize elements * remove Change interface * remove String interface * rename Node.entries to Node.nodes * remove unnecessary value queries * default to selection when iterating, cleanup * remove unused files * update scroll into view logic * fix undoing, remove constructor types * dont sync selection while composing * add workflows * remove unused deps * convert mentions example * tweaks * convert remaining examples * rename h to jsx, update schema * fix schema tests * fix slate-schema logic and tests * really fix slate-schema and forced-layout example * get start of insertFragment tests working * remove Fragment interface * remove debugger * get all non-skipped tests passing * cleanup deps * run prettier * configure eslint for typescript * more eslint fixes... * more passing * update some docs * fix examples * port windows undo hotkey change * fix deps, add basic firefox support * add event overriding, update walkthroughs * add commands, remove classes, cleanup examples * cleanup rollup config * update tests * rename queries tests * update other tests * update walkthroughs * cleanup interface exports * cleanup, change mark transforms to require location * undo mark transform change * more * fix tests * fix example * update walkthroughs * update docs * update docs * remove annotations * remove value, move selection and children to editor * add migrating doc * fix lint * fix tests * fix DOM types aliasing * add next export * update deps, fix prod build * fix prod build * update scripts * update docs and changelogs * update workflow and pull request template
This commit is contained in:
334
site/pages/examples/[example].js
Normal file
334
site/pages/examples/[example].js
Normal file
@@ -0,0 +1,334 @@
|
||||
import React, { useState } from 'react'
|
||||
import { cx, css } from 'emotion'
|
||||
import { useRouter } from 'next/router'
|
||||
import Head from 'next/head'
|
||||
import Link from 'next/link'
|
||||
import dynamic from 'next/dynamic'
|
||||
import ErrorBoundary from 'react-error-boundary'
|
||||
|
||||
import { Icon } from '../../components'
|
||||
|
||||
import CheckLists from '../../examples/check-lists'
|
||||
import Embeds from '../../examples/embeds'
|
||||
import ForcedLayout from '../../examples/forced-layout'
|
||||
import HoveringToolbar from '../../examples/hovering-toolbar'
|
||||
import HugeDocument from '../../examples/huge-document'
|
||||
import Images from '../../examples/images'
|
||||
import Links from '../../examples/links'
|
||||
import MarkdownPreview from '../../examples/markdown-preview'
|
||||
import MarkdownShortcuts from '../../examples/markdown-shortcuts'
|
||||
import Mentions from '../../examples/mentions'
|
||||
import PasteHtml from '../../examples/paste-html'
|
||||
import PlainText from '../../examples/plain-text'
|
||||
import ReadOnly from '../../examples/read-only'
|
||||
import RichText from '../../examples/rich-text'
|
||||
import SearchHighlighting from '../../examples/search-highlighting'
|
||||
import Tables from '../../examples/tables'
|
||||
|
||||
const EXAMPLES = [
|
||||
['Checklists', CheckLists, 'check-lists'],
|
||||
['Embeds', Embeds, 'embeds'],
|
||||
['Forced Layout', ForcedLayout, 'forced-layout'],
|
||||
['Hovering Toolbar', HoveringToolbar, 'hovering-toolbar'],
|
||||
['Huge Document', HugeDocument, 'huge-document'],
|
||||
['Images', Images, 'images'],
|
||||
['Links', Links, 'links'],
|
||||
['Markdown Preview', MarkdownPreview, 'markdown-preview'],
|
||||
['Markdown Shortcuts', MarkdownShortcuts, 'markdown-shortcuts'],
|
||||
['Mentions', Mentions, 'mentions'],
|
||||
['Paste HTML', PasteHtml, 'paste-html'],
|
||||
['Plain Text', PlainText, 'plain-text'],
|
||||
['Read-only', ReadOnly, 'read-only'],
|
||||
['Rich Text', RichText, 'rich-text'],
|
||||
['Search Highlighting', SearchHighlighting, 'search-highlighting'],
|
||||
['Tables', Tables, 'tables'],
|
||||
]
|
||||
|
||||
const Header = props => (
|
||||
<div
|
||||
{...props}
|
||||
className={css`
|
||||
align-items: center;
|
||||
background: #000;
|
||||
color: #aaa;
|
||||
display: flex;
|
||||
height: 42px;
|
||||
position: relative;
|
||||
z-index: 1; /* To appear above the underlay */
|
||||
`}
|
||||
/>
|
||||
)
|
||||
|
||||
const Title = props => (
|
||||
<span
|
||||
{...props}
|
||||
className={css`
|
||||
margin-left: 1em;
|
||||
`}
|
||||
/>
|
||||
)
|
||||
|
||||
const LinkList = props => (
|
||||
<div
|
||||
{...props}
|
||||
className={css`
|
||||
margin-left: auto;
|
||||
margin-right: 1em;
|
||||
`}
|
||||
/>
|
||||
)
|
||||
|
||||
const A = props => (
|
||||
<a
|
||||
{...props}
|
||||
className={css`
|
||||
margin-left: 1em;
|
||||
color: #aaa;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
`}
|
||||
/>
|
||||
)
|
||||
|
||||
const TabList = ({ isVisible, ...props }) => (
|
||||
<div
|
||||
{...props}
|
||||
className={css`
|
||||
background-color: #222;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
padding-top: 0.2em;
|
||||
position: absolute;
|
||||
transition: width 0.2s;
|
||||
width: ${isVisible ? '200px' : '0'};
|
||||
white-space: nowrap;
|
||||
max-height: 70vh;
|
||||
z-index: 1; /* To appear above the underlay */
|
||||
`}
|
||||
/>
|
||||
)
|
||||
|
||||
const TabListUnderlay = ({ isVisible, ...props }) => (
|
||||
<div
|
||||
{...props}
|
||||
className={css`
|
||||
background-color: rgba(200, 200, 200, 0.8);
|
||||
display: ${isVisible ? 'block' : 'none'};
|
||||
height: 100%;
|
||||
top: 0;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
`}
|
||||
/>
|
||||
)
|
||||
|
||||
const TabButton = props => (
|
||||
<span
|
||||
{...props}
|
||||
className={css`
|
||||
margin-left: 0.8em;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
color: #aaa;
|
||||
font-size: 24px;
|
||||
}
|
||||
`}
|
||||
/>
|
||||
)
|
||||
|
||||
const Tab = React.forwardRef(({ active, href, ...props }, ref) => (
|
||||
<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 {
|
||||
background: #333;
|
||||
}
|
||||
`}
|
||||
/>
|
||||
))
|
||||
|
||||
const Wrapper = ({ className, ...props }) => (
|
||||
<div
|
||||
{...props}
|
||||
className={cx(
|
||||
className,
|
||||
css`
|
||||
max-width: 42em;
|
||||
margin: 20px auto;
|
||||
padding: 20px;
|
||||
`
|
||||
)}
|
||||
/>
|
||||
)
|
||||
|
||||
const ExampleHeader = props => (
|
||||
<div
|
||||
{...props}
|
||||
className={css`
|
||||
align-items: center;
|
||||
background-color: #555;
|
||||
color: #ddd;
|
||||
display: flex;
|
||||
height: 42px;
|
||||
position: relative;
|
||||
z-index: 1; /* To appear above the underlay */
|
||||
`}
|
||||
/>
|
||||
)
|
||||
|
||||
const ExampleTitle = props => (
|
||||
<span
|
||||
{...props}
|
||||
className={css`
|
||||
margin-left: 1em;
|
||||
`}
|
||||
/>
|
||||
)
|
||||
|
||||
const ExampleContent = props => (
|
||||
<Wrapper
|
||||
{...props}
|
||||
className={css`
|
||||
background: #fff;
|
||||
`}
|
||||
/>
|
||||
)
|
||||
|
||||
const Warning = props => (
|
||||
<Wrapper
|
||||
{...props}
|
||||
className={css`
|
||||
background: #fffae0;
|
||||
|
||||
& > pre {
|
||||
background: #fbf1bd;
|
||||
white-space: pre;
|
||||
overflow-x: scroll;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
`}
|
||||
/>
|
||||
)
|
||||
|
||||
const ExamplePage = () => {
|
||||
const [error, setError] = useState()
|
||||
const [stacktrace, setStacktrace] = useState()
|
||||
const [showTabs, setShowTabs] = useState()
|
||||
const router = useRouter()
|
||||
const { example = 'rich-text' } = router.query
|
||||
const EXAMPLE = EXAMPLES.find(e => e[2] === example)
|
||||
const [name, Component, path] = EXAMPLE
|
||||
return (
|
||||
<ErrorBoundary
|
||||
onError={(error, stacktrace) => {
|
||||
setError(error)
|
||||
setStacktrace(stacktrace)
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<Head>
|
||||
<title>Slate Examples</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link rel="stylesheet" href="/index.css" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://fonts.googleapis.com/css?family=Roboto:400,400i,700,700i&subset=latin-ext"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://fonts.googleapis.com/icon?family=Material+Icons"
|
||||
/>
|
||||
</Head>
|
||||
<Header>
|
||||
<Title>Slate Examples</Title>
|
||||
<LinkList>
|
||||
<A href="https://github.com/ianstormtaylor/slate">GitHub</A>
|
||||
<A href="https://docs.slatejs.org/">Docs</A>
|
||||
</LinkList>
|
||||
</Header>
|
||||
<ExampleHeader>
|
||||
<TabButton
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
setShowTabs(!showTabs)
|
||||
}}
|
||||
>
|
||||
<Icon>menu</Icon>
|
||||
</TabButton>
|
||||
<ExampleTitle>
|
||||
{name}
|
||||
<A
|
||||
href={`https://github.com/ianstormtaylor/slate/blob/master/examples${path}`}
|
||||
>
|
||||
(View Source)
|
||||
</A>
|
||||
</ExampleTitle>
|
||||
</ExampleHeader>
|
||||
<TabList isVisible={showTabs}>
|
||||
{EXAMPLES.map(([n, , p]) => (
|
||||
<Link
|
||||
key={p}
|
||||
href="/examples/[example]"
|
||||
as={`/examples/${p}`}
|
||||
passHref
|
||||
>
|
||||
<Tab onClick={() => setShowTabs(false)}>{n}</Tab>
|
||||
</Link>
|
||||
))}
|
||||
</TabList>
|
||||
{error ? (
|
||||
<Warning>
|
||||
<p>An error was thrown by one of the example's React components!</p>
|
||||
<pre>
|
||||
<code>
|
||||
{error.stack}
|
||||
{'\n'}
|
||||
{stacktrace}
|
||||
</code>
|
||||
</pre>
|
||||
</Warning>
|
||||
) : (
|
||||
<ExampleContent>
|
||||
<Component />
|
||||
</ExampleContent>
|
||||
)}
|
||||
<TabListUnderlay
|
||||
isVisible={showTabs}
|
||||
onClick={() => setShowTabs(false)}
|
||||
/>
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
)
|
||||
}
|
||||
|
||||
// Disable SSR because it results in a double rendering which makes debugging
|
||||
// examples more challenging. No idea how any of this works.
|
||||
const NoSsrExamplePage = dynamic(() => Promise.resolve(ExamplePage), {
|
||||
ssr: false,
|
||||
})
|
||||
|
||||
NoSsrExamplePage.getInitialProps = () => {
|
||||
return {}
|
||||
}
|
||||
|
||||
export default NoSsrExamplePage
|
14
site/pages/examples/index.js
Normal file
14
site/pages/examples/index.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import { useEffect } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
const Example = () => {
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
router.replace(`/examples/rich-text`)
|
||||
})
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export default Example
|
Reference in New Issue
Block a user