From d64ddf6c1b18947d8ba25e840cbdb96c6adaaf7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Mon, 8 Mar 2021 23:10:10 +0100 Subject: [PATCH] refactoring --- .../{EditorContent.jsx => EditorContent.tsx} | 12 +- packages/react/src/ReactNodeViewRenderer.ts | 326 +++++++++--------- packages/react/src/ReactRenderer.ts | 86 ++--- packages/react/src/useEditor.ts | 2 +- tsconfig.json | 2 +- 5 files changed, 217 insertions(+), 211 deletions(-) rename packages/react/src/{EditorContent.jsx => EditorContent.tsx} (72%) diff --git a/packages/react/src/EditorContent.jsx b/packages/react/src/EditorContent.tsx similarity index 72% rename from packages/react/src/EditorContent.jsx rename to packages/react/src/EditorContent.tsx index 3d7f48a2..eb14d226 100644 --- a/packages/react/src/EditorContent.jsx +++ b/packages/react/src/EditorContent.tsx @@ -1,10 +1,16 @@ import React from 'react' +import { Editor } from './Editor' -export class PureEditorContent extends React.Component { - constructor(props) { +type EditorContentProps = { + editor: Editor | null +} + +export class PureEditorContent extends React.Component { + editorContentRef: React.RefObject + + constructor(props: EditorContentProps) { super(props) this.editorContentRef = React.createRef() - this.editorPortalRef = React.createRef() this.state = { editor: this.props.editor diff --git a/packages/react/src/ReactNodeViewRenderer.ts b/packages/react/src/ReactNodeViewRenderer.ts index c319fc69..b735fbc1 100644 --- a/packages/react/src/ReactNodeViewRenderer.ts +++ b/packages/react/src/ReactNodeViewRenderer.ts @@ -1,208 +1,208 @@ -// @ts-nocheck -import { Node, NodeViewRenderer, NodeViewRendererProps } from '@tiptap/core' -import { Decoration, NodeView } from 'prosemirror-view' -import { NodeSelection } from 'prosemirror-state' -import { Node as ProseMirrorNode } from 'prosemirror-model' -import React from 'react' -import ReactDOM from 'react-dom' -import { Editor } from './Editor' -import { ReactRenderer } from './ReactRenderer' +// // @ts-nocheck +// import { Node, NodeViewRenderer, NodeViewRendererProps } from '@tiptap/core' +// import { Decoration, NodeView } from 'prosemirror-view' +// import { NodeSelection } from 'prosemirror-state' +// import { Node as ProseMirrorNode } from 'prosemirror-model' +// import React from 'react' +// import ReactDOM from 'react-dom' +// import { Editor } from './Editor' +// import { ReactRenderer } from './ReactRenderer' -interface ReactNodeViewRendererOptions { - stopEvent: ((event: Event) => boolean) | null, - update: ((node: ProseMirrorNode, decorations: Decoration[]) => boolean) | null, -} +// interface ReactNodeViewRendererOptions { +// stopEvent: ((event: Event) => boolean) | null, +// update: ((node: ProseMirrorNode, decorations: Decoration[]) => boolean) | null, +// } -class ReactNodeView implements NodeView { +// class ReactNodeView implements NodeView { - renderer!: ReactRenderer +// renderer!: ReactRenderer - editor: Editor +// editor: Editor - extension!: Node +// extension!: Node - node!: ProseMirrorNode +// node!: ProseMirrorNode - decorations!: Decoration[] +// decorations!: Decoration[] - getPos!: any +// getPos!: any - isDragging = false +// isDragging = false - options: ReactNodeViewRendererOptions = { - stopEvent: null, - update: null, - } +// options: ReactNodeViewRendererOptions = { +// stopEvent: null, +// update: null, +// } - constructor(component: any, props: NodeViewRendererProps, options?: Partial) { - this.options = { ...this.options, ...options } - this.editor = props.editor as Editor - this.extension = props.extension - this.node = props.node - this.getPos = props.getPos - this.mount(component) - } +// constructor(component: any, props: NodeViewRendererProps, options?: Partial) { +// this.options = { ...this.options, ...options } +// this.editor = props.editor as Editor +// this.extension = props.extension +// this.node = props.node +// this.getPos = props.getPos +// this.mount(component) +// } - mount(component: any) { - const props = {} +// mount(component: any) { +// const props = {} - if (!component.displayName) { - component.displayName = this.extension.config.name - } +// if (!component.displayName) { +// component.displayName = this.extension.config.name +// } - this.renderer = new ReactRenderer(component, { - editor: this.editor, - props, - }) - } +// this.renderer = new ReactRenderer(component, { +// editor: this.editor, +// props, +// }) +// } - get dom() { - // if (!this.renderer.element) { - // return null - // } +// get dom() { +// // if (!this.renderer.element) { +// // return null +// // } - // if (!this.renderer.element.hasAttribute('data-node-view-wrapper')) { - // throw Error('Please use the NodeViewWrapper component for your node view.') - // } +// // if (!this.renderer.element.hasAttribute('data-node-view-wrapper')) { +// // throw Error('Please use the NodeViewWrapper component for your node view.') +// // } - return this.renderer.element - } +// return this.renderer.element +// } - get contentDOM() { - // console.log(this.dom) - // return null - // if (!this.renderer.element) { - // return null - // } +// get contentDOM() { +// // console.log(this.dom) +// // return null +// // if (!this.renderer.element) { +// // return null +// // } - const hasContent = !this.node.type.isAtom +// const hasContent = !this.node.type.isAtom - if (!hasContent) { - return null - } +// if (!hasContent) { +// return null +// } - const contentElement = this.dom.querySelector('[data-node-view-content]') +// const contentElement = this.dom.querySelector('[data-node-view-content]') - return contentElement || this.dom - } +// return contentElement || this.dom +// } - stopEvent(event: Event) { - if (typeof this.options.stopEvent === 'function') { - return this.options.stopEvent(event) - } +// stopEvent(event: Event) { +// if (typeof this.options.stopEvent === 'function') { +// return this.options.stopEvent(event) +// } - const target = (event.target as HTMLElement) - const isInElement = this.dom.contains(target) && !this.contentDOM?.contains(target) +// const target = (event.target as HTMLElement) +// const isInElement = this.dom.contains(target) && !this.contentDOM?.contains(target) - // ignore all events from child nodes - if (!isInElement) { - return false - } +// // ignore all events from child nodes +// if (!isInElement) { +// return false +// } - const { isEditable } = this.editor - const { isDragging } = this - const isDraggable = !!this.node.type.spec.draggable - const isSelectable = NodeSelection.isSelectable(this.node) - const isCopyEvent = event.type === 'copy' - const isPasteEvent = event.type === 'paste' - const isCutEvent = event.type === 'cut' - const isClickEvent = event.type === 'mousedown' - const isDragEvent = event.type.startsWith('drag') || event.type === 'drop' +// const { isEditable } = this.editor +// const { isDragging } = this +// const isDraggable = !!this.node.type.spec.draggable +// const isSelectable = NodeSelection.isSelectable(this.node) +// const isCopyEvent = event.type === 'copy' +// const isPasteEvent = event.type === 'paste' +// const isCutEvent = event.type === 'cut' +// const isClickEvent = event.type === 'mousedown' +// const isDragEvent = event.type.startsWith('drag') || event.type === 'drop' - // ProseMirror tries to drag selectable nodes - // even if `draggable` is set to `false` - // this fix prevents that - if (!isDraggable && isSelectable && isDragEvent) { - event.preventDefault() - } +// // ProseMirror tries to drag selectable nodes +// // even if `draggable` is set to `false` +// // this fix prevents that +// if (!isDraggable && isSelectable && isDragEvent) { +// event.preventDefault() +// } - if (isDraggable && isDragEvent && !isDragging) { - event.preventDefault() - return false - } +// if (isDraggable && isDragEvent && !isDragging) { +// event.preventDefault() +// return false +// } - // we have to store that dragging started - if (isDraggable && isEditable && !isDragging && isClickEvent) { - const dragHandle = target.closest('[data-drag-handle]') - const isValidDragHandle = dragHandle - && (this.dom === dragHandle || (this.dom.contains(dragHandle))) +// // we have to store that dragging started +// if (isDraggable && isEditable && !isDragging && isClickEvent) { +// const dragHandle = target.closest('[data-drag-handle]') +// const isValidDragHandle = dragHandle +// && (this.dom === dragHandle || (this.dom.contains(dragHandle))) - if (isValidDragHandle) { - this.isDragging = true - document.addEventListener('dragend', () => { - this.isDragging = false - }, { once: true }) - } - } +// if (isValidDragHandle) { +// this.isDragging = true +// document.addEventListener('dragend', () => { +// this.isDragging = false +// }, { once: true }) +// } +// } - // these events are handled by prosemirror - if ( - isDragging - || isCopyEvent - || isPasteEvent - || isCutEvent - || (isClickEvent && isSelectable) - ) { - return false - } +// // these events are handled by prosemirror +// if ( +// isDragging +// || isCopyEvent +// || isPasteEvent +// || isCutEvent +// || (isClickEvent && isSelectable) +// ) { +// return false +// } - return true - } +// return true +// } - ignoreMutation(mutation: MutationRecord | { type: 'selection'; target: Element }) { - if (mutation.type === 'selection') { - if (this.node.isLeaf) { - return true - } +// ignoreMutation(mutation: MutationRecord | { type: 'selection'; target: Element }) { +// if (mutation.type === 'selection') { +// if (this.node.isLeaf) { +// return true +// } - return false - } +// return false +// } - if (!this.contentDOM) { - return true - } +// if (!this.contentDOM) { +// return true +// } - const contentDOMHasChanged = !this.contentDOM.contains(mutation.target) - || this.contentDOM === mutation.target +// const contentDOMHasChanged = !this.contentDOM.contains(mutation.target) +// || this.contentDOM === mutation.target - return contentDOMHasChanged - } +// return contentDOMHasChanged +// } - destroy() { - this.renderer.destroy() - } +// destroy() { +// this.renderer.destroy() +// } - update(node: ProseMirrorNode, decorations: Decoration[]) { - if (typeof this.options.update === 'function') { - return this.options.update(node, decorations) - } +// update(node: ProseMirrorNode, decorations: Decoration[]) { +// if (typeof this.options.update === 'function') { +// return this.options.update(node, decorations) +// } - if (node.type !== this.node.type) { - return false - } +// if (node.type !== this.node.type) { +// return false +// } - if (node === this.node && this.decorations === decorations) { - return true - } +// if (node === this.node && this.decorations === decorations) { +// return true +// } - this.node = node - this.decorations = decorations - // this.renderer.updateProps({ node, decorations }) - this.renderer.render() +// this.node = node +// this.decorations = decorations +// // this.renderer.updateProps({ node, decorations }) +// this.renderer.render() - return true - } -} +// return true +// } +// } -export function ReactNodeViewRenderer(component: any, options?: Partial): NodeViewRenderer { - return (props: NodeViewRendererProps) => { - // try to get the parent component - // this is important for vue devtools to show the component hierarchy correctly - // maybe it’s `undefined` because isn’t rendered yet - if (!(props.editor as Editor).contentComponent) { - return {} - } +// export function ReactNodeViewRenderer(component: any, options?: Partial): NodeViewRenderer { +// return (props: NodeViewRendererProps) => { +// // try to get the parent component +// // this is important for vue devtools to show the component hierarchy correctly +// // maybe it’s `undefined` because isn’t rendered yet +// if (!(props.editor as Editor).contentComponent) { +// return {} +// } - return new ReactNodeView(component, props, options) as NodeView - } -} +// return new ReactNodeView(component, props, options) as NodeView +// } +// } diff --git a/packages/react/src/ReactRenderer.ts b/packages/react/src/ReactRenderer.ts index 6f7ece45..3bae50d0 100644 --- a/packages/react/src/ReactRenderer.ts +++ b/packages/react/src/ReactRenderer.ts @@ -1,58 +1,58 @@ -// @ts-nocheck +// // @ts-nocheck -import React from 'react' -import { render, unmountComponentAtNode } from 'react-dom' +// import React from 'react' +// import { render, unmountComponentAtNode } from 'react-dom' -import { Editor } from './Editor' +// import { Editor } from './Editor' -export interface VueRendererOptions { - as?: string; - editor: Editor; - props?: { [key: string]: any }; -} +// export interface VueRendererOptions { +// as?: string; +// editor: Editor; +// props?: { [key: string]: any }; +// } -export class ReactRenderer { - id: string +// export class ReactRenderer { +// id: string - editor: Editor +// editor: Editor - component: any +// component: any - teleportElement: Element +// teleportElement: Element - element: Element +// element: Element - props: { [key: string]: any } +// props: { [key: string]: any } - constructor(component: any, { props = {}, editor }: VueRendererOptions) { - this.id = Math.floor(Math.random() * 0xFFFFFFFF).toString() - this.component = component - this.editor = editor - this.props = props +// constructor(component: any, { props = {}, editor }: VueRendererOptions) { +// this.id = Math.floor(Math.random() * 0xFFFFFFFF).toString() +// this.component = component +// this.editor = editor +// this.props = props - this.teleportElement = document.createElement('div') - // this.teleportElement.setAttribute('data-bla', '') - // render(React.createElement(component), this.teleportElement) - // render(React.createElement(component), this.teleportElement) - this.render() - // this.element = this.teleportElement.firstElementChild as Element - this.element = this.teleportElement - } +// this.teleportElement = document.createElement('div') +// // this.teleportElement.setAttribute('data-bla', '') +// // render(React.createElement(component), this.teleportElement) +// // render(React.createElement(component), this.teleportElement) +// this.render() +// // this.element = this.teleportElement.firstElementChild as Element +// this.element = this.teleportElement +// } - render() { - render(React.createElement(this.component), this.teleportElement) - } +// render() { +// render(React.createElement(this.component), this.teleportElement) +// } - updateProps(props: { [key: string]: any } = {}) { - // TODO - } +// updateProps(props: { [key: string]: any } = {}) { +// // TODO +// } - destroy() { - // TODO - // console.log('DESTROY', { bla: this.teleportElement }) - // console.log(document.querySelector('[data-bla]')) - unmountComponentAtNode(this.teleportElement) - // unmountComponentAtNode(document.querySelector('[data-bla]')) - } +// destroy() { +// // TODO +// // console.log('DESTROY', { bla: this.teleportElement }) +// // console.log(document.querySelector('[data-bla]')) +// unmountComponentAtNode(this.teleportElement) +// // unmountComponentAtNode(document.querySelector('[data-bla]')) +// } -} +// } diff --git a/packages/react/src/useEditor.ts b/packages/react/src/useEditor.ts index 0405c8d9..165e52d6 100644 --- a/packages/react/src/useEditor.ts +++ b/packages/react/src/useEditor.ts @@ -3,7 +3,7 @@ import { EditorOptions } from '@tiptap/core' import { Editor } from './Editor' function useForceUpdate() { - const [_, setValue] = useState(0) + const [, setValue] = useState(0) return () => setValue(value => value + 1) } diff --git a/tsconfig.json b/tsconfig.json index 33c0a338..9700a48c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,7 @@ "target": "es2019", "module": "esnext", "strict": true, - "jsx": "preserve", + "jsx": "react", "importHelpers": true, "moduleResolution": "node", "esModuleInterop": true,