@tmagic/stage 1.0.0-beta.9 → 1.0.0-rc.11
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/README.md +1 -0
- package/dist/tmagic-stage.es.js +516 -297
- package/dist/tmagic-stage.es.js.map +1 -1
- package/dist/tmagic-stage.umd.js +517 -299
- package/dist/tmagic-stage.umd.js.map +1 -1
- package/dist/types/src/StageCore.d.ts +4 -4
- package/dist/types/src/StageDragResize.d.ts +21 -7
- package/dist/types/src/StageHighlight.d.ts +2 -0
- package/dist/types/src/StageMask.d.ts +18 -0
- package/dist/types/src/TargetCalibrate.d.ts +20 -0
- package/dist/types/src/const.d.ts +26 -1
- package/dist/types/src/types.d.ts +22 -6
- package/dist/types/src/util.d.ts +3 -2
- package/package.json +12 -8
- package/src/Rule.ts +13 -5
- package/src/StageCore.ts +43 -23
- package/src/StageDragResize.ts +214 -98
- package/src/StageHighlight.ts +16 -1
- package/src/StageMask.ts +93 -27
- package/src/StageRender.ts +4 -16
- package/src/TargetCalibrate.ts +119 -0
- package/src/const.ts +28 -2
- package/src/types.ts +23 -6
- package/src/util.ts +40 -29
- package/LICENSE +0 -5432
- package/tsconfig.json +0 -9
- package/vite.config.ts +0 -27
package/dist/tmagic-stage.es.js
CHANGED
|
@@ -5,6 +5,8 @@ import { throttle } from 'lodash-es';
|
|
|
5
5
|
import Guides from '@scena/guides';
|
|
6
6
|
|
|
7
7
|
const GHOST_EL_ID_PREFIX = "ghost_el_";
|
|
8
|
+
const DRAG_EL_ID_PREFIX = "drag_el_";
|
|
9
|
+
const HIGHLIGHT_EL_ID_PREFIX = "highlight_el_";
|
|
8
10
|
const DEFAULT_ZOOM = 1;
|
|
9
11
|
var GuidesType = /* @__PURE__ */ ((GuidesType2) => {
|
|
10
12
|
GuidesType2["HORIZONTAL"] = "horizontal";
|
|
@@ -14,6 +16,8 @@ var GuidesType = /* @__PURE__ */ ((GuidesType2) => {
|
|
|
14
16
|
var ZIndex = /* @__PURE__ */ ((ZIndex2) => {
|
|
15
17
|
ZIndex2["MASK"] = "99999";
|
|
16
18
|
ZIndex2["SELECTED_EL"] = "666";
|
|
19
|
+
ZIndex2["GHOST_EL"] = "700";
|
|
20
|
+
ZIndex2["DRAG_EL"] = "9";
|
|
17
21
|
return ZIndex2;
|
|
18
22
|
})(ZIndex || {});
|
|
19
23
|
var MouseButton = /* @__PURE__ */ ((MouseButton2) => {
|
|
@@ -29,31 +33,22 @@ var Mode = /* @__PURE__ */ ((Mode2) => {
|
|
|
29
33
|
return Mode2;
|
|
30
34
|
})(Mode || {});
|
|
31
35
|
const SELECTED_CLASS = "tmagic-stage-selected-area";
|
|
36
|
+
const H_GUIDE_LINE_STORAGE_KEY = "$MagicStageHorizontalGuidelinesData";
|
|
37
|
+
const V_GUIDE_LINE_STORAGE_KEY = "$MagicStageVerticalGuidelinesData";
|
|
32
38
|
|
|
39
|
+
const getParents = (el, relative) => {
|
|
40
|
+
let cur = el.parentElement;
|
|
41
|
+
const parents = [];
|
|
42
|
+
while (cur && cur !== relative) {
|
|
43
|
+
parents.push(cur);
|
|
44
|
+
cur = cur.parentElement;
|
|
45
|
+
}
|
|
46
|
+
return parents;
|
|
47
|
+
};
|
|
33
48
|
const getOffset = (el) => {
|
|
34
|
-
const { transform } = getComputedStyle(el);
|
|
35
49
|
const { offsetParent } = el;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (transform.indexOf("matrix") > -1) {
|
|
39
|
-
let a = 1;
|
|
40
|
-
let b = 1;
|
|
41
|
-
let c = 1;
|
|
42
|
-
let d = 1;
|
|
43
|
-
let e = 0;
|
|
44
|
-
let f = 0;
|
|
45
|
-
transform.replace(/matrix\((.+), (.+), (.+), (.+), (.+), (.+)\)/, ($0, $1, $2, $3, $4, $5, $6) => {
|
|
46
|
-
a = +$1;
|
|
47
|
-
b = +$2;
|
|
48
|
-
c = +$3;
|
|
49
|
-
d = +$4;
|
|
50
|
-
e = +$5;
|
|
51
|
-
f = +$6;
|
|
52
|
-
return transform;
|
|
53
|
-
});
|
|
54
|
-
left = a * left + c * top + e;
|
|
55
|
-
top = b * left + d * top + f;
|
|
56
|
-
}
|
|
50
|
+
const left = el.offsetLeft;
|
|
51
|
+
const top = el.offsetTop;
|
|
57
52
|
if (offsetParent) {
|
|
58
53
|
const parentOffset = getOffset(offsetParent);
|
|
59
54
|
return {
|
|
@@ -154,58 +149,76 @@ const removeSelectedClassName = (doc) => {
|
|
|
154
149
|
if (oldEl) {
|
|
155
150
|
oldEl.classList.remove(SELECTED_CLASS);
|
|
156
151
|
oldEl.parentNode?.classList.remove(`${SELECTED_CLASS}-parent`);
|
|
152
|
+
doc.querySelectorAll(`.${SELECTED_CLASS}-parents`).forEach((item) => {
|
|
153
|
+
item.classList.remove(`${SELECTED_CLASS}-parents`);
|
|
154
|
+
});
|
|
157
155
|
}
|
|
158
156
|
};
|
|
159
|
-
const addSelectedClassName = (el) => {
|
|
157
|
+
const addSelectedClassName = (el, doc) => {
|
|
160
158
|
el.classList.add(SELECTED_CLASS);
|
|
161
159
|
el.parentNode?.classList.add(`${SELECTED_CLASS}-parent`);
|
|
160
|
+
getParents(el, doc.body).forEach((item) => {
|
|
161
|
+
item.classList.add(`${SELECTED_CLASS}-parents`);
|
|
162
|
+
});
|
|
163
|
+
};
|
|
164
|
+
const getGuideLineFromCache = (type) => {
|
|
165
|
+
const key = {
|
|
166
|
+
[GuidesType.HORIZONTAL]: H_GUIDE_LINE_STORAGE_KEY,
|
|
167
|
+
[GuidesType.VERTICAL]: V_GUIDE_LINE_STORAGE_KEY
|
|
168
|
+
}[type];
|
|
169
|
+
if (!key)
|
|
170
|
+
return [];
|
|
171
|
+
const guideLineCacheData = globalThis.localStorage.getItem(key);
|
|
172
|
+
if (guideLineCacheData) {
|
|
173
|
+
try {
|
|
174
|
+
return JSON.parse(guideLineCacheData) || [];
|
|
175
|
+
} catch (e) {
|
|
176
|
+
console.error(e);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return [];
|
|
162
180
|
};
|
|
163
181
|
|
|
164
182
|
class StageDragResize extends EventEmitter {
|
|
165
|
-
core;
|
|
166
|
-
container;
|
|
167
|
-
target;
|
|
168
|
-
dragEl;
|
|
169
|
-
moveable;
|
|
170
|
-
horizontalGuidelines = [];
|
|
171
|
-
verticalGuidelines = [];
|
|
172
|
-
moveableOptions = {};
|
|
173
|
-
dragStatus = "end" /* END */;
|
|
174
|
-
ghostEl;
|
|
175
|
-
mode = Mode.ABSOLUTE;
|
|
176
|
-
moveableHelper;
|
|
177
183
|
constructor(config) {
|
|
178
184
|
super();
|
|
185
|
+
this.horizontalGuidelines = getGuideLineFromCache(GuidesType.HORIZONTAL);
|
|
186
|
+
this.verticalGuidelines = getGuideLineFromCache(GuidesType.VERTICAL);
|
|
187
|
+
this.elementGuidelines = [];
|
|
188
|
+
this.mode = Mode.ABSOLUTE;
|
|
189
|
+
this.moveableOptions = {};
|
|
190
|
+
this.dragStatus = "end" /* END */;
|
|
179
191
|
this.core = config.core;
|
|
180
192
|
this.container = config.container;
|
|
193
|
+
this.dragEl = globalThis.document.createElement("div");
|
|
194
|
+
this.container.append(this.dragEl);
|
|
181
195
|
}
|
|
182
|
-
|
|
196
|
+
select(el, event) {
|
|
197
|
+
const oldTarget = this.target;
|
|
183
198
|
this.target = el;
|
|
184
|
-
if (
|
|
185
|
-
this.
|
|
199
|
+
if (!this.moveable || this.target !== oldTarget) {
|
|
200
|
+
this.init(el);
|
|
201
|
+
this.moveableHelper = MoveableHelper.create({
|
|
202
|
+
useBeforeRender: true,
|
|
203
|
+
useRender: false,
|
|
204
|
+
createAuto: true
|
|
205
|
+
});
|
|
206
|
+
this.initMoveable();
|
|
207
|
+
} else {
|
|
208
|
+
this.updateMoveable();
|
|
186
209
|
}
|
|
187
|
-
this.mode = getMode(el);
|
|
188
|
-
this.destroyDragEl();
|
|
189
|
-
this.destroyGhostEl();
|
|
190
|
-
this.dragEl = this.generateDragEl(el);
|
|
191
|
-
this.moveableOptions = await this.getOptions({
|
|
192
|
-
target: this.dragEl || this.target
|
|
193
|
-
});
|
|
194
|
-
this.moveableHelper = MoveableHelper.create({
|
|
195
|
-
useBeforeRender: true,
|
|
196
|
-
useRender: false,
|
|
197
|
-
createAuto: true
|
|
198
|
-
});
|
|
199
|
-
this.initMoveable();
|
|
200
210
|
if (event) {
|
|
201
211
|
this.moveable?.dragStart(event);
|
|
202
212
|
}
|
|
203
213
|
}
|
|
204
|
-
|
|
214
|
+
updateMoveable(el = this.target) {
|
|
205
215
|
if (!this.moveable)
|
|
206
216
|
throw new Error("\u672A\u521D\u59CB\u5316moveable");
|
|
207
|
-
|
|
208
|
-
|
|
217
|
+
if (!el)
|
|
218
|
+
throw new Error("\u4E3A\u9009\u4E2D\u4EFB\u4F55\u8282\u70B9");
|
|
219
|
+
this.target = el;
|
|
220
|
+
this.init(el);
|
|
221
|
+
Object.entries(this.moveableOptions).forEach(([key, value]) => {
|
|
209
222
|
this.moveable[key] = value;
|
|
210
223
|
});
|
|
211
224
|
this.moveable.updateTarget();
|
|
@@ -213,15 +226,19 @@ class StageDragResize extends EventEmitter {
|
|
|
213
226
|
setGuidelines(type, guidelines) {
|
|
214
227
|
if (type === GuidesType.HORIZONTAL) {
|
|
215
228
|
this.horizontalGuidelines = guidelines;
|
|
229
|
+
this.moveableOptions.horizontalGuidelines = guidelines;
|
|
216
230
|
} else if (type === GuidesType.VERTICAL) {
|
|
217
231
|
this.verticalGuidelines = guidelines;
|
|
232
|
+
this.moveableOptions.verticalGuidelines = guidelines;
|
|
218
233
|
}
|
|
219
|
-
this.
|
|
234
|
+
this.updateMoveable();
|
|
220
235
|
}
|
|
221
236
|
clearGuides() {
|
|
222
|
-
this.verticalGuidelines = [];
|
|
223
237
|
this.horizontalGuidelines = [];
|
|
224
|
-
this.
|
|
238
|
+
this.verticalGuidelines = [];
|
|
239
|
+
this.moveableOptions.horizontalGuidelines = [];
|
|
240
|
+
this.moveableOptions.verticalGuidelines = [];
|
|
241
|
+
this.updateMoveable();
|
|
225
242
|
}
|
|
226
243
|
destroy() {
|
|
227
244
|
this.moveable?.destroy();
|
|
@@ -230,6 +247,37 @@ class StageDragResize extends EventEmitter {
|
|
|
230
247
|
this.dragStatus = "end" /* END */;
|
|
231
248
|
this.removeAllListeners();
|
|
232
249
|
}
|
|
250
|
+
init(el) {
|
|
251
|
+
if (/(auto|scroll)/.test(el.style.overflow)) {
|
|
252
|
+
el.style.overflow = "hidden";
|
|
253
|
+
}
|
|
254
|
+
this.mode = getMode(el);
|
|
255
|
+
this.destroyGhostEl();
|
|
256
|
+
this.updateDragEl(el);
|
|
257
|
+
this.moveableOptions = this.getOptions({
|
|
258
|
+
target: this.dragEl
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
setElementGuidelines(nodes) {
|
|
262
|
+
this.elementGuidelines.forEach((node) => {
|
|
263
|
+
node.remove();
|
|
264
|
+
});
|
|
265
|
+
this.elementGuidelines = [];
|
|
266
|
+
if (this.mode === Mode.ABSOLUTE) {
|
|
267
|
+
const frame = document.createDocumentFragment();
|
|
268
|
+
for (const node of nodes) {
|
|
269
|
+
const { width, height } = node.getBoundingClientRect();
|
|
270
|
+
if (node === this.target)
|
|
271
|
+
continue;
|
|
272
|
+
const { left, top } = getOffset(node);
|
|
273
|
+
const elementGuideline = document.createElement("div");
|
|
274
|
+
elementGuideline.style.cssText = `position: absolute;width: ${width}px;height: ${height}px;top: ${top}px;left: ${left}px`;
|
|
275
|
+
this.elementGuidelines.push(elementGuideline);
|
|
276
|
+
frame.append(elementGuideline);
|
|
277
|
+
}
|
|
278
|
+
this.container.append(frame);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
233
281
|
initMoveable() {
|
|
234
282
|
this.moveable?.destroy();
|
|
235
283
|
this.moveable = new Moveable(this.container, {
|
|
@@ -237,35 +285,38 @@ class StageDragResize extends EventEmitter {
|
|
|
237
285
|
});
|
|
238
286
|
this.bindResizeEvent();
|
|
239
287
|
this.bindDragEvent();
|
|
288
|
+
this.bindRotateEvent();
|
|
289
|
+
this.bindScaleEvent();
|
|
240
290
|
}
|
|
241
291
|
bindResizeEvent() {
|
|
242
292
|
if (!this.moveable)
|
|
243
293
|
throw new Error("moveable \u4E3A\u521D\u59CB\u5316");
|
|
294
|
+
const frame = {
|
|
295
|
+
left: 0,
|
|
296
|
+
top: 0
|
|
297
|
+
};
|
|
244
298
|
this.moveable.on("resizeStart", (e) => {
|
|
245
|
-
if (
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
299
|
+
if (!this.target)
|
|
300
|
+
return;
|
|
301
|
+
this.dragStatus = "start" /* START */;
|
|
302
|
+
this.moveableHelper?.onResizeStart(e);
|
|
303
|
+
frame.top = this.target.offsetTop;
|
|
304
|
+
frame.left = this.target.offsetLeft;
|
|
305
|
+
}).on("resize", (e) => {
|
|
306
|
+
const { width, height, drag } = e;
|
|
251
307
|
if (!this.moveable || !this.target || !this.dragEl)
|
|
252
308
|
return;
|
|
253
309
|
const { beforeTranslate } = drag;
|
|
254
310
|
this.dragStatus = "ing" /* ING */;
|
|
255
|
-
this.
|
|
256
|
-
this.target.style.height = `${height}px`;
|
|
257
|
-
this.dragEl.style.width = `${width}px`;
|
|
258
|
-
this.dragEl.style.height = `${height}px`;
|
|
311
|
+
this.moveableHelper?.onResize(e);
|
|
259
312
|
if (this.mode === Mode.SORTABLE) {
|
|
260
|
-
this.
|
|
261
|
-
|
|
262
|
-
|
|
313
|
+
this.target.style.top = "0px";
|
|
314
|
+
} else {
|
|
315
|
+
this.target.style.left = `${frame.left + beforeTranslate[0]}px`;
|
|
316
|
+
this.target.style.top = `${frame.top + beforeTranslate[1]}px`;
|
|
263
317
|
}
|
|
264
|
-
this.
|
|
265
|
-
this.
|
|
266
|
-
const offset = getAbsolutePosition(this.target, { left: beforeTranslate[0], top: beforeTranslate[1] });
|
|
267
|
-
this.target.style.left = `${offset.left}px`;
|
|
268
|
-
this.target.style.top = `${offset.top}px`;
|
|
318
|
+
this.target.style.width = `${width}px`;
|
|
319
|
+
this.target.style.height = `${height}px`;
|
|
269
320
|
}).on("resizeEnd", () => {
|
|
270
321
|
this.dragStatus = "end" /* END */;
|
|
271
322
|
this.update(true);
|
|
@@ -274,7 +325,7 @@ class StageDragResize extends EventEmitter {
|
|
|
274
325
|
bindDragEvent() {
|
|
275
326
|
if (!this.moveable)
|
|
276
327
|
throw new Error("moveable \u4E3A\u521D\u59CB\u5316");
|
|
277
|
-
|
|
328
|
+
const frame = {
|
|
278
329
|
left: 0,
|
|
279
330
|
top: 0
|
|
280
331
|
};
|
|
@@ -283,23 +334,22 @@ class StageDragResize extends EventEmitter {
|
|
|
283
334
|
throw new Error("\u672A\u9009\u4E2D\u7EC4\u4EF6");
|
|
284
335
|
this.dragStatus = "start" /* START */;
|
|
285
336
|
this.moveableHelper?.onDragStart(e);
|
|
286
|
-
offset = getAbsolutePosition(this.target, { left: 0, top: 0 });
|
|
287
337
|
if (this.mode === Mode.SORTABLE) {
|
|
288
338
|
this.ghostEl = this.generateGhostEl(this.target);
|
|
289
339
|
}
|
|
340
|
+
frame.top = this.target.offsetTop;
|
|
341
|
+
frame.left = this.target.offsetLeft;
|
|
290
342
|
}).on("drag", (e) => {
|
|
291
343
|
if (!this.target || !this.dragEl)
|
|
292
344
|
return;
|
|
293
345
|
this.dragStatus = "ing" /* ING */;
|
|
294
|
-
const { left, top } = e;
|
|
295
346
|
if (this.ghostEl) {
|
|
296
|
-
this.
|
|
297
|
-
this.ghostEl.style.top = `${top + offset.top}px`;
|
|
347
|
+
this.ghostEl.style.top = `${frame.top + e.beforeTranslate[1]}px`;
|
|
298
348
|
return;
|
|
299
349
|
}
|
|
300
350
|
this.moveableHelper?.onDrag(e);
|
|
301
|
-
this.target.style.left = `${left +
|
|
302
|
-
this.target.style.top = `${top +
|
|
351
|
+
this.target.style.left = `${frame.left + e.beforeTranslate[0]}px`;
|
|
352
|
+
this.target.style.top = `${frame.top + e.beforeTranslate[1]}px`;
|
|
303
353
|
}).on("dragEnd", () => {
|
|
304
354
|
if (this.dragStatus === "ing" /* ING */) {
|
|
305
355
|
switch (this.mode) {
|
|
@@ -314,13 +364,53 @@ class StageDragResize extends EventEmitter {
|
|
|
314
364
|
this.destroyGhostEl();
|
|
315
365
|
});
|
|
316
366
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
367
|
+
bindRotateEvent() {
|
|
368
|
+
if (!this.moveable)
|
|
369
|
+
throw new Error("moveable \u4E3A\u521D\u59CB\u5316");
|
|
370
|
+
this.moveable.on("rotateStart", (e) => {
|
|
371
|
+
this.dragStatus = "start" /* START */;
|
|
372
|
+
this.moveableHelper?.onRotateStart(e);
|
|
373
|
+
}).on("rotate", (e) => {
|
|
374
|
+
if (!this.target || !this.dragEl)
|
|
375
|
+
return;
|
|
376
|
+
this.dragStatus = "ing" /* ING */;
|
|
377
|
+
this.moveableHelper?.onRotate(e);
|
|
378
|
+
const frame = this.moveableHelper?.getFrame(e.target);
|
|
379
|
+
this.target.style.transform = frame?.toCSSObject().transform || "";
|
|
380
|
+
}).on("rotateEnd", (e) => {
|
|
381
|
+
this.dragStatus = "end" /* END */;
|
|
382
|
+
const frame = this.moveableHelper?.getFrame(e.target);
|
|
383
|
+
this.emit("update", {
|
|
384
|
+
el: this.target,
|
|
385
|
+
style: {
|
|
386
|
+
transform: frame?.get("transform")
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
bindScaleEvent() {
|
|
392
|
+
if (!this.moveable)
|
|
393
|
+
throw new Error("moveable \u4E3A\u521D\u59CB\u5316");
|
|
394
|
+
this.moveable.on("scaleStart", (e) => {
|
|
395
|
+
this.dragStatus = "start" /* START */;
|
|
396
|
+
this.moveableHelper?.onScaleStart(e);
|
|
397
|
+
}).on("scale", (e) => {
|
|
398
|
+
if (!this.target || !this.dragEl)
|
|
399
|
+
return;
|
|
400
|
+
this.dragStatus = "ing" /* ING */;
|
|
401
|
+
this.moveableHelper?.onScale(e);
|
|
402
|
+
const frame = this.moveableHelper?.getFrame(e.target);
|
|
403
|
+
this.target.style.transform = frame?.toCSSObject().transform || "";
|
|
404
|
+
}).on("scaleEnd", (e) => {
|
|
405
|
+
this.dragStatus = "end" /* END */;
|
|
406
|
+
const frame = this.moveableHelper?.getFrame(e.target);
|
|
407
|
+
this.emit("update", {
|
|
408
|
+
el: this.target,
|
|
409
|
+
style: {
|
|
410
|
+
transform: frame?.get("transform")
|
|
411
|
+
}
|
|
412
|
+
});
|
|
322
413
|
});
|
|
323
|
-
return getSnapElements(el).filter((element) => element !== this.target && !this.target?.contains(element));
|
|
324
414
|
}
|
|
325
415
|
sort() {
|
|
326
416
|
if (!this.target || !this.ghostEl)
|
|
@@ -342,12 +432,13 @@ class StageDragResize extends EventEmitter {
|
|
|
342
432
|
}
|
|
343
433
|
}
|
|
344
434
|
update(isResize = false) {
|
|
345
|
-
|
|
346
|
-
|
|
435
|
+
if (!this.target)
|
|
436
|
+
return;
|
|
437
|
+
const offset = this.mode === Mode.SORTABLE ? { left: 0, top: 0 } : { left: this.target.offsetLeft, top: this.target.offsetTop };
|
|
347
438
|
const left = this.calcValueByFontsize(offset.left);
|
|
348
439
|
const top = this.calcValueByFontsize(offset.top);
|
|
349
|
-
const width = this.calcValueByFontsize(
|
|
350
|
-
const height = this.calcValueByFontsize(
|
|
440
|
+
const width = this.calcValueByFontsize(this.target.clientWidth);
|
|
441
|
+
const height = this.calcValueByFontsize(this.target.clientHeight);
|
|
351
442
|
this.emit("update", {
|
|
352
443
|
el: this.target,
|
|
353
444
|
style: isResize ? { left, top, width, height } : { left, top }
|
|
@@ -359,8 +450,8 @@ class StageDragResize extends EventEmitter {
|
|
|
359
450
|
}
|
|
360
451
|
const ghostEl = el.cloneNode(true);
|
|
361
452
|
const { top, left } = getAbsolutePosition(el, getOffset(el));
|
|
362
|
-
ghostEl.id = `${GHOST_EL_ID_PREFIX}${
|
|
363
|
-
ghostEl.style.zIndex =
|
|
453
|
+
ghostEl.id = `${GHOST_EL_ID_PREFIX}${el.id}`;
|
|
454
|
+
ghostEl.style.zIndex = ZIndex.GHOST_EL;
|
|
364
455
|
ghostEl.style.opacity = ".5";
|
|
365
456
|
ghostEl.style.position = "absolute";
|
|
366
457
|
ghostEl.style.left = `${left}px`;
|
|
@@ -372,44 +463,51 @@ class StageDragResize extends EventEmitter {
|
|
|
372
463
|
this.ghostEl?.remove();
|
|
373
464
|
this.ghostEl = void 0;
|
|
374
465
|
}
|
|
375
|
-
|
|
376
|
-
if (this.dragEl) {
|
|
377
|
-
this.destroyDragEl();
|
|
378
|
-
}
|
|
379
|
-
const { width, height } = el.getBoundingClientRect();
|
|
466
|
+
updateDragEl(el) {
|
|
380
467
|
const offset = getOffset(el);
|
|
381
|
-
const
|
|
382
|
-
dragEl.style.cssText = `
|
|
468
|
+
const { transform } = getComputedStyle(el);
|
|
469
|
+
this.dragEl.style.cssText = `
|
|
383
470
|
position: absolute;
|
|
471
|
+
transform: ${transform};
|
|
384
472
|
left: ${offset.left}px;
|
|
385
473
|
top: ${offset.top}px;
|
|
386
|
-
width: ${
|
|
387
|
-
height: ${
|
|
474
|
+
width: ${el.clientWidth}px;
|
|
475
|
+
height: ${el.clientHeight}px;
|
|
476
|
+
z-index: ${ZIndex.DRAG_EL};
|
|
388
477
|
`;
|
|
389
|
-
this.
|
|
390
|
-
|
|
478
|
+
this.dragEl.id = `${DRAG_EL_ID_PREFIX}${el.id}`;
|
|
479
|
+
if (typeof this.core.config.updateDragEl === "function") {
|
|
480
|
+
this.core.config.updateDragEl(this.dragEl, el);
|
|
481
|
+
}
|
|
391
482
|
}
|
|
392
483
|
destroyDragEl() {
|
|
393
484
|
this.dragEl?.remove();
|
|
394
|
-
this.dragEl = void 0;
|
|
395
485
|
}
|
|
396
|
-
|
|
486
|
+
getOptions(options = {}) {
|
|
397
487
|
if (!this.target)
|
|
398
488
|
return {};
|
|
399
489
|
const isAbsolute = this.mode === Mode.ABSOLUTE;
|
|
490
|
+
const isFixed = this.mode === Mode.FIXED;
|
|
400
491
|
let { moveableOptions = {} } = this.core.config;
|
|
401
492
|
if (typeof moveableOptions === "function") {
|
|
402
493
|
moveableOptions = moveableOptions(this.core);
|
|
403
494
|
}
|
|
495
|
+
const elementGuidelines = moveableOptions.elementGuidelines || this.target.parentElement?.children || [];
|
|
496
|
+
this.setElementGuidelines(elementGuidelines);
|
|
497
|
+
if (moveableOptions.elementGuidelines) {
|
|
498
|
+
delete moveableOptions.elementGuidelines;
|
|
499
|
+
}
|
|
404
500
|
return {
|
|
405
|
-
origin:
|
|
501
|
+
origin: false,
|
|
406
502
|
rootContainer: this.core.container,
|
|
407
503
|
zoom: 1,
|
|
408
504
|
dragArea: false,
|
|
409
505
|
draggable: true,
|
|
410
506
|
resizable: true,
|
|
411
|
-
|
|
412
|
-
|
|
507
|
+
scalable: false,
|
|
508
|
+
rotatable: false,
|
|
509
|
+
snappable: isAbsolute || isFixed,
|
|
510
|
+
snapGap: isAbsolute || isFixed,
|
|
413
511
|
snapThreshold: 5,
|
|
414
512
|
snapDigit: 0,
|
|
415
513
|
throttleDrag: 0,
|
|
@@ -422,8 +520,16 @@ class StageDragResize extends EventEmitter {
|
|
|
422
520
|
center: isAbsolute,
|
|
423
521
|
middle: isAbsolute
|
|
424
522
|
},
|
|
523
|
+
elementSnapDirections: {
|
|
524
|
+
top: isAbsolute,
|
|
525
|
+
right: isAbsolute,
|
|
526
|
+
bottom: isAbsolute,
|
|
527
|
+
left: isAbsolute
|
|
528
|
+
},
|
|
529
|
+
isDisplayInnerSnapDigit: true,
|
|
425
530
|
horizontalGuidelines: this.horizontalGuidelines,
|
|
426
531
|
verticalGuidelines: this.verticalGuidelines,
|
|
532
|
+
elementGuidelines: this.elementGuidelines,
|
|
427
533
|
bounds: {
|
|
428
534
|
top: 0,
|
|
429
535
|
left: 0,
|
|
@@ -492,15 +598,83 @@ const up = (deltaTop, target) => {
|
|
|
492
598
|
};
|
|
493
599
|
};
|
|
494
600
|
|
|
601
|
+
class TargetCalibrate extends EventEmitter {
|
|
602
|
+
constructor(config) {
|
|
603
|
+
super();
|
|
604
|
+
this.parent = config.parent;
|
|
605
|
+
this.mask = config.mask;
|
|
606
|
+
this.dr = config.dr;
|
|
607
|
+
this.core = config.core;
|
|
608
|
+
this.operationEl = globalThis.document.createElement("div");
|
|
609
|
+
this.parent.append(this.operationEl);
|
|
610
|
+
}
|
|
611
|
+
update(el, prefix) {
|
|
612
|
+
const { left, top } = this.getOffset(el);
|
|
613
|
+
const { transform } = getComputedStyle(el);
|
|
614
|
+
this.operationEl.style.cssText = `
|
|
615
|
+
position: absolute;
|
|
616
|
+
transform: ${transform};
|
|
617
|
+
left: ${left}px;
|
|
618
|
+
top: ${top}px;
|
|
619
|
+
width: ${el.clientWidth}px;
|
|
620
|
+
height: ${el.clientHeight}px;
|
|
621
|
+
`;
|
|
622
|
+
this.operationEl.id = `${prefix}${el.id}`;
|
|
623
|
+
if (typeof this.core.config.updateDragEl === "function") {
|
|
624
|
+
this.core.config.updateDragEl(this.operationEl, el);
|
|
625
|
+
}
|
|
626
|
+
return this.operationEl;
|
|
627
|
+
}
|
|
628
|
+
destroy() {
|
|
629
|
+
this.operationEl?.remove();
|
|
630
|
+
}
|
|
631
|
+
getOffset(el) {
|
|
632
|
+
const { offsetParent } = el;
|
|
633
|
+
const left = el.offsetLeft;
|
|
634
|
+
const top = el.offsetTop;
|
|
635
|
+
if (offsetParent) {
|
|
636
|
+
const parentOffset = this.getOffset(offsetParent);
|
|
637
|
+
return {
|
|
638
|
+
left: left + parentOffset.left,
|
|
639
|
+
top: top + parentOffset.top
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
if (this.dr.mode === Mode.FIXED) {
|
|
643
|
+
if (getMode(el) === Mode.FIXED) {
|
|
644
|
+
return {
|
|
645
|
+
left,
|
|
646
|
+
top
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
return {
|
|
650
|
+
left: left - this.mask.scrollLeft,
|
|
651
|
+
top: top - this.mask.scrollTop
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
if (getMode(el) === Mode.FIXED) {
|
|
655
|
+
return {
|
|
656
|
+
left: left + this.mask.scrollLeft,
|
|
657
|
+
top: top + this.mask.scrollTop
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
return {
|
|
661
|
+
left,
|
|
662
|
+
top
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
495
667
|
class StageHighlight extends EventEmitter {
|
|
496
|
-
core;
|
|
497
|
-
container;
|
|
498
|
-
target;
|
|
499
|
-
moveable;
|
|
500
668
|
constructor(config) {
|
|
501
669
|
super();
|
|
502
670
|
this.core = config.core;
|
|
503
671
|
this.container = config.container;
|
|
672
|
+
this.calibrationTarget = new TargetCalibrate({
|
|
673
|
+
parent: this.core.mask.content,
|
|
674
|
+
mask: this.core.mask,
|
|
675
|
+
dr: this.core.dr,
|
|
676
|
+
core: this.core
|
|
677
|
+
});
|
|
504
678
|
}
|
|
505
679
|
highlight(el) {
|
|
506
680
|
if (!el || el === this.target)
|
|
@@ -508,32 +682,66 @@ class StageHighlight extends EventEmitter {
|
|
|
508
682
|
this.target = el;
|
|
509
683
|
this.moveable?.destroy();
|
|
510
684
|
this.moveable = new Moveable(this.container, {
|
|
511
|
-
target: this.
|
|
685
|
+
target: this.calibrationTarget.update(el, HIGHLIGHT_EL_ID_PREFIX),
|
|
686
|
+
origin: false,
|
|
687
|
+
rootContainer: this.core.container,
|
|
688
|
+
zoom: 1
|
|
512
689
|
});
|
|
513
690
|
}
|
|
514
691
|
clearHighlight() {
|
|
515
692
|
if (!this.moveable)
|
|
516
693
|
return;
|
|
694
|
+
this.target = void 0;
|
|
517
695
|
this.moveable.target = null;
|
|
518
696
|
this.moveable.updateTarget();
|
|
519
697
|
}
|
|
520
698
|
destroy() {
|
|
521
699
|
this.moveable?.destroy();
|
|
700
|
+
this.calibrationTarget.destroy();
|
|
522
701
|
}
|
|
523
702
|
}
|
|
524
703
|
|
|
525
704
|
class Rule extends EventEmitter$1 {
|
|
526
|
-
hGuides;
|
|
527
|
-
vGuides;
|
|
528
|
-
horizontalGuidelines = [];
|
|
529
|
-
verticalGuidelines = [];
|
|
530
|
-
container;
|
|
531
|
-
containerResizeObserver;
|
|
532
705
|
constructor(container) {
|
|
533
706
|
super();
|
|
707
|
+
this.horizontalGuidelines = getGuideLineFromCache(GuidesType.HORIZONTAL);
|
|
708
|
+
this.verticalGuidelines = getGuideLineFromCache(GuidesType.VERTICAL);
|
|
709
|
+
this.getGuidesStyle = (type) => ({
|
|
710
|
+
position: "fixed",
|
|
711
|
+
zIndex: 1,
|
|
712
|
+
left: type === GuidesType.HORIZONTAL ? 0 : "-30px",
|
|
713
|
+
top: type === GuidesType.HORIZONTAL ? "-30px" : 0,
|
|
714
|
+
width: type === GuidesType.HORIZONTAL ? "100%" : "30px",
|
|
715
|
+
height: type === GuidesType.HORIZONTAL ? "30px" : "100%"
|
|
716
|
+
});
|
|
717
|
+
this.createGuides = (type, defaultGuides = []) => new Guides(this.container, {
|
|
718
|
+
type,
|
|
719
|
+
defaultGuides,
|
|
720
|
+
displayDragPos: true,
|
|
721
|
+
backgroundColor: "#fff",
|
|
722
|
+
lineColor: "#000",
|
|
723
|
+
textColor: "#000",
|
|
724
|
+
style: this.getGuidesStyle(type)
|
|
725
|
+
});
|
|
726
|
+
this.hGuidesChangeGuidesHandler = (e) => {
|
|
727
|
+
this.horizontalGuidelines = e.guides;
|
|
728
|
+
this.emit("changeGuides", {
|
|
729
|
+
type: GuidesType.HORIZONTAL,
|
|
730
|
+
guides: this.horizontalGuidelines
|
|
731
|
+
});
|
|
732
|
+
globalThis.localStorage.setItem(H_GUIDE_LINE_STORAGE_KEY, JSON.stringify(e.guides));
|
|
733
|
+
};
|
|
734
|
+
this.vGuidesChangeGuidesHandler = (e) => {
|
|
735
|
+
this.verticalGuidelines = e.guides;
|
|
736
|
+
this.emit("changeGuides", {
|
|
737
|
+
type: GuidesType.VERTICAL,
|
|
738
|
+
guides: this.verticalGuidelines
|
|
739
|
+
});
|
|
740
|
+
globalThis.localStorage.setItem(V_GUIDE_LINE_STORAGE_KEY, JSON.stringify(e.guides));
|
|
741
|
+
};
|
|
534
742
|
this.container = container;
|
|
535
|
-
this.hGuides = this.createGuides(GuidesType.HORIZONTAL);
|
|
536
|
-
this.vGuides = this.createGuides(GuidesType.VERTICAL);
|
|
743
|
+
this.hGuides = this.createGuides(GuidesType.HORIZONTAL, this.horizontalGuidelines);
|
|
744
|
+
this.vGuides = this.createGuides(GuidesType.VERTICAL, this.verticalGuidelines);
|
|
537
745
|
this.hGuides.on("changeGuides", this.hGuidesChangeGuidesHandler);
|
|
538
746
|
this.vGuides.on("changeGuides", this.vGuidesChangeGuidesHandler);
|
|
539
747
|
this.containerResizeObserver = new ResizeObserver(() => {
|
|
@@ -567,6 +775,8 @@ class Rule extends EventEmitter$1 {
|
|
|
567
775
|
type: GuidesType.HORIZONTAL,
|
|
568
776
|
guides: []
|
|
569
777
|
});
|
|
778
|
+
globalThis.localStorage.setItem(V_GUIDE_LINE_STORAGE_KEY, "[]");
|
|
779
|
+
globalThis.localStorage.setItem(H_GUIDE_LINE_STORAGE_KEY, "[]");
|
|
570
780
|
}
|
|
571
781
|
showRule(show = true) {
|
|
572
782
|
if (show) {
|
|
@@ -599,37 +809,6 @@ class Rule extends EventEmitter$1 {
|
|
|
599
809
|
this.containerResizeObserver.disconnect();
|
|
600
810
|
this.removeAllListeners();
|
|
601
811
|
}
|
|
602
|
-
getGuidesStyle = (type) => ({
|
|
603
|
-
position: "fixed",
|
|
604
|
-
zIndex: 1,
|
|
605
|
-
left: type === GuidesType.HORIZONTAL ? 0 : "-30px",
|
|
606
|
-
top: type === GuidesType.HORIZONTAL ? "-30px" : 0,
|
|
607
|
-
width: type === GuidesType.HORIZONTAL ? "100%" : "30px",
|
|
608
|
-
height: type === GuidesType.HORIZONTAL ? "30px" : "100%"
|
|
609
|
-
});
|
|
610
|
-
createGuides = (type, defaultGuides = []) => new Guides(this.container, {
|
|
611
|
-
type,
|
|
612
|
-
defaultGuides,
|
|
613
|
-
displayDragPos: true,
|
|
614
|
-
backgroundColor: "#fff",
|
|
615
|
-
lineColor: "#000",
|
|
616
|
-
textColor: "#000",
|
|
617
|
-
style: this.getGuidesStyle(type)
|
|
618
|
-
});
|
|
619
|
-
hGuidesChangeGuidesHandler = (e) => {
|
|
620
|
-
this.horizontalGuidelines = e.guides;
|
|
621
|
-
this.emit("changeGuides", {
|
|
622
|
-
type: GuidesType.HORIZONTAL,
|
|
623
|
-
guides: this.horizontalGuidelines
|
|
624
|
-
});
|
|
625
|
-
};
|
|
626
|
-
vGuidesChangeGuidesHandler = (e) => {
|
|
627
|
-
this.verticalGuidelines = e.guides;
|
|
628
|
-
this.emit("changeGuides", {
|
|
629
|
-
type: GuidesType.VERTICAL,
|
|
630
|
-
guides: this.verticalGuidelines
|
|
631
|
-
});
|
|
632
|
-
};
|
|
633
812
|
}
|
|
634
813
|
|
|
635
814
|
const wrapperClassName = "editor-mask-wrapper";
|
|
@@ -667,32 +846,73 @@ const createWrapper = () => {
|
|
|
667
846
|
return el;
|
|
668
847
|
};
|
|
669
848
|
class StageMask extends Rule {
|
|
670
|
-
content = createContent();
|
|
671
|
-
wrapper;
|
|
672
|
-
core;
|
|
673
|
-
page = null;
|
|
674
|
-
pageScrollParent = null;
|
|
675
|
-
scrollTop = 0;
|
|
676
|
-
scrollLeft = 0;
|
|
677
|
-
width = 0;
|
|
678
|
-
height = 0;
|
|
679
|
-
wrapperHeight = 0;
|
|
680
|
-
wrapperWidth = 0;
|
|
681
|
-
mode = Mode.ABSOLUTE;
|
|
682
|
-
pageResizeObserver = null;
|
|
683
|
-
wrapperResizeObserver = null;
|
|
684
|
-
highlightHandler = throttle((event) => {
|
|
685
|
-
this.emit("highlight", event);
|
|
686
|
-
}, throttleTime);
|
|
687
849
|
constructor(config) {
|
|
688
850
|
const wrapper = createWrapper();
|
|
689
851
|
super(wrapper);
|
|
852
|
+
this.content = createContent();
|
|
853
|
+
this.page = null;
|
|
854
|
+
this.pageScrollParent = null;
|
|
855
|
+
this.scrollTop = 0;
|
|
856
|
+
this.scrollLeft = 0;
|
|
857
|
+
this.width = 0;
|
|
858
|
+
this.height = 0;
|
|
859
|
+
this.wrapperHeight = 0;
|
|
860
|
+
this.wrapperWidth = 0;
|
|
861
|
+
this.maxScrollTop = 0;
|
|
862
|
+
this.maxScrollLeft = 0;
|
|
863
|
+
this.intersectionObserver = null;
|
|
864
|
+
this.mode = Mode.ABSOLUTE;
|
|
865
|
+
this.pageResizeObserver = null;
|
|
866
|
+
this.wrapperResizeObserver = null;
|
|
867
|
+
this.highlightHandler = throttle((event) => {
|
|
868
|
+
this.emit("highlight", event);
|
|
869
|
+
}, throttleTime);
|
|
870
|
+
this.mouseDownHandler = (event) => {
|
|
871
|
+
this.emit("clearHighlight");
|
|
872
|
+
event.stopImmediatePropagation();
|
|
873
|
+
event.stopPropagation();
|
|
874
|
+
if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT)
|
|
875
|
+
return;
|
|
876
|
+
if (event.target.className.indexOf("moveable-control") !== -1) {
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
this.content.removeEventListener("mousemove", this.highlightHandler);
|
|
880
|
+
this.emit("beforeSelect", event);
|
|
881
|
+
globalThis.document.addEventListener("mouseup", this.mouseUpHandler);
|
|
882
|
+
};
|
|
883
|
+
this.mouseUpHandler = () => {
|
|
884
|
+
globalThis.document.removeEventListener("mouseup", this.mouseUpHandler);
|
|
885
|
+
this.content.addEventListener("mousemove", this.highlightHandler);
|
|
886
|
+
this.emit("select");
|
|
887
|
+
};
|
|
888
|
+
this.mouseWheelHandler = (event) => {
|
|
889
|
+
this.emit("clearHighlight");
|
|
890
|
+
if (!this.page)
|
|
891
|
+
throw new Error("page \u672A\u521D\u59CB\u5316");
|
|
892
|
+
const { deltaY, deltaX } = event;
|
|
893
|
+
if (this.page.clientHeight < this.wrapperHeight && deltaY)
|
|
894
|
+
return;
|
|
895
|
+
if (this.page.clientWidth < this.wrapperWidth && deltaX)
|
|
896
|
+
return;
|
|
897
|
+
if (this.maxScrollTop > 0) {
|
|
898
|
+
this.scrollTop = this.scrollTop + deltaY;
|
|
899
|
+
}
|
|
900
|
+
if (this.maxScrollLeft > 0) {
|
|
901
|
+
this.scrollLeft = this.scrollLeft + deltaX;
|
|
902
|
+
}
|
|
903
|
+
this.scroll();
|
|
904
|
+
this.emit("scroll", event);
|
|
905
|
+
};
|
|
906
|
+
this.mouseLeaveHandler = () => {
|
|
907
|
+
setTimeout(() => this.emit("clearHighlight"), throttleTime);
|
|
908
|
+
};
|
|
690
909
|
this.wrapper = wrapper;
|
|
691
910
|
this.core = config.core;
|
|
692
911
|
this.content.addEventListener("mousedown", this.mouseDownHandler);
|
|
693
912
|
this.wrapper.appendChild(this.content);
|
|
694
913
|
this.content.addEventListener("wheel", this.mouseWheelHandler);
|
|
695
914
|
this.content.addEventListener("mousemove", this.highlightHandler);
|
|
915
|
+
this.content.addEventListener("mouseleave", this.mouseLeaveHandler);
|
|
696
916
|
}
|
|
697
917
|
setMode(mode) {
|
|
698
918
|
this.mode = mode;
|
|
@@ -711,12 +931,33 @@ class StageMask extends Rule {
|
|
|
711
931
|
this.page = page;
|
|
712
932
|
this.pageScrollParent = getScrollParent(page) || this.core.renderer.contentWindow?.document.documentElement || null;
|
|
713
933
|
this.pageResizeObserver?.disconnect();
|
|
934
|
+
this.wrapperResizeObserver?.disconnect();
|
|
935
|
+
this.intersectionObserver?.disconnect();
|
|
936
|
+
if (typeof IntersectionObserver !== "undefined") {
|
|
937
|
+
this.intersectionObserver = new IntersectionObserver((entries) => {
|
|
938
|
+
entries.forEach((entry) => {
|
|
939
|
+
const { target, intersectionRatio } = entry;
|
|
940
|
+
if (intersectionRatio <= 0) {
|
|
941
|
+
this.scrollIntoView(target);
|
|
942
|
+
}
|
|
943
|
+
this.intersectionObserver?.unobserve(target);
|
|
944
|
+
});
|
|
945
|
+
}, {
|
|
946
|
+
root: this.pageScrollParent,
|
|
947
|
+
rootMargin: "0px",
|
|
948
|
+
threshold: 1
|
|
949
|
+
});
|
|
950
|
+
}
|
|
714
951
|
if (typeof ResizeObserver !== "undefined") {
|
|
715
952
|
this.pageResizeObserver = new ResizeObserver((entries) => {
|
|
716
953
|
const [entry] = entries;
|
|
717
954
|
const { clientHeight, clientWidth } = entry.target;
|
|
718
955
|
this.setHeight(clientHeight);
|
|
719
956
|
this.setWidth(clientWidth);
|
|
957
|
+
this.scroll();
|
|
958
|
+
if (this.core.dr.moveable) {
|
|
959
|
+
this.core.dr.updateMoveable();
|
|
960
|
+
}
|
|
720
961
|
});
|
|
721
962
|
this.pageResizeObserver.observe(page);
|
|
722
963
|
this.wrapperResizeObserver = new ResizeObserver((entries) => {
|
|
@@ -724,6 +965,8 @@ class StageMask extends Rule {
|
|
|
724
965
|
const { clientHeight, clientWidth } = entry.target;
|
|
725
966
|
this.wrapperHeight = clientHeight;
|
|
726
967
|
this.wrapperWidth = clientWidth;
|
|
968
|
+
this.setMaxScrollLeft();
|
|
969
|
+
this.setMaxScrollTop();
|
|
727
970
|
});
|
|
728
971
|
this.wrapperResizeObserver.observe(this.wrapper);
|
|
729
972
|
}
|
|
@@ -736,16 +979,32 @@ class StageMask extends Rule {
|
|
|
736
979
|
setLayout(el) {
|
|
737
980
|
this.setMode(isFixedParent(el) ? Mode.FIXED : Mode.ABSOLUTE);
|
|
738
981
|
}
|
|
982
|
+
scrollIntoView(el) {
|
|
983
|
+
el.scrollIntoView();
|
|
984
|
+
if (!this.pageScrollParent)
|
|
985
|
+
return;
|
|
986
|
+
this.scrollLeft = this.pageScrollParent.scrollLeft;
|
|
987
|
+
this.scrollTop = this.pageScrollParent.scrollTop;
|
|
988
|
+
this.scroll();
|
|
989
|
+
}
|
|
739
990
|
destroy() {
|
|
740
991
|
this.content?.remove();
|
|
741
992
|
this.page = null;
|
|
742
993
|
this.pageScrollParent = null;
|
|
743
994
|
this.pageResizeObserver?.disconnect();
|
|
744
995
|
this.wrapperResizeObserver?.disconnect();
|
|
996
|
+
this.content.removeEventListener("mouseleave", this.mouseLeaveHandler);
|
|
745
997
|
super.destroy();
|
|
746
998
|
}
|
|
747
999
|
scroll() {
|
|
1000
|
+
this.fixScrollValue();
|
|
748
1001
|
let { scrollLeft, scrollTop } = this;
|
|
1002
|
+
if (this.pageScrollParent) {
|
|
1003
|
+
this.pageScrollParent.scrollTo({
|
|
1004
|
+
top: scrollTop,
|
|
1005
|
+
left: scrollLeft
|
|
1006
|
+
});
|
|
1007
|
+
}
|
|
749
1008
|
if (this.mode === Mode.FIXED) {
|
|
750
1009
|
scrollLeft = 0;
|
|
751
1010
|
scrollTop = 0;
|
|
@@ -758,74 +1017,67 @@ class StageMask extends Rule {
|
|
|
758
1017
|
}
|
|
759
1018
|
setHeight(height) {
|
|
760
1019
|
this.height = height;
|
|
1020
|
+
this.setMaxScrollTop();
|
|
761
1021
|
this.content.style.height = `${height}px`;
|
|
762
1022
|
}
|
|
763
1023
|
setWidth(width) {
|
|
764
1024
|
this.width = width;
|
|
1025
|
+
this.setMaxScrollLeft();
|
|
765
1026
|
this.content.style.width = `${width}px`;
|
|
766
1027
|
}
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
this.
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
this.emit("select");
|
|
784
|
-
};
|
|
785
|
-
mouseWheelHandler = (event) => {
|
|
786
|
-
if (!this.page)
|
|
787
|
-
throw new Error("page \u672A\u521D\u59CB\u5316");
|
|
788
|
-
const { deltaY, deltaX } = event;
|
|
789
|
-
const { height, wrapperHeight, width, wrapperWidth } = this;
|
|
790
|
-
const maxScrollTop = height - wrapperHeight;
|
|
791
|
-
const maxScrollLeft = width - wrapperWidth;
|
|
792
|
-
if (maxScrollTop > 0) {
|
|
793
|
-
if (deltaY > 0) {
|
|
794
|
-
this.scrollTop = this.scrollTop + Math.min(maxScrollTop - this.scrollTop, deltaY);
|
|
795
|
-
} else {
|
|
796
|
-
this.scrollTop = Math.max(this.scrollTop + deltaY, 0);
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
if (width > wrapperWidth) {
|
|
800
|
-
if (deltaX > 0) {
|
|
801
|
-
this.scrollLeft = this.scrollLeft + Math.min(maxScrollLeft - this.scrollLeft, deltaX);
|
|
802
|
-
} else {
|
|
803
|
-
this.scrollLeft = Math.max(this.scrollLeft + deltaX, 0);
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
if (this.mode !== Mode.FIXED) {
|
|
807
|
-
this.scrollTo(this.scrollLeft, this.scrollTop);
|
|
808
|
-
}
|
|
809
|
-
if (this.pageScrollParent) {
|
|
810
|
-
this.pageScrollParent.scrollTo({
|
|
811
|
-
top: this.scrollTop,
|
|
812
|
-
left: this.scrollLeft
|
|
813
|
-
});
|
|
814
|
-
}
|
|
815
|
-
this.scroll();
|
|
816
|
-
this.emit("scroll", event);
|
|
817
|
-
};
|
|
1028
|
+
setMaxScrollLeft() {
|
|
1029
|
+
this.maxScrollLeft = Math.max(this.width - this.wrapperWidth, 0);
|
|
1030
|
+
}
|
|
1031
|
+
setMaxScrollTop() {
|
|
1032
|
+
this.maxScrollTop = Math.max(this.height - this.wrapperHeight, 0);
|
|
1033
|
+
}
|
|
1034
|
+
fixScrollValue() {
|
|
1035
|
+
if (this.scrollTop < 0)
|
|
1036
|
+
this.scrollTop = 0;
|
|
1037
|
+
if (this.scrollLeft < 0)
|
|
1038
|
+
this.scrollLeft = 0;
|
|
1039
|
+
if (this.maxScrollTop < this.scrollTop)
|
|
1040
|
+
this.scrollTop = this.maxScrollTop;
|
|
1041
|
+
if (this.maxScrollLeft < this.scrollLeft)
|
|
1042
|
+
this.scrollLeft = this.maxScrollLeft;
|
|
1043
|
+
}
|
|
818
1044
|
}
|
|
819
1045
|
|
|
820
1046
|
class StageRender extends EventEmitter {
|
|
821
|
-
contentWindow = null;
|
|
822
|
-
runtime = null;
|
|
823
|
-
iframe;
|
|
824
|
-
runtimeUrl;
|
|
825
|
-
core;
|
|
826
|
-
render;
|
|
827
1047
|
constructor({ core }) {
|
|
828
1048
|
super();
|
|
1049
|
+
this.contentWindow = null;
|
|
1050
|
+
this.runtime = null;
|
|
1051
|
+
this.getMagicApi = () => ({
|
|
1052
|
+
onPageElUpdate: (el) => this.emit("page-el-update", el),
|
|
1053
|
+
onRuntimeReady: (runtime) => {
|
|
1054
|
+
this.runtime = runtime;
|
|
1055
|
+
globalThis.runtime = runtime;
|
|
1056
|
+
this.emit("runtime-ready", runtime);
|
|
1057
|
+
}
|
|
1058
|
+
});
|
|
1059
|
+
this.getRuntime = () => {
|
|
1060
|
+
if (this.runtime)
|
|
1061
|
+
return Promise.resolve(this.runtime);
|
|
1062
|
+
return new Promise((resolve) => {
|
|
1063
|
+
const listener = (runtime) => {
|
|
1064
|
+
this.off("runtime-ready", listener);
|
|
1065
|
+
resolve(runtime);
|
|
1066
|
+
};
|
|
1067
|
+
this.on("runtime-ready", listener);
|
|
1068
|
+
});
|
|
1069
|
+
};
|
|
1070
|
+
this.loadHandler = async () => {
|
|
1071
|
+
this.contentWindow = this.iframe?.contentWindow;
|
|
1072
|
+
this.contentWindow.magic = this.getMagicApi();
|
|
1073
|
+
if (this.render) {
|
|
1074
|
+
const el = await this.render(this.core);
|
|
1075
|
+
if (el) {
|
|
1076
|
+
this.iframe?.contentDocument?.body?.appendChild(el);
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
this.emit("onload");
|
|
1080
|
+
};
|
|
829
1081
|
this.core = core;
|
|
830
1082
|
this.runtimeUrl = core.config.runtimeUrl || "";
|
|
831
1083
|
this.render = core.config.render;
|
|
@@ -838,14 +1090,6 @@ class StageRender extends EventEmitter {
|
|
|
838
1090
|
`;
|
|
839
1091
|
this.iframe.addEventListener("load", this.loadHandler);
|
|
840
1092
|
}
|
|
841
|
-
getMagicApi = () => ({
|
|
842
|
-
onPageElUpdate: (el) => this.emit("page-el-update", el),
|
|
843
|
-
onRuntimeReady: (runtime) => {
|
|
844
|
-
this.runtime = runtime;
|
|
845
|
-
globalThis.runtime = runtime;
|
|
846
|
-
this.emit("runtime-ready", runtime);
|
|
847
|
-
}
|
|
848
|
-
});
|
|
849
1093
|
async mount(el) {
|
|
850
1094
|
if (this.iframe) {
|
|
851
1095
|
if (!isSameDomain(this.runtimeUrl) && this.runtimeUrl) {
|
|
@@ -856,23 +1100,10 @@ class StageRender extends EventEmitter {
|
|
|
856
1100
|
this.iframe.srcdoc = html;
|
|
857
1101
|
}
|
|
858
1102
|
el.appendChild(this.iframe);
|
|
859
|
-
this.contentWindow = this.iframe?.contentWindow;
|
|
860
|
-
this.contentWindow.magic = this.getMagicApi();
|
|
861
1103
|
} else {
|
|
862
1104
|
throw Error("mount \u5931\u8D25");
|
|
863
1105
|
}
|
|
864
1106
|
}
|
|
865
|
-
getRuntime = () => {
|
|
866
|
-
if (this.runtime)
|
|
867
|
-
return Promise.resolve(this.runtime);
|
|
868
|
-
return new Promise((resolve) => {
|
|
869
|
-
const listener = (runtime) => {
|
|
870
|
-
this.off("runtime-ready", listener);
|
|
871
|
-
resolve(runtime);
|
|
872
|
-
};
|
|
873
|
-
this.on("runtime-ready", listener);
|
|
874
|
-
});
|
|
875
|
-
};
|
|
876
1107
|
destroy() {
|
|
877
1108
|
this.iframe?.removeEventListener("load", this.loadHandler);
|
|
878
1109
|
this.contentWindow = null;
|
|
@@ -880,49 +1111,25 @@ class StageRender extends EventEmitter {
|
|
|
880
1111
|
this.iframe = void 0;
|
|
881
1112
|
this.removeAllListeners();
|
|
882
1113
|
}
|
|
883
|
-
loadHandler = async () => {
|
|
884
|
-
this.emit("onload");
|
|
885
|
-
if (this.render) {
|
|
886
|
-
const el = await this.render(this.core);
|
|
887
|
-
if (el) {
|
|
888
|
-
this.iframe?.contentDocument?.body?.appendChild(el);
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
if (this.contentWindow) {
|
|
892
|
-
const style = this.contentWindow.document.createElement("style");
|
|
893
|
-
style.id = "tmagic-stage-render";
|
|
894
|
-
style.innerHTML = `
|
|
895
|
-
.${SELECTED_CLASS}, .${SELECTED_CLASS}-parent {
|
|
896
|
-
z-index: ${ZIndex.SELECTED_EL};
|
|
897
|
-
}
|
|
898
|
-
`;
|
|
899
|
-
this.contentWindow.document.head.appendChild(style);
|
|
900
|
-
}
|
|
901
|
-
};
|
|
902
1114
|
}
|
|
903
1115
|
|
|
904
1116
|
class StageCore extends EventEmitter {
|
|
905
|
-
selectedDom;
|
|
906
|
-
highlightedDom;
|
|
907
|
-
renderer;
|
|
908
|
-
mask;
|
|
909
|
-
dr;
|
|
910
|
-
highlightLayer;
|
|
911
|
-
config;
|
|
912
|
-
zoom = DEFAULT_ZOOM;
|
|
913
|
-
container;
|
|
914
|
-
canSelect;
|
|
915
1117
|
constructor(config) {
|
|
916
1118
|
super();
|
|
1119
|
+
this.zoom = DEFAULT_ZOOM;
|
|
917
1120
|
this.config = config;
|
|
918
1121
|
this.setZoom(config.zoom);
|
|
919
1122
|
this.canSelect = config.canSelect || ((el) => !!el.id);
|
|
920
1123
|
this.renderer = new StageRender({ core: this });
|
|
921
1124
|
this.mask = new StageMask({ core: this });
|
|
922
1125
|
this.dr = new StageDragResize({ core: this, container: this.mask.content });
|
|
923
|
-
this.highlightLayer = new StageHighlight({ core: this, container: this.mask.
|
|
924
|
-
this.renderer.on("runtime-ready", (runtime) =>
|
|
925
|
-
|
|
1126
|
+
this.highlightLayer = new StageHighlight({ core: this, container: this.mask.wrapper });
|
|
1127
|
+
this.renderer.on("runtime-ready", (runtime) => {
|
|
1128
|
+
this.emit("runtime-ready", runtime);
|
|
1129
|
+
});
|
|
1130
|
+
this.renderer.on("page-el-update", (el) => {
|
|
1131
|
+
this.mask?.observe(el);
|
|
1132
|
+
});
|
|
926
1133
|
this.mask.on("beforeSelect", (event) => {
|
|
927
1134
|
this.setElementFromPoint(event);
|
|
928
1135
|
}).on("select", () => {
|
|
@@ -932,6 +1139,10 @@ class StageCore extends EventEmitter {
|
|
|
932
1139
|
this.emit("changeGuides", data);
|
|
933
1140
|
}).on("highlight", async (event) => {
|
|
934
1141
|
await this.setElementFromPoint(event);
|
|
1142
|
+
if (this.highlightedDom === this.selectedDom) {
|
|
1143
|
+
this.highlightLayer.clearHighlight();
|
|
1144
|
+
return;
|
|
1145
|
+
}
|
|
935
1146
|
this.highlightLayer.highlight(this.highlightedDom);
|
|
936
1147
|
this.emit("highlight", this.highlightedDom);
|
|
937
1148
|
}).on("clearHighlight", async () => {
|
|
@@ -959,7 +1170,7 @@ class StageCore extends EventEmitter {
|
|
|
959
1170
|
let stopped = false;
|
|
960
1171
|
const stop = () => stopped = true;
|
|
961
1172
|
for (const el of els) {
|
|
962
|
-
if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.canSelect(el, stop)) {
|
|
1173
|
+
if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.canSelect(el, event, stop)) {
|
|
963
1174
|
if (stopped)
|
|
964
1175
|
break;
|
|
965
1176
|
if (event.type === "mousemove") {
|
|
@@ -976,47 +1187,58 @@ class StageCore extends EventEmitter {
|
|
|
976
1187
|
if (el === this.selectedDom)
|
|
977
1188
|
return;
|
|
978
1189
|
const runtime = await this.renderer.getRuntime();
|
|
1190
|
+
await runtime?.select?.(el.id);
|
|
979
1191
|
if (runtime?.beforeSelect) {
|
|
980
1192
|
await runtime.beforeSelect(el);
|
|
981
1193
|
}
|
|
982
1194
|
this.mask.setLayout(el);
|
|
983
|
-
this.dr
|
|
1195
|
+
this.dr.select(el, event);
|
|
1196
|
+
if (this.config.autoScrollIntoView || el.dataset.autoScrollIntoView) {
|
|
1197
|
+
this.mask.intersectionObserver?.observe(el);
|
|
1198
|
+
}
|
|
984
1199
|
this.selectedDom = el;
|
|
985
1200
|
if (this.renderer.contentWindow) {
|
|
986
1201
|
removeSelectedClassName(this.renderer.contentWindow.document);
|
|
987
1202
|
if (this.selectedDom) {
|
|
988
|
-
addSelectedClassName(this.selectedDom);
|
|
1203
|
+
addSelectedClassName(this.selectedDom, this.renderer.contentWindow.document);
|
|
989
1204
|
}
|
|
990
1205
|
}
|
|
991
1206
|
}
|
|
992
1207
|
update(data) {
|
|
993
1208
|
const { config } = data;
|
|
994
|
-
this.renderer?.getRuntime().then((runtime) => {
|
|
1209
|
+
return this.renderer?.getRuntime().then((runtime) => {
|
|
995
1210
|
runtime?.update?.(data);
|
|
996
1211
|
setTimeout(() => {
|
|
997
1212
|
const el = this.renderer.contentWindow?.document.getElementById(`${config.id}`);
|
|
998
|
-
if (el) {
|
|
1213
|
+
if (el && el.id === this.selectedDom?.id) {
|
|
1214
|
+
this.selectedDom = el;
|
|
999
1215
|
this.mask.setLayout(el);
|
|
1000
|
-
this.dr
|
|
1216
|
+
this.dr.updateMoveable(el);
|
|
1001
1217
|
}
|
|
1002
1218
|
}, 0);
|
|
1003
1219
|
});
|
|
1004
1220
|
}
|
|
1005
1221
|
async highlight(idOrEl) {
|
|
1006
|
-
|
|
1222
|
+
let el;
|
|
1223
|
+
try {
|
|
1224
|
+
el = await this.getTargetElement(idOrEl);
|
|
1225
|
+
} catch (error) {
|
|
1226
|
+
this.highlightLayer.clearHighlight();
|
|
1227
|
+
return;
|
|
1228
|
+
}
|
|
1007
1229
|
if (el === this.highlightedDom)
|
|
1008
1230
|
return;
|
|
1009
1231
|
this.highlightLayer.highlight(el);
|
|
1010
1232
|
this.highlightedDom = el;
|
|
1011
1233
|
}
|
|
1012
1234
|
sortNode(data) {
|
|
1013
|
-
this.renderer?.getRuntime().then((runtime) => runtime?.sortNode?.(data));
|
|
1235
|
+
return this.renderer?.getRuntime().then((runtime) => runtime?.sortNode?.(data));
|
|
1014
1236
|
}
|
|
1015
1237
|
add(data) {
|
|
1016
|
-
this.renderer?.getRuntime().then((runtime) => runtime?.add?.(data));
|
|
1238
|
+
return this.renderer?.getRuntime().then((runtime) => runtime?.add?.(data));
|
|
1017
1239
|
}
|
|
1018
1240
|
remove(data) {
|
|
1019
|
-
this.renderer?.getRuntime().then((runtime) => runtime?.remove?.(data));
|
|
1241
|
+
return this.renderer?.getRuntime().then((runtime) => runtime?.remove?.(data));
|
|
1020
1242
|
}
|
|
1021
1243
|
setZoom(zoom = DEFAULT_ZOOM) {
|
|
1022
1244
|
this.zoom = zoom;
|
|
@@ -1042,16 +1264,13 @@ class StageCore extends EventEmitter {
|
|
|
1042
1264
|
this.container = void 0;
|
|
1043
1265
|
}
|
|
1044
1266
|
async getTargetElement(idOrEl) {
|
|
1045
|
-
let el;
|
|
1046
1267
|
if (typeof idOrEl === "string" || typeof idOrEl === "number") {
|
|
1047
|
-
const
|
|
1048
|
-
el = await runtime?.select?.(`${idOrEl}`);
|
|
1268
|
+
const el = this.renderer.contentWindow?.document.getElementById(`${idOrEl}`);
|
|
1049
1269
|
if (!el)
|
|
1050
1270
|
throw new Error(`\u4E0D\u5B58\u5728ID\u4E3A${idOrEl}\u7684\u5143\u7D20`);
|
|
1051
|
-
|
|
1052
|
-
el = idOrEl;
|
|
1271
|
+
return el;
|
|
1053
1272
|
}
|
|
1054
|
-
return
|
|
1273
|
+
return idOrEl;
|
|
1055
1274
|
}
|
|
1056
1275
|
}
|
|
1057
1276
|
|