refactoring

This commit is contained in:
Philipp Kühn
2021-03-15 09:00:44 +01:00
parent 385ee1d1f4
commit e765c8e981
10 changed files with 48 additions and 63 deletions

View File

@@ -110,7 +110,7 @@ export default {
}) })
}, },
onKeyDown(props) { onKeyDown(props) {
return component.vm.onKeyDown(props) return component.ref.onKeyDown(props)
}, },
onExit() { onExit() {
popup[0].destroy() popup[0].destroy()

View File

@@ -105,7 +105,7 @@ export default {
}) })
}, },
onKeyDown(props) { onKeyDown(props) {
return component.vm.onKeyDown(props) return component.ref.onKeyDown(props)
}, },
onExit() { onExit() {
popup[0].destroy() popup[0].destroy()

View File

@@ -69,7 +69,7 @@ export default {
}) })
}, },
onKeyDown(props) { onKeyDown(props) {
return component.vm.onKeyDown(props) return component.ref.onKeyDown(props)
}, },
onExit() { onExit() {
popup[0].destroy() popup[0].destroy()

View File

@@ -1,6 +1,7 @@
import React from 'react' import React from 'react'
import { Editor as CoreEditor } from '@tiptap/core' import { Editor as CoreEditor } from '@tiptap/core'
import { EditorContentProps, EditorContentState } from './EditorContent'
export class Editor extends CoreEditor { export class Editor extends CoreEditor {
public contentComponent: React.Component | null = null public contentComponent: React.Component<EditorContentProps, EditorContentState> | null = null
} }

View File

@@ -2,11 +2,6 @@ import React from 'react'
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
import { Editor } from './Editor' import { Editor } from './Editor'
import { ReactRenderer } from './ReactRenderer' import { ReactRenderer } from './ReactRenderer'
import { ReactNodeViewContext } from './useReactNodeView'
type EditorContentProps = {
editor: Editor | null
}
const Portals: React.FC<{ renderers: Map<string, ReactRenderer> }> = ({ renderers }) => { const Portals: React.FC<{ renderers: Map<string, ReactRenderer> }> = ({ renderers }) => {
return ( return (
@@ -22,7 +17,16 @@ const Portals: React.FC<{ renderers: Map<string, ReactRenderer> }> = ({ renderer
) )
} }
export class PureEditorContent extends React.Component<EditorContentProps, any> { export interface EditorContentProps {
editor: Editor | null,
}
export interface EditorContentState {
editor: Editor | null,
renderers: Map<string, ReactRenderer>
}
export class PureEditorContent extends React.Component<EditorContentProps, EditorContentState> {
editorContentRef: React.RefObject<any> editorContentRef: React.RefObject<any>
constructor(props: EditorContentProps) { constructor(props: EditorContentProps) {

View File

@@ -78,30 +78,23 @@ class ReactNodeView implements NodeView {
Component.displayName = capitalizeFirstChar(this.extension.config.name) Component.displayName = capitalizeFirstChar(this.extension.config.name)
} }
const ReactNodeView: React.FC = (props) => { const ReactNodeView: React.FunctionComponent = (props) => {
const [isEditable, setIsEditable] = useState(this.editor.isEditable) const [isEditable, setIsEditable] = useState(this.editor.isEditable)
const onDragStart = this.onDragStart.bind(this)
const handleEditableChange = () => { const onViewUpdate = () => {
setIsEditable(this.editor.isEditable) setIsEditable(this.editor.isEditable)
} }
const onDragStart = this.onDragStart.bind(this)
useEffect(() => { useEffect(() => {
this.editor.on('viewUpdate', handleEditableChange) this.editor.on('viewUpdate', onViewUpdate)
return () => { return () => {
this.editor.off('viewUpdate', handleEditableChange) this.editor.off('viewUpdate', onViewUpdate)
} }
}, []) }, [])
return ( return (
<ReactNodeViewContext.Provider <ReactNodeViewContext.Provider value={{ onDragStart, isEditable }}>
value={{
onDragStart,
isEditable,
}}
>
<Component {...props} /> <Component {...props} />
</ReactNodeViewContext.Provider> </ReactNodeViewContext.Provider>
) )

View File

@@ -1,28 +1,19 @@
import React from 'react' import React from 'react'
import { AnyObject } from '@tiptap/core'
import { Editor } from './Editor' import { Editor } from './Editor'
export interface ReactRendererOptions {
as?: string,
editor: Editor,
props?: { [key: string]: any },
}
function isFunctionalComponent(Component: any) {
return (
typeof Component === 'function' // can be various things
&& !(
Component.prototype // native arrows don't have prototypes
&& Component.prototype.isReactComponent // special property
)
);
}
function isClassComponent(Component: any) { function isClassComponent(Component: any) {
return !!( return !!(
typeof Component === 'function' typeof Component === 'function'
&& Component.prototype && Component.prototype
&& Component.prototype.isReactComponent && Component.prototype.isReactComponent
); )
}
export interface ReactRendererOptions {
as?: string,
editor: Editor,
props?: AnyObject,
} }
export class ReactRenderer { export class ReactRenderer {
@@ -34,13 +25,13 @@ export class ReactRenderer {
element: Element element: Element
props: { [key: string]: any } props: AnyObject
reactElement: React.ReactNode reactElement: React.ReactNode
ref: React.Component | null = null ref: React.Component | null = null
constructor(component: any, { props = {}, editor }: ReactRendererOptions) { constructor(component: React.Component | React.FunctionComponent, { props = {}, editor }: ReactRendererOptions) {
this.id = Math.floor(Math.random() * 0xFFFFFFFF).toString() this.id = Math.floor(Math.random() * 0xFFFFFFFF).toString()
this.component = component this.component = component
this.editor = editor this.editor = editor
@@ -50,7 +41,7 @@ export class ReactRenderer {
this.render() this.render()
} }
render() { render(): void {
const Component = this.component const Component = this.component
const props = this.props const props = this.props
@@ -62,8 +53,6 @@ export class ReactRenderer {
if (this.editor?.contentComponent) { if (this.editor?.contentComponent) {
this.editor.contentComponent.setState({ this.editor.contentComponent.setState({
// TODO
// @ts-ignore
renderers: this.editor.contentComponent.state.renderers.set( renderers: this.editor.contentComponent.state.renderers.set(
this.id, this.id,
this, this,
@@ -72,7 +61,7 @@ export class ReactRenderer {
} }
} }
updateProps(props: { [key: string]: any } = {}) { updateProps(props: AnyObject = {}): void {
this.props = { this.props = {
...this.props, ...this.props,
...props, ...props,
@@ -81,10 +70,8 @@ export class ReactRenderer {
this.render() this.render()
} }
destroy() { destroy(): void {
if (this.editor?.contentComponent) { if (this.editor?.contentComponent) {
// TODO
// @ts-ignore
const { renderers } = this.editor.contentComponent.state const { renderers } = this.editor.contentComponent.state
renderers.delete(this.id) renderers.delete(this.id)
@@ -94,5 +81,4 @@ export class ReactRenderer {
}) })
} }
} }
} }

View File

@@ -1,11 +1,11 @@
import React, { useContext } from 'react' import { createContext, useContext } from 'react'
export interface ReactNodeViewContextProps { export interface ReactNodeViewContextProps {
isEditable: boolean, isEditable: boolean,
onDragStart: (event: DragEvent) => void, onDragStart: (event: DragEvent) => void,
} }
export const ReactNodeViewContext = React.createContext<Partial<ReactNodeViewContextProps>>({ export const ReactNodeViewContext = createContext<Partial<ReactNodeViewContextProps>>({
isEditable: undefined, isEditable: undefined,
onDragStart: undefined, onDragStart: undefined,
}) })

View File

@@ -1,21 +1,22 @@
import Vue from 'vue' import Vue from 'vue'
import { AnyObject } from '@tiptap/core'
import { VueConstructor } from 'vue/types/umd' import { VueConstructor } from 'vue/types/umd'
export class VueRenderer { export class VueRenderer {
vm!: Vue ref!: Vue
constructor(component: Vue | VueConstructor, props: any) { constructor(component: Vue | VueConstructor, props: any) {
const Component = Vue.extend(component) const Component = Vue.extend(component)
this.vm = new Component(props).$mount() this.ref = new Component(props).$mount()
} }
get element() { get element() {
return this.vm.$el return this.ref.$el
} }
updateProps(props: { [key: string]: any } = {}) { updateProps(props: AnyObject = {}) {
if (!this.vm.$props) { if (!this.ref.$props) {
return return
} }
@@ -26,13 +27,13 @@ export class VueRenderer {
Object Object
.entries(props) .entries(props)
.forEach(([key, value]) => { .forEach(([key, value]) => {
this.vm.$props[key] = value this.ref.$props[key] = value
}) })
Vue.config.silent = originalSilent Vue.config.silent = originalSilent
} }
destroy() { destroy() {
this.vm.$destroy() this.ref.$destroy()
} }
} }

View File

@@ -1,10 +1,10 @@
import { reactive, markRaw, Component } from 'vue' import { reactive, markRaw, Component } from 'vue'
import { AnyObject } from '@tiptap/core'
import { Editor } from './Editor' import { Editor } from './Editor'
export interface VueRendererOptions { export interface VueRendererOptions {
as?: string,
editor: Editor, editor: Editor,
props?: { [key: string]: any }, props?: AnyObject,
} }
export class VueRenderer { export class VueRenderer {
@@ -18,7 +18,7 @@ export class VueRenderer {
element: Element element: Element
props: { [key: string]: any } props: AnyObject
constructor(component: Component, { props = {}, editor }: VueRendererOptions) { constructor(component: Component, { props = {}, editor }: VueRendererOptions) {
this.id = Math.floor(Math.random() * 0xFFFFFFFF).toString() this.id = Math.floor(Math.random() * 0xFFFFFFFF).toString()
@@ -44,7 +44,7 @@ export class VueRenderer {
return this.editor.contentComponent?.ctx.$refs[this.id] return this.editor.contentComponent?.ctx.$refs[this.id]
} }
updateProps(props: { [key: string]: any } = {}) { updateProps(props: AnyObject = {}) {
Object Object
.entries(props) .entries(props)
.forEach(([key, value]) => { .forEach(([key, value]) => {