@tmagic/stage 1.1.0-beta.1 → 1.1.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{tmagic-stage.es.js → tmagic-stage.mjs} +617 -259
- package/dist/tmagic-stage.mjs.map +1 -0
- package/dist/tmagic-stage.umd.js +634 -270
- package/dist/tmagic-stage.umd.js.map +1 -1
- package/package.json +14 -11
- package/src/StageCore.ts +115 -20
- package/src/StageDragResize.ts +86 -144
- package/src/StageHighlight.ts +1 -1
- package/src/StageMask.ts +29 -5
- package/src/StageMultiDragResize.ts +260 -0
- package/src/StageRender.ts +28 -18
- package/src/TargetCalibrate.ts +2 -1
- package/src/const.ts +2 -0
- package/src/style.css +1 -0
- package/src/types.ts +38 -16
- package/src/util.ts +87 -2
- package/tsconfig.build.json +13 -0
- package/{dist/types/src → types}/Rule.d.ts +0 -0
- package/{dist/types/src → types}/StageCore.d.ts +21 -3
- package/{dist/types/src → types}/StageDragResize.d.ts +9 -18
- package/{dist/types/src → types}/StageHighlight.d.ts +0 -0
- package/{dist/types/src → types}/StageMask.d.ts +1 -0
- package/types/StageMultiDragResize.d.ts +51 -0
- package/{dist/types/src → types}/StageRender.d.ts +1 -0
- package/{dist/types/src → types}/TargetCalibrate.d.ts +0 -0
- package/{dist/types/src → types}/const.d.ts +1 -0
- package/{dist/types/src → types}/index.d.ts +0 -0
- package/types/logger.d.ts +5 -0
- package/{dist/types/src → types}/types.d.ts +36 -16
- package/{dist/types/src → types}/util.d.ts +16 -1
- package/dist/tmagic-stage.es.js.map +0 -1
- package/dist/types/src/vite-env.d.ts +0 -1
- package/src/vite-env.d.ts +0 -1
package/package.json
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.1.0-beta.
|
|
2
|
+
"version": "1.1.0-beta.12",
|
|
3
3
|
"name": "@tmagic/stage",
|
|
4
4
|
"sideEffects": [
|
|
5
5
|
"dist/*"
|
|
6
6
|
],
|
|
7
7
|
"main": "dist/tmagic-stage.umd.js",
|
|
8
|
-
"module": "dist/tmagic-stage.
|
|
9
|
-
"types": "
|
|
8
|
+
"module": "dist/tmagic-stage.mjs",
|
|
9
|
+
"types": "types/index.d.ts",
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
|
-
"import": "./dist/tmagic-stage.
|
|
12
|
+
"import": "./dist/tmagic-stage.mjs",
|
|
13
13
|
"require": "./dist/tmagic-stage.umd.js"
|
|
14
14
|
},
|
|
15
15
|
"./*": "./*"
|
|
16
16
|
},
|
|
17
17
|
"license": "Apache-2.0",
|
|
18
18
|
"scripts": {
|
|
19
|
-
"build": "vite build"
|
|
19
|
+
"build": "npm run build:type && vite build",
|
|
20
|
+
"build:type": "npm run clear:type && tsc --declaration --emitDeclarationOnly --project tsconfig.build.json",
|
|
21
|
+
"clear:type": "rimraf ./types"
|
|
20
22
|
},
|
|
21
23
|
"engines": {
|
|
22
24
|
"node": ">=14"
|
|
@@ -27,10 +29,11 @@
|
|
|
27
29
|
},
|
|
28
30
|
"dependencies": {
|
|
29
31
|
"@scena/guides": "^0.17.0",
|
|
30
|
-
"@tmagic/core": "1.1.0-beta.
|
|
31
|
-
"@tmagic/schema": "1.1.0-beta.
|
|
32
|
-
"@tmagic/utils": "1.1.0-beta.
|
|
32
|
+
"@tmagic/core": "1.1.0-beta.12",
|
|
33
|
+
"@tmagic/schema": "1.1.0-beta.12",
|
|
34
|
+
"@tmagic/utils": "1.1.0-beta.12",
|
|
33
35
|
"events": "^3.3.0",
|
|
36
|
+
"keycon": "^1.1.2",
|
|
34
37
|
"lodash-es": "^4.17.21",
|
|
35
38
|
"moveable": "^0.30.0",
|
|
36
39
|
"moveable-helper": "^0.4.0"
|
|
@@ -39,9 +42,9 @@
|
|
|
39
42
|
"@types/events": "^3.0.0",
|
|
40
43
|
"@types/lodash-es": "^4.17.4",
|
|
41
44
|
"@types/node": "^15.12.4",
|
|
45
|
+
"rimraf": "^3.0.2",
|
|
42
46
|
"sass": "^1.35.1",
|
|
43
|
-
"typescript": "^4.
|
|
44
|
-
"vite": "^
|
|
45
|
-
"vite-plugin-dts": "^0.9.6"
|
|
47
|
+
"typescript": "^4.7.4",
|
|
48
|
+
"vite": "^3.0.4"
|
|
46
49
|
}
|
|
47
50
|
}
|
package/src/StageCore.ts
CHANGED
|
@@ -19,20 +19,24 @@
|
|
|
19
19
|
import { EventEmitter } from 'events';
|
|
20
20
|
|
|
21
21
|
import type { Id } from '@tmagic/schema';
|
|
22
|
+
import { addClassName } from '@tmagic/utils';
|
|
22
23
|
|
|
23
|
-
import { DEFAULT_ZOOM, GHOST_EL_ID_PREFIX } from './const';
|
|
24
|
+
import { CONTAINER_HIGHLIGHT_CLASS, DEFAULT_ZOOM, GHOST_EL_ID_PREFIX, PAGE_CLASS } from './const';
|
|
24
25
|
import StageDragResize from './StageDragResize';
|
|
25
26
|
import StageHighlight from './StageHighlight';
|
|
26
27
|
import StageMask from './StageMask';
|
|
28
|
+
import StageMultiDragResize from './StageMultiDragResize';
|
|
27
29
|
import StageRender from './StageRender';
|
|
28
30
|
import {
|
|
29
31
|
CanSelect,
|
|
32
|
+
ContainerHighlightType,
|
|
30
33
|
GuidesEventData,
|
|
31
34
|
IsContainer,
|
|
32
35
|
RemoveData,
|
|
33
36
|
Runtime,
|
|
34
37
|
SortEventData,
|
|
35
38
|
StageCoreConfig,
|
|
39
|
+
StageDragStatus,
|
|
36
40
|
UpdateData,
|
|
37
41
|
UpdateEventData,
|
|
38
42
|
} from './types';
|
|
@@ -40,17 +44,21 @@ import { addSelectedClassName, removeSelectedClassName } from './util';
|
|
|
40
44
|
|
|
41
45
|
export default class StageCore extends EventEmitter {
|
|
42
46
|
public container?: HTMLDivElement;
|
|
43
|
-
|
|
44
|
-
public selectedDom:
|
|
47
|
+
// 当前选中的节点
|
|
48
|
+
public selectedDom: HTMLElement | undefined;
|
|
49
|
+
// 多选选中的节点组
|
|
50
|
+
public selectedDomList: HTMLElement[] = [];
|
|
45
51
|
public highlightedDom: Element | undefined;
|
|
46
52
|
public renderer: StageRender;
|
|
47
53
|
public mask: StageMask;
|
|
48
54
|
public dr: StageDragResize;
|
|
55
|
+
public multiDr: StageMultiDragResize;
|
|
49
56
|
public highlightLayer: StageHighlight;
|
|
50
57
|
public config: StageCoreConfig;
|
|
51
58
|
public zoom = DEFAULT_ZOOM;
|
|
52
59
|
public containerHighlightClassName: string;
|
|
53
60
|
public containerHighlightDuration: number;
|
|
61
|
+
public containerHighlightType?: ContainerHighlightType;
|
|
54
62
|
public isContainer: IsContainer;
|
|
55
63
|
|
|
56
64
|
private canSelect: CanSelect;
|
|
@@ -63,12 +71,14 @@ export default class StageCore extends EventEmitter {
|
|
|
63
71
|
this.setZoom(config.zoom);
|
|
64
72
|
this.canSelect = config.canSelect || ((el: HTMLElement) => !!el.id);
|
|
65
73
|
this.isContainer = config.isContainer;
|
|
66
|
-
this.containerHighlightClassName = config.containerHighlightClassName;
|
|
67
|
-
this.containerHighlightDuration = config.containerHighlightDuration;
|
|
74
|
+
this.containerHighlightClassName = config.containerHighlightClassName || CONTAINER_HIGHLIGHT_CLASS;
|
|
75
|
+
this.containerHighlightDuration = config.containerHighlightDuration || 800;
|
|
76
|
+
this.containerHighlightType = config.containerHighlightType;
|
|
68
77
|
|
|
69
78
|
this.renderer = new StageRender({ core: this });
|
|
70
79
|
this.mask = new StageMask({ core: this });
|
|
71
|
-
this.dr = new StageDragResize({ core: this, container: this.mask.content });
|
|
80
|
+
this.dr = new StageDragResize({ core: this, container: this.mask.content, mask: this.mask });
|
|
81
|
+
this.multiDr = new StageMultiDragResize({ core: this, container: this.mask.content, mask: this.mask });
|
|
72
82
|
this.highlightLayer = new StageHighlight({ core: this, container: this.mask.wrapper });
|
|
73
83
|
|
|
74
84
|
this.renderer.on('runtime-ready', (runtime: Runtime) => {
|
|
@@ -79,8 +89,11 @@ export default class StageCore extends EventEmitter {
|
|
|
79
89
|
});
|
|
80
90
|
|
|
81
91
|
this.mask
|
|
82
|
-
.on('beforeSelect', (event: MouseEvent) => {
|
|
83
|
-
this.
|
|
92
|
+
.on('beforeSelect', async (event: MouseEvent) => {
|
|
93
|
+
this.clearSelectStatus('multiSelect');
|
|
94
|
+
const el = await this.getElementFromPoint(event);
|
|
95
|
+
if (!el) return;
|
|
96
|
+
this.select(el, event);
|
|
84
97
|
})
|
|
85
98
|
.on('select', () => {
|
|
86
99
|
this.emit('select', this.selectedDom);
|
|
@@ -90,16 +103,37 @@ export default class StageCore extends EventEmitter {
|
|
|
90
103
|
this.emit('changeGuides', data);
|
|
91
104
|
})
|
|
92
105
|
.on('highlight', async (event: MouseEvent) => {
|
|
93
|
-
await this.
|
|
106
|
+
const el = await this.getElementFromPoint(event);
|
|
107
|
+
if (!el) return;
|
|
108
|
+
// 如果多选组件处于拖拽状态时不进行组件高亮
|
|
109
|
+
if (this.multiDr.dragStatus === StageDragStatus.ING) return;
|
|
110
|
+
await this.highlight(el);
|
|
94
111
|
if (this.highlightedDom === this.selectedDom) {
|
|
95
112
|
this.highlightLayer.clearHighlight();
|
|
96
113
|
return;
|
|
97
114
|
}
|
|
98
|
-
this.highlightLayer.highlight(this.highlightedDom as HTMLElement);
|
|
99
115
|
this.emit('highlight', this.highlightedDom);
|
|
100
116
|
})
|
|
101
117
|
.on('clearHighlight', async () => {
|
|
102
118
|
this.highlightLayer.clearHighlight();
|
|
119
|
+
})
|
|
120
|
+
.on('beforeMultiSelect', async (event: MouseEvent) => {
|
|
121
|
+
const el = await this.getElementFromPoint(event);
|
|
122
|
+
if (!el) return;
|
|
123
|
+
// 如果已有单选选中元素,不是magic-ui-page就可以加入多选列表
|
|
124
|
+
if (this.selectedDom && !this.selectedDom.className.includes(PAGE_CLASS)) {
|
|
125
|
+
this.selectedDomList.push(this.selectedDom as HTMLElement);
|
|
126
|
+
this.selectedDom = undefined;
|
|
127
|
+
}
|
|
128
|
+
// 判断元素是否已在多选列表
|
|
129
|
+
const existIndex = this.selectedDomList.findIndex((selectedDom) => selectedDom.id === el.id);
|
|
130
|
+
if (existIndex !== -1) {
|
|
131
|
+
// 再次点击取消选中
|
|
132
|
+
this.selectedDomList.splice(existIndex, 1);
|
|
133
|
+
} else {
|
|
134
|
+
this.selectedDomList.push(el);
|
|
135
|
+
}
|
|
136
|
+
this.multiSelect(this.selectedDomList);
|
|
103
137
|
});
|
|
104
138
|
|
|
105
139
|
// 要先触发select,在触发update
|
|
@@ -110,6 +144,16 @@ export default class StageCore extends EventEmitter {
|
|
|
110
144
|
.on('sort', (data: UpdateEventData) => {
|
|
111
145
|
setTimeout(() => this.emit('sort', data));
|
|
112
146
|
});
|
|
147
|
+
|
|
148
|
+
this.multiDr
|
|
149
|
+
.on('update', (data: UpdateEventData) => {
|
|
150
|
+
setTimeout(() => this.emit('update', data));
|
|
151
|
+
})
|
|
152
|
+
.on('select', async (id: Id) => {
|
|
153
|
+
const el = await this.getTargetElement(id);
|
|
154
|
+
this.select(el); // 选中
|
|
155
|
+
setTimeout(() => this.emit('select', el)); // set node
|
|
156
|
+
});
|
|
113
157
|
}
|
|
114
158
|
|
|
115
159
|
public getElementsFromPoint(event: MouseEvent) {
|
|
@@ -130,29 +174,35 @@ export default class StageCore extends EventEmitter {
|
|
|
130
174
|
return doc?.elementsFromPoint(x / zoom, y / zoom) as HTMLElement[];
|
|
131
175
|
}
|
|
132
176
|
|
|
133
|
-
public async
|
|
177
|
+
public async getElementFromPoint(event: MouseEvent) {
|
|
134
178
|
const els = this.getElementsFromPoint(event);
|
|
135
|
-
|
|
136
179
|
let stopped = false;
|
|
137
180
|
const stop = () => (stopped = true);
|
|
138
181
|
for (const el of els) {
|
|
139
|
-
if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && (await this.
|
|
182
|
+
if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && (await this.isElCanSelect(el, event, stop))) {
|
|
140
183
|
if (stopped) break;
|
|
141
|
-
|
|
142
|
-
this.highlight(el);
|
|
143
|
-
break;
|
|
144
|
-
}
|
|
145
|
-
this.select(el, event);
|
|
146
|
-
break;
|
|
184
|
+
return el;
|
|
147
185
|
}
|
|
148
186
|
}
|
|
149
187
|
}
|
|
150
188
|
|
|
189
|
+
public async isElCanSelect(el: HTMLElement, event: MouseEvent, stop: () => boolean): Promise<Boolean> {
|
|
190
|
+
// 执行业务方传入的判断逻辑
|
|
191
|
+
const canSelectByProp = await this.canSelect(el, event, stop);
|
|
192
|
+
if (!canSelectByProp) return false;
|
|
193
|
+
// 多选规则
|
|
194
|
+
if (this.mask.isMultiSelectStatus) {
|
|
195
|
+
return this.multiDr.canSelect(el, stop);
|
|
196
|
+
}
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
199
|
+
|
|
151
200
|
/**
|
|
152
201
|
* 选中组件
|
|
153
202
|
* @param idOrEl 组件Dom节点的id属性,或者Dom节点
|
|
154
203
|
*/
|
|
155
204
|
public async select(idOrEl: Id | HTMLElement, event?: MouseEvent): Promise<void> {
|
|
205
|
+
this.clearSelectStatus('multiSelect');
|
|
156
206
|
const el = await this.getTargetElement(idOrEl);
|
|
157
207
|
|
|
158
208
|
if (el === this.selectedDom) return;
|
|
@@ -182,6 +232,17 @@ export default class StageCore extends EventEmitter {
|
|
|
182
232
|
}
|
|
183
233
|
}
|
|
184
234
|
|
|
235
|
+
/**
|
|
236
|
+
* 多选
|
|
237
|
+
* @param domList 多选节点
|
|
238
|
+
*/
|
|
239
|
+
public async multiSelect(idOrElList: HTMLElement[] | Id[]): Promise<void> {
|
|
240
|
+
this.clearSelectStatus('select');
|
|
241
|
+
const elList = await Promise.all(idOrElList.map(async (idOrEl) => await this.getTargetElement(idOrEl)));
|
|
242
|
+
this.multiDr.multiSelect(elList);
|
|
243
|
+
this.emit('multiSelect', elList);
|
|
244
|
+
}
|
|
245
|
+
|
|
185
246
|
/**
|
|
186
247
|
* 更新选中的节点
|
|
187
248
|
* @param data 更新的数据
|
|
@@ -217,7 +278,7 @@ export default class StageCore extends EventEmitter {
|
|
|
217
278
|
this.highlightLayer.clearHighlight();
|
|
218
279
|
return;
|
|
219
280
|
}
|
|
220
|
-
if (el === this.highlightedDom) return;
|
|
281
|
+
if (el === this.highlightedDom || !el) return;
|
|
221
282
|
this.highlightLayer.highlight(el);
|
|
222
283
|
this.highlightedDom = el;
|
|
223
284
|
}
|
|
@@ -238,6 +299,19 @@ export default class StageCore extends EventEmitter {
|
|
|
238
299
|
this.zoom = zoom;
|
|
239
300
|
}
|
|
240
301
|
|
|
302
|
+
/**
|
|
303
|
+
* 用于在切换选择模式时清除上一次的状态
|
|
304
|
+
* @param selectType 需要清理的选择模式 多选:multiSelect,单选:select
|
|
305
|
+
*/
|
|
306
|
+
public clearSelectStatus(selectType: String) {
|
|
307
|
+
if (selectType === 'multiSelect') {
|
|
308
|
+
this.multiDr.clearSelectStatus();
|
|
309
|
+
this.selectedDomList = [];
|
|
310
|
+
} else {
|
|
311
|
+
this.dr.clearSelectStatus();
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
241
315
|
/**
|
|
242
316
|
* 挂载Dom节点
|
|
243
317
|
* @param el 将stage挂载到该Dom节点上
|
|
@@ -260,6 +334,27 @@ export default class StageCore extends EventEmitter {
|
|
|
260
334
|
this.dr.clearGuides();
|
|
261
335
|
}
|
|
262
336
|
|
|
337
|
+
public async addContainerHighlightClassName(event: MouseEvent, exclude: Element[]) {
|
|
338
|
+
const els = this.getElementsFromPoint(event);
|
|
339
|
+
const { renderer } = this;
|
|
340
|
+
const doc = renderer.contentWindow?.document;
|
|
341
|
+
|
|
342
|
+
if (!doc) return;
|
|
343
|
+
|
|
344
|
+
for (const el of els) {
|
|
345
|
+
if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && (await this.isContainer(el)) && !exclude.includes(el)) {
|
|
346
|
+
addClassName(el, doc, this.containerHighlightClassName);
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
public getAddContainerHighlightClassNameTimeout(event: MouseEvent, exclude: Element[] = []): NodeJS.Timeout {
|
|
353
|
+
return globalThis.setTimeout(() => {
|
|
354
|
+
this.addContainerHighlightClassName(event, exclude);
|
|
355
|
+
}, this.containerHighlightDuration);
|
|
356
|
+
}
|
|
357
|
+
|
|
263
358
|
/**
|
|
264
359
|
* 销毁实例
|
|
265
360
|
*/
|