Files
tiptap/docs/src/demos/Experiments/Annotation/extension/annotation.ts
2021-02-11 22:48:04 +01:00

94 lines
2.1 KiB
TypeScript

import { Extension, Command } from '@tiptap/core'
import { AnnotationItem } from './AnnotationItem'
import { AnnotationPlugin, AnnotationPluginKey } from './AnnotationPlugin'
function randomId() {
return Math.floor(Math.random() * 0xffffffff)
}
export interface AnnotationOptions {
HTMLAttributes: {
[key: string]: any
},
onUpdate: (items: [any?]) => {},
/**
* An initialized Y.js document.
*/
document: any,
/**
* Name of a Y.js fragment, can be changed to sync multiple fields with one Y.js document.
*/
field: string,
/**
* A raw Y.js map, can be used instead of `document` and `field`.
*/
map: any,
}
export const Annotation = Extension.create({
name: 'annotation',
defaultOptions: <AnnotationOptions>{
HTMLAttributes: {
class: 'annotation',
},
onUpdate: decorations => decorations,
document: null,
field: 'annotations',
map: null,
},
addCommands() {
return {
addAnnotation: (content: any): Command => ({ dispatch, state }) => {
const { selection } = state
if (selection.empty) {
return false
}
if (dispatch && content) {
dispatch(state.tr.setMeta(AnnotationPluginKey, {
type: 'addAnnotation',
from: selection.from,
to: selection.to,
data: new AnnotationItem(
randomId(),
content,
),
}))
}
return true
},
deleteAnnotation: (id: number): Command => ({ dispatch, state }) => {
if (dispatch) {
dispatch(state.tr.setMeta(AnnotationPluginKey, { type: 'deleteAnnotation', id }))
}
return true
},
}
},
addProseMirrorPlugins() {
const map = this.options.map
? this.options.map
: this.options.document.getMap(this.options.field)
return [
AnnotationPlugin({
HTMLAttributes: this.options.HTMLAttributes,
onUpdate: this.options.onUpdate,
map,
}),
]
},
})
declare module '@tiptap/core' {
interface AllExtensions {
Annotation: typeof Annotation,
}
}