diff --git a/docs/src/demos/Examples/Default/React/index.jsx b/docs/src/demos/Examples/Default/React/index.jsx index 085713b2..3f8d89df 100644 --- a/docs/src/demos/Examples/Default/React/index.jsx +++ b/docs/src/demos/Examples/Default/React/index.jsx @@ -1,12 +1,7 @@ import React from 'react' -import tippy from 'tippy.js' -import { useEditor, EditorContent, ReactRenderer, ReactNodeViewRenderer, NodeViewWrapper, NodeViewContent } from '@tiptap/react' +import { useEditor, EditorContent } from '@tiptap/react' import { defaultExtensions } from '@tiptap/starter-kit' -import Heading from '@tiptap/extension-heading' -import Paragraph from '@tiptap/extension-paragraph' -import Mention from '@tiptap/extension-mention' import './styles.scss' -import { render } from 'react-dom' const MenuBar = ({ editor }) => { if (!editor) { @@ -127,162 +122,45 @@ const MenuBar = ({ editor }) => { ) } -const MentionList = (props) => { - console.log({props}) - - return ( -
- mentions - {props.items.map((item) => ( -
- {item} -
- ))} -
- ) -} - -class MentionList2 extends React.Component { - - onKeyDown(props) { - console.log('onKeyDown', props) - } - - render() { - return ( -
- mentions - {this.props.items.map((item, index) => ( -
- {item} -
- ))} -
- ) - } -} - export default () => { const editor = useEditor({ - // onTransaction({ editor }) { - // console.log('anchor', editor.state.selection.anchor) - // }, extensions: [ - ...defaultExtensions().filter(item => item.config.name !== 'heading'), - Heading.extend({ - draggable: true, - addNodeView() { - return ReactNodeViewRenderer((props) => { - return ( - -
- - level: {props.node.attrs.level} - - -
-
- ) - }) - } - }), - Mention.configure({ - suggestion: { - items: query => { - return [ - 'Lea Thompson', 'Cyndi Lauper', 'Tom Cruise', 'Madonna', 'Jerry Hall', 'Joan Collins', 'Winona Ryder', 'Christina Applegate', 'Alyssa Milano', 'Molly Ringwald', 'Ally Sheedy', 'Debbie Harry', 'Olivia Newton-John', 'Elton John', 'Michael J. Fox', 'Axl Rose', 'Emilio Estevez', 'Ralph Macchio', 'Rob Lowe', 'Jennifer Grey', 'Mickey Rourke', 'John Cusack', 'Matthew Broderick', 'Justine Bateman', 'Lisa Bonet', - ].filter(item => item.toLowerCase().startsWith(query.toLowerCase())).slice(0, 10) - }, - render: () => { - let reactRenderer - let popup - - return { - onStart: props => { - reactRenderer = new ReactRenderer(MentionList2, { - props, - editor: props.editor, - }) - - popup = tippy('body', { - getReferenceClientRect: props.clientRect, - appendTo: () => document.body, - content: reactRenderer.element, - showOnCreate: true, - interactive: true, - trigger: 'manual', - placement: 'bottom-start', - }) - }, - onUpdate(props) { - reactRenderer.updateProps(props) - - popup[0].setProps({ - getReferenceClientRect: props.clientRect, - }) - }, - onKeyDown(props) { - return reactRenderer.ref.onKeyDown(props) - }, - onExit() { - popup[0].destroy() - reactRenderer.destroy() - }, - } - } - }, - }) + ...defaultExtensions(), ], content: ` -

heading

-

heading

-

paragraph

+

+ Hi there, +

+

+ this is a basic basic example of tiptap. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists: +

+ +

+ Isn’t that great? And all of that is editable. But wait, there’s more. Let’s try a code block: +

+
body {
+  display: none;
+}
+

+ I know, I know, this is impressive. It’s only the tip of the iceberg though. Give it a try and click a little bit around. Don’t forget to check the other examples too. +

+
+ Wow, that’s amazing. Good work, boy! 👏 +
+ — Mom +
`, -// content: ` -//

-// Hi there, -//

-//

-// this is a basic basic example of tiptap. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists: -//

-// -//

-// Isn’t that great? And all of that is editable. But wait, there’s more. Let’s try a code block: -//

