feature(core): add onPaste and onDrop events to editor (#4843)

This commit is contained in:
bdbch 2024-08-21 18:46:49 +02:00 committed by GitHub
parent da8fcf373e
commit 9e18d243e0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 63 additions and 2 deletions

View File

@ -0,0 +1,5 @@
---
"@tiptap/core": minor
---
Added `onPaste` and `onDrop` options to the editor allowing for easier event binding for both cases

View File

@ -0,0 +1,5 @@
---
"@tiptap/vue-3": patch
---
Fixed an issue where plugin registration on editor initialization would break Vue3 editors.

View File

@ -24,6 +24,8 @@ import { isActive } from './helpers/isActive.js'
import { isNodeEmpty } from './helpers/isNodeEmpty.js'
import { resolveFocusPosition } from './helpers/resolveFocusPosition.js'
import { NodePos } from './NodePos.js'
import { DropPlugin } from './plugins/DropPlugin.js'
import { PastePlugin } from './plugins/PastePlugin.js'
import { style } from './style.js'
import {
CanCommands,
@ -88,6 +90,8 @@ export class Editor extends EventEmitter<EditorEvents> {
onBlur: () => null,
onDestroy: () => null,
onContentError: ({ error }) => { throw error },
onPaste: () => null,
onDrop: () => null,
}
constructor(options: Partial<EditorOptions> = {}) {
@ -109,6 +113,14 @@ export class Editor extends EventEmitter<EditorEvents> {
this.on('blur', this.options.onBlur)
this.on('destroy', this.options.onDestroy)
if (this.options.onPaste) {
this.registerPlugin(PastePlugin(this.options.onPaste))
}
if (this.options.onDrop) {
this.registerPlugin(DropPlugin(this.options.onDrop))
}
window.setTimeout(() => {
if (this.isDestroyed) {
return

View File

@ -11,6 +11,8 @@ export * from './NodePos.js'
export * from './NodeView.js'
export * from './PasteRule.js'
export * from './pasteRules/index.js'
export * from './plugins/DropPlugin.js'
export * from './plugins/PastePlugin.js'
export * from './Tracker.js'
export * from './types.js'
export * from './utilities/index.js'

View File

@ -0,0 +1,14 @@
import { Plugin, PluginKey } from '@tiptap/pm/state'
import { Slice } from 'packages/pm/model'
export const DropPlugin = (onDrop: (e: DragEvent, slice: Slice, moved: boolean) => void) => {
return new Plugin({
key: new PluginKey('tiptapDrop'),
props: {
handleDrop: (_, e, slice, moved) => {
onDrop(e, slice, moved)
},
},
})
}

View File

@ -0,0 +1,14 @@
import { Slice } from '@tiptap/pm/model'
import { Plugin, PluginKey } from '@tiptap/pm/state'
export const PastePlugin = (onPaste: (e: ClipboardEvent, slice: Slice) => void) => {
return new Plugin({
key: new PluginKey('tiptapPaste'),
props: {
handlePaste: (_view, e, slice) => {
onPaste(e, slice)
},
},
})
}

View File

@ -3,6 +3,7 @@ import {
Node as ProseMirrorNode,
NodeType,
ParseOptions,
Slice,
} from '@tiptap/pm/model'
import { EditorState, Transaction } from '@tiptap/pm/state'
import {
@ -121,6 +122,8 @@ export interface EditorOptions {
onFocus: (props: EditorEvents['focus']) => void;
onBlur: (props: EditorEvents['blur']) => void;
onDestroy: (props: EditorEvents['destroy']) => void;
onPaste: (e: ClipboardEvent, slice: Slice) => void
onDrop: (e: DragEvent, slice: Slice, moved: boolean) => void
}
export type HTMLContent = string;

View File

@ -149,6 +149,8 @@ class EditorInstanceManager {
onTransaction: (...args) => this.options.current.onTransaction?.(...args),
onUpdate: (...args) => this.options.current.onUpdate?.(...args),
onContentError: (...args) => this.options.current.onContentError?.(...args),
onDrop: (...args) => this.options.current.onDrop?.(...args),
onPaste: (...args) => this.options.current.onPaste?.(...args),
}
const editor = new Editor(optionsToApply)

View File

@ -75,7 +75,9 @@ export class Editor extends CoreEditor {
handlePlugins?: (newPlugin: Plugin, plugins: Plugin[]) => Plugin[],
): void {
super.registerPlugin(plugin, handlePlugins)
this.reactiveState.value = this.view.state
if (this.reactiveState) {
this.reactiveState.value = this.view.state
}
}
/**
@ -83,6 +85,8 @@ export class Editor extends CoreEditor {
*/
public unregisterPlugin(nameOrPluginKey: string | PluginKey): void {
super.unregisterPlugin(nameOrPluginKey)
this.reactiveState.value = this.view.state
if (this.reactiveState) {
this.reactiveState.value = this.view.state
}
}
}