diff --git a/packages/core/src/Editor.ts b/packages/core/src/Editor.ts index 30309009..a8834078 100644 --- a/packages/core/src/Editor.ts +++ b/packages/core/src/Editor.ts @@ -50,6 +50,11 @@ export class Editor extends EventEmitter { extensions: [], autoFocus: false, editable: true, + onInit: () => null, + onUpdate: () => null, + onTransaction: () => null, + onFocus: () => null, + onBlur: () => null, } constructor(options: Partial = {}) { @@ -67,8 +72,16 @@ export class Editor extends EventEmitter { this.createSchema() this.createView() this.injectCSS() + this.on('init', this.options.onInit) + this.on('update', this.options.onUpdate) + this.on('transaction', this.options.onTransaction) + this.on('focus', this.options.onFocus) + this.on('blur', this.options.onBlur) - window.setTimeout(() => this.commands.focus(this.options.autoFocus), 0) + window.setTimeout(() => { + this.commands.focus(this.options.autoFocus) + this.emit('init') + }, 0) } /** @@ -281,10 +294,22 @@ export class Editor extends EventEmitter { */ private dispatchTransaction(transaction: Transaction) { const state = this.state.apply(transaction) + this.view.updateState(state) this.storeSelection() this.emit('transaction', { transaction }) + const focus = transaction.getMeta('focus') + const blur = transaction.getMeta('blur') + + if (focus) { + this.emit('focus', { event: focus.event }) + } + + if (blur) { + this.emit('blur', { event: blur.event }) + } + if (!transaction.docChanged || transaction.getMeta('preventUpdate')) { return } diff --git a/packages/core/src/extensions/focusEvents.ts b/packages/core/src/extensions/focusEvents.ts index 468d105f..051571f4 100644 --- a/packages/core/src/extensions/focusEvents.ts +++ b/packages/core/src/extensions/focusEvents.ts @@ -13,19 +13,19 @@ export const FocusEvents = Extension.create({ tabindex: '0', }, handleDOMEvents: { - focus: () => { + focus: (view, event) => { editor.isFocused = true - const transaction = editor.state.tr.setMeta('focused', true) - editor.view.dispatch(transaction) + const transaction = editor.state.tr.setMeta('focus', { event }) + view.dispatch(transaction) return true }, - blur: () => { + blur: (view, event) => { editor.isFocused = false - const transaction = editor.state.tr.setMeta('focused', false) - editor.view.dispatch(transaction) + const transaction = editor.state.tr.setMeta('blur', { event }) + view.dispatch(transaction) return true }, diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index fef308bb..65d018a9 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -16,6 +16,11 @@ export interface EditorOptions { injectCSS: boolean, autoFocus: 'start' | 'end' | number | boolean | null, editable: boolean, + onInit: () => void, + onUpdate: () => void, + onTransaction: () => void, + onFocus: (props: { event: FocusEvent }) => void, + onBlur: (props: { event: FocusEvent }) => void, } export type EditorContent = string | JSON | null