From 5940a01e49b692a549f64c18c44ab5e77a3806a6 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Tue, 17 Feb 2026 12:42:31 +0400 Subject: [PATCH] Type canvas events --- packages/core/src/canvas/index.ts | 2 +- packages/core/src/canvas/types.ts | 88 ++++++++++++++++++- packages/core/src/canvas/view/CanvasView.ts | 4 +- packages/core/src/commands/view/CanvasMove.ts | 7 +- .../core/src/commands/view/ComponentDrag.ts | 3 +- .../core/src/commands/view/SelectComponent.ts | 5 +- packages/core/src/editor/types.ts | 9 +- packages/core/src/utils/Droppable.ts | 11 +-- 8 files changed, 109 insertions(+), 20 deletions(-) diff --git a/packages/core/src/canvas/index.ts b/packages/core/src/canvas/index.ts index f1d3f2486..a89badcf2 100644 --- a/packages/core/src/canvas/index.ts +++ b/packages/core/src/canvas/index.ts @@ -911,7 +911,7 @@ export default class CanvasModule extends Module { if (opts.spots || opts.all) { this.refreshSpots(); - em.trigger('canvas:updateTools'); // this should be deprecated + em.trigger(CanvasEvents.updateTools); // this should be deprecated } em.set('canvasOffset', this.getOffset()); // this should be deprecated diff --git a/packages/core/src/canvas/types.ts b/packages/core/src/canvas/types.ts index bd1a6bb28..3f5bbea0f 100644 --- a/packages/core/src/canvas/types.ts +++ b/packages/core/src/canvas/types.ts @@ -1,4 +1,10 @@ -import { SetOptions } from '../common'; +import type Component from '../dom_components/model/Component'; +import type Dragger from '../utils/Dragger'; +import type { DraggableContent } from '../utils/sorter/types'; +import type CanvasSpot from './model/CanvasSpot'; +import type Frame from './model/Frame'; +import type FrameView from './view/FrameView'; +import { ObjectAny, SetOptions } from '../common'; export interface ToScreenOption { toScreen?: boolean; @@ -24,20 +30,40 @@ export interface SetZoomOptions extends SetOptions { from?: string; } +export interface CanvasDragDataResult { + content: DraggableContent['content']; + setContent: (content: DraggableContent['content']) => void; +} + +export interface CanvasSpotEventProps { + spot: CanvasSpot; +} + +export interface CanvasFrameEventProps { + el: HTMLIFrameElement; + model: Frame; + view: FrameView; + window: Window; +} + +export interface CanvasToolsUpdateEventProps extends ObjectAny { + type: string; +} + /**{START_EVENTS}*/ export enum CanvasEvents { /** - * @event `canvas:dragenter` Something is dragged inside the canvas, `DataTransfer` instance passed as an argument. + * @event `canvas:dragenter` Something is dragged inside the canvas. `DataTransfer` instance and dragged content are passed as arguments. */ dragEnter = 'canvas:dragenter', /** - * @event `canvas:dragover` Something is dragging on the canvas, `DataTransfer` instance passed as an argument. + * @event `canvas:dragover` Something is dragging on the canvas. Triggering event is passed as an argument. */ dragOver = 'canvas:dragover', /** - * @event `canvas:dragend` When a drag operation is ended, `DataTransfer` instance passed as an argument. + * @event `canvas:dragend` When a drag operation is ended, triggering event is passed as an argument. */ dragEnd = 'canvas:dragend', @@ -123,6 +149,32 @@ export enum CanvasEvents { */ refresh = 'canvas:refresh', + /** + * @event `canvas:update` Canvas was updated. + */ + update = 'canvas:update', + updateTools = 'canvas:updateTools', + + /** + * @event `canvas:tools:update` Canvas tools were updated. + */ + toolsUpdate = 'canvas:tools:update', + + /** + * @event `canvas:move:start` Canvas move started. + */ + moveStart = 'canvas:move:start', + + /** + * @event `canvas:move` Canvas is moving. + */ + move = 'canvas:move', + + /** + * @event `canvas:move:end` Canvas move ended. + */ + moveEnd = 'canvas:move:end', + /** * @event `canvas:frame:load` Frame loaded in canvas. The event is triggered right after iframe's `onload`. * @example @@ -161,5 +213,33 @@ export enum CanvasEvents { } /**{END_EVENTS}*/ +export type CanvasEvent = `${CanvasEvents}`; + +export interface CanvasEventCallback { + [CanvasEvents.dragEnter]: [DataTransfer | null | undefined, NonNullable]; + [CanvasEvents.dragOver]: [Event]; + [CanvasEvents.dragEnd]: [Event | undefined]; + [CanvasEvents.dragData]: [DataTransfer | null | undefined, CanvasDragDataResult]; + [CanvasEvents.drop]: [DataTransfer | null | undefined, Component | Component[]]; + [CanvasEvents.spot]: []; + [CanvasEvents.spotAdd]: [CanvasSpotEventProps]; + [CanvasEvents.spotUpdate]: [CanvasSpotEventProps]; + [CanvasEvents.spotRemove]: [CanvasSpotEventProps]; + [CanvasEvents.coords]: []; + [CanvasEvents.zoom]: [{ options: SetZoomOptions }]; + [CanvasEvents.pointer]: []; + [CanvasEvents.refresh]: [CanvasRefreshOptions]; + [CanvasEvents.update]: [Event | { options: SetZoomOptions } | undefined]; + [CanvasEvents.updateTools]: []; + [CanvasEvents.toolsUpdate]: [CanvasToolsUpdateEventProps]; + [CanvasEvents.moveStart]: [Dragger]; + [CanvasEvents.move]: [Dragger]; + [CanvasEvents.moveEnd]: [Dragger]; + [CanvasEvents.frameLoad]: [CanvasFrameEventProps]; + [CanvasEvents.frameLoadHead]: [CanvasFrameEventProps]; + [CanvasEvents.frameLoadBody]: [CanvasFrameEventProps]; + [CanvasEvents.frameUnload]: [{ frame: Frame }]; +} + // need this to avoid the TS documentation generator to break export default CanvasEvents; diff --git a/packages/core/src/canvas/view/CanvasView.ts b/packages/core/src/canvas/view/CanvasView.ts index d22895e5e..fbf8152c7 100644 --- a/packages/core/src/canvas/view/CanvasView.ts +++ b/packages/core/src/canvas/view/CanvasView.ts @@ -16,7 +16,7 @@ import { import { getComponentView, getElement, getUiClass } from '../../utils/mixins'; import Canvas from '../model/Canvas'; import Frame from '../model/Frame'; -import { GetBoxRectOptions, ToWorldOption } from '../types'; +import { CanvasEvents, GetBoxRectOptions, ToWorldOption } from '../types'; import FrameView from './FrameView'; import FramesView from './FramesView'; import { ComponentsEvents } from '../../dom_components/types'; @@ -242,7 +242,7 @@ export default class CanvasView extends ModuleView { this.updateFramesArea(); this.clearOff(); toolsWrpEl.style.display = 'none'; - em.trigger('canvas:update', ev); + em.trigger(CanvasEvents.update, ev); clearTimeout(this.timerZoom); this.timerZoom = setTimeout(() => { em.stopDefault(defOpts); diff --git a/packages/core/src/commands/view/CanvasMove.ts b/packages/core/src/commands/view/CanvasMove.ts index 4040a5069..1014a1379 100644 --- a/packages/core/src/commands/view/CanvasMove.ts +++ b/packages/core/src/commands/view/CanvasMove.ts @@ -1,4 +1,5 @@ import { bindAll } from 'underscore'; +import { CanvasEvents } from '../../canvas/types'; import Dragger from '../../utils/Dragger'; import { getKeyChar, off, on } from '../../utils/dom'; import { CommandObject } from './CommandAbstract'; @@ -47,13 +48,13 @@ export default { canvasModel.set({ x, y }); }, onStart(ev, dragger) { - em.trigger('canvas:move:start', dragger); + em.trigger(CanvasEvents.moveStart, dragger); }, onDrag(ev, dragger) { - em.trigger('canvas:move', dragger); + em.trigger(CanvasEvents.move, dragger); }, onEnd(ev, dragger) { - em.trigger('canvas:move:end', dragger); + em.trigger(CanvasEvents.moveEnd, dragger); }, }); this.dragger = dragger; diff --git a/packages/core/src/commands/view/ComponentDrag.ts b/packages/core/src/commands/view/ComponentDrag.ts index d997e4d11..e3a83f323 100644 --- a/packages/core/src/commands/view/ComponentDrag.ts +++ b/packages/core/src/commands/view/ComponentDrag.ts @@ -1,4 +1,5 @@ import { keys, bindAll, each, isUndefined, debounce } from 'underscore'; +import { CanvasEvents } from '../../canvas/types'; import Dragger, { DraggerOptions } from '../../utils/Dragger'; import type { CommandObject } from './CommandAbstract'; import type Editor from '../../editor'; @@ -115,7 +116,7 @@ export default { this.elGuideInfoContentY = elInfoY.querySelector(`.${pfx}guide-info__content`) ?? undefined; em.on( - 'canvas:update frame:scroll', + `${CanvasEvents.update} frame:scroll`, debounce(() => { this.updateGuides(); opts.debug && this.guides?.forEach((item) => this.renderGuide(item)); diff --git a/packages/core/src/commands/view/SelectComponent.ts b/packages/core/src/commands/view/SelectComponent.ts index 4682109f0..5f44b79c8 100644 --- a/packages/core/src/commands/view/SelectComponent.ts +++ b/packages/core/src/commands/view/SelectComponent.ts @@ -1,5 +1,6 @@ import { bindAll, debounce, isElement } from 'underscore'; import { CanvasSpotBuiltInTypes } from '../../canvas/model/CanvasSpot'; +import { CanvasEvents } from '../../canvas/types'; import Component from '../../dom_components/model/Component'; import Toolbar from '../../dom_components/model/Toolbar'; import { ComponentsEvents } from '../../dom_components/types'; @@ -98,7 +99,7 @@ export default { em[method](`${ComponentsEvents.resize} styleable:change ${ComponentsEvents.input}`, this.updateGlobalPos, this); em[method](`${eventCmpUpdate}:toolbar`, this._upToolbar, this); em[method]('frame:updated', this.onFrameUpdated, this); - em[method]('canvas:updateTools', this.onFrameUpdated, this); + em[method](CanvasEvents.updateTools, this.onFrameUpdated, this); em[method](em.Canvas.events.refresh, this.updateAttached, this); em.Canvas.getFrames().forEach((frame) => { const { view } = frame; @@ -596,7 +597,7 @@ export default { }, 0), _trgToolUp(type: string, opts = {}) { - this.em.trigger('canvas:tools:update', { + this.em.trigger(CanvasEvents.toolsUpdate, { type, ...opts, }); diff --git a/packages/core/src/editor/types.ts b/packages/core/src/editor/types.ts index faf341c2d..1916bf24a 100644 --- a/packages/core/src/editor/types.ts +++ b/packages/core/src/editor/types.ts @@ -1,8 +1,8 @@ import { AssetEvent, AssetsEventCallback } from '../asset_manager/types'; import { BlockEvent, BlocksEventCallback } from '../block_manager/types'; -import { CanvasEvent } from '../canvas'; import { CommandEvent } from '../commands'; import { LiteralUnion } from '../common'; +import { CanvasEvent, CanvasEventCallback } from '../canvas/types'; import { DataSourceEvent, DataSourcesEventCallback } from '../data_sources/types'; import { ComponentEvent } from '../dom_components'; import { KeymapEvent } from '../keymaps'; @@ -36,7 +36,12 @@ export type EditorConfigType = EditorConfig & { pStylePrefix?: string }; export type EditorModelParam = Parameters[N]; -export interface EditorEventCallbacks extends AssetsEventCallback, BlocksEventCallback, DataSourcesEventCallback { +export interface EditorEventCallbacks + extends AssetsEventCallback, + BlocksEventCallback, + CanvasEventCallback, + DataSourcesEventCallback +{ [key: string]: any[]; } diff --git a/packages/core/src/utils/Droppable.ts b/packages/core/src/utils/Droppable.ts index 5d5a8aac7..d20831377 100644 --- a/packages/core/src/utils/Droppable.ts +++ b/packages/core/src/utils/Droppable.ts @@ -1,5 +1,6 @@ import { bindAll, indexOf } from 'underscore'; import CanvasModule from '../canvas'; +import CanvasEvents from '../canvas/types'; import { ObjectStrings } from '../common'; import Component from '../dom_components/model/Component'; import EditorModel from '../editor/model/Editor'; @@ -94,7 +95,7 @@ export default class Droppable { this.counter = 0; dragStop && dragStop(cancel || !this.over); this.__customTglEff(false); - em.trigger('canvas:dragend', ev); + em.trigger(CanvasEvents.dragEnd, ev); } handleDragLeave(ev: Event) { @@ -204,7 +205,7 @@ export default class Droppable { } this.dragStop = dragStop; - em.trigger('canvas:dragenter', dt, content); + em.trigger(CanvasEvents.dragEnter, dt, content); } handleDragEnd(model: any, dt: any) { @@ -212,7 +213,7 @@ export default class Droppable { this.over = false; if (model) { em.set('dragResult', model); - em.trigger('canvas:drop', dt, model); + em.trigger(CanvasEvents.drop, dt, model); } em.runDefault({ preserveSelected: 1 }); } @@ -223,7 +224,7 @@ export default class Droppable { */ handleDragOver(ev: Event) { ev.preventDefault(); - this.em.trigger('canvas:dragover', ev); + this.em.trigger(CanvasEvents.dragOver, ev); } /** @@ -286,7 +287,7 @@ export default class Droppable { result.content = content; }, }; - em.trigger('canvas:dragdata', dt, result); + em.trigger(CanvasEvents.dragData, dt, result); return result; } }