-//
body {
-//   display: none;
-// }
-//

-// I know, I know, this is impressive. It’s only the tip of the iceberg though. Give it a try and click a little bit around. Don’t forget to check the other examples too. -//

-//
-// Wow, that’s amazing. Good work, boy! 👏 -//
-// — Mom -//
-// `, }) return (
-
- - -
diff --git a/docs/src/demos/ReactPlayground/index.jsx b/docs/src/demos/ReactPlayground/index.jsx new file mode 100644 index 00000000..085713b2 --- /dev/null +++ b/docs/src/demos/ReactPlayground/index.jsx @@ -0,0 +1,290 @@ +import React from 'react' +import tippy from 'tippy.js' +import { useEditor, EditorContent, ReactRenderer, ReactNodeViewRenderer, NodeViewWrapper, NodeViewContent } from '@tiptap/react' +import { defaultExtensions } from '@tiptap/starter-kit' +import Heading from '@tiptap/extension-heading' +import Paragraph from '@tiptap/extension-paragraph' +import Mention from '@tiptap/extension-mention' +import './styles.scss' +import { render } from 'react-dom' + +const MenuBar = ({ editor }) => { + if (!editor) { + return null + } + + return ( + <> + + + + + + + + + + + + + + + + + + + + + + + ) +} + +const MentionList = (props) => { + console.log({props}) + + return ( +
+ mentions + {props.items.map((item) => ( +
+ {item} +
+ ))} +
+ ) +} + +class MentionList2 extends React.Component { + + onKeyDown(props) { + console.log('onKeyDown', props) + } + + render() { + return ( +
+ mentions + {this.props.items.map((item, index) => ( +
+ {item} +
+ ))} +
+ ) + } +} + +export default () => { + const editor = useEditor({ + // onTransaction({ editor }) { + // console.log('anchor', editor.state.selection.anchor) + // }, + extensions: [ + ...defaultExtensions().filter(item => item.config.name !== 'heading'), + Heading.extend({ + draggable: true, + addNodeView() { + return ReactNodeViewRenderer((props) => { + return ( + +
+ + level: {props.node.attrs.level} + + +
+
+ ) + }) + } + }), + Mention.configure({ + suggestion: { + items: query => { + return [ + 'Lea Thompson', 'Cyndi Lauper', 'Tom Cruise', 'Madonna', 'Jerry Hall', 'Joan Collins', 'Winona Ryder', 'Christina Applegate', 'Alyssa Milano', 'Molly Ringwald', 'Ally Sheedy', 'Debbie Harry', 'Olivia Newton-John', 'Elton John', 'Michael J. Fox', 'Axl Rose', 'Emilio Estevez', 'Ralph Macchio', 'Rob Lowe', 'Jennifer Grey', 'Mickey Rourke', 'John Cusack', 'Matthew Broderick', 'Justine Bateman', 'Lisa Bonet', + ].filter(item => item.toLowerCase().startsWith(query.toLowerCase())).slice(0, 10) + }, + render: () => { + let reactRenderer + let popup + + return { + onStart: props => { + reactRenderer = new ReactRenderer(MentionList2, { + props, + editor: props.editor, + }) + + popup = tippy('body', { + getReferenceClientRect: props.clientRect, + appendTo: () => document.body, + content: reactRenderer.element, + showOnCreate: true, + interactive: true, + trigger: 'manual', + placement: 'bottom-start', + }) + }, + onUpdate(props) { + reactRenderer.updateProps(props) + + popup[0].setProps({ + getReferenceClientRect: props.clientRect, + }) + }, + onKeyDown(props) { + return reactRenderer.ref.onKeyDown(props) + }, + onExit() { + popup[0].destroy() + reactRenderer.destroy() + }, + } + } + }, + }) + ], + content: ` +

heading

+

heading

+

paragraph

+ `, +// content: ` +//

+// Hi there, +//

+//

+// this is a basic basic example of tiptap. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists: +//

+// +//

+// Isn’t that great? And all of that is editable. But wait, there’s more. Let’s try a code block: +//

+//
body {
+//   display: none;
+// }
+//

+// I know, I know, this is impressive. It’s only the tip of the iceberg though. Give it a try and click a little bit around. Don’t forget to check the other examples too. +//

+//
+// Wow, that’s amazing. Good work, boy! 👏 +//
+// — Mom +//
+// `, + }) + + return ( +
+
+ + +
+ + +
+ ) +} diff --git a/docs/src/demos/ReactPlayground/index.spec.js b/docs/src/demos/ReactPlayground/index.spec.js new file mode 100644 index 00000000..350c2d41 --- /dev/null +++ b/docs/src/demos/ReactPlayground/index.spec.js @@ -0,0 +1,22 @@ +context('/demos/Examples/Default/React', () => { + before(() => { + cy.visit('/demos/Examples/Default/React') + }) + + beforeEach(() => { + cy.get('.ProseMirror').then(([{ editor }]) => { + editor.commands.setContent('

Example Text

') + cy.get('.ProseMirror').type('{selectall}') + }) + }) + + it('should apply the paragraph style when the keyboard shortcut is pressed', () => { + cy.get('.ProseMirror h1').should('exist') + cy.get('.ProseMirror p').should('not.exist') + + cy.get('.ProseMirror') + .trigger('keydown', { modKey: true, altKey: true, key: '0' }) + .find('p') + .should('contain', 'Example Text') + }) +}) diff --git a/docs/src/demos/ReactPlayground/styles.scss b/docs/src/demos/ReactPlayground/styles.scss new file mode 100644 index 00000000..dc996245 --- /dev/null +++ b/docs/src/demos/ReactPlayground/styles.scss @@ -0,0 +1,55 @@ +/* Basic editor styles */ +.ProseMirror { + > * + * { + margin-top: 0.75em; + } + + ul, + ol { + padding: 0 1rem; + } + + h1, + h2, + h3, + h4, + h5, + h6 { + line-height: 1.1; + } + + code { + background-color: rgba(#616161, 0.1); + color: #616161; + } + + pre { + background: #0D0D0D; + color: #FFF; + font-family: 'JetBrainsMono', monospace; + padding: 0.75rem 1rem; + border-radius: 0.5rem; + + code { + color: inherit; + background: none; + font-size: 0.8rem; + } + } + + img { + max-width: 100%; + height: auto; + } + + blockquote { + padding-left: 1rem; + border-left: 2px solid rgba(#0D0D0D, 0.1); + } + + hr { + border: none; + border-top: 2px solid rgba(#0D0D0D, 0.1); + margin: 2rem 0; + } +}