feat(stage,editor): 选中的元素不存在时不报错,并完善事件ts定义

fix #579
This commit is contained in:
roymondchen 2024-03-18 17:25:40 +08:00
parent 42f1f28b02
commit fff56a97f7
11 changed files with 306 additions and 145 deletions

View File

@ -41,7 +41,7 @@ class StageOverlay extends BaseService {
this.state[name] = value;
}
public openOverlay(el: HTMLElement | undefined | null) {
public openOverlay(el: HTMLElement | null) {
const stageOptions = this.get('stageOptions');
if (!el || !stageOptions) return;
@ -168,7 +168,7 @@ class StageOverlay extends BaseService {
});
if (await stageOptions?.canSelect?.(contentEl)) {
subStage?.select(contentEl);
subStage?.select(contentEl.id);
}
}

View File

@ -25,15 +25,25 @@ import { Env } from '@tmagic/core';
import type { Id } from '@tmagic/schema';
import { addClassName, getDocument, removeClassNameByClassName } from '@tmagic/utils';
import { CONTAINER_HIGHLIGHT_CLASS_NAME, GHOST_EL_ID_PREFIX, GuidesType, MouseButton, PAGE_CLASS } from './const';
import {
AbleActionEventType,
CONTAINER_HIGHLIGHT_CLASS_NAME,
ContainerHighlightType,
GHOST_EL_ID_PREFIX,
GuidesType,
MouseButton,
PAGE_CLASS,
SelectStatus,
StageDragStatus,
} from './const';
import DragResizeHelper from './DragResizeHelper';
import StageDragResize from './StageDragResize';
import StageHighlight from './StageHighlight';
import StageMultiDragResize from './StageMultiDragResize';
import {
import type {
ActionManagerConfig,
ActionManagerEvents,
CanSelect,
ContainerHighlightType,
CustomizeMoveableOptions,
CustomizeMoveableOptionsCallbackConfig,
GetElementsFromPoint,
@ -42,8 +52,7 @@ import {
IsContainer,
Point,
RemoveEventData,
SelectStatus,
StageDragStatus,
SortEventData,
UpdateEventData,
} from './types';
import { isMoveableButton } from './util';
@ -62,7 +71,7 @@ export default class ActionManager extends EventEmitter {
/** 单选、多选、高亮的容器蒙层的content */
private container: HTMLElement;
/** 当前选中的节点 */
private selectedEl: HTMLElement | undefined;
private selectedEl: HTMLElement | null = null;
/** 多选选中的节点组 */
private selectedElList: HTMLElement[] = [];
/** 当前高亮的节点 */
@ -96,7 +105,7 @@ export default class ActionManager extends EventEmitter {
}
this.emit('mousemove', event);
this.highlight(el);
this.highlight(el.id);
}, throttleTime);
constructor(config: ActionManagerConfig) {
@ -181,11 +190,11 @@ export default class ActionManager extends EventEmitter {
return el.id === this.selectedEl?.id;
}
public setSelectedEl(el?: HTMLElement): void {
public setSelectedEl(el: HTMLElement | null): void {
this.selectedEl = el;
}
public getSelectedEl(): HTMLElement | undefined {
public getSelectedEl(): HTMLElement | null {
return this.selectedEl;
}
@ -207,7 +216,7 @@ export default class ActionManager extends EventEmitter {
* @param event
* @returns
*/
public async getElementFromPoint(event: MouseEvent): Promise<HTMLElement | undefined> {
public async getElementFromPoint(event: MouseEvent): Promise<HTMLElement | null> {
const els = this.getElementsFromPoint(event as Point);
this.emit('get-elements-from-point', els);
@ -220,6 +229,7 @@ export default class ActionManager extends EventEmitter {
return el;
}
}
return null;
}
/**
@ -257,14 +267,20 @@ export default class ActionManager extends EventEmitter {
return this.multiDr?.canSelect(el, selectedEl) || false;
}
public select(el: HTMLElement, event: MouseEvent | undefined): void {
public select(el: HTMLElement | null, event?: MouseEvent): void {
this.setSelectedEl(el);
this.clearSelectStatus(SelectStatus.MULTI_SELECT);
this.dr.select(el, event);
}
public multiSelect(idOrElList: HTMLElement[] | Id[]): void {
this.selectedElList = idOrElList.map((idOrEl) => this.getTargetElement(idOrEl));
public multiSelect(ids: Id[]): void {
this.selectedElList = [];
ids.forEach((id) => {
const el = this.getTargetElement(id);
if (el) {
this.selectedElList.push(el);
}
});
this.clearSelectStatus(SelectStatus.SELECT);
this.multiDr?.multiSelect(this.selectedElList);
}
@ -277,10 +293,10 @@ export default class ActionManager extends EventEmitter {
this.highlightedEl = el;
}
public highlight(idOrEl: Id | HTMLElement): void {
public highlight(id: Id): void {
let el;
try {
el = this.getTargetElement(idOrEl);
el = this.getTargetElement(id);
} catch (error) {
this.clearHighlight();
return;
@ -366,6 +382,20 @@ export default class ActionManager extends EventEmitter {
this.highlightLayer.destroy();
}
public on<Name extends keyof ActionManagerEvents, Param extends ActionManagerEvents[Name]>(
eventName: Name,
listener: (...args: Param) => void,
) {
return super.on(eventName, listener as any);
}
public emit<Name extends keyof ActionManagerEvents, Param extends ActionManagerEvents[Name]>(
eventName: Name,
...args: Param
) {
return super.emit(eventName, ...args);
}
private createDr(config: ActionManagerConfig) {
const createDrHelper = () =>
new DragResizeHelper({
@ -388,14 +418,14 @@ export default class ActionManager extends EventEmitter {
// 点击组件并立即拖动的场景要保证select先被触发延迟update通知
setTimeout(() => this.emit('update', data));
})
.on('sort', (data: UpdateEventData) => {
.on('sort', (data: SortEventData) => {
// 点击组件并立即拖动的场景要保证select先被触发延迟update通知
setTimeout(() => this.emit('sort', data));
})
.on('select-parent', () => {
.on(AbleActionEventType.SELECT_PARENT, () => {
this.emit('select-parent');
})
.on('remove', () => {
.on(AbleActionEventType.REMOVE, () => {
const drTarget = this.dr.getTarget();
if (!drTarget) return;
const data: RemoveEventData = {
@ -430,11 +460,10 @@ export default class ActionManager extends EventEmitter {
?.on('update', (data: UpdateEventData) => {
this.emit('multi-update', data);
})
.on('change-to-select', async (id: Id, e: MouseEvent) => {
.on('change-to-select', (id: Id, e: MouseEvent) => {
// 如果还在多选状态,不触发切换到单选
if (this.isMultiSelectStatus) return false;
const el = this.getTargetElement(id);
this.emit('change-to-select', el, e);
if (this.isMultiSelectStatus) return;
this.emit('change-to-select', id, e);
});
return multiDr;
@ -474,13 +503,16 @@ export default class ActionManager extends EventEmitter {
// 如果已有单选选中元素不是magic-ui-page就可以加入多选列表
if (this.selectedEl && !this.selectedEl.className.includes(PAGE_CLASS)) {
this.selectedElList.push(this.selectedEl as HTMLElement);
this.setSelectedEl(undefined);
this.setSelectedEl(null);
}
// 判断元素是否已在多选列表
const existIndex = this.selectedElList.findIndex((selectedDom) => selectedDom.id === el.id);
if (existIndex !== -1) {
// 再次点击取消选中
this.selectedElList.splice(existIndex, 1);
if (this.selectedElList.length > 1) {
this.selectedElList.splice(existIndex, 1);
}
} else {
this.selectedElList.push(el);
}
@ -580,6 +612,7 @@ export default class ActionManager extends EventEmitter {
if (!el) return;
this.emit('before-select', el, event);
}
getDocument().addEventListener('mouseup', this.mouseUpHandler);
};

View File

@ -16,7 +16,7 @@
* limitations under the License.
*/
import {
import type {
OnDrag,
OnDragGroup,
OnDragGroupStart,
@ -34,7 +34,7 @@ import MoveableHelper from 'moveable-helper';
import { DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, Mode, ZIndex } from './const';
import TargetShadow from './TargetShadow';
import { DragResizeHelperConfig, Rect, TargetElement } from './types';
import type { DragResizeHelperConfig, Rect, TargetElement } from './types';
import { calcValueByFontsize, getAbsolutePosition, getBorderWidth, getMarginValue, getOffset } from './util';
/**

View File

@ -28,12 +28,14 @@ import StageMask from './StageMask';
import StageRender from './StageRender';
import type {
ActionManagerConfig,
CoreEvents,
CustomizeRender,
GuidesEventData,
Point,
RemoveData,
RemoveEventData,
Runtime,
SortEventData,
StageCoreConfig,
UpdateData,
UpdateEventData,
@ -81,41 +83,41 @@ export default class StageCore extends EventEmitter {
/**
*
* @param idOrEl id或者元素
* @param id id
*/
public async select(idOrEl: Id | HTMLElement, event?: MouseEvent): Promise<void> {
const el = this.renderer.getTargetElement(idOrEl);
public async select(id: Id, event?: MouseEvent): Promise<void> {
const el = this.renderer.getTargetElement(id);
if (el === this.actionManager.getSelectedEl()) return;
await this.renderer.select([el]);
await this.renderer.select([id]);
this.mask.setLayout(el);
el && this.mask.setLayout(el);
this.actionManager.select(el, event);
if (this.autoScrollIntoView || el.dataset.autoScrollIntoView) {
if (el && (this.autoScrollIntoView || el.dataset.autoScrollIntoView)) {
this.mask.observerIntersection(el);
}
}
/**
*
* @param idOrElList id或元素列表
* @param ids id列表
*/
public async multiSelect(idOrElList: HTMLElement[] | Id[]): Promise<void> {
const els = idOrElList.map((idOrEl) => this.renderer.getTargetElement(idOrEl));
public async multiSelect(ids: Id[]): Promise<void> {
const els = ids.map((id) => this.renderer.getTargetElement(id)).filter((el) => Boolean(el));
if (els.length === 0) return;
const lastEl = els[els.length - 1];
// 是否减少了组件选择
const isReduceSelect = els.length < this.actionManager.getSelectedElList().length;
await this.renderer.select(els);
await this.renderer.select(ids);
this.mask.setLayout(lastEl);
lastEl && this.mask.setLayout(lastEl);
this.actionManager.multiSelect(idOrElList);
this.actionManager.multiSelect(ids);
if ((this.autoScrollIntoView || lastEl.dataset.autoScrollIntoView) && !isReduceSelect) {
if (lastEl && (this.autoScrollIntoView || lastEl.dataset.autoScrollIntoView) && !isReduceSelect) {
this.mask.observerIntersection(lastEl);
}
}
@ -124,8 +126,8 @@ export default class StageCore extends EventEmitter {
*
* @param el
*/
public highlight(idOrEl: Id | HTMLElement): void {
this.actionManager.highlight(idOrEl);
public highlight(id: Id): void {
this.actionManager.highlight(id);
}
public clearHighlight(): void {
@ -248,6 +250,17 @@ export default class StageCore extends EventEmitter {
this.container = undefined;
}
public on<Name extends keyof CoreEvents, Param extends CoreEvents[Name]>(
eventName: Name,
listener: (...args: Param) => void | Promise<void>,
) {
return super.on(eventName, listener as any);
}
public emit<Name extends keyof CoreEvents, Param extends CoreEvents[Name]>(eventName: Name, ...args: Param) {
return super.emit(eventName, ...args);
}
/**
*
*/
@ -280,7 +293,7 @@ export default class StageCore extends EventEmitter {
updateDragEl: config.updateDragEl,
getRootContainer: () => this.container,
getRenderDocument: () => this.renderer.getDocument(),
getTargetElement: (idOrEl: Id | HTMLElement) => this.renderer.getTargetElement(idOrEl),
getTargetElement: (id: Id) => this.renderer.getTargetElement(id),
getElementsFromPoint: (point: Point) => this.renderer.getElementsFromPoint(point),
};
@ -322,14 +335,14 @@ export default class StageCore extends EventEmitter {
*/
private initActionManagerEvent(): void {
this.actionManager
.on('before-select', (idOrEl: Id | HTMLElement, event?: MouseEvent) => {
this.select(idOrEl, event);
.on('before-select', (el: HTMLElement, event?: MouseEvent) => {
this.select(el.id, event);
})
.on('select', (selectedEl: HTMLElement, event: MouseEvent) => {
this.emit('select', selectedEl, event);
})
.on('before-multi-select', (idOrElList: HTMLElement[] | Id[]) => {
this.multiSelect(idOrElList);
.on('before-multi-select', (els: HTMLElement[]) => {
this.multiSelect(els.map((el) => el.id));
})
.on('multi-select', (selectedElList: HTMLElement[], event: MouseEvent) => {
this.emit('multi-select', selectedElList, event);
@ -347,7 +360,7 @@ export default class StageCore extends EventEmitter {
.on('update', (data: UpdateEventData) => {
this.emit('update', data);
})
.on('sort', (data: UpdateEventData) => {
.on('sort', (data: SortEventData) => {
this.emit('sort', data);
})
.on('select-parent', () => {
@ -364,10 +377,13 @@ export default class StageCore extends EventEmitter {
private initMulDrEvent(): void {
this.actionManager
// 多选切换到单选
.on('change-to-select', (el: HTMLElement, e: MouseEvent) => {
this.select(el);
.on('change-to-select', (id: Id, e: MouseEvent) => {
this.select(id);
// 先保证画布内完成渲染,再通知外部更新
setTimeout(() => this.emit('select', el, e));
setTimeout(() => {
const el = this.renderer.getTargetElement(id);
el && this.emit('select', el, e);
});
})
.on('multi-update', (data: UpdateEventData) => {
this.emit('update', data);
@ -378,7 +394,7 @@ export default class StageCore extends EventEmitter {
* Highlight类通过ActionManager抛出来的事件监听
*/
private initHighlightEvent(): void {
this.actionManager.on('highlight', async (highlightEl: HTMLElement) => {
this.actionManager.on('highlight', (highlightEl: HTMLElement) => {
this.emit('highlight', highlightEl);
});
}

View File

@ -19,11 +19,16 @@
/* eslint-disable no-param-reassign */
import Moveable, { MoveableOptions } from 'moveable';
import { Mode } from './const';
import { Mode, StageDragStatus } from './const';
import DragResizeHelper from './DragResizeHelper';
import MoveableOptionsManager from './MoveableOptionsManager';
import type { DelayedMarkContainer, GetRenderDocument, MarkContainerEnd, StageDragResizeConfig } from './types';
import { StageDragStatus } from './types';
import type {
DelayedMarkContainer,
DrEvents,
GetRenderDocument,
MarkContainerEnd,
StageDragResizeConfig,
} from './types';
import { down, getMode, up } from './util';
/**
@ -32,7 +37,7 @@ import { down, getMode, up } from './util';
*/
export default class StageDragResize extends MoveableOptionsManager {
/** 目标节点 */
private target?: HTMLElement;
private target: HTMLElement | null = null;
/** Moveable拖拽类实例 */
private moveable?: Moveable;
/** 拖动状态 */
@ -70,7 +75,12 @@ export default class StageDragResize extends MoveableOptionsManager {
* @param el Dom节点元素
* @param event
*/
public select(el: HTMLElement, event?: MouseEvent): void {
public select(el: HTMLElement | null, event?: MouseEvent): void {
if (!el) {
this.moveable?.destroy();
this.moveable = undefined;
return;
}
// 从不能拖动到能拖动的节点之间切换要重新创建moveable不然dragStart不生效
if (!this.moveable || el !== this.target) {
this.initMoveable(el);
@ -119,6 +129,17 @@ export default class StageDragResize extends MoveableOptionsManager {
this.removeAllListeners();
}
public on<Name extends keyof DrEvents, Param extends DrEvents[Name]>(
eventName: Name,
listener: (...args: Param) => void | Promise<void>,
) {
return super.on(eventName, listener as any);
}
public emit<Name extends keyof DrEvents, Param extends DrEvents[Name]>(eventName: Name, ...args: Param) {
return super.emit(eventName, ...args);
}
private init(el: HTMLElement): MoveableOptions {
// 如果有滚动条会导致resize时获取到widthheight不准确
if (/(auto|scroll)/.test(el.style.overflow)) {
@ -247,16 +268,19 @@ export default class StageDragResize extends MoveableOptionsManager {
.on('rotateEnd', (e) => {
this.dragStatus = StageDragStatus.END;
const frame = this.dragResizeHelper?.getFrame(e.target);
this.emit('update', {
data: [
{
el: this.target,
style: {
transform: frame?.get('transform'),
if (this.target && frame) {
this.emit('update', {
data: [
{
el: this.target,
style: {
transform: frame.get('transform'),
},
},
},
],
});
],
parentEl: null,
});
}
});
}
@ -276,16 +300,19 @@ export default class StageDragResize extends MoveableOptionsManager {
.on('scaleEnd', (e) => {
this.dragStatus = StageDragStatus.END;
const frame = this.dragResizeHelper.getFrame(e.target);
this.emit('update', {
data: [
{
el: this.target,
style: {
transform: frame?.get('transform'),
if (this.target && frame) {
this.emit('update', {
data: [
{
el: this.target,
style: {
transform: frame.get('transform'),
},
},
},
],
});
],
parentEl: null,
});
}
});
}

View File

@ -20,7 +20,7 @@ import { createDiv, getDocument, injectStyle } from '@tmagic/utils';
import { Mode, ZIndex } from './const';
import Rule from './Rule';
import type { RuleOptions } from './types';
import type { MaskEvents, RuleOptions } from './types';
import { getScrollParent, isFixedParent } from './util';
const wrapperClassName = 'editor-mask-wrapper';
@ -178,6 +178,17 @@ export default class StageMask extends Rule {
super.destroy();
}
public on<Name extends keyof MaskEvents, Param extends MaskEvents[Name]>(
eventName: Name,
listener: (...args: Param) => void | Promise<void>,
) {
return super.on(eventName, listener as any);
}
public emit<Name extends keyof MaskEvents, Param extends MaskEvents[Name]>(eventName: Name, ...args: Param) {
return super.emit(eventName, ...args);
}
/**
* 使
*/

View File

@ -18,7 +18,7 @@
import Moveable from 'moveable';
import { DRAG_EL_ID_PREFIX, Mode } from './const';
import { DRAG_EL_ID_PREFIX, Mode, StageDragStatus } from './const';
import DragResizeHelper from './DragResizeHelper';
import MoveableOptionsManager from './MoveableOptionsManager';
import {
@ -26,7 +26,7 @@ import {
GetRenderDocument,
MarkContainerEnd,
MoveableOptionsManagerConfig,
StageDragStatus,
MultiDrEvents,
StageMultiDragResizeConfig,
} from './types';
import { getMode } from './util';
@ -137,7 +137,7 @@ export default class StageMultiDragResize extends MoveableOptionsManager {
});
}
public canSelect(el: HTMLElement, selectedEl: HTMLElement | undefined): boolean {
public canSelect(el: HTMLElement, selectedEl: HTMLElement | null): boolean {
const currentTargetMode = getMode(el);
let selectedElMode = '';
@ -196,6 +196,17 @@ export default class StageMultiDragResize extends MoveableOptionsManager {
this.dragResizeHelper.destroy();
}
public on<Name extends keyof MultiDrEvents, Param extends MultiDrEvents[Name]>(
eventName: Name,
listener: (...args: Param) => void | Promise<void>,
) {
return super.on(eventName, listener as any);
}
public emit<Name extends keyof MultiDrEvents, Param extends MultiDrEvents[Name]>(eventName: Name, ...args: Param) {
return super.emit(eventName, ...args);
}
/**
*
* @param isResize

View File

@ -21,17 +21,9 @@ import { EventEmitter } from 'events';
import { Id } from '@tmagic/schema';
import { getHost, injectStyle, isSameDomain } from '@tmagic/utils';
import { DEFAULT_ZOOM } from './const';
import { DEFAULT_ZOOM, RenderType } from './const';
import style from './style.css?raw';
import {
type Point,
type RemoveData,
RenderType,
type Runtime,
type RuntimeWindow,
type StageRenderConfig,
type UpdateData,
} from './types';
import type { Point, RemoveData, RenderEvents, Runtime, RuntimeWindow, StageRenderConfig, UpdateData } from './types';
import { addSelectedClassName, removeSelectedClassName } from './util';
export default class StageRender extends EventEmitter {
@ -87,15 +79,13 @@ export default class StageRender extends EventEmitter {
runtime?.update?.(data);
}
public async select(els: HTMLElement[]): Promise<void> {
public async select(ids: Id[]): Promise<void> {
const runtime = await this.getRuntime();
for (const el of els) {
await runtime?.select?.(el.id);
if (runtime?.beforeSelect) {
await runtime.beforeSelect(el);
}
this.flagSelectedEl(el);
for (const id of ids) {
await runtime?.select?.(id);
this.flagSelectedEl(this.getTargetElement(id));
}
}
@ -161,13 +151,8 @@ export default class StageRender extends EventEmitter {
return this.getDocument()?.elementsFromPoint(x / this.zoom, y / this.zoom) as HTMLElement[];
}
public getTargetElement(idOrEl: Id | HTMLElement): HTMLElement {
if (typeof idOrEl === 'string' || typeof idOrEl === 'number') {
const el = this.getDocument()?.getElementById(`${idOrEl}`);
if (!el) throw new Error(`不存在ID为${idOrEl}的元素`);
return el;
}
return idOrEl;
public getTargetElement(id: Id): HTMLElement | null {
return this.getDocument()?.getElementById(`${id}`) || null;
}
/**
@ -181,6 +166,17 @@ export default class StageRender extends EventEmitter {
this.removeAllListeners();
}
public on<Name extends keyof RenderEvents, Param extends RenderEvents[Name]>(
eventName: Name,
listener: (...args: Param) => void | Promise<void>,
) {
return super.on(eventName, listener as any);
}
public emit<Name extends keyof RenderEvents, Param extends RenderEvents[Name]>(eventName: Name, ...args: Param) {
return super.emit(eventName, ...args);
}
private createIframe(): HTMLIFrameElement {
this.iframe = globalThis.document.createElement('iframe');
// 同源,直接加载
@ -214,11 +210,11 @@ export default class StageRender extends EventEmitter {
* runtime中对被选中的元素进行标记
* @param el
*/
private flagSelectedEl(el: HTMLElement): void {
private flagSelectedEl(el: HTMLElement | null): void {
const doc = this.getDocument();
if (doc) {
removeSelectedClassName(doc);
addSelectedClassName(el, doc);
el && addSelectedClassName(el, doc);
}
}

View File

@ -78,3 +78,34 @@ export enum AbleActionEventType {
SELECT_PARENT = 'select-parent',
REMOVE = 'remove',
}
/** 将组件添加到容器的方式 */
export enum ContainerHighlightType {
/** 默认方式:组件在容器上方悬停一段时间后加入 */
DEFAULT = 'default',
/** 按住alt键并在容器上方悬停一段时间后加入 */
ALT = 'alt',
}
export enum RenderType {
IFRAME = 'iframe',
NATIVE = 'native',
}
/** 选择状态 */
export enum SelectStatus {
/** 单选 */
SELECT = 'select',
/** 多选 */
MULTI_SELECT = 'multiSelect',
}
/** 拖动状态 */
export enum StageDragStatus {
/** 开始拖动 */
START = 'start',
/** 拖动中 */
ING = 'ing',
/** 拖动结束 */
END = 'end',
}

View File

@ -17,12 +17,12 @@
*/
import type { GuidesOptions } from '@scena/guides';
import type { MoveableOptions } from 'moveable';
import type { MoveableOptions, OnDragStart } from 'moveable';
import Core from '@tmagic/core';
import type { Id, MApp, MContainer, MNode } from '@tmagic/schema';
import { GuidesType, ZIndex } from './const';
import { AbleActionEventType, ContainerHighlightType, GuidesType, RenderType, ZIndex } from './const';
import DragResizeHelper from './DragResizeHelper';
import StageCore from './StageCore';
@ -36,8 +36,8 @@ export type CustomizeMoveableOptions =
| ((config?: CustomizeMoveableOptionsCallbackConfig) => MoveableOptions)
| MoveableOptions
| undefined;
/** render提供给的接口如果是id转成el如果是el则直接返回 */
export type GetTargetElement = (idOrEl: Id | HTMLElement) => HTMLElement;
/** render提供给的接口id转成el */
export type GetTargetElement = (id: Id) => HTMLElement | null;
/** render提供的接口通过坐标获得坐标下所有HTML元素数组 */
export type GetElementsFromPoint = (point: Point) => HTMLElement[];
export type GetRenderDocument = () => Document | undefined;
@ -45,19 +45,6 @@ export type DelayedMarkContainer = (event: MouseEvent, exclude: Element[]) => No
export type MarkContainerEnd = () => HTMLElement | null;
export type GetRootContainer = () => HTMLDivElement | undefined;
/** 将组件添加到容器的方式 */
export enum ContainerHighlightType {
/** 默认方式:组件在容器上方悬停一段时间后加入 */
DEFAULT = 'default',
/** 按住alt键并在容器上方悬停一段时间后加入 */
ALT = 'alt',
}
export enum RenderType {
IFRAME = 'iframe',
NATIVE = 'native',
}
export type UpdateDragEl = (el: TargetElement, target: TargetElement, container: HTMLElement) => void;
export interface StageCoreConfig {
@ -106,7 +93,7 @@ export interface MoveableOptionsManagerConfig {
}
export interface CustomizeMoveableOptionsCallbackConfig {
targetEl?: HTMLElement;
targetEl: HTMLElement | null;
targetElId?: string;
targetEls?: HTMLElement[];
targetElIds?: string[];
@ -151,24 +138,6 @@ export interface DragResizeHelperConfig {
updateDragEl?: UpdateDragEl;
}
/** 选择状态 */
export enum SelectStatus {
/** 单选 */
SELECT = 'select',
/** 多选 */
MULTI_SELECT = 'multiSelect',
}
/** 拖动状态 */
export enum StageDragStatus {
/** 开始拖动 */
START = 'start',
/** 拖动中 */
ING = 'ing',
/** 拖动结束 */
END = 'end',
}
export type Rect = {
width: number;
height: number;
@ -234,7 +203,6 @@ export interface RemoveData {
export interface Runtime {
getApp?: () => Core | undefined;
beforeSelect?: (el: HTMLElement) => Promise<boolean> | boolean;
updateRootConfig?: (config: MApp) => void;
updatePageId?: (id: Id) => void;
select?: (id: Id) => Promise<HTMLElement> | HTMLElement;
@ -271,3 +239,71 @@ export interface TargetShadowConfig {
export interface RuleOptions {
guidesOptions?: Partial<GuidesOptions>;
}
export interface CoreEvents {
mounted: [];
'runtime-ready': [runtime: Runtime];
'page-el-update': [el: HTMLElement];
'change-guides': [data: GuidesEventData];
select: [selectedEl: HTMLElement, event: MouseEvent];
'multi-select': [selectedElList: HTMLElement[], event: MouseEvent];
dblclick: [event: MouseEvent];
update: [data: UpdateEventData];
sort: [data: SortEventData];
'select-parent': [];
remove: [data: RemoveEventData];
highlight: [highlightEl: HTMLElement];
mousemove: [event: MouseEvent];
mouseleave: [event: MouseEvent];
'drag-start': [event: OnDragStart];
}
export interface RenderEvents {
onload: [];
'page-el-update': [el: HTMLElement];
'runtime-ready': [runtime: Runtime];
}
export interface MaskEvents {
scroll: [event: WheelEvent];
'change-guides': [
data: {
type: GuidesType.HORIZONTAL;
guides: number[];
},
];
}
export interface ActionManagerEvents {
dblclick: [event: MouseEvent];
mousemove: [event: MouseEvent];
mouseleave: [event: MouseEvent];
highlight: [el: HTMLElement];
update: [data: UpdateEventData];
sort: [data: SortEventData];
remove: [data: RemoveEventData];
select: [selectedEl: HTMLElement | null, event: MouseEvent];
'select-parent': [];
'drag-start': [event: OnDragStart];
'multi-update': [data: UpdateEventData];
'change-to-select': [id: Id, event: MouseEvent];
'before-multi-select': [selectedElList: HTMLElement[]];
'before-select': [el: HTMLElement, event: MouseEvent];
'multi-select': [selectedElList: HTMLElement[], event: MouseEvent];
'get-elements-from-point': [els: HTMLElement[]];
}
export interface DrEvents {
'update-moveable': [];
[AbleActionEventType.REMOVE]: [];
[AbleActionEventType.SELECT_PARENT]: [];
'drag-start': [event: OnDragStart];
update: [data: UpdateEventData];
sort: [data: SortEventData];
}
export interface MultiDrEvents {
'update-moveable': [];
'change-to-select': [id: Id, event: MouseEvent];
update: [data: UpdateEventData];
}

View File

@ -177,7 +177,7 @@ export const calcValueByFontsize = (doc: Document, value: number) => {
* @param {number} deltaTop
* @param {Object} detail
*/
export const down = (deltaTop: number, target: TargetElement): SortEventData | void => {
export const down = (deltaTop: number, target: TargetElement): SortEventData => {
let swapIndex = 0;
let addUpH = target.clientHeight;
const brothers = Array.from(target.parentNode?.children || []).filter(
@ -213,7 +213,7 @@ export const down = (deltaTop: number, target: TargetElement): SortEventData | v
* @param {number} deltaTop
* @param {Object} detail
*/
export const up = (deltaTop: number, target: TargetElement): SortEventData | void => {
export const up = (deltaTop: number, target: TargetElement): SortEventData => {
const brothers = Array.from(target.parentNode?.children || []).filter(
(node) => !node.id.startsWith(GHOST_EL_ID_PREFIX),
);