69 lines
2.0 KiB
TypeScript
69 lines
2.0 KiB
TypeScript
import type { EditorView, NodeView, NodeViewConstructor } from 'prosemirror-view'
|
|
import type { Node } from 'prosemirror-model'
|
|
|
|
class ImageView implements NodeView {
|
|
node: Node
|
|
view: EditorView
|
|
getPos: () => number
|
|
dom: Element
|
|
container: HTMLElement
|
|
handle: HTMLElement
|
|
onResizeFn: any
|
|
onResizeEndFn: any
|
|
width: number
|
|
updating: number
|
|
|
|
constructor(node: Node, view: EditorView, getPos: () => number) {
|
|
this.node = node
|
|
this.view = view
|
|
this.getPos = getPos
|
|
this.onResizeFn = this.onResize.bind(this)
|
|
this.onResizeEndFn = this.onResizeEnd.bind(this)
|
|
|
|
this.container = document.createElement('span')
|
|
this.container.className = 'image-container'
|
|
if (node.attrs.width) this.setWidth(node.attrs.width)
|
|
|
|
const image = document.createElement('img')
|
|
image.setAttribute('title', node.attrs.title ?? '')
|
|
image.setAttribute('src', node.attrs.src)
|
|
|
|
this.handle = document.createElement('span')
|
|
this.handle.className = 'resize-handle'
|
|
this.handle.addEventListener('mousedown', (e) => {
|
|
e.preventDefault()
|
|
window.addEventListener('mousemove', this.onResizeFn)
|
|
window.addEventListener('mouseup', this.onResizeEndFn)
|
|
})
|
|
|
|
this.container.appendChild(image)
|
|
this.container.appendChild(this.handle)
|
|
this.dom = this.container
|
|
}
|
|
|
|
onResize(e: MouseEvent) {
|
|
this.width = e.pageX - this.container.getBoundingClientRect().left
|
|
this.setWidth(this.width)
|
|
}
|
|
|
|
onResizeEnd() {
|
|
window.removeEventListener('mousemove', this.onResizeFn)
|
|
if (this.updating === this.width) return
|
|
this.updating = this.width
|
|
const tr = this.view.state.tr
|
|
tr.setNodeMarkup(this.getPos(), undefined, {
|
|
...this.node.attrs,
|
|
width: this.width
|
|
})
|
|
|
|
this.view.dispatch(tr)
|
|
}
|
|
|
|
setWidth(width: number) {
|
|
this.container.style.width = width + 'px'
|
|
}
|
|
}
|
|
|
|
export const createImageView: NodeViewConstructor = (node: Node, view: EditorView, getPos: () => number) =>
|
|
new ImageView(node, view, getPos)
|