diff --git a/docs/api.mjs b/docs/api.mjs index 6ad7b70e2..d68d9c18f 100644 --- a/docs/api.mjs +++ b/docs/api.mjs @@ -15,13 +15,28 @@ const REPLACE_EVENTS = '{REPLACE\\_EVENTS}'; const log = (...args) => console.log(...args); +const hasTemplateLiteralType = (value) => { + if (!value || typeof value !== 'object') return false; + if (value.type === 'TemplateLiteralType') return true; + return Object.values(value).some((item) => + Array.isArray(item) ? item.some((nested) => hasTemplateLiteralType(nested)) : hasTemplateLiteralType(item), + ); +}; + +const sanitizeUnsupportedTypes = (comments = []) => + comments.map((comment) => + comment.kind === 'typedef' && hasTemplateLiteralType(comment.type) + ? { ...comment, type: { type: 'NameExpression', name: 'string' } } + : comment, + ); + const getEventsMdFromTypes = async (filePath) => { const dirname = filePath.replace(basename(filePath), ''); const typesFilePath = `${dirname}types.ts`; if (existsSync(typesFilePath)) { const resTypes = await build([typesFilePath], { shallow: true }).then((cm) => - formats.md(cm /*{ markdownToc: true }*/), + formats.md(sanitizeUnsupportedTypes(cm) /*{ markdownToc: true }*/), ); const indexFrom = resTypes.indexOf(START_EVENTS) + START_EVENTS.length; const indexTo = resTypes.indexOf(END_EVENTS); @@ -31,10 +46,12 @@ const getEventsMdFromTypes = async (filePath) => { .replace(/\n### Examples\n/gi, '') .replace(/\n## types\n/gi, '') .replace(/## /gi, '* ') + .replace(/^\* [A-Za-z][A-Za-z0-9]*Event\s*$/gm, '') .replace(/\\`/gi, '`') .replace(/##/gi, '') .replace(/\\\[/gi, '[') .replace(/\]\\\(/gi, '](') + .replace(/\n{3,}/g, '\n\n') .trim(); return result; diff --git a/docs/api/assets.md b/docs/api/assets.md index 637d1fef3..37a235080 100644 --- a/docs/api/assets.md +++ b/docs/api/assets.md @@ -85,6 +85,8 @@ editor.on('asset:custom', ({ container, assets, ... }) => { ... }); editor.on('asset', ({ event, model, ... }) => { ... }); ``` +* AssetsEventCallback + ## Methods * [open][2] diff --git a/docs/api/canvas.md b/docs/api/canvas.md index c82ef3a82..cb48c5756 100644 --- a/docs/api/canvas.md +++ b/docs/api/canvas.md @@ -24,11 +24,11 @@ canvas.setCoords(...); ``` ## Available Events -* `canvas:dragenter` Something is dragged inside the canvas, `DataTransfer` instance passed as an argument. +* `canvas:dragenter` Something is dragged inside the canvas. `DataTransfer` instance and dragged content are passed as arguments. -* `canvas:dragover` Something is dragging on the canvas, `DataTransfer` instance passed as an argument. +* `canvas:dragover` Something is dragging on the canvas. Triggering event is passed as an argument. -* `canvas:dragend` When a drag operation is ended, `DataTransfer` instance passed as an argument. +* `canvas:dragend` When a drag operation is ended, triggering event is passed as an argument. * `canvas:dragdata` On any dataTransfer parse, `DataTransfer` instance and the `result` are passed as arguments. By changing `result.content` you're able to customize what is dropped. @@ -98,6 +98,16 @@ editor.on('canvas:refresh', (canvasRefreshOptions) => { }); ``` +* `canvas:update` Canvas was updated. + +* `canvas:tools:update` Canvas tools were updated. + +* `canvas:move:start` Canvas move started. + +* `canvas:move` Canvas is moving. + +* `canvas:move:end` Canvas move ended. + * `canvas:frame:load` Frame loaded in canvas. The event is triggered right after iframe's `onload`. ```javascript diff --git a/docs/api/commands.md b/docs/api/commands.md index 20491ad7c..32ee5cbb3 100644 --- a/docs/api/commands.md +++ b/docs/api/commands.md @@ -16,7 +16,7 @@ Once the editor is instantiated you can use its API and listen to its events. Be ```js // Listen to events -editor.on('run', () => { ... }); +editor.on('command:run', () => { ... }); // Use the API const commands = editor.Commands; @@ -91,6 +91,8 @@ editor.on('command:call', ({ id, result, options, type }) => { editor.on('command:call:my-command', ({ result, options, type }) => { ... }); ``` +* CommandEventOptions + ## Methods * [add][2] diff --git a/docs/api/datasources.md b/docs/api/datasources.md index 108caa2e3..ae853a24b 100644 --- a/docs/api/datasources.md +++ b/docs/api/datasources.md @@ -113,6 +113,18 @@ const ds = dsm.get('my_data_source_id'); Returns **[DataSource]** Data source. +## getAll + +Return all data sources. + +### Examples + +```javascript +const ds = dsm.getAll(); +``` + +Returns **[Array][8]<[DataSource]>** + ## getValue Get value from data sources by path. @@ -121,6 +133,7 @@ Get value from data sources by path. * `path` **[String][7]** Path to value. * `defValue` **any** Default value if the path is not found. +* `opts` **{context: Record<[string][7], any>?}?** Returns **any** const value = dsm.getValue('ds\_id.record\_id.propName', 'defaultValue'); @@ -139,7 +152,7 @@ Set value in data sources by path. dsm.setValue('ds_id.record_id.propName', 'new value'); ``` -Returns **[Boolean][8]** Returns true if the value was set successfully +Returns **[Boolean][9]** Returns true if the value was set successfully ## remove @@ -183,7 +196,7 @@ data record, and optional property path. Store data sources to a JSON object. -Returns **[Array][9]** Stored data sources. +Returns **[Array][8]** Stored data sources. ## load @@ -209,6 +222,6 @@ Returns **[Object][6]** Loaded data sources. [7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String -[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean +[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array -[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array +[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean diff --git a/docs/api/device_manager.md b/docs/api/device_manager.md index 4a6f6e914..47c2c2a0e 100644 --- a/docs/api/device_manager.md +++ b/docs/api/device_manager.md @@ -31,16 +31,16 @@ editor.on('device:add', (device) => { ... }); editor.on('device:remove', (device) => { ... }); ``` -* `device:select` A new device is selected. The `Device` is passed as an argument. +* `device:select` A new device is selected. Current and previous `Device` are passed as arguments. ```javascript -editor.on('device:select', (device) => { ... }); +editor.on('device:select', (newDevice, prevDevice) => { ... }); ``` -* `device:update` Device updated. The `Device` and the object containing changes are passed as arguments. +* `device:update` Device updated. The `Device`, changed properties, and update options are passed as arguments. ```javascript -editor.on('device:update', (device) => { ... }); +editor.on('device:update', (device, changes, options) => { ... }); ``` * `device` Catch-all event for all the events mentioned above. diff --git a/docs/api/layer_manager.md b/docs/api/layer_manager.md index 8ae97605e..ea5f42fc1 100644 --- a/docs/api/layer_manager.md +++ b/docs/api/layer_manager.md @@ -38,6 +38,12 @@ editor.on('layer:component', (component, opts) => { ... }); editor.on('layer:custom', ({ container, root }) => { ... }); ``` +* `layer:render` Component layer rendered. Object with component and rendered layer element is passed as an argument. + +```javascript +editor.on('layer:render', ({ component, el }) => { ... }); +``` + ## Methods * [setRoot][1] diff --git a/docs/api/rich_text_editor.md b/docs/api/rich_text_editor.md index d002ad9fd..870a075bc 100644 --- a/docs/api/rich_text_editor.md +++ b/docs/api/rich_text_editor.md @@ -40,6 +40,8 @@ editor.on('rte:disable', (view, rte) => { ... }); editor.on('rte:custom', ({ enabled, container, actions }) => { ... }); ``` +* RichTextEditorEventCallback + ## Methods * [add][3] diff --git a/docs/api/selector_manager.md b/docs/api/selector_manager.md index 9d5630ba6..6ad1fc8ed 100644 --- a/docs/api/selector_manager.md +++ b/docs/api/selector_manager.md @@ -84,8 +84,6 @@ editor.on('selector:custom', ({ states, selected, container }) => { ... }); editor.on('selector', ({ event, selector, changes, ... }) => { ... }); ``` -* SelectorStringObject - ## Methods * [getConfig][2] diff --git a/packages/core/src/asset_manager/index.ts b/packages/core/src/asset_manager/index.ts index 5dd338121..523c3cf5a 100644 --- a/packages/core/src/asset_manager/index.ts +++ b/packages/core/src/asset_manager/index.ts @@ -40,7 +40,7 @@ import { ProjectData } from '../storage_manager'; import defConfig, { AssetManagerConfig } from './config/config'; import Asset from './model/Asset'; import Assets from './model/Assets'; -import AssetsEvents, { AssetAddInput, AssetOpenOptions, AssetProps } from './types'; +import AssetsEvents, { AssetAddInput, AssetOpenOptions, AssetProps, AssetsCustomData } from './types'; import AssetsView from './view/AssetsView'; import FileUploaderView from './view/FileUploader'; @@ -381,7 +381,7 @@ export default class AssetManager extends ItemManagerModule this.close(), remove: (asset: string | Asset, opts?: Record) => this.remove(asset, opts), - select: (asset: Asset, complete: boolean) => { + select: (asset: Asset, complete?: boolean) => { const res = this.add(asset); isFunction(bhv.select) && bhv.select(res, complete); }, 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..7696aaa7b 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'; @@ -98,7 +98,7 @@ export default class CanvasView extends ModuleView { this.clsUnscale = `${pfx}unscale`; this._initFrames(); this.listenTo(em, events.refresh, this.clearOff); - this.listenTo(em, 'component:selected', this.checkSelected); + this.listenTo(em, ComponentsEvents.selected, this.checkSelected); this.listenTo(em, `${events.coords} ${events.zoom}`, this.updateFrames); this.listenTo(model, 'change:frames', this._onFramesUpdate); this.toggleListeners(true); @@ -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/canvas/view/FrameView.ts b/packages/core/src/canvas/view/FrameView.ts index d2b16ea4c..9542b347e 100644 --- a/packages/core/src/canvas/view/FrameView.ts +++ b/packages/core/src/canvas/view/FrameView.ts @@ -11,7 +11,7 @@ import { append, appendVNodes, createCustomEvent, createEl, motionsEv, off, on } import { hasDnd, setViewEl } from '../../utils/mixins'; import Canvas from '../model/Canvas'; import Frame from '../model/Frame'; -import CanvasEvents from '../types'; +import CanvasEvents, { CanvasFrameEventProps } from '../types'; import FrameWrapView from './FrameWrapView'; export default class FrameView extends ModuleView { @@ -252,7 +252,7 @@ export default class FrameView extends ModuleView { renderScripts() { const { el, model, em } = this; const evLoad = 'frame:load'; - const evOpts: ObjectAny = { el, model, view: this }; + const evOpts = { el, model, view: this } as unknown as CanvasFrameEventProps; const canvas = this.getCanvasModel(); const appendScript = (scripts: any[]) => { if (scripts.length > 0) { diff --git a/packages/core/src/commands/index.ts b/packages/core/src/commands/index.ts index 87018e5f7..a9c65b972 100644 --- a/packages/core/src/commands/index.ts +++ b/packages/core/src/commands/index.ts @@ -12,7 +12,7 @@ * * ```js * // Listen to events - * editor.on('run', () => { ... }); + * editor.on('command:run', () => { ... }); * * // Use the API * const commands = editor.Commands; @@ -39,12 +39,12 @@ import { isFunction, includes } from 'underscore'; import CommandAbstract, { Command, CommandOptions, CommandObject, CommandFunction } from './view/CommandAbstract'; import defConfig, { CommandsConfig } from './config/config'; import { Module } from '../abstract'; -import Component, { eventDrag } from '../dom_components/model/Component'; +import Component from '../dom_components/model/Component'; +import { ComponentsEvents } from '../dom_components/types'; import type Editor from '../editor/model/Editor'; import type { ObjectAny } from '../common'; import CommandsEvents from './types'; - -export type CommandEvent = 'run' | 'stop' | `run:${string}` | `stop:${string}` | `abort:${string}`; +export type { CommandEvent } from './types'; const commandsDef = [ ['preview', 'Preview', 'preview'], @@ -75,9 +75,9 @@ const commandsDef = [ const defComOptions = { preserveSelected: 1 }; -export const getOnComponentDragStart = (em: Editor) => (data: any) => em.trigger(`${eventDrag}:start`, data); +export const getOnComponentDragStart = (em: Editor) => (data: any) => em.trigger(ComponentsEvents.dragStart, data); -export const getOnComponentDrag = (em: Editor) => (data: any) => em.trigger(eventDrag, data); +export const getOnComponentDrag = (em: Editor) => (data: any) => em.trigger(ComponentsEvents.drag, data); export const getOnComponentDragEnd = (em: Editor, targets: Component[], opts: { altMode?: boolean } = {}) => @@ -87,7 +87,7 @@ export const getOnComponentDragEnd = em.setSelected(targets); targets[0].emitUpdate(); }); - em.trigger(`${eventDrag}:end`, data); + em.trigger(ComponentsEvents.dragEnd, data); // Defer selectComponent in order to prevent canvas "freeze" #2692 setTimeout(() => em.runDefault(defComOptions)); diff --git a/packages/core/src/commands/types.ts b/packages/core/src/commands/types.ts index aa6b6f9b1..d56f3e9be 100644 --- a/packages/core/src/commands/types.ts +++ b/packages/core/src/commands/types.ts @@ -78,5 +78,42 @@ export enum CommandsEvents { } /**{END_EVENTS}*/ +export type CommandEventOptions = Record; + +export interface CommandEventBeforeData { + options: CommandEventOptions; +} + +export interface CommandEventData { + id: string | number; + result: any; + options: CommandEventOptions; +} + +export interface CommandCallEventData extends CommandEventData { + type: 'run' | 'stop'; +} + +export type CommandEvent = + | `${CommandsEvents.run}` + | `${CommandsEvents.stop}` + | `${CommandsEvents.call}` + | `${CommandsEvents.runCommand}${string}` + | `${CommandsEvents.runBeforeCommand}${string}` + | `${CommandsEvents.abort}${string}` + | `${CommandsEvents.stopCommand}${string}` + | `${CommandsEvents.stopBeforeCommand}${string}` + | `${CommandsEvents.callCommand}${string}`; + +export interface CommandsEventCallback { + [CommandsEvents.run]: [CommandEventData]; + [CommandsEvents.stop]: [CommandEventData]; + [CommandsEvents.call]: [CommandCallEventData]; + [key: `${CommandsEvents.runCommand}${string}`]: [CommandEventData | CommandEventBeforeData]; + [key: `${CommandsEvents.abort}${string}`]: [CommandEventBeforeData]; + [key: `${CommandsEvents.stopCommand}${string}`]: [CommandEventData | CommandEventBeforeData]; + [key: `${CommandsEvents.callCommand}${string}`]: [CommandCallEventData]; +} + // need this to avoid the TS documentation generator to break export default CommandsEvents; 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/CommandAbstract.ts b/packages/core/src/commands/view/CommandAbstract.ts index d6c692f1c..c9e9356a4 100644 --- a/packages/core/src/commands/view/CommandAbstract.ts +++ b/packages/core/src/commands/view/CommandAbstract.ts @@ -2,7 +2,7 @@ import CanvasModule from '../../canvas'; import { Model, ObjectAny } from '../../common'; import Editor from '../../editor'; import EditorModel from '../../editor/model/Editor'; -import CommandsEvents from '../types'; +import CommandsEvents, { type CommandCallEventData, type CommandEventData } from '../types'; interface ICommand { run?: CommandAbstract['run']; @@ -120,8 +120,8 @@ export default class CommandAbstract extends Model { const sender = options.sender || editor; const result = this.run(editor, sender, options); - const data = { id, result, options }; - const dataCall = { ...data, type: 'run' }; + const data: CommandEventData = { id, result, options }; + const dataCall: CommandCallEventData = { ...data, type: 'run' }; if (!this.noStop) { editor.Commands.active[id] = result; @@ -146,8 +146,8 @@ export default class CommandAbstract extends Model { const sender = options.sender || editor; editor.trigger(`${CommandsEvents.stopBeforeCommand}${id}`, { options }); const result = this.stop(editor, sender, options); - const data = { id, result, options }; - const dataCall = { ...data, type: 'stop' }; + const data: CommandEventData = { id, result, options }; + const dataCall: CommandCallEventData = { ...data, type: 'stop' }; delete editor.Commands.active[id]; editor.trigger(`${CommandsEvents.stopCommand}${id}`, data); editor.trigger(`${CommandsEvents.callCommand}${id}`, dataCall); 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/OpenTraitManager.ts b/packages/core/src/commands/view/OpenTraitManager.ts index cb458a6e9..1076f57ff 100644 --- a/packages/core/src/commands/view/OpenTraitManager.ts +++ b/packages/core/src/commands/view/OpenTraitManager.ts @@ -1,5 +1,6 @@ import { CommandObject } from './CommandAbstract'; import { $ } from '../../common'; +import { ComponentsEvents } from '../../dom_components/types'; export default { run(editor, sender) { @@ -40,7 +41,7 @@ export default { panelC?.set('appendContent', this.$cn.get(0)).trigger('change:appendContent'); this.target = editor.getModel(); - this.listenTo(this.target, 'component:toggled', this.toggleTm); + this.listenTo(this.target, ComponentsEvents.toggled, this.toggleTm); } this.toggleTm(); diff --git a/packages/core/src/commands/view/PasteComponent.ts b/packages/core/src/commands/view/PasteComponent.ts index cb9585ca5..f97f926b3 100644 --- a/packages/core/src/commands/view/PasteComponent.ts +++ b/packages/core/src/commands/view/PasteComponent.ts @@ -1,5 +1,6 @@ import { isArray, contains } from 'underscore'; import Component from '../../dom_components/model/Component'; +import { ComponentsEvents } from '../../dom_components/types'; import { CommandObject } from './CommandAbstract'; import Editor from '../../editor'; @@ -33,7 +34,7 @@ export default { } added = isArray(added) ? added : [added]; - added.forEach((add) => ed.trigger('component:paste', add)); + added.forEach((add) => ed.trigger(ComponentsEvents.paste, add)); }); lastSelected.emitUpdate(); diff --git a/packages/core/src/commands/view/SelectComponent.ts b/packages/core/src/commands/view/SelectComponent.ts index 4682109f0..e22849fc8 100644 --- a/packages/core/src/commands/view/SelectComponent.ts +++ b/packages/core/src/commands/view/SelectComponent.ts @@ -1,8 +1,9 @@ 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'; +import { ComponentResizeInitEventData, ComponentsEvents } from '../../dom_components/types'; import ToolbarView from '../../dom_components/view/ToolbarView'; import { isDoc, isTaggableNode, isVisible, off, on } from '../../utils/dom'; import { getComponentModel, getComponentView, hasWin, isObject } from '../../utils/mixins'; @@ -93,12 +94,12 @@ export default { }; methods[method](window, 'resize', this.onFrameUpdated); methods[method](listenToEl, 'scroll', this.onContainerChange); - em[method](`component:toggled ${eventCmpUpdate} undo redo`, this.onSelect, this); + em[method](`${ComponentsEvents.toggled} ${eventCmpUpdate} undo redo`, this.onSelect, this); em[method]('change:componentHovered', this.onHovered, this); 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; @@ -403,7 +404,7 @@ export default { component, hasCustomResize, resizable, - }; + } as ComponentResizeInitEventData; component && em.trigger(ComponentsEvents.resizeInit, initEventOpts); const resizableResult = initEventOpts.resizable; @@ -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/device_manager/types.ts b/packages/core/src/device_manager/types.ts index e9d0aa7fb..855bd67ab 100644 --- a/packages/core/src/device_manager/types.ts +++ b/packages/core/src/device_manager/types.ts @@ -1,3 +1,12 @@ +import { + EventCallbackAdd, + EventCallbackAll, + EventCallbackRemove, + EventCallbackRemoveBefore, + SetOptions, +} from '../common'; +import Device, { DeviceProperties } from './model/Device'; + /**{START_EVENTS}*/ export enum DeviceEvents { /** @@ -17,17 +26,17 @@ export enum DeviceEvents { removeBefore = 'device:remove:before', /** - * @event `device:select` A new device is selected. The `Device` is passed as an argument. + * @event `device:select` A new device is selected. Current and previous `Device` are passed as arguments. * @example - * editor.on('device:select', (device) => { ... }); + * editor.on('device:select', (newDevice, prevDevice) => { ... }); */ select = 'device:select', selectBefore = 'device:select:before', /** - * @event `device:update` Device updated. The `Device` and the object containing changes are passed as arguments. + * @event `device:update` Device updated. The `Device`, changed properties, and update options are passed as arguments. * @example - * editor.on('device:update', (device) => { ... }); + * editor.on('device:update', (device, changes, options) => { ... }); */ update = 'device:update', @@ -40,5 +49,16 @@ export enum DeviceEvents { } /**{END_EVENTS}*/ +export type DeviceEvent = `${DeviceEvents}`; + +export interface DevicesEventCallback { + [DeviceEvents.add]: EventCallbackAdd; + [DeviceEvents.remove]: EventCallbackRemove; + [DeviceEvents.removeBefore]: EventCallbackRemoveBefore; + [DeviceEvents.select]: [Device | null | undefined, Device | null | undefined]; + [DeviceEvents.update]: [Device, Partial, SetOptions]; + [DeviceEvents.all]: EventCallbackAll; +} + // This is necessary to prevent the TS documentation generator from breaking. export default DeviceEvents; diff --git a/packages/core/src/dom_components/index.ts b/packages/core/src/dom_components/index.ts index 807492318..f50e9cfa6 100644 --- a/packages/core/src/dom_components/index.ts +++ b/packages/core/src/dom_components/index.ts @@ -131,24 +131,7 @@ import ComponentView, { IComponentView } from './view/ComponentView'; import ComponentWrapperView from './view/ComponentWrapperView'; import ComponentsView from './view/ComponentsView'; -export type ComponentEvent = - | 'component:create' - | 'component:mount' - | 'component:add' - | 'component:remove' - | 'component:remove:before' - | 'component:clone' - | 'component:update' - | 'component:styleUpdate' - | 'component:selected' - | 'component:deselected' - | 'component:toggled' - | 'component:type:add' - | 'component:type:update' - | 'component:drag:start' - | 'component:drag' - | 'component:drag:end' - | 'component:resize'; +export type { ComponentEvent } from './types'; export interface ComponentModelDefinition extends IComponent { defaults?: ComponentDefinition | (() => ComponentDefinition); @@ -634,8 +617,8 @@ export default class ComponentManager extends ItemManagerModule this.em.trigger(event, component, opts)); + [ComponentsEvents.selected, ComponentsEvents.toggled].forEach((event) => this.em.trigger(event, component, opts)); } } @@ -698,7 +681,9 @@ export default class ComponentManager extends ItemManagerModule this.em.trigger(event, component, opts)); + [ComponentsEvents.deselected, ComponentsEvents.toggled].forEach((event) => + this.em.trigger(event, component, opts), + ); } } @@ -775,7 +760,7 @@ export default class ComponentManager extends ItemManagerModule { export const avoidInline = (em: EditorModel) => !!em?.getConfig().avoidInlineStyle; -export const eventDrag = 'component:drag'; +export const eventDrag = ComponentsEvents.drag; export const keySymbols = '__symbols'; export const keySymbol = '__symbol'; export const keySymbolOvrd = '__symbol_ovrd'; @@ -1048,7 +1048,7 @@ export default class Component extends StyleableModel { const resolvedAttributes = this.dataResolverWatchers.getValueOrResolver('attributes', attrs); traits.length && this.setAttributes(resolvedAttributes); this.on(event, this.initTraits); - changed && em && em.trigger('component:toggled'); + changed && em && em.trigger(ComponentsEvents.toggled); return this; } @@ -1310,7 +1310,7 @@ export default class Component extends StyleableModel { updateTrait(id: string, props: Partial) { const trait = this.getTrait(id); trait && trait.set(props); - this.em?.trigger('component:toggled'); + this.em?.trigger(ComponentsEvents.toggled); return this; } @@ -1341,7 +1341,7 @@ export default class Component extends StyleableModel { const toRemove = ids.map((id) => this.getTrait(id)); const { traits } = this; const removed = toRemove.length ? traits.remove(toRemove) : []; - this.em?.trigger('component:toggled'); + this.em?.trigger(ComponentsEvents.toggled); return isArray(removed) ? removed : [removed]; } @@ -1361,7 +1361,7 @@ export default class Component extends StyleableModel { addTrait(trait: Parameters[0], opts: AddOptions = {}) { this.__loadTraits(); const added = this.traits.add(trait, opts); - this.em?.trigger('component:toggled'); + this.em?.trigger(ComponentsEvents.toggled); return isArray(added) ? added : [added]; } @@ -1467,7 +1467,7 @@ export default class Component extends StyleableModel { } } - const event = 'component:clone'; + const event = ComponentsEvents.clone; em && em.trigger(event, cloned); this.trigger(event, cloned); diff --git a/packages/core/src/dom_components/model/ComponentVideo.ts b/packages/core/src/dom_components/model/ComponentVideo.ts index 1bd420723..4288d25c4 100644 --- a/packages/core/src/dom_components/model/ComponentVideo.ts +++ b/packages/core/src/dom_components/model/ComponentVideo.ts @@ -1,5 +1,6 @@ import { ObjectAny } from '../../common'; import { isDef, isEmptyObj, toLowerCase } from '../../utils/mixins'; +import { ComponentsEvents } from '../types'; import ComponentImage from './ComponentImage'; import { ComponentOptions, ComponentProperties } from './types'; @@ -90,7 +91,7 @@ export default class ComponentVideo extends ComponentImage { this.set({ tagName }, { silent: true }); // avoid break in view // @ts-ignore this.set({ traits }); - em.get('ready') && em.trigger('component:toggled'); + em.get('ready') && em.trigger(ComponentsEvents.toggled); } /** diff --git a/packages/core/src/dom_components/model/Components.ts b/packages/core/src/dom_components/model/Components.ts index f62832eaf..74f6273b3 100644 --- a/packages/core/src/dom_components/model/Components.ts +++ b/packages/core/src/dom_components/model/Components.ts @@ -168,7 +168,7 @@ Component> { Components.cloneCssRules(em, fromDefOpts.visitedCmps); this.reset(newCmps, opts as any); - em?.trigger('component:content', parent, opts, input); + em?.trigger(ComponentsEvents.content, parent, opts, input); (parent as ComponentText).__checkInnerChilds?.(); } diff --git a/packages/core/src/dom_components/model/Symbols.ts b/packages/core/src/dom_components/model/Symbols.ts index 71da66f1f..4332647f0 100644 --- a/packages/core/src/dom_components/model/Symbols.ts +++ b/packages/core/src/dom_components/model/Symbols.ts @@ -50,7 +50,7 @@ export default class Symbols extends Components { const { em, events } = this; const eventType = isInstance ? events.symbolInstance : events.symbolMain; em.trigger(event, props); - em.trigger(eventType, { ...props, event }); + em.trigger(eventType, { ...props, event } as any); this.refreshDbn(); } } diff --git a/packages/core/src/dom_components/types.ts b/packages/core/src/dom_components/types.ts index d0c5782fd..3df7798b1 100644 --- a/packages/core/src/dom_components/types.ts +++ b/packages/core/src/dom_components/types.ts @@ -1,5 +1,24 @@ -import { AddOptions, OptionAsDocument, WithHTMLParserOptions } from '../common'; -import Component from './model/Component'; +import type { + AddOptions, + EventCallbackAdd, + EventCallbackRemoveBefore, + ObjectAny, + OptionAsDocument, + WithHTMLParserOptions, +} from '../common'; +import type CssRule from '../css_composer/model/CssRule'; +import type { + ComponentResizeEventEndProps, + ComponentResizeEventMoveProps, + ComponentResizeEventStartProps, + ComponentResizeEventUpdateProps, +} from '../commands/view/Resize'; +import type { StyleProps } from '../domain_abstract/model/StyleableModel'; +import type Selector from '../selector_manager/model/Selector'; +import type Component from './model/Component'; +import type { ResetFromStringOptions } from './model/Components'; +import type { ComponentOptions, ComponentStackItem } from './model/types'; +import type ComponentView from './view/ComponentView'; export enum ActionLabelComponents { remove = 'component:remove', @@ -38,6 +57,7 @@ export enum ComponentsEvents { remove = 'component:remove', removeBefore = 'component:remove:before', removed = 'component:removed', + clone = 'component:clone', /** * @event `component:create` Component created. @@ -52,6 +72,7 @@ export enum ComponentsEvents { * editor.on('component:update', (component) => { ... }); */ update = 'component:update', + updateProperty = 'component:update:', updateInside = 'component:update-inside', /** @@ -69,6 +90,20 @@ export enum ComponentsEvents { */ select = 'component:select', selectBefore = 'component:select:before', + selected = 'component:selected', + deselected = 'component:deselected', + toggled = 'component:toggled', + hover = 'component:hover', + hoverBefore = 'component:hover:before', + hovered = 'component:hovered', + unhovered = 'component:unhovered', + paste = 'component:paste', + syncStyle = 'component:sync-style', + typeAdd = 'component:type:add', + typeUpdate = 'component:type:update', + dragStart = 'component:drag:start', + drag = 'component:drag', + dragEnd = 'component:drag:end', /** * @event `component:mount` Component is mounted in the canvas. @@ -105,6 +140,7 @@ export enum ComponentsEvents { * editor.on('component:input', (component) => { ... }); */ input = 'component:input', + content = 'component:content', /** * @event `component:resize` Component resized. This event is triggered when the component is resized in the canvas. @@ -214,3 +250,149 @@ export enum ComponentsEvents { */ symbol = 'symbol', } + +type ComponentEventStatic = Exclude< + `${ComponentsEvents}`, + `${ComponentsEvents.updateProperty}` | `${ComponentsEvents.styleUpdateProperty}` +>; + +type SymbolMainEvent = + | ComponentsEvents.symbolMainAdd + | ComponentsEvents.symbolMainUpdate + | ComponentsEvents.symbolMainUpdateDeep + | ComponentsEvents.symbolMainRemove; + +type SymbolInstanceEvent = ComponentsEvents.symbolInstanceAdd | ComponentsEvents.symbolInstanceRemove; + +export type ComponentEvent = + | ComponentEventStatic + | `${ComponentsEvents.updateProperty}${string}` + | `${ComponentsEvents.styleUpdateProperty}${string}`; + +export interface ComponentScriptEventData { + component: Component; + view: ComponentView; + el: HTMLElement; +} + +export interface ComponentStyleUpdateEventData { + style: StyleProps; +} + +export interface ComponentUpdateEventData { + component: Component; + changed: ObjectAny; + options: ObjectAny; +} + +export interface ComponentTypeEventData extends Partial> { + id: string; + [key: string]: any; +} + +export interface ComponentDragEventData { + target?: Component; + parent?: Component; + index?: number; + cancelled?: boolean; + [key: string]: unknown; +} + +export interface ComponentResizeEventEndData { + type: 'end'; + component: Component; + el: HTMLElement; +} + +export type ComponentResizeEventData = + | ({ type: 'start' } & ComponentResizeEventStartProps) + | ({ type: 'move' } & ComponentResizeEventMoveProps) + | ComponentResizeEventEndData; + +export interface ComponentResizeInitEventData { + component: Component; + hasCustomResize: boolean; + resizable: Component['resizable']; +} + +export interface ComponentRemovedEventData { + removeOptions: ObjectAny; +} + +export interface ComponentSyncStyleEventData { + component: Component | undefined; + selectors: Selector[]; + mediaText: string; + rule: CssRule; + ruleComponents: CssRule[]; + state: string; +} + +export interface SymbolEventData { + component: Component; + changed?: ObjectAny; + options?: ObjectAny; +} + +export interface SymbolMainEventData extends SymbolEventData { + event: SymbolMainEvent; +} + +export interface SymbolInstanceEventData extends SymbolEventData { + event: SymbolInstanceEvent; +} + +export interface ComponentsEventCallback { + [ComponentsEvents.add]: EventCallbackAdd; + [ComponentsEvents.remove]: [Component]; + [ComponentsEvents.removeBefore]: EventCallbackRemoveBefore; + [ComponentsEvents.removed]: [Component, ComponentRemovedEventData | undefined]; + [ComponentsEvents.clone]: [Component]; + [ComponentsEvents.create]: [Component, ComponentOptions]; + [ComponentsEvents.update]: [Component, ...any[]]; + [ComponentsEvents.updateInside]: [ComponentUpdateEventData]; + [ComponentsEvents.styleUpdate]: [Component, ComponentStyleUpdateEventData]; + [ComponentsEvents.select]: [Component, ObjectAny]; + [ComponentsEvents.selectBefore]: [Component, ObjectAny]; + [ComponentsEvents.selected]: [Component, ObjectAny]; + [ComponentsEvents.deselected]: [Component, ObjectAny]; + [ComponentsEvents.toggled]: [Component?, ObjectAny?]; + [ComponentsEvents.hover]: [Component | undefined, ObjectAny]; + [ComponentsEvents.hoverBefore]: [Component, ObjectAny]; + [ComponentsEvents.hovered]: [Component, ObjectAny]; + [ComponentsEvents.unhovered]: [Component, ObjectAny]; + [ComponentsEvents.paste]: [Component]; + [ComponentsEvents.syncStyle]: [ComponentSyncStyleEventData]; + [ComponentsEvents.typeAdd]: [ComponentTypeEventData]; + [ComponentsEvents.typeUpdate]: [ComponentTypeEventData]; + [ComponentsEvents.dragStart]: [ComponentDragEventData]; + [ComponentsEvents.drag]: [ComponentDragEventData]; + [ComponentsEvents.dragEnd]: [ComponentDragEventData]; + [ComponentsEvents.mount]: [Component]; + [ComponentsEvents.scriptMount]: [ComponentScriptEventData]; + [ComponentsEvents.scriptMountBefore]: [ComponentScriptEventData]; + [ComponentsEvents.scriptUnmount]: [ComponentScriptEventData]; + [ComponentsEvents.render]: [ComponentScriptEventData]; + [ComponentsEvents.input]: [Component]; + [ComponentsEvents.content]: [Component | undefined, ResetFromStringOptions, string]; + [ComponentsEvents.resize]: [ComponentResizeEventData]; + [ComponentsEvents.resizeStart]: [ComponentResizeEventStartProps | ComponentResizeEventMoveProps]; + [ComponentsEvents.resizeMove]: [ComponentResizeEventMoveProps]; + [ComponentsEvents.resizeEnd]: [ComponentResizeEventEndProps]; + [ComponentsEvents.resizeUpdate]: [ComponentResizeEventUpdateProps]; + [ComponentsEvents.resizeInit]: [ComponentResizeInitEventData]; + [ComponentsEvents.symbolMainAdd]: [SymbolEventData]; + [ComponentsEvents.symbolMainUpdate]: [ComponentUpdateEventData]; + [ComponentsEvents.symbolMainUpdateDeep]: [ComponentUpdateEventData]; + [ComponentsEvents.symbolMainRemove]: [SymbolEventData]; + [ComponentsEvents.symbolMain]: [SymbolMainEventData]; + [ComponentsEvents.symbolInstanceAdd]: [SymbolEventData]; + [ComponentsEvents.symbolInstanceRemove]: [SymbolEventData]; + [ComponentsEvents.symbolInstance]: [SymbolInstanceEventData]; + [ComponentsEvents.symbol]: []; + [key: `${ComponentsEvents.updateProperty}${string}`]: [Component, ...any[]]; + [key: `${ComponentsEvents.styleUpdateProperty}${string}`]: [Component, ComponentStyleUpdateEventData]; +} + +// need this to avoid the TS documentation generator to break +export default ComponentsEvents; diff --git a/packages/core/src/domain_abstract/ui/InputColor.ts b/packages/core/src/domain_abstract/ui/InputColor.ts index 051dffab5..3776c168d 100644 --- a/packages/core/src/domain_abstract/ui/InputColor.ts +++ b/packages/core/src/domain_abstract/ui/InputColor.ts @@ -1,4 +1,5 @@ import { isUndefined } from 'underscore'; +import { ComponentsEvents } from '../../dom_components/types'; import ColorPicker from '../../utils/ColorPicker'; import $ from '../../utils/cash-dom'; import Input from './Input'; @@ -166,7 +167,7 @@ export default class InputColor extends Input { }); if (em && em.on!) { - this.listenTo(em, 'component:selected', () => { + this.listenTo(em, ComponentsEvents.selected, () => { this.movedColor && handleChange(this.movedColor); changed = true; this.movedColor = ''; diff --git a/packages/core/src/editor/model/Editor.ts b/packages/core/src/editor/model/Editor.ts index 1dc90fee5..7c0b89815 100644 --- a/packages/core/src/editor/model/Editor.ts +++ b/packages/core/src/editor/model/Editor.ts @@ -46,6 +46,7 @@ import DataSourceManager from '../../data_sources'; import { ComponentsEvents } from '../../dom_components/types'; import { InitEditorConfig } from '../..'; import { EditorEvents, SelectComponentOptions } from '../types'; +import type { EditorEvent, EditorEventCallbacks, EditorEventHandler } from '../types'; Backbone.$ = $; @@ -242,6 +243,25 @@ export default class EditorModel extends Model { return this.get('DataSources'); } + on(event: E, callback: EditorEventHandler, context?: any) { + return super.on(event, callback, context); + } + + once(event: E, callback: EditorEventHandler, context?: any) { + return super.once(event, callback, context); + } + + off(event?: E, callback?: EditorEventHandler, context?: any) { + return super.off(event, callback, context); + } + + trigger( + event: E, + ...args: E extends keyof EditorEventCallbacks ? EditorEventCallbacks[E] : any[] + ) { + return super.trigger(event, ...args); + } + constructor(conf: EditorConfig = {}) { super(); this._config = conf; @@ -284,11 +304,11 @@ export default class EditorModel extends Model { toLog.forEach((e) => this.listenLog(e as keyof typeof logs)); // Deprecations - [{ from: 'change:selectedComponent', to: 'component:toggled' }].forEach((event) => { + [{ from: 'change:selectedComponent', to: ComponentsEvents.toggled }].forEach((event) => { const eventFrom = event.from; const eventTo = event.to; this.listenTo(this, eventFrom, (...args) => { - this.trigger(eventTo, ...args); + this.trigger(eventTo, ...(args as any)); this.logWarning(`The event '${eventFrom}' is deprecated, replace it with '${eventTo}'`); }); }); @@ -492,8 +512,8 @@ export default class EditorModel extends Model { * */ componentHovered(editor: any, component: any, options: any) { const prev = this.previous('componentHovered'); - prev && this.trigger('component:unhovered', prev, options); - component && this.trigger('component:hovered', component, options); + prev && this.trigger(ComponentsEvents.unhovered, prev, options); + component && this.trigger(ComponentsEvents.hovered, component, options); } /** @@ -711,9 +731,8 @@ export default class EditorModel extends Model { return upHovered(); } - const ev = 'component:hover'; opts.forceChange && upHovered(); - this.trigger(`${ev}:before`, cmp, opts); + this.trigger(ComponentsEvents.hoverBefore, cmp, opts); // Check for valid hoverable if (!cmp.get('hoverable')) { @@ -728,7 +747,7 @@ export default class EditorModel extends Model { if (!opts.abort) { upHovered(cmp, opts); - this.trigger(ev, cmp, opts); + this.trigger(ComponentsEvents.hover, cmp, opts); } } diff --git a/packages/core/src/editor/types.ts b/packages/core/src/editor/types.ts index faf341c2d..31691b7e5 100644 --- a/packages/core/src/editor/types.ts +++ b/packages/core/src/editor/types.ts @@ -1,34 +1,54 @@ 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 type { LiteralUnion, ObjectAny } from '../common'; +import { CanvasEvent, CanvasEventCallback } from '../canvas/types'; +import { CommandEvent, CommandsEventCallback } from '../commands/types'; import { DataSourceEvent, DataSourcesEventCallback } from '../data_sources/types'; -import { ComponentEvent } from '../dom_components'; -import { KeymapEvent } from '../keymaps'; -import { ModalEvent } from '../modal_dialog'; -import { RichTextEditorEvent } from '../rich_text_editor'; -import { SelectorEvent } from '../selector_manager'; -import { StyleManagerEvent } from '../style_manager'; +import { DeviceEvent, DevicesEventCallback } from '../device_manager/types'; +import { ComponentEvent, ComponentsEventCallback } from '../dom_components/types'; +import { I18nEvent, I18nEventCallback } from '../i18n/types'; +import { KeymapEvent, KeymapsEventCallback } from '../keymaps/types'; +import { ModalEvent, ModalEventCallback } from '../modal_dialog/types'; +import { LayerEvent, LayerEventCallback } from '../navigator/types'; +import { PageEvent, PagesEventCallback } from '../pages/types'; +import { ParserEvent, ParserEventCallback } from '../parser/types'; +import { RichTextEditorEvent, RichTextEditorEventCallback } from '../rich_text_editor'; +import { SelectorEvent, SelectorEventCallback } from '../selector_manager/types'; +import type { ProjectData } from '../storage_manager'; +import { StorageEvent, StorageEventCallback } from '../storage_manager/types'; +import { StyleManagerEvent, StyleManagerEventCallback } from '../style_manager/types'; +import { TraitEvent, TraitEventCallback } from '../trait_manager/types'; import { EditorConfig } from './config/config'; -import EditorModel from './model/Editor'; +import type EditorModel from './model/Editor'; +import type { EditorLoadOptions } from './model/Editor'; -type GeneralEvent = 'canvasScroll' | 'undo' | 'redo' | 'load' | 'update'; +type EditorLogEvent = + | `${EditorEvents.log}:${string}` + | `${EditorEvents.log}-${string}` + | `${EditorEvents.log}-${string}:${string}`; + +type EditorCoreEvent = `${EditorEvents}` | EditorLogEvent | 'canvasScroll'; type EditorBuiltInEvents = + | EditorCoreEvent | DataSourceEvent + | DeviceEvent + | I18nEvent | ComponentEvent | BlockEvent | AssetEvent | KeymapEvent + | LayerEvent + | PageEvent + | ParserEvent | StyleManagerEvent | StorageEvent | CanvasEvent | SelectorEvent | RichTextEditorEvent + | TraitEvent | ModalEvent - | CommandEvent - | GeneralEvent; + | CommandEvent; export type EditorEvent = LiteralUnion; @@ -36,7 +56,64 @@ export type EditorConfigType = EditorConfig & { pStylePrefix?: string }; export type EditorModelParam = Parameters[N]; -export interface EditorEventCallbacks extends AssetsEventCallback, BlocksEventCallback, DataSourcesEventCallback { +export interface EditorProjectEventData { + project: ProjectData; + options: EditorLoadOptions; + initial: boolean; +} + +export interface EditorProjectLoadEventData extends EditorProjectEventData { + loaded: boolean; +} + +export interface EditorProjectGetEventData { + project: ProjectData; +} + +export interface EditorLogEventOptions extends ObjectAny { + ns?: string; + level?: string; +} + +export interface EditorEventCoreCallbacks { + [EditorEvents.update]: []; + [EditorEvents.updateBefore]: [Record]; + [EditorEvents.undo]: []; + [EditorEvents.redo]: []; + [EditorEvents.load]: [EditorModel['Editor']]; + [EditorEvents.projectLoad]: [EditorProjectLoadEventData]; + [EditorEvents.projectLoaded]: [EditorProjectEventData]; + [EditorEvents.projectGet]: [EditorProjectGetEventData]; + [EditorEvents.log]: [string, EditorLogEventOptions]; + [EditorEvents.telemetryInit]: []; + [EditorEvents.destroy]: []; + [EditorEvents.destroyed]: []; + [key: `log:${string}`]: [string, EditorLogEventOptions]; + [key: `log-${string}`]: [string, EditorLogEventOptions]; + [key: `log-${string}:${string}`]: [string, EditorLogEventOptions]; + canvasScroll: []; +} + +export interface EditorEventCallbacks + extends EditorEventCoreCallbacks, + AssetsEventCallback, + BlocksEventCallback, + CanvasEventCallback, + CommandsEventCallback, + DataSourcesEventCallback, + DevicesEventCallback, + ComponentsEventCallback, + I18nEventCallback, + KeymapsEventCallback, + LayerEventCallback, + ModalEventCallback, + PagesEventCallback, + ParserEventCallback, + RichTextEditorEventCallback, + SelectorEventCallback, + StorageEventCallback, + StyleManagerEventCallback, + TraitEventCallback { [key: string]: any[]; } diff --git a/packages/core/src/i18n/types.ts b/packages/core/src/i18n/types.ts index 90f4527f5..ef31073d2 100644 --- a/packages/core/src/i18n/types.ts +++ b/packages/core/src/i18n/types.ts @@ -27,5 +27,13 @@ export enum I18nEvents { } /**{END_EVENTS}*/ +export type I18nEvent = `${I18nEvents}`; + +export interface I18nEventCallback { + [I18nEvents.add]: [Messages]; + [I18nEvents.update]: [Messages]; + [I18nEvents.locale]: [{ value: string; valuePrev: string | undefined }]; +} + // need this to avoid the TS documentation generator to break export default I18nEvents; diff --git a/packages/core/src/keymaps/index.ts b/packages/core/src/keymaps/index.ts index 7f35f444a..9e5618847 100644 --- a/packages/core/src/keymaps/index.ts +++ b/packages/core/src/keymaps/index.ts @@ -41,8 +41,7 @@ import keymaster from '../utils/keymaster'; import { hasWin } from '../utils/mixins'; import defConfig, { Keymap, KeymapOptions, KeymapsConfig } from './config'; import { KeymapsEvents } from './types'; - -export type KeymapEvent = `${KeymapsEvents}`; +export type { KeymapEvent } from './types'; hasWin() && keymaster.init(window); @@ -118,7 +117,9 @@ export default class KeymapsModule extends Module { modal?: ModalView; diff --git a/packages/core/src/modal_dialog/types.ts b/packages/core/src/modal_dialog/types.ts index eda97a0e9..cba18fe93 100644 --- a/packages/core/src/modal_dialog/types.ts +++ b/packages/core/src/modal_dialog/types.ts @@ -1,3 +1,5 @@ +import { ObjectAny } from '../common'; + /**{START_EVENTS}*/ export enum ModalEvents { /** @@ -23,5 +25,21 @@ export enum ModalEvents { } /**{END_EVENTS}*/ +export type ModalEvent = `${ModalEvents}`; + +export interface ModalEventData { + open: boolean; + attributes: ObjectAny; + title: Node; + content: Node; + close: () => void; +} + +export interface ModalEventCallback { + [ModalEvents.open]: []; + [ModalEvents.close]: []; + [ModalEvents.all]: [ModalEventData]; +} + // need this to avoid the TS documentation generator to break export default ModalEvents; diff --git a/packages/core/src/navigator/index.ts b/packages/core/src/navigator/index.ts index f45a27726..11019ef6d 100644 --- a/packages/core/src/navigator/index.ts +++ b/packages/core/src/navigator/index.ts @@ -47,8 +47,7 @@ import { hasWin, isComponent, isDef } from '../utils/mixins'; import defConfig, { LayerManagerConfig } from './config/config'; import { LayerData, LayerEvents } from './types'; import View from './view/ItemView'; - -export type LayerEvent = `${LayerEvents}`; +export type { LayerEvent } from './types'; const styleOpts = { mediaText: '' }; @@ -79,7 +78,7 @@ export default class LayerManager extends Module { onLoad() { const { em, config, model } = this; - model.listenTo(em, 'component:selected', this.componentChanged); + model.listenTo(em, ComponentsEvents.selected, this.componentChanged); model.on('change:root', this.__onRootChange); model.listenTo(em, propsToListen, this.__onComponent); this.componentChanged(); @@ -180,7 +179,7 @@ export default class LayerManager extends Module { component.setStyle(style, styleOpts as any); this.updateLayer(component); - this.em.trigger('component:toggled'); // Updates Style Manager #2938 + this.em.trigger(ComponentsEvents.toggled); // Updates Style Manager #2938 } /** diff --git a/packages/core/src/navigator/types.ts b/packages/core/src/navigator/types.ts index 5557967a6..b74aacaca 100644 --- a/packages/core/src/navigator/types.ts +++ b/packages/core/src/navigator/types.ts @@ -1,3 +1,4 @@ +import { ObjectAny } from '../common'; import Component from '../dom_components/model/Component'; export interface LayerData { @@ -32,8 +33,34 @@ export enum LayerEvents { * editor.on('layer:custom', ({ container, root }) => { ... }); */ custom = 'layer:custom', + + /** + * @event `layer:render` Component layer rendered. Object with component and rendered layer element is passed as an argument. + * @example + * editor.on('layer:render', ({ component, el }) => { ... }); + */ + render = 'layer:render', } /**{END_EVENTS}*/ +export type LayerEvent = `${LayerEvents}`; + +export interface LayerCustomEventData { + container: HTMLElement | undefined; + root: Component; +} + +export interface LayerRenderEventData { + component: Component; + el: HTMLElement; +} + +export interface LayerEventCallback { + [LayerEvents.root]: [Component]; + [LayerEvents.component]: [Component, ObjectAny?]; + [LayerEvents.custom]: [LayerCustomEventData]; + [LayerEvents.render]: [LayerRenderEventData]; +} + // need this to avoid the TS documentation generator to break export default LayerEvents; diff --git a/packages/core/src/navigator/view/ItemView.ts b/packages/core/src/navigator/view/ItemView.ts index 3b9080b73..9faa1f7de 100644 --- a/packages/core/src/navigator/view/ItemView.ts +++ b/packages/core/src/navigator/view/ItemView.ts @@ -5,6 +5,7 @@ import ComponentView from '../../dom_components/view/ComponentView'; import EditorModel from '../../editor/model/Editor'; import { isEnterKey, isEscKey } from '../../utils/dom'; import LayerManager from '../index'; +import { LayerEvents } from '../types'; import ItemsView from './ItemsView'; import { getOnComponentDrag, getOnComponentDragEnd, getOnComponentDragStart } from '../../commands'; import Sorter from '../../utils/sorter/Sorter'; @@ -450,6 +451,6 @@ export default class ItemView extends View { const { onRender } = config; const opt = { component: model, el }; onRender.bind(this)(opt); - this.em.trigger('layer:render', opt); + this.em.trigger(LayerEvents.render, opt); } } diff --git a/packages/core/src/pages/types.ts b/packages/core/src/pages/types.ts index 4cd2a218f..44ba190da 100644 --- a/packages/core/src/pages/types.ts +++ b/packages/core/src/pages/types.ts @@ -1,4 +1,13 @@ +import { + AddOptions, + EventCallbackRemove, + EventCallbackRemoveBefore, + EventCallbackUpdate, + ObjectAny, + SetOptions, +} from '../common'; import { ModuleConfig } from '../abstract/Module'; +import Page from './model/Page'; import { PageProperties } from './model/Page'; export interface PageManagerConfig extends ModuleConfig { @@ -66,5 +75,22 @@ export enum PagesEvents { } /**{END_EVENTS}*/ +export type PageEvent = `${PagesEvents}`; + +export interface PagesEventCallback { + [PagesEvents.add]: [Page, AddOptions]; + [PagesEvents.addBefore]: [ + PageProperties, + AddPage: () => Page | undefined, + AddOptions & SelectableOption & AbortOption, + ]; + [PagesEvents.remove]: EventCallbackRemove; + [PagesEvents.removeBefore]: EventCallbackRemoveBefore; + [PagesEvents.select]: [Page, Page | undefined]; + [PagesEvents.selectBefore]: [Page, SetOptions]; + [PagesEvents.update]: EventCallbackUpdate; + [PagesEvents.all]: [{ event: string; page: Page; options: ObjectAny }]; +} + // need this to avoid the TS documentation generator to break export default PagesEvents; diff --git a/packages/core/src/parser/index.ts b/packages/core/src/parser/index.ts index 0e6abf30c..5093fb410 100644 --- a/packages/core/src/parser/index.ts +++ b/packages/core/src/parser/index.ts @@ -96,7 +96,7 @@ export default class ParserModule extends Module; error: unknown }, + ]; + [ParserEvents.all]: [{ event: ParserEvent; input: string } & ObjectAny]; +} + // need this to avoid the TS documentation generator to break export default ParserEvents; diff --git a/packages/core/src/rich_text_editor/index.ts b/packages/core/src/rich_text_editor/index.ts index aa0b6c2d3..92c8e96c1 100644 --- a/packages/core/src/rich_text_editor/index.ts +++ b/packages/core/src/rich_text_editor/index.ts @@ -43,7 +43,7 @@ import defConfig, { CustomRTE, CustomRteOptions, RichTextEditorConfig } from './ import RichTextEditor, { RichTextEditorAction } from './model/RichTextEditor'; import { ModelRTE, RichTextEditorEvents, RteDisableResult } from './types'; -export type { RichTextEditorEvent, RteDisableResult } from './types'; +export type { RichTextEditorEvent, RichTextEditorEventCallback, RteDisableResult } from './types'; const eventsUp = `${CanvasEvents.refresh} frame:scroll ${ComponentsEvents.update}`; diff --git a/packages/core/src/rich_text_editor/types.ts b/packages/core/src/rich_text_editor/types.ts index 53ea30fad..d8be45b1e 100644 --- a/packages/core/src/rich_text_editor/types.ts +++ b/packages/core/src/rich_text_editor/types.ts @@ -1,4 +1,6 @@ -import ComponentTextView from '../dom_components/view/ComponentTextView'; +import type ComponentTextView from '../dom_components/view/ComponentTextView'; +import type RichTextEditor from './model/RichTextEditor'; +import type { RichTextEditorAction } from './model/RichTextEditor'; export interface ModelRTE { currentView?: ComponentTextView; @@ -10,6 +12,12 @@ export interface RteDisableResult { forceSync?: boolean; } +export interface RichTextEditorCustomEventProps { + enabled: boolean; + container: HTMLElement; + actions: RichTextEditorAction[]; +} + /**{START_EVENTS}*/ export enum RichTextEditorEvents { /** @@ -35,5 +43,11 @@ export enum RichTextEditorEvents { } /**{END_EVENTS}*/ +export interface RichTextEditorEventCallback { + [RichTextEditorEvents.enable]: [ComponentTextView, RichTextEditor]; + [RichTextEditorEvents.disable]: [ComponentTextView, RichTextEditor | undefined]; + [RichTextEditorEvents.custom]: [RichTextEditorCustomEventProps]; +} + // need this to avoid the TS documentation generator to break export default RichTextEditorEvents; diff --git a/packages/core/src/selector_manager/index.ts b/packages/core/src/selector_manager/index.ts index 274660e79..3b8062957 100644 --- a/packages/core/src/selector_manager/index.ts +++ b/packages/core/src/selector_manager/index.ts @@ -127,8 +127,8 @@ export default class SelectorManager extends ItemManagerModule em.trigger(events.state, value)); this.model.on('change:cFirst', (m, value) => em.trigger('selector:type', value)); const eventCmpUpdateCls = `${ComponentsEvents.update}:classes`; - em.on(`component:toggled ${eventCmpUpdateCls}`, this.__updateSelectedByComponents); - const listenTo = `component:toggled ${eventCmpUpdateCls} change:device styleManager:update selector:state selector:type style:target`; + em.on(`${ComponentsEvents.toggled} ${eventCmpUpdateCls}`, this.__updateSelectedByComponents); + const listenTo = `${ComponentsEvents.toggled} ${eventCmpUpdateCls} change:device styleManager:update selector:state selector:type style:target`; this.model.listenTo(em, listenTo, () => this.__update()); } diff --git a/packages/core/src/selector_manager/types.ts b/packages/core/src/selector_manager/types.ts index ddb11a35a..02845f4b8 100644 --- a/packages/core/src/selector_manager/types.ts +++ b/packages/core/src/selector_manager/types.ts @@ -1,3 +1,16 @@ +import { + Collection, + EventCallbackAdd, + EventCallbackAll, + EventCallbackRemove, + EventCallbackRemoveBefore, + EventCallbackUpdate, + ObjectAny, +} from '../common'; +import Selector from './model/Selector'; +import Selectors from './model/Selectors'; +import State from './model/State'; + /**{START_EVENTS}*/ export enum SelectorEvents { /** @@ -51,7 +64,31 @@ export enum SelectorEvents { } /**{END_EVENTS}*/ +export type SelectorEvent = `${SelectorEvents}`; + export type SelectorStringObject = string | { name?: string; label?: string; type?: number }; +export type SelectorStateEventData = State | Collection | string; + +export interface SelectorStateEventOptions extends ObjectAny { + event?: string; +} + +export interface SelectorCustomEventData { + states: State[]; + selected: Selector[]; + container: HTMLElement | undefined; +} + +export interface SelectorEventCallback { + [SelectorEvents.add]: EventCallbackAdd; + [SelectorEvents.remove]: EventCallbackRemove; + [SelectorEvents.removeBefore]: EventCallbackRemoveBefore; + [SelectorEvents.update]: EventCallbackUpdate; + [SelectorEvents.state]: [SelectorStateEventData, SelectorStateEventOptions?]; + [SelectorEvents.custom]: [SelectorCustomEventData]; + [SelectorEvents.all]: EventCallbackAll; +} + // need this to avoid the TS documentation generator to break export default SelectorEvents; diff --git a/packages/core/src/selector_manager/view/ClassTagsView.ts b/packages/core/src/selector_manager/view/ClassTagsView.ts index 5da9b1268..da84e91f1 100644 --- a/packages/core/src/selector_manager/view/ClassTagsView.ts +++ b/packages/core/src/selector_manager/view/ClassTagsView.ts @@ -86,7 +86,7 @@ export default class ClassTagsView extends View { this.checkSync = debounce(this.checkSync.bind(this), 0); const eventCmpUpdate = ComponentsEvents.update; const evClsUp = `${eventCmpUpdate}:classes`; - const toList = `component:toggled ${evClsUp}`; + const toList = `${ComponentsEvents.toggled} ${evClsUp}`; const toListCls = `${evClsUp} ${eventCmpUpdate}:attributes:id change:state`; this.listenTo(em, toList, this.componentChanged); this.listenTo(em, 'styleManager:update', this.componentChanged); @@ -126,8 +126,8 @@ export default class ClassTagsView extends View { }); style && rule.addStyle(style); - em.trigger('component:toggled'); - em.trigger('component:sync-style', { + em.trigger(ComponentsEvents.toggled); + em.trigger(ComponentsEvents.syncStyle, { component: target, selectors, mediaText, diff --git a/packages/core/src/storage_manager/index.ts b/packages/core/src/storage_manager/index.ts index 272d42f45..677b5be75 100644 --- a/packages/core/src/storage_manager/index.ts +++ b/packages/core/src/storage_manager/index.ts @@ -47,13 +47,10 @@ import LocalStorage from './model/LocalStorage'; import RemoteStorage from './model/RemoteStorage'; import EditorModel from '../editor/model/Editor'; import IStorage, { StorageOptions, ProjectData } from './model/IStorage'; -import StorageEvents from './types'; +import StorageEvents, { StorageEventType } from './types'; export type { StorageOptions, ProjectData } from './model/IStorage'; - -export type StorageEvent = `${StorageEvents}`; - -type StorageEventType = 'store' | 'load'; +export type { StorageEvent, StorageEventCallback, StorageEventType } from './types'; const STORAGE_LOCAL = 'local'; const STORAGE_REMOTE = 'remote'; diff --git a/packages/core/src/storage_manager/types.ts b/packages/core/src/storage_manager/types.ts index 7bb67c9fb..e021408e8 100644 --- a/packages/core/src/storage_manager/types.ts +++ b/packages/core/src/storage_manager/types.ts @@ -1,3 +1,7 @@ +import { ProjectData } from './model/IStorage'; + +export type StorageEventType = 'store' | 'load'; + /**{START_EVENTS}*/ export enum StorageEvents { /** @@ -112,5 +116,24 @@ export enum StorageEvents { } /**{END_EVENTS}*/ +export type StorageEvent = `${StorageEvents}`; + +export interface StorageEventCallback { + [StorageEvents.start]: [StorageEventType, ProjectData | undefined]; + [StorageEvents.startStore]: [ProjectData]; + [StorageEvents.startLoad]: [ProjectData | undefined]; + [StorageEvents.load]: [ProjectData, unknown]; + [StorageEvents.store]: [ProjectData, unknown]; + [StorageEvents.after]: []; + [StorageEvents.afterStore]: [ProjectData, unknown]; + [StorageEvents.afterLoad]: [ProjectData, unknown]; + [StorageEvents.end]: [StorageEventType, unknown, unknown?]; + [StorageEvents.endStore]: [unknown, unknown?]; + [StorageEvents.endLoad]: [unknown, unknown?]; + [StorageEvents.error]: [unknown, StorageEventType]; + [StorageEvents.errorStore]: [unknown]; + [StorageEvents.errorLoad]: [unknown]; +} + // need this to avoid the TS documentation generator to break export default StorageEvents; diff --git a/packages/core/src/style_manager/index.ts b/packages/core/src/style_manager/index.ts index de5abf53c..04c59ac0c 100644 --- a/packages/core/src/style_manager/index.ts +++ b/packages/core/src/style_manager/index.ts @@ -68,9 +68,7 @@ import { PropertyTypes, StyleManagerEvents, StyleTarget } from './types'; import { CustomPropertyView } from './view/PropertyView'; import SectorsView from './view/SectorsView'; -export type { PropertyTypes, StyleModuleParam, StyleTarget } from './types'; - -export type StyleManagerEvent = `${StyleManagerEvents}`; +export type { PropertyTypes, StyleManagerEventCallback, StyleModuleParam, StyleTarget } from './types'; const propDef = (value: any) => value || value === 0; @@ -116,11 +114,11 @@ export default class StyleManager extends ItemManagerModule< // Triggers for the selection refresh and properties const eventCmpUpdate = ComponentsEvents.update; - const ev = `component:toggled ${eventCmpUpdate}:classes change:state change:device frame:resized selector:type`; + const ev = `${ComponentsEvents.toggled} ${eventCmpUpdate}:classes change:state change:device frame:resized selector:type`; this.upAll = debounce(() => this.__upSel(), 0); model.listenTo(em, ev, this.upAll as any); // Clear state target on any component selection change, without debounce (#4208) - model.listenTo(em, 'component:toggled', this.__clearStateTarget); + model.listenTo(em, ComponentsEvents.toggled, this.__clearStateTarget); // Triggers only for properties (avoid selection refresh) const upProps = debounce(() => { diff --git a/packages/core/src/style_manager/types.ts b/packages/core/src/style_manager/types.ts index e4b432a6c..0193116af 100644 --- a/packages/core/src/style_manager/types.ts +++ b/packages/core/src/style_manager/types.ts @@ -1,5 +1,10 @@ import StyleManager from '.'; +import { AddOptions, ObjectAny, RemoveOptions } from '../common'; import StyleableModel from '../domain_abstract/model/StyleableModel'; +import Property, { PropertyProps } from './model/Property'; +import PropertyStack from './model/PropertyStack'; +import Sector, { SectorProperties } from './model/Sector'; +import Sectors from './model/Sectors'; import { PropertyNumberProps } from './model/PropertyNumber'; import { PropertySelectProps } from './model/PropertySelect'; import { PropertyStackProps } from './model/PropertyStack'; @@ -84,5 +89,42 @@ export enum StyleManagerEvents { } /**{END_EVENTS}*/ +export type StyleManagerEvent = `${StyleManagerEvents}`; + +export interface StyleManagerPropertyUpdateEventData { + property: Property; + from: Partial; + to: Partial; + value: any; + opts: ObjectAny; +} + +export interface StyleManagerLayerSelectEventData { + property: PropertyStack; +} + +export interface StyleManagerCustomEventData { + container: HTMLElement | undefined; +} + +export interface StyleManagerAllEventData { + event: string; + model?: Sector | Sectors; + options: ObjectAny; +} + +export interface StyleManagerEventCallback { + [StyleManagerEvents.sectorAdd]: [Sector, AddOptions]; + [StyleManagerEvents.sectorRemove]: [Sector, RemoveOptions]; + [StyleManagerEvents.sectorUpdate]: [Sector, Partial, ObjectAny]; + [StyleManagerEvents.propertyAdd]: [Property, AddOptions]; + [StyleManagerEvents.propertyRemove]: [Property, RemoveOptions]; + [StyleManagerEvents.propertyUpdate]: [StyleManagerPropertyUpdateEventData]; + [StyleManagerEvents.target]: [StyleTarget | undefined]; + [StyleManagerEvents.layerSelect]: [StyleManagerLayerSelectEventData]; + [StyleManagerEvents.custom]: [StyleManagerCustomEventData]; + [StyleManagerEvents.all]: [StyleManagerAllEventData]; +} + // need this to avoid the TS documentation generator to break export default StyleManagerEvents; diff --git a/packages/core/src/trait_manager/index.ts b/packages/core/src/trait_manager/index.ts index 31a4a3cc9..c089dae51 100644 --- a/packages/core/src/trait_manager/index.ts +++ b/packages/core/src/trait_manager/index.ts @@ -32,6 +32,7 @@ import { bindAll, debounce } from 'underscore'; import { Module } from '../abstract'; import { Model } from '../common'; import Component from '../dom_components/model/Component'; +import { ComponentsEvents } from '../dom_components/types'; import EditorModel from '../editor/model/Editor'; import defConfig from './config/config'; import { @@ -89,7 +90,7 @@ export default class TraitManager extends Module { const upAll = debounce(() => this.__upSel(), 0); const update = debounce(() => this.__onUp(), 0); - state.listenTo(em, 'component:toggled', upAll); + state.listenTo(em, ComponentsEvents.toggled, upAll); state.listenTo(em, events.value, update); state.on('change:traits', this.__onSelect); @@ -226,7 +227,7 @@ export default class TraitManager extends Module { __onSelect() { const { em, events, state } = this; const { component, traits } = state.attributes; - em.trigger(events.select, { component, traits }); + em.trigger(events.select, { component, traits: traits as Trait[] }); } __trgCustom(opts: TraitCustomData = {}) { diff --git a/packages/core/src/trait_manager/model/Trait.ts b/packages/core/src/trait_manager/model/Trait.ts index 2c5622902..040cab74d 100644 --- a/packages/core/src/trait_manager/model/Trait.ts +++ b/packages/core/src/trait_manager/model/Trait.ts @@ -257,7 +257,7 @@ export default class Trait extends Model { component.trigger(TraitsEvents.value, props); em?.trigger(TraitsEvents.value, props); // This should be triggered for any trait prop change - em?.trigger('trait:update', props); + em?.trigger(TraitsEvents.update, props); } getTargetValue(opts: TraitGetValueOptions = {}) { diff --git a/packages/core/src/trait_manager/types.ts b/packages/core/src/trait_manager/types.ts index 9f84639c0..edacb6f82 100644 --- a/packages/core/src/trait_manager/types.ts +++ b/packages/core/src/trait_manager/types.ts @@ -1,4 +1,5 @@ -import { CategoryProperties, ItemsByCategory } from '../abstract/ModuleCategory'; +import Category, { CategoryProperties, ItemsByCategory } from '../abstract/ModuleCategory'; +import { ObjectAny } from '../common'; import Component from '../dom_components/model/Component'; import Editor from '../editor'; import EditorModel from '../editor/model/Editor'; @@ -38,6 +39,34 @@ export interface TraitCustomData { container?: HTMLElement; } +export interface TraitSelectEventData { + component?: Component; + traits: Trait[]; +} + +export interface TraitValueEventData { + trait: Trait; + component: Component; + value: any; +} + +export interface TraitCategoryUpdateEventData { + category: Category; + changes: Partial; + options: ObjectAny; +} + +export interface TraitAllEventData { + event: string; + trait?: Trait; + component?: Component; + value?: any; + category?: Category; + changes?: Partial; + options?: ObjectAny; + container?: HTMLElement; +} + export interface TraitProperties { /** * Trait type, defines how the trait should be rendered. @@ -177,8 +206,6 @@ export interface TraitOption { [key: string]: unknown; } -export type TraitsEvent = `${TraitsEvents}`; - /**{START_EVENTS}*/ export enum TraitsEvents { /** @@ -194,6 +221,7 @@ export enum TraitsEvents { * editor.on('trait:value', ({ trait, component, value }) => { ... }); */ value = 'trait:value', + update = 'trait:update', /** * @event `trait:category:update` Trait category updated. @@ -218,5 +246,16 @@ export enum TraitsEvents { } /**{END_EVENTS}*/ +export type TraitEvent = `${TraitsEvents}`; + +export interface TraitEventCallback { + [TraitsEvents.select]: [TraitSelectEventData]; + [TraitsEvents.value]: [TraitValueEventData]; + [TraitsEvents.update]: [TraitValueEventData]; + [TraitsEvents.categoryUpdate]: [TraitCategoryUpdateEventData]; + [TraitsEvents.custom]: [TraitCustomData]; + [TraitsEvents.all]: [TraitAllEventData]; +} + // need this to avoid the TS documentation generator to break export default TraitsEvents; diff --git a/packages/core/src/trait_manager/view/TraitsView.ts b/packages/core/src/trait_manager/view/TraitsView.ts index a070cd480..703642986 100644 --- a/packages/core/src/trait_manager/view/TraitsView.ts +++ b/packages/core/src/trait_manager/view/TraitsView.ts @@ -1,5 +1,6 @@ import TraitManager from '..'; import CategoryView from '../../abstract/ModuleCategoryView'; +import { ComponentsEvents } from '../../dom_components/types'; import DomainViews from '../../domain_abstract/view/DomainViews'; import EditorModel from '../../editor/model/Editor'; import Trait from '../model/Trait'; @@ -49,7 +50,7 @@ export default class TraitsView extends DomainViews { this.classNoCat = `${ppfx}traits-empty-c`; this.catsClass = `${ppfx}trait-categories`; this.collection = new Traits([], { em }); - this.listenTo(em, 'component:toggled', this.updatedCollection); + this.listenTo(em, ComponentsEvents.toggled, this.updatedCollection); this.updatedCollection(); } 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; } } diff --git a/packages/core/test/specs/pages/index.ts b/packages/core/test/specs/pages/index.ts index 8be5a9e02..1942ecc56 100644 --- a/packages/core/test/specs/pages/index.ts +++ b/packages/core/test/specs/pages/index.ts @@ -197,7 +197,7 @@ describe('Managing pages', () => { test('Abort add page', () => { em.on(pm.events.addBefore, (p, c, opts) => { - opts.abort = 1; + opts.abort = true; }); pm.add({}); expect(pm.getAll().length).toBe(1); @@ -205,7 +205,7 @@ describe('Managing pages', () => { test('Abort add page and complete', () => { em.on(pm.events.addBefore, (p, complete, opts) => { - opts.abort = 1; + opts.abort = true; complete(); }); pm.add({}); @@ -223,7 +223,7 @@ describe('Managing pages', () => { test('Abort remove page', () => { em.on(pm.events.removeBefore, (p, c, opts) => { - opts.abort = 1; + (opts as any).abort = true; }); const page = pm.add({})!; pm.remove(`${page.id}`); @@ -232,7 +232,7 @@ describe('Managing pages', () => { test('Abort remove page and complete', () => { em.on(pm.events.removeBefore, (p, complete, opts) => { - opts.abort = 1; + (opts as any).abort = true; complete(); }); const page = pm.add({})!;