Merge branch 'main' of https://github.com/ueberdosis/tiptap-next into feature/remove-inferred-commands

# Conflicts:
#	docs/src/demos/Experiments/Annotation/extension/annotation.ts
#	docs/src/demos/Experiments/Color/extension/Color.ts
#	docs/src/demos/Experiments/Details/details.ts
This commit is contained in:
Philipp Kühn
2021-02-16 18:08:12 +01:00
57 changed files with 813 additions and 694 deletions

View File

@@ -0,0 +1,144 @@
import * as Y from 'yjs'
import { Extension, Command } from '@tiptap/core'
import { AnnotationPlugin, AnnotationPluginKey } from './AnnotationPlugin'
export interface AddAnnotationAction {
type: 'addAnnotation',
data: any,
from: number,
to: number,
}
export interface UpdateAnnotationAction {
type: 'updateAnnotation',
id: string,
data: any,
}
export interface DeleteAnnotationAction {
type: 'deleteAnnotation',
id: string,
}
export interface AnnotationOptions {
HTMLAttributes: {
[key: string]: any
},
/**
* An event listener which receives annotations for the current selection.
*/
onUpdate: (items: [any?]) => {},
/**
* An initialized Y.js document.
*/
document: Y.Doc | null,
/**
* Name of a Y.js map, 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: Y.Map<any> | null,
instance: string,
}
function getMapFromOptions(options: AnnotationOptions): Y.Map<any> {
return options.map
? options.map
: options.document?.getMap(options.field) as Y.Map<any>
}
declare module '@tiptap/core' {
interface AllCommands {
annotation: {
addAnnotation: (data: any) => Command,
updateAnnotation: (id: string, data: any) => Command,
deleteAnnotation: (id: string) => Command,
}
}
}
export const CollaborationAnnotation = Extension.create({
name: 'annotation',
defaultOptions: <AnnotationOptions>{
HTMLAttributes: {
class: 'annotation',
},
onUpdate: decorations => decorations,
document: null,
field: 'annotations',
map: null,
instance: '',
},
onCreate() {
const map = getMapFromOptions(this.options)
map.observe(() => {
console.log(`[${this.options.instance}] map updated → createDecorations`)
const transaction = this.editor.state.tr.setMeta(AnnotationPluginKey, {
type: 'createDecorations',
})
this.editor.view.dispatch(transaction)
})
},
addCommands() {
return {
addAnnotation: (data: any) => ({ dispatch, state }) => {
const { selection } = state
if (selection.empty) {
return false
}
if (dispatch && data) {
state.tr.setMeta(AnnotationPluginKey, <AddAnnotationAction>{
type: 'addAnnotation',
from: selection.from,
to: selection.to,
data,
})
}
return true
},
updateAnnotation: (id: string, data: any) => ({ dispatch, state }) => {
if (dispatch) {
state.tr.setMeta(AnnotationPluginKey, <UpdateAnnotationAction>{
type: 'updateAnnotation',
id,
data,
})
}
return true
},
deleteAnnotation: id => ({ dispatch, state }) => {
if (dispatch) {
state.tr.setMeta(AnnotationPluginKey, <DeleteAnnotationAction>{
type: 'deleteAnnotation',
id,
})
}
return true
},
}
},
addProseMirrorPlugins() {
return [
AnnotationPlugin({
HTMLAttributes: this.options.HTMLAttributes,
onUpdate: this.options.onUpdate,
map: getMapFromOptions(this.options),
instance: this.options.instance,
}),
]
},
})