From 54e85fd28491fcf2d5a88fb5abda1f8414ada92b Mon Sep 17 00:00:00 2001 From: HuiiBuh <46561026+HuiiBuh@users.noreply.github.com> Date: Thu, 30 Sep 2021 09:25:40 +0200 Subject: [PATCH] feat: #1898 Made the EventEmitter generic to improve the types of the tiptap events (#1959) --- .gitignore | 2 ++ packages/core/src/Editor.ts | 6 +++--- packages/core/src/EventEmitter.ts | 12 ++++++++---- packages/core/src/types.ts | 31 +++++++++++++++++++++---------- 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index fabfc461f7c..68e2522038f 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,5 @@ yarn-error.log* tests/cypress/videos /tests/cypress/screenshots +# Ignore intellij project files +.idea diff --git a/packages/core/src/Editor.ts b/packages/core/src/Editor.ts index c71ffb5c212..c242e497085 100644 --- a/packages/core/src/Editor.ts +++ b/packages/core/src/Editor.ts @@ -23,7 +23,7 @@ import { CanCommands, ChainedCommands, SingleCommands, - TextSerializer, + TextSerializer, EditorEvents, } from './types' import * as extensions from './extensions' import style from './style' @@ -34,7 +34,7 @@ export interface HTMLElement { editor?: Editor } -export class Editor extends EventEmitter { +export class Editor extends EventEmitter { private commandManager!: CommandManager @@ -195,7 +195,7 @@ export class Editor extends EventEmitter { /** * Unregister a ProseMirror plugin. * - * @param name The plugins name + * @param nameOrPluginKey The plugins name */ public unregisterPlugin(nameOrPluginKey: string | PluginKey): void { if (this.isDestroyed) { diff --git a/packages/core/src/EventEmitter.ts b/packages/core/src/EventEmitter.ts index e7eb8a7b9b2..68777c93a3d 100644 --- a/packages/core/src/EventEmitter.ts +++ b/packages/core/src/EventEmitter.ts @@ -1,8 +1,12 @@ -export default class EventEmitter { +type StringKeyOf = Extract; +type CallbackType, EVENT extends StringKeyOf> = T[EVENT] extends any[] ? T[EVENT] : [T[EVENT]]; +type CallbackFunction, EVENT extends StringKeyOf> = (...props: CallbackType) => any + +export default class EventEmitter> { private callbacks: { [key: string]: Function[] } = {} - public on(event: string, fn: Function): this { + public on>(event: EVENT, fn: CallbackFunction): this { if (!this.callbacks[event]) { this.callbacks[event] = [] } @@ -12,7 +16,7 @@ export default class EventEmitter { return this } - protected emit(event: string, ...args: any): this { + protected emit>(event: EVENT, ...args: CallbackType): this { const callbacks = this.callbacks[event] if (callbacks) { @@ -22,7 +26,7 @@ export default class EventEmitter { return this } - public off(event: string, fn?: Function): this { + public off>(event: EVENT, fn?: CallbackFunction): this { const callbacks = this.callbacks[event] if (callbacks) { diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 25682574bd2..454639f73fd 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -39,6 +39,17 @@ export type MaybeReturnType = T extends (...args: any) => any ? ReturnType : T +export interface EditorEvents { + beforeCreate: { editor: Editor } + create: { editor: Editor } + update: { editor: Editor, transaction: Transaction } + selectionUpdate: { editor: Editor, transaction: Transaction } + transaction: { editor: Editor, transaction: Transaction } + focus: { editor: Editor, event: FocusEvent, transaction: Transaction } + blur: { editor: Editor, event: FocusEvent, transaction: Transaction } + destroy: void +} + export interface EditorOptions { element: Element, content: Content, @@ -51,14 +62,14 @@ export interface EditorOptions { enableInputRules: boolean, enablePasteRules: boolean, enableCoreExtensions: boolean, - onBeforeCreate: (props: { editor: Editor }) => void, - onCreate: (props: { editor: Editor }) => void, - onUpdate: (props: { editor: Editor, transaction: Transaction }) => void, - onSelectionUpdate: (props: { editor: Editor, transaction: Transaction }) => void, - onTransaction: (props: { editor: Editor, transaction: Transaction }) => void, - onFocus: (props: { editor: Editor, event: FocusEvent, transaction: Transaction }) => void, - onBlur: (props: { editor: Editor, event: FocusEvent, transaction: Transaction }) => void, - onDestroy: () => void, + onBeforeCreate: (props: EditorEvents['beforeCreate']) => void, + onCreate: (props: EditorEvents['create']) => void, + onUpdate: (props: EditorEvents['update']) => void, + onSelectionUpdate: (props: EditorEvents['selectionUpdate']) => void, + onTransaction: (props: EditorEvents['transaction']) => void, + onFocus: (props: EditorEvents['focus']) => void, + onBlur: (props: EditorEvents['blur']) => void, + onDestroy: (props: EditorEvents['destroy']) => void, } export type HTMLContent = string @@ -122,7 +133,7 @@ export type GlobalAttributes = { export type PickValue = T[K] -export type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ((k: infer I)=>void) +export type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never @@ -133,7 +144,7 @@ export type Overwrite = Pick> & U; export type ValuesOf = T[keyof T]; -export type KeysWithTypeOf = ({[P in keyof T]: T[P] extends Type ? P : never })[keyof T] +export type KeysWithTypeOf = ({ [P in keyof T]: T[P] extends Type ? P : never })[keyof T] export type NodeViewProps = { editor: Editor,