MindMap/frontend/src/lib/mind-elixir/src/utils/pubsub.ts

124 lines
3.1 KiB
TypeScript

import type { Arrow } from '../arrow'
import type { Summary } from '../summary'
import type { NodeObj } from '../types/index'
type NodeOperation =
| {
name: 'moveNodeIn' | 'moveDownNode' | 'moveUpNode' | 'copyNode' | 'addChild' | 'insertParent' | 'insertBefore' | 'beginEdit'
obj: NodeObj
}
| {
name: 'insertSibling'
type: 'before' | 'after'
obj: NodeObj
}
| {
name: 'reshapeNode'
obj: NodeObj
origin: NodeObj
}
| {
name: 'finishEdit'
obj: NodeObj
origin: string
}
| {
name: 'finishEditTable'
obj: NodeObj
origin: string
}
| {
name: 'moveNodeAfter' | 'moveNodeBefore' | 'moveNodeIn'
objs: NodeObj[]
toObj: NodeObj
}
type MultipleNodeOperation =
| {
name: 'removeNodes'
objs: NodeObj[]
}
| {
name: 'copyNodes'
objs: NodeObj[]
}
export type SummaryOperation =
| {
name: 'createSummary'
obj: Summary
}
| {
name: 'removeSummary'
obj: { id: string }
}
| {
name: 'finishEditSummary'
obj: Summary
}
export type ArrowOperation =
| {
name: 'createArrow'
obj: Arrow
}
| {
name: 'removeArrow'
obj: { id: string }
}
| {
name: 'finishEditArrowLabel'
obj: Arrow
}
export type Operation = NodeOperation | MultipleNodeOperation | SummaryOperation | ArrowOperation
export type OperationType = Operation['name']
export type EventMap = {
operation: (info: Operation) => void
selectNewNode: (nodeObj: NodeObj) => void
selectNodes: (nodeObj: NodeObj[]) => void
unselectNodes: (nodeObj: NodeObj[]) => void
expandNode: (nodeObj: NodeObj) => void
linkDiv: () => void
scale: (scale: number) => void
move: (data: { dx: number; dy: number }) => void
/**
* please use throttling to prevent performance degradation
*/
updateArrowDelta: (arrow: Arrow) => void
showContextMenu: (e: MouseEvent) => void
showImagePreview: (imageUrl: string, altText?: string) => void
}
export function createBus<T extends Record<string, (...args: any[]) => void> = EventMap>() {
return {
handlers: {} as Record<keyof T, ((...arg: any[]) => void)[]>,
addListener: function <K extends keyof T>(type: K, handler: T[K]) {
if (this.handlers[type] === undefined) this.handlers[type] = []
this.handlers[type].push(handler)
},
fire: function <K extends keyof T>(type: K, ...payload: Parameters<T[K]>) {
if (this.handlers[type] instanceof Array) {
const handlers = this.handlers[type]
for (let i = 0; i < handlers.length; i++) {
handlers[i](...payload)
}
}
},
removeListener: function <K extends keyof T>(type: K, handler: T[K]) {
if (!this.handlers[type]) return
const handlers = this.handlers[type]
if (!handler) {
handlers.length = 0
} else if (handlers.length) {
for (let i = 0; i < handlers.length; i++) {
if (handlers[i] === handler) {
this.handlers[type].splice(i, 1)
}
}
}
},
}
}