56 lines
1.7 KiB
TypeScript
56 lines
1.7 KiB
TypeScript
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
// @ts-nocheck
|
|
import { renderGrouped } from 'prosemirror-menu'
|
|
import { EditorState, Plugin } from 'prosemirror-state'
|
|
import styles from '../styles/ProseMirror.module.scss'
|
|
import type { EditorView } from 'prosemirror-view'
|
|
import type { DiscoursSchema } from '../schema'
|
|
import { buildMenuItems } from '../helpers/menu'
|
|
|
|
export class SelectionMenuView {
|
|
tooltip: HTMLDivElement
|
|
|
|
constructor(view: EditorView, schema: DiscoursSchema) {
|
|
this.tooltip = document.createElement('div')
|
|
this.tooltip.className = styles.selectionMenu
|
|
view.dom.parentNode.appendChild(this.tooltip)
|
|
const { dom } = renderGrouped(view, buildMenuItems(schema))
|
|
this.tooltip.appendChild(dom)
|
|
this.update(view, null)
|
|
}
|
|
|
|
update(view: EditorView, lastState: EditorState) {
|
|
const state = view.state
|
|
|
|
if (lastState && lastState.doc.eq(state.doc) && lastState.selection.eq(state.selection)) {
|
|
return
|
|
}
|
|
|
|
if (state.selection.empty) {
|
|
this.tooltip.style.display = 'none'
|
|
return
|
|
}
|
|
|
|
this.tooltip.style.display = ''
|
|
const { from, to } = state.selection
|
|
const start = view.coordsAtPos(from)
|
|
const end = view.coordsAtPos(to)
|
|
const box = this.tooltip.offsetParent.getBoundingClientRect()
|
|
const width = this.tooltip.getBoundingClientRect().width
|
|
const left = (start.left + end.left - width) / 2
|
|
this.tooltip.style.left = `${left - box.left}px`
|
|
this.tooltip.style.bottom = `${box.bottom - start.top + 8}px`
|
|
}
|
|
|
|
destroy() {
|
|
this.tooltip.remove()
|
|
}
|
|
}
|
|
|
|
export const selectionMenu = (schema: DiscoursSchema) =>
|
|
new Plugin({
|
|
view(editorView: EditorView) {
|
|
return new SelectionMenuView(editorView, schema)
|
|
}
|
|
})
|