From 077c540cf9f00aa769693c6340f4af912e7fd90e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Chong?= Date: Wed, 30 Oct 2024 05:44:45 -0400 Subject: [PATCH] docs: add drag handle demo for React (#5783) --- .../DragHandle/React/Component.jsx | 11 ++ .../DragHandle/React/DraggableItem.js | 30 +++++ .../DragHandle/React/index.html | 0 .../GuideNodeViews/DragHandle/React/index.jsx | 33 +++++ .../DragHandle/React/styles.scss | 124 ++++++++++++++++++ 5 files changed, 198 insertions(+) create mode 100644 demos/src/GuideNodeViews/DragHandle/React/Component.jsx create mode 100644 demos/src/GuideNodeViews/DragHandle/React/DraggableItem.js create mode 100644 demos/src/GuideNodeViews/DragHandle/React/index.html create mode 100644 demos/src/GuideNodeViews/DragHandle/React/index.jsx create mode 100644 demos/src/GuideNodeViews/DragHandle/React/styles.scss diff --git a/demos/src/GuideNodeViews/DragHandle/React/Component.jsx b/demos/src/GuideNodeViews/DragHandle/React/Component.jsx new file mode 100644 index 000000000..0789010b5 --- /dev/null +++ b/demos/src/GuideNodeViews/DragHandle/React/Component.jsx @@ -0,0 +1,11 @@ +import { NodeViewContent, NodeViewWrapper } from '@tiptap/react' +import React from 'react' + +export default () => { + return ( + +
+ + + ) +} diff --git a/demos/src/GuideNodeViews/DragHandle/React/DraggableItem.js b/demos/src/GuideNodeViews/DragHandle/React/DraggableItem.js new file mode 100644 index 000000000..f964519d2 --- /dev/null +++ b/demos/src/GuideNodeViews/DragHandle/React/DraggableItem.js @@ -0,0 +1,30 @@ +import { mergeAttributes, Node } from '@tiptap/core' +import { ReactNodeViewRenderer } from '@tiptap/react' + +import Component from './Component.jsx' + +export default Node.create({ + name: 'draggableItem', + + group: 'block', + + content: 'block+', + + draggable: true, + + parseHTML() { + return [ + { + tag: 'div[data-type="draggable-item"]', + }, + ] + }, + + renderHTML({ HTMLAttributes }) { + return ['div', mergeAttributes(HTMLAttributes, { 'data-type': 'draggable-item' }), 0] + }, + + addNodeView() { + return ReactNodeViewRenderer(Component) + }, +}) diff --git a/demos/src/GuideNodeViews/DragHandle/React/index.html b/demos/src/GuideNodeViews/DragHandle/React/index.html new file mode 100644 index 000000000..e69de29bb diff --git a/demos/src/GuideNodeViews/DragHandle/React/index.jsx b/demos/src/GuideNodeViews/DragHandle/React/index.jsx new file mode 100644 index 000000000..e581ac65d --- /dev/null +++ b/demos/src/GuideNodeViews/DragHandle/React/index.jsx @@ -0,0 +1,33 @@ +import './styles.scss' + +import { EditorProvider } from '@tiptap/react' +import StarterKit from '@tiptap/starter-kit' +import React from 'react' + +import DraggableItem from './DraggableItem.js' + +const extensions = [ + StarterKit, + DraggableItem, +] + +const content = ` +

This is a boring paragraph.

+
+

Followed by a fancy draggable item.

+
+
+

And another draggable item.

+
+

And a nested one.

+
+

But can we go deeper?

+
+
+
+

Let’s finish with a boring paragraph.

+ ` + +export default () => { + return +} diff --git a/demos/src/GuideNodeViews/DragHandle/React/styles.scss b/demos/src/GuideNodeViews/DragHandle/React/styles.scss new file mode 100644 index 000000000..dd2ebd606 --- /dev/null +++ b/demos/src/GuideNodeViews/DragHandle/React/styles.scss @@ -0,0 +1,124 @@ +/* Basic editor styles */ +.tiptap { + :first-child { + margin-top: 0; + } + + /* List styles */ + ul, + ol { + padding: 0 1rem; + margin: 1.25rem 1rem 1.25rem 0.4rem; + + li p { + margin-top: 0.25em; + margin-bottom: 0.25em; + } + } + + /* Heading styles */ + h1, + h2, + h3, + h4, + h5, + h6 { + line-height: 1.1; + margin-top: 2.5rem; + text-wrap: pretty; + } + + h1, + h2 { + margin-top: 3.5rem; + margin-bottom: 1.5rem; + } + + h1 { + font-size: 1.4rem; + } + + h2 { + font-size: 1.2rem; + } + + h3 { + font-size: 1.1rem; + } + + h4, + h5, + h6 { + font-size: 1rem; + } + + /* Code and preformatted text styles */ + code { + background-color: var(--purple-light); + border-radius: 0.4rem; + color: var(--black); + font-size: 0.85rem; + padding: 0.25em 0.3em; + } + + pre { + background: var(--black); + border-radius: 0.5rem; + color: var(--white); + font-family: "JetBrainsMono", monospace; + margin: 1.5rem 0; + padding: 0.75rem 1rem; + + code { + background: none; + color: inherit; + font-size: 0.8rem; + padding: 0; + } + } + + blockquote { + border-left: 3px solid var(--gray-3); + margin: 1.5rem 0; + padding-left: 1rem; + } + + hr { + border: none; + border-top: 1px solid var(--gray-2); + margin: 2rem 0; + } + + // Focus styles + .has-focus { + border-radius: 3px; + box-shadow: 0 0 0 2px var(--purple); + } +} + +.draggable-item { + display: flex; + padding: 0.5rem; + margin: 0.5rem 0; + border-radius: 0.5rem; + background: white; + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.05), 0px 10px 20px rgba(0, 0, 0, 0.1); + + .drag-handle { + flex: 0 0 auto; + position: relative; + width: 1rem; + height: 1rem; + top: 0.3rem; + margin-right: 0.5rem; + cursor: grab; + background-image: url('data:image/svg+xml;charset=UTF-8,'); + background-repeat: no-repeat; + background-size: contain; + background-position: center; + } + + .content { + flex: 1 1 auto; + } +}