@tmagic/stage 1.1.0-beta.7 → 1.1.0
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.mjs +136 -40
- package/dist/tmagic-stage.mjs.map +1 -1
- package/dist/tmagic-stage.umd.js +141 -43
- package/dist/tmagic-stage.umd.js.map +1 -1
- package/package.json +4 -4
- package/src/StageCore.ts +19 -7
- package/src/StageDragResize.ts +54 -32
- package/src/StageMultiDragResize.ts +92 -23
- package/src/style.css +4 -0
- package/src/types.ts +34 -14
- package/types/StageCore.d.ts +2 -1
- package/types/StageDragResize.d.ts +2 -0
- package/types/StageMultiDragResize.d.ts +3 -1
- package/types/types.d.ts +32 -14
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.1.0
|
|
2
|
+
"version": "1.1.0",
|
|
3
3
|
"name": "@tmagic/stage",
|
|
4
4
|
"sideEffects": [
|
|
5
5
|
"dist/*"
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@scena/guides": "^0.17.0",
|
|
32
|
-
"@tmagic/core": "1.1.0
|
|
33
|
-
"@tmagic/schema": "1.1.0
|
|
34
|
-
"@tmagic/utils": "1.1.0
|
|
32
|
+
"@tmagic/core": "1.1.0",
|
|
33
|
+
"@tmagic/schema": "1.1.0",
|
|
34
|
+
"@tmagic/utils": "1.1.0",
|
|
35
35
|
"events": "^3.3.0",
|
|
36
36
|
"keycon": "^1.1.2",
|
|
37
37
|
"lodash-es": "^4.17.21",
|
package/src/StageCore.ts
CHANGED
|
@@ -21,7 +21,7 @@ import { EventEmitter } from 'events';
|
|
|
21
21
|
import type { Id } from '@tmagic/schema';
|
|
22
22
|
import { addClassName } from '@tmagic/utils';
|
|
23
23
|
|
|
24
|
-
import { DEFAULT_ZOOM, GHOST_EL_ID_PREFIX, PAGE_CLASS } from './const';
|
|
24
|
+
import { CONTAINER_HIGHLIGHT_CLASS, DEFAULT_ZOOM, GHOST_EL_ID_PREFIX, PAGE_CLASS } from './const';
|
|
25
25
|
import StageDragResize from './StageDragResize';
|
|
26
26
|
import StageHighlight from './StageHighlight';
|
|
27
27
|
import StageMask from './StageMask';
|
|
@@ -29,12 +29,14 @@ import StageMultiDragResize from './StageMultiDragResize';
|
|
|
29
29
|
import StageRender from './StageRender';
|
|
30
30
|
import {
|
|
31
31
|
CanSelect,
|
|
32
|
+
ContainerHighlightType,
|
|
32
33
|
GuidesEventData,
|
|
33
34
|
IsContainer,
|
|
34
35
|
RemoveData,
|
|
35
36
|
Runtime,
|
|
36
37
|
SortEventData,
|
|
37
38
|
StageCoreConfig,
|
|
39
|
+
StageDragStatus,
|
|
38
40
|
UpdateData,
|
|
39
41
|
UpdateEventData,
|
|
40
42
|
} from './types';
|
|
@@ -56,6 +58,7 @@ export default class StageCore extends EventEmitter {
|
|
|
56
58
|
public zoom = DEFAULT_ZOOM;
|
|
57
59
|
public containerHighlightClassName: string;
|
|
58
60
|
public containerHighlightDuration: number;
|
|
61
|
+
public containerHighlightType?: ContainerHighlightType;
|
|
59
62
|
public isContainer: IsContainer;
|
|
60
63
|
|
|
61
64
|
private canSelect: CanSelect;
|
|
@@ -68,8 +71,9 @@ export default class StageCore extends EventEmitter {
|
|
|
68
71
|
this.setZoom(config.zoom);
|
|
69
72
|
this.canSelect = config.canSelect || ((el: HTMLElement) => !!el.id);
|
|
70
73
|
this.isContainer = config.isContainer;
|
|
71
|
-
this.containerHighlightClassName = config.containerHighlightClassName;
|
|
72
|
-
this.containerHighlightDuration = config.containerHighlightDuration;
|
|
74
|
+
this.containerHighlightClassName = config.containerHighlightClassName || CONTAINER_HIGHLIGHT_CLASS;
|
|
75
|
+
this.containerHighlightDuration = config.containerHighlightDuration || 800;
|
|
76
|
+
this.containerHighlightType = config.containerHighlightType;
|
|
73
77
|
|
|
74
78
|
this.renderer = new StageRender({ core: this });
|
|
75
79
|
this.mask = new StageMask({ core: this });
|
|
@@ -101,6 +105,8 @@ export default class StageCore extends EventEmitter {
|
|
|
101
105
|
.on('highlight', async (event: MouseEvent) => {
|
|
102
106
|
const el = await this.getElementFromPoint(event);
|
|
103
107
|
if (!el) return;
|
|
108
|
+
// 如果多选组件处于拖拽状态时不进行组件高亮
|
|
109
|
+
if (this.multiDr.dragStatus === StageDragStatus.ING) return;
|
|
104
110
|
await this.highlight(el);
|
|
105
111
|
if (this.highlightedDom === this.selectedDom) {
|
|
106
112
|
this.highlightLayer.clearHighlight();
|
|
@@ -139,9 +145,15 @@ export default class StageCore extends EventEmitter {
|
|
|
139
145
|
setTimeout(() => this.emit('sort', data));
|
|
140
146
|
});
|
|
141
147
|
|
|
142
|
-
this.multiDr
|
|
143
|
-
|
|
144
|
-
|
|
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
|
+
});
|
|
145
157
|
}
|
|
146
158
|
|
|
147
159
|
public getElementsFromPoint(event: MouseEvent) {
|
|
@@ -337,7 +349,7 @@ export default class StageCore extends EventEmitter {
|
|
|
337
349
|
}
|
|
338
350
|
}
|
|
339
351
|
|
|
340
|
-
public getAddContainerHighlightClassNameTimeout(event: MouseEvent, exclude: Element[] = []) {
|
|
352
|
+
public getAddContainerHighlightClassNameTimeout(event: MouseEvent, exclude: Element[] = []): NodeJS.Timeout {
|
|
341
353
|
return globalThis.setTimeout(() => {
|
|
342
354
|
this.addContainerHighlightClassName(event, exclude);
|
|
343
355
|
}, this.containerHighlightDuration);
|
package/src/StageDragResize.ts
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
/* eslint-disable no-param-reassign */
|
|
20
20
|
import { EventEmitter } from 'events';
|
|
21
21
|
|
|
22
|
+
import KeyController from 'keycon';
|
|
22
23
|
import type { MoveableOptions } from 'moveable';
|
|
23
24
|
import Moveable from 'moveable';
|
|
24
25
|
import MoveableHelper from 'moveable-helper';
|
|
@@ -29,18 +30,9 @@ import { DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, GuidesType, Mode, ZIndex } from
|
|
|
29
30
|
import StageCore from './StageCore';
|
|
30
31
|
import StageMask from './StageMask';
|
|
31
32
|
import type { StageDragResizeConfig } from './types';
|
|
33
|
+
import { ContainerHighlightType, StageDragStatus } from './types';
|
|
32
34
|
import { calcValueByFontsize, down, getAbsolutePosition, getMode, getOffset, getTargetElStyle, up } from './util';
|
|
33
35
|
|
|
34
|
-
/** 拖动状态 */
|
|
35
|
-
enum ActionStatus {
|
|
36
|
-
/** 开始拖动 */
|
|
37
|
-
START = 'start',
|
|
38
|
-
/** 拖动中 */
|
|
39
|
-
ING = 'ing',
|
|
40
|
-
/** 拖动结束 */
|
|
41
|
-
END = 'end',
|
|
42
|
-
}
|
|
43
|
-
|
|
44
36
|
/**
|
|
45
37
|
* 选中框
|
|
46
38
|
*/
|
|
@@ -66,10 +58,11 @@ export default class StageDragResize extends EventEmitter {
|
|
|
66
58
|
|
|
67
59
|
private moveableOptions: MoveableOptions = {};
|
|
68
60
|
/** 拖动状态 */
|
|
69
|
-
private dragStatus:
|
|
61
|
+
private dragStatus: StageDragStatus = StageDragStatus.END;
|
|
70
62
|
/** 流式布局下,目标节点的镜像节点 */
|
|
71
63
|
private ghostEl: HTMLElement | undefined;
|
|
72
64
|
private moveableHelper?: MoveableHelper;
|
|
65
|
+
private isContainerHighlight: Boolean = false;
|
|
73
66
|
|
|
74
67
|
constructor(config: StageDragResizeConfig) {
|
|
75
68
|
super();
|
|
@@ -77,6 +70,20 @@ export default class StageDragResize extends EventEmitter {
|
|
|
77
70
|
this.core = config.core;
|
|
78
71
|
this.container = config.container;
|
|
79
72
|
this.mask = config.mask;
|
|
73
|
+
|
|
74
|
+
KeyController.global.keydown('alt', (e) => {
|
|
75
|
+
e.inputEvent.preventDefault();
|
|
76
|
+
this.isContainerHighlight = true;
|
|
77
|
+
});
|
|
78
|
+
KeyController.global.keyup('alt', (e) => {
|
|
79
|
+
e.inputEvent.preventDefault();
|
|
80
|
+
|
|
81
|
+
const doc = this.core.renderer.contentWindow?.document;
|
|
82
|
+
if (doc && this.canContainerHighlight()) {
|
|
83
|
+
removeClassNameByClassName(doc, this.core.containerHighlightClassName);
|
|
84
|
+
}
|
|
85
|
+
this.isContainerHighlight = false;
|
|
86
|
+
});
|
|
80
87
|
}
|
|
81
88
|
|
|
82
89
|
/**
|
|
@@ -165,7 +172,7 @@ export default class StageDragResize extends EventEmitter {
|
|
|
165
172
|
this.moveable?.destroy();
|
|
166
173
|
this.destroyGhostEl();
|
|
167
174
|
this.destroyDragEl();
|
|
168
|
-
this.dragStatus =
|
|
175
|
+
this.dragStatus = StageDragStatus.END;
|
|
169
176
|
this.removeAllListeners();
|
|
170
177
|
}
|
|
171
178
|
|
|
@@ -243,7 +250,7 @@ export default class StageDragResize extends EventEmitter {
|
|
|
243
250
|
.on('resizeStart', (e) => {
|
|
244
251
|
if (!this.target) return;
|
|
245
252
|
|
|
246
|
-
this.dragStatus =
|
|
253
|
+
this.dragStatus = StageDragStatus.START;
|
|
247
254
|
this.moveableHelper?.onResizeStart(e);
|
|
248
255
|
|
|
249
256
|
frame.top = this.target.offsetTop;
|
|
@@ -254,14 +261,15 @@ export default class StageDragResize extends EventEmitter {
|
|
|
254
261
|
if (!this.moveable || !this.target || !this.dragEl) return;
|
|
255
262
|
|
|
256
263
|
const { beforeTranslate } = drag;
|
|
257
|
-
this.dragStatus =
|
|
258
|
-
|
|
259
|
-
this.moveableHelper?.onResize(e);
|
|
264
|
+
this.dragStatus = StageDragStatus.ING;
|
|
260
265
|
|
|
261
266
|
// 流式布局
|
|
262
267
|
if (this.mode === Mode.SORTABLE) {
|
|
263
268
|
this.target.style.top = '0px';
|
|
269
|
+
this.dragEl.style.width = `${width}px`;
|
|
270
|
+
this.dragEl.style.height = `${height}px`;
|
|
264
271
|
} else {
|
|
272
|
+
this.moveableHelper?.onResize(e);
|
|
265
273
|
this.target.style.left = `${frame.left + beforeTranslate[0]}px`;
|
|
266
274
|
this.target.style.top = `${frame.top + beforeTranslate[1]}px`;
|
|
267
275
|
}
|
|
@@ -270,7 +278,7 @@ export default class StageDragResize extends EventEmitter {
|
|
|
270
278
|
this.target.style.height = `${height}px`;
|
|
271
279
|
})
|
|
272
280
|
.on('resizeEnd', () => {
|
|
273
|
-
this.dragStatus =
|
|
281
|
+
this.dragStatus = StageDragStatus.END;
|
|
274
282
|
this.update(true);
|
|
275
283
|
});
|
|
276
284
|
}
|
|
@@ -292,7 +300,7 @@ export default class StageDragResize extends EventEmitter {
|
|
|
292
300
|
.on('dragStart', (e) => {
|
|
293
301
|
if (!this.target) throw new Error('未选中组件');
|
|
294
302
|
|
|
295
|
-
this.dragStatus =
|
|
303
|
+
this.dragStatus = StageDragStatus.START;
|
|
296
304
|
|
|
297
305
|
this.moveableHelper?.onDragStart(e);
|
|
298
306
|
|
|
@@ -311,9 +319,11 @@ export default class StageDragResize extends EventEmitter {
|
|
|
311
319
|
timeout = undefined;
|
|
312
320
|
}
|
|
313
321
|
|
|
314
|
-
|
|
322
|
+
if (this.canContainerHighlight()) {
|
|
323
|
+
timeout = this.core.getAddContainerHighlightClassNameTimeout(e.inputEvent, [this.target]);
|
|
324
|
+
}
|
|
315
325
|
|
|
316
|
-
this.dragStatus =
|
|
326
|
+
this.dragStatus = StageDragStatus.ING;
|
|
317
327
|
|
|
318
328
|
// 流式布局
|
|
319
329
|
if (this.ghostEl) {
|
|
@@ -334,12 +344,12 @@ export default class StageDragResize extends EventEmitter {
|
|
|
334
344
|
|
|
335
345
|
let parentEl: HTMLElement | null = null;
|
|
336
346
|
|
|
337
|
-
if (doc) {
|
|
347
|
+
if (doc && this.canContainerHighlight()) {
|
|
338
348
|
parentEl = removeClassNameByClassName(doc, this.core.containerHighlightClassName);
|
|
339
349
|
}
|
|
340
350
|
|
|
341
351
|
// 点击不拖动时会触发dragStart和dragEnd,但是不会有drag事件
|
|
342
|
-
if (this.dragStatus ===
|
|
352
|
+
if (this.dragStatus === StageDragStatus.ING) {
|
|
343
353
|
if (parentEl) {
|
|
344
354
|
this.update(false, parentEl);
|
|
345
355
|
} else {
|
|
@@ -353,7 +363,7 @@ export default class StageDragResize extends EventEmitter {
|
|
|
353
363
|
}
|
|
354
364
|
}
|
|
355
365
|
|
|
356
|
-
this.dragStatus =
|
|
366
|
+
this.dragStatus = StageDragStatus.END;
|
|
357
367
|
this.destroyGhostEl();
|
|
358
368
|
});
|
|
359
369
|
}
|
|
@@ -363,18 +373,18 @@ export default class StageDragResize extends EventEmitter {
|
|
|
363
373
|
|
|
364
374
|
this.moveable
|
|
365
375
|
.on('rotateStart', (e) => {
|
|
366
|
-
this.dragStatus =
|
|
376
|
+
this.dragStatus = StageDragStatus.START;
|
|
367
377
|
this.moveableHelper?.onRotateStart(e);
|
|
368
378
|
})
|
|
369
379
|
.on('rotate', (e) => {
|
|
370
380
|
if (!this.target || !this.dragEl) return;
|
|
371
|
-
this.dragStatus =
|
|
381
|
+
this.dragStatus = StageDragStatus.ING;
|
|
372
382
|
this.moveableHelper?.onRotate(e);
|
|
373
383
|
const frame = this.moveableHelper?.getFrame(e.target);
|
|
374
384
|
this.target.style.transform = frame?.toCSSObject().transform || '';
|
|
375
385
|
})
|
|
376
386
|
.on('rotateEnd', (e) => {
|
|
377
|
-
this.dragStatus =
|
|
387
|
+
this.dragStatus = StageDragStatus.END;
|
|
378
388
|
const frame = this.moveableHelper?.getFrame(e.target);
|
|
379
389
|
this.emit('update', {
|
|
380
390
|
el: this.target,
|
|
@@ -390,18 +400,18 @@ export default class StageDragResize extends EventEmitter {
|
|
|
390
400
|
|
|
391
401
|
this.moveable
|
|
392
402
|
.on('scaleStart', (e) => {
|
|
393
|
-
this.dragStatus =
|
|
403
|
+
this.dragStatus = StageDragStatus.START;
|
|
394
404
|
this.moveableHelper?.onScaleStart(e);
|
|
395
405
|
})
|
|
396
406
|
.on('scale', (e) => {
|
|
397
407
|
if (!this.target || !this.dragEl) return;
|
|
398
|
-
this.dragStatus =
|
|
408
|
+
this.dragStatus = StageDragStatus.ING;
|
|
399
409
|
this.moveableHelper?.onScale(e);
|
|
400
410
|
const frame = this.moveableHelper?.getFrame(e.target);
|
|
401
411
|
this.target.style.transform = frame?.toCSSObject().transform || '';
|
|
402
412
|
})
|
|
403
413
|
.on('scaleEnd', (e) => {
|
|
404
|
-
this.dragStatus =
|
|
414
|
+
this.dragStatus = StageDragStatus.END;
|
|
405
415
|
const frame = this.moveableHelper?.getFrame(e.target);
|
|
406
416
|
this.emit('update', {
|
|
407
417
|
el: this.target,
|
|
@@ -459,9 +469,13 @@ export default class StageDragResize extends EventEmitter {
|
|
|
459
469
|
}
|
|
460
470
|
|
|
461
471
|
this.emit('update', {
|
|
462
|
-
|
|
472
|
+
data: [
|
|
473
|
+
{
|
|
474
|
+
el: this.target,
|
|
475
|
+
style: isResize ? { left, top, width, height } : { left, top },
|
|
476
|
+
},
|
|
477
|
+
],
|
|
463
478
|
parentEl,
|
|
464
|
-
style: isResize ? { left, top, width, height } : { left, top },
|
|
465
479
|
});
|
|
466
480
|
}
|
|
467
481
|
|
|
@@ -505,6 +519,7 @@ export default class StageDragResize extends EventEmitter {
|
|
|
505
519
|
|
|
506
520
|
const isAbsolute = this.mode === Mode.ABSOLUTE;
|
|
507
521
|
const isFixed = this.mode === Mode.FIXED;
|
|
522
|
+
const isSortable = this.mode === Mode.SORTABLE;
|
|
508
523
|
|
|
509
524
|
let { moveableOptions = {} } = this.core.config;
|
|
510
525
|
|
|
@@ -559,11 +574,18 @@ export default class StageDragResize extends EventEmitter {
|
|
|
559
574
|
// 设置0的话无法移动到left为0,所以只能设置为-1
|
|
560
575
|
left: -1,
|
|
561
576
|
right: this.container.clientWidth - 1,
|
|
562
|
-
bottom: this.container.clientHeight,
|
|
577
|
+
bottom: isSortable ? undefined : this.container.clientHeight,
|
|
563
578
|
...(moveableOptions.bounds || {}),
|
|
564
579
|
},
|
|
565
580
|
...options,
|
|
566
581
|
...moveableOptions,
|
|
567
582
|
};
|
|
568
583
|
}
|
|
584
|
+
|
|
585
|
+
private canContainerHighlight() {
|
|
586
|
+
return (
|
|
587
|
+
this.core.containerHighlightType === ContainerHighlightType.DEFAULT ||
|
|
588
|
+
(this.core.containerHighlightType === ContainerHighlightType.ALT && this.isContainerHighlight)
|
|
589
|
+
);
|
|
590
|
+
}
|
|
569
591
|
}
|
|
@@ -18,15 +18,16 @@
|
|
|
18
18
|
|
|
19
19
|
import { EventEmitter } from 'events';
|
|
20
20
|
|
|
21
|
-
import type { MoveableOptions } from 'moveable';
|
|
21
|
+
import type { MoveableOptions, OnDragStart, OnResizeStart } from 'moveable';
|
|
22
22
|
import Moveable from 'moveable';
|
|
23
23
|
import MoveableHelper from 'moveable-helper';
|
|
24
24
|
|
|
25
25
|
import { DRAG_EL_ID_PREFIX, PAGE_CLASS } from './const';
|
|
26
26
|
import StageCore from './StageCore';
|
|
27
27
|
import StageMask from './StageMask';
|
|
28
|
-
import { StageDragResizeConfig } from './types';
|
|
28
|
+
import { StageDragResizeConfig, StageDragStatus } from './types';
|
|
29
29
|
import { calcValueByFontsize, getMode, getTargetElStyle } from './util';
|
|
30
|
+
|
|
30
31
|
export default class StageMultiDragResize extends EventEmitter {
|
|
31
32
|
public core: StageCore;
|
|
32
33
|
public mask: StageMask;
|
|
@@ -38,6 +39,8 @@ export default class StageMultiDragResize extends EventEmitter {
|
|
|
38
39
|
public dragElList: HTMLDivElement[] = [];
|
|
39
40
|
/** Moveable多选拖拽类实例 */
|
|
40
41
|
public moveableForMulti?: Moveable;
|
|
42
|
+
/** 拖动状态 */
|
|
43
|
+
public dragStatus: StageDragStatus = StageDragStatus.END;
|
|
41
44
|
private multiMoveableHelper?: MoveableHelper;
|
|
42
45
|
|
|
43
46
|
constructor(config: StageDragResizeConfig) {
|
|
@@ -82,23 +85,68 @@ export default class StageMultiDragResize extends EventEmitter {
|
|
|
82
85
|
createAuto: true,
|
|
83
86
|
});
|
|
84
87
|
const frames: { left: number; top: number; id: string }[] = [];
|
|
88
|
+
|
|
89
|
+
const setFrames = (events: OnDragStart[] | OnResizeStart[]) => {
|
|
90
|
+
// 记录拖动前快照
|
|
91
|
+
events.forEach((ev) => {
|
|
92
|
+
// 实际目标元素
|
|
93
|
+
const matchEventTarget = this.targetList.find(
|
|
94
|
+
(targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ''),
|
|
95
|
+
);
|
|
96
|
+
if (!matchEventTarget) return;
|
|
97
|
+
frames.push({
|
|
98
|
+
left: matchEventTarget.offsetLeft,
|
|
99
|
+
top: matchEventTarget.offsetTop,
|
|
100
|
+
id: matchEventTarget.id,
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
|
|
85
105
|
this.moveableForMulti
|
|
86
|
-
.on('
|
|
106
|
+
.on('resizeGroupStart', (params) => {
|
|
87
107
|
const { events } = params;
|
|
88
|
-
this.multiMoveableHelper?.
|
|
89
|
-
|
|
108
|
+
this.multiMoveableHelper?.onResizeGroupStart(params);
|
|
109
|
+
setFrames(events);
|
|
110
|
+
this.dragStatus = StageDragStatus.START;
|
|
111
|
+
})
|
|
112
|
+
.on('resizeGroup', (params) => {
|
|
113
|
+
const { events } = params;
|
|
114
|
+
// 拖动过程更新
|
|
90
115
|
events.forEach((ev) => {
|
|
91
|
-
|
|
92
|
-
const
|
|
116
|
+
const { width, height, beforeTranslate } = ev.drag;
|
|
117
|
+
const frameSnapShot = frames.find(
|
|
118
|
+
(frameItem) => frameItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ''),
|
|
119
|
+
);
|
|
120
|
+
if (!frameSnapShot) return;
|
|
121
|
+
const targeEl = this.targetList.find(
|
|
93
122
|
(targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ''),
|
|
94
123
|
);
|
|
95
|
-
if (!
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
124
|
+
if (!targeEl) return;
|
|
125
|
+
// 元素与其所属组同时加入多选列表时,只更新父元素
|
|
126
|
+
const isParentIncluded = this.targetList.find((targetItem) => targetItem.id === targeEl.parentElement?.id);
|
|
127
|
+
if (!isParentIncluded) {
|
|
128
|
+
// 更新页面元素位置
|
|
129
|
+
targeEl.style.left = `${frameSnapShot.left + beforeTranslate[0]}px`;
|
|
130
|
+
targeEl.style.top = `${frameSnapShot.top + beforeTranslate[1]}px`;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// 更新页面元素位置
|
|
134
|
+
targeEl.style.width = `${width}px`;
|
|
135
|
+
targeEl.style.height = `${height}px`;
|
|
101
136
|
});
|
|
137
|
+
this.multiMoveableHelper?.onResizeGroup(params);
|
|
138
|
+
this.dragStatus = StageDragStatus.ING;
|
|
139
|
+
})
|
|
140
|
+
.on('resizeGroupEnd', () => {
|
|
141
|
+
this.update(true);
|
|
142
|
+
this.dragStatus = StageDragStatus.END;
|
|
143
|
+
})
|
|
144
|
+
.on('dragGroupStart', (params) => {
|
|
145
|
+
const { events } = params;
|
|
146
|
+
this.multiMoveableHelper?.onDragGroupStart(params);
|
|
147
|
+
// 记录拖动前快照
|
|
148
|
+
setFrames(events);
|
|
149
|
+
this.dragStatus = StageDragStatus.START;
|
|
102
150
|
})
|
|
103
151
|
.on('dragGroup', (params) => {
|
|
104
152
|
const { events } = params;
|
|
@@ -121,9 +169,18 @@ export default class StageMultiDragResize extends EventEmitter {
|
|
|
121
169
|
}
|
|
122
170
|
});
|
|
123
171
|
this.multiMoveableHelper?.onDragGroup(params);
|
|
172
|
+
this.dragStatus = StageDragStatus.ING;
|
|
124
173
|
})
|
|
125
174
|
.on('dragGroupEnd', () => {
|
|
126
175
|
this.update();
|
|
176
|
+
this.dragStatus = StageDragStatus.END;
|
|
177
|
+
})
|
|
178
|
+
.on('clickGroup', (params) => {
|
|
179
|
+
const { inputTarget, targets } = params;
|
|
180
|
+
// 如果此时mask不处于多选状态下,且有多个元素被选中,同时点击的元素在选中元素中的其中一项,代表多选态切换为该元素的单选态
|
|
181
|
+
if (!this.mask.isMultiSelectStatus && targets.length > 1 && targets.includes(inputTarget)) {
|
|
182
|
+
this.emit('select', inputTarget.id.replace(DRAG_EL_ID_PREFIX, ''));
|
|
183
|
+
}
|
|
127
184
|
});
|
|
128
185
|
}
|
|
129
186
|
|
|
@@ -192,16 +249,19 @@ export default class StageMultiDragResize extends EventEmitter {
|
|
|
192
249
|
const doc = contentWindow?.document;
|
|
193
250
|
if (!doc) return;
|
|
194
251
|
|
|
195
|
-
this.
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
252
|
+
this.emit('update', {
|
|
253
|
+
data: this.targetList.map((targetItem) => {
|
|
254
|
+
const offset = { left: targetItem.offsetLeft, top: targetItem.offsetTop };
|
|
255
|
+
const left = calcValueByFontsize(doc, offset.left);
|
|
256
|
+
const top = calcValueByFontsize(doc, offset.top);
|
|
257
|
+
const width = calcValueByFontsize(doc, targetItem.clientWidth);
|
|
258
|
+
const height = calcValueByFontsize(doc, targetItem.clientHeight);
|
|
259
|
+
return {
|
|
260
|
+
el: targetItem,
|
|
261
|
+
style: isResize ? { left, top, width, height } : { left, top },
|
|
262
|
+
};
|
|
263
|
+
}),
|
|
264
|
+
parentEl: null,
|
|
205
265
|
});
|
|
206
266
|
}
|
|
207
267
|
|
|
@@ -228,6 +288,15 @@ export default class StageMultiDragResize extends EventEmitter {
|
|
|
228
288
|
zoom: 1,
|
|
229
289
|
origin: true,
|
|
230
290
|
padding: { left: 0, top: 0, right: 0, bottom: 0 },
|
|
291
|
+
snappable: true,
|
|
292
|
+
bounds: {
|
|
293
|
+
top: 0,
|
|
294
|
+
// 设置0的话无法移动到left为0,所以只能设置为-1
|
|
295
|
+
left: -1,
|
|
296
|
+
right: this.container.clientWidth - 1,
|
|
297
|
+
bottom: this.container.clientHeight,
|
|
298
|
+
...(multiMoveableOptions.bounds || {}),
|
|
299
|
+
},
|
|
231
300
|
...options,
|
|
232
301
|
...multiMoveableOptions,
|
|
233
302
|
};
|
package/src/style.css
CHANGED
package/src/types.ts
CHANGED
|
@@ -29,6 +29,11 @@ import StageMask from './StageMask';
|
|
|
29
29
|
export type CanSelect = (el: HTMLElement, event: MouseEvent, stop: () => boolean) => boolean | Promise<boolean>;
|
|
30
30
|
export type IsContainer = (el: HTMLElement) => boolean | Promise<boolean>;
|
|
31
31
|
|
|
32
|
+
export enum ContainerHighlightType {
|
|
33
|
+
DEFAULT = 'default',
|
|
34
|
+
ALT = 'alt',
|
|
35
|
+
}
|
|
36
|
+
|
|
32
37
|
export type StageCoreConfig = {
|
|
33
38
|
/** 需要对齐的dom节点的CSS选择器字符串 */
|
|
34
39
|
snapElementQuerySelector?: string;
|
|
@@ -36,8 +41,9 @@ export type StageCoreConfig = {
|
|
|
36
41
|
zoom?: number;
|
|
37
42
|
canSelect?: CanSelect;
|
|
38
43
|
isContainer: IsContainer;
|
|
39
|
-
containerHighlightClassName
|
|
40
|
-
containerHighlightDuration
|
|
44
|
+
containerHighlightClassName?: string;
|
|
45
|
+
containerHighlightDuration?: number;
|
|
46
|
+
containerHighlightType?: ContainerHighlightType;
|
|
41
47
|
moveableOptions?: ((core?: StageCore) => MoveableOptions) | MoveableOptions;
|
|
42
48
|
multiMoveableOptions?: ((core?: StageCore) => MoveableOptions) | MoveableOptions;
|
|
43
49
|
/** runtime 的HTML地址,可以是一个HTTP地址,如果和编辑器不同域,需要设置跨域,也可以是一个相对或绝对路径 */
|
|
@@ -61,6 +67,16 @@ export interface StageDragResizeConfig {
|
|
|
61
67
|
mask: StageMask;
|
|
62
68
|
}
|
|
63
69
|
|
|
70
|
+
/** 拖动状态 */
|
|
71
|
+
export enum StageDragStatus {
|
|
72
|
+
/** 开始拖动 */
|
|
73
|
+
START = 'start',
|
|
74
|
+
/** 拖动中 */
|
|
75
|
+
ING = 'ing',
|
|
76
|
+
/** 拖动结束 */
|
|
77
|
+
END = 'end',
|
|
78
|
+
}
|
|
79
|
+
|
|
64
80
|
export type Rect = {
|
|
65
81
|
width: number;
|
|
66
82
|
height: number;
|
|
@@ -77,19 +93,21 @@ export interface GuidesEventData {
|
|
|
77
93
|
}
|
|
78
94
|
|
|
79
95
|
export interface UpdateEventData {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
96
|
+
data: {
|
|
97
|
+
el: HTMLElement;
|
|
98
|
+
style: {
|
|
99
|
+
width?: number;
|
|
100
|
+
height?: number;
|
|
101
|
+
left?: number;
|
|
102
|
+
top?: number;
|
|
103
|
+
transform?: {
|
|
104
|
+
rotate?: string;
|
|
105
|
+
scale?: string;
|
|
106
|
+
};
|
|
91
107
|
};
|
|
92
|
-
|
|
108
|
+
ghostEl?: HTMLElement;
|
|
109
|
+
}[];
|
|
110
|
+
parentEl: HTMLElement | null;
|
|
93
111
|
}
|
|
94
112
|
|
|
95
113
|
export interface SortEventData {
|
|
@@ -101,11 +119,13 @@ export interface SortEventData {
|
|
|
101
119
|
export interface UpdateData {
|
|
102
120
|
config: MNode;
|
|
103
121
|
parent?: MContainer;
|
|
122
|
+
parentId?: Id;
|
|
104
123
|
root: MApp;
|
|
105
124
|
}
|
|
106
125
|
|
|
107
126
|
export interface RemoveData {
|
|
108
127
|
id: Id;
|
|
128
|
+
parentId: Id;
|
|
109
129
|
root: MApp;
|
|
110
130
|
}
|
|
111
131
|
|
package/types/StageCore.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import StageHighlight from './StageHighlight';
|
|
|
7
7
|
import StageMask from './StageMask';
|
|
8
8
|
import StageMultiDragResize from './StageMultiDragResize';
|
|
9
9
|
import StageRender from './StageRender';
|
|
10
|
-
import { IsContainer, RemoveData, SortEventData, StageCoreConfig, UpdateData } from './types';
|
|
10
|
+
import { ContainerHighlightType, IsContainer, RemoveData, SortEventData, StageCoreConfig, UpdateData } from './types';
|
|
11
11
|
export default class StageCore extends EventEmitter {
|
|
12
12
|
container?: HTMLDivElement;
|
|
13
13
|
selectedDom: HTMLElement | undefined;
|
|
@@ -22,6 +22,7 @@ export default class StageCore extends EventEmitter {
|
|
|
22
22
|
zoom: number;
|
|
23
23
|
containerHighlightClassName: string;
|
|
24
24
|
containerHighlightDuration: number;
|
|
25
|
+
containerHighlightType?: ContainerHighlightType;
|
|
25
26
|
isContainer: IsContainer;
|
|
26
27
|
private canSelect;
|
|
27
28
|
constructor(config: StageCoreConfig);
|
|
@@ -33,6 +33,7 @@ export default class StageDragResize extends EventEmitter {
|
|
|
33
33
|
/** 流式布局下,目标节点的镜像节点 */
|
|
34
34
|
private ghostEl;
|
|
35
35
|
private moveableHelper?;
|
|
36
|
+
private isContainerHighlight;
|
|
36
37
|
constructor(config: StageDragResizeConfig);
|
|
37
38
|
/**
|
|
38
39
|
* 将选中框渲染并覆盖到选中的组件Dom节点上方
|
|
@@ -67,4 +68,5 @@ export default class StageDragResize extends EventEmitter {
|
|
|
67
68
|
private setGhostElChildrenId;
|
|
68
69
|
private destroyGhostEl;
|
|
69
70
|
private getOptions;
|
|
71
|
+
private canContainerHighlight;
|
|
70
72
|
}
|
|
@@ -3,7 +3,7 @@ import { EventEmitter } from 'events';
|
|
|
3
3
|
import Moveable from 'moveable';
|
|
4
4
|
import StageCore from './StageCore';
|
|
5
5
|
import StageMask from './StageMask';
|
|
6
|
-
import { StageDragResizeConfig } from './types';
|
|
6
|
+
import { StageDragResizeConfig, StageDragStatus } from './types';
|
|
7
7
|
export default class StageMultiDragResize extends EventEmitter {
|
|
8
8
|
core: StageCore;
|
|
9
9
|
mask: StageMask;
|
|
@@ -15,6 +15,8 @@ export default class StageMultiDragResize extends EventEmitter {
|
|
|
15
15
|
dragElList: HTMLDivElement[];
|
|
16
16
|
/** Moveable多选拖拽类实例 */
|
|
17
17
|
moveableForMulti?: Moveable;
|
|
18
|
+
/** 拖动状态 */
|
|
19
|
+
dragStatus: StageDragStatus;
|
|
18
20
|
private multiMoveableHelper?;
|
|
19
21
|
constructor(config: StageDragResizeConfig);
|
|
20
22
|
/**
|