refactoring
This commit is contained in:
@@ -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()
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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 {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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]) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user