@tmagic/stage 1.0.0-beta.8 → 1.0.0-beta.9

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.
@@ -1,13 +1,14 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('events'), require('moveable'), require('@scena/guides')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'events', 'moveable', '@scena/guides'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.TMagicStage = {}, global.EventEmitter, global.Moveable, global.Guides));
5
- })(this, (function (exports, EventEmitter, Moveable, Guides) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('events'), require('moveable'), require('moveable-helper'), require('lodash-es'), require('@scena/guides')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'events', 'moveable', 'moveable-helper', 'lodash-es', '@scena/guides'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.TMagicStage = {}, global.EventEmitter, global.Moveable, global.MoveableHelper, global.lodashEs, global.Guides));
5
+ })(this, (function (exports, EventEmitter, Moveable, MoveableHelper, lodashEs, Guides) { 'use strict';
6
6
 
7
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
8
 
9
9
  var EventEmitter__default = /*#__PURE__*/_interopDefaultLegacy(EventEmitter);
10
10
  var Moveable__default = /*#__PURE__*/_interopDefaultLegacy(Moveable);
11
+ var MoveableHelper__default = /*#__PURE__*/_interopDefaultLegacy(MoveableHelper);
11
12
  var Guides__default = /*#__PURE__*/_interopDefaultLegacy(Guides);
12
13
 
13
14
  const GHOST_EL_ID_PREFIX = "ghost_el_";
@@ -19,6 +20,7 @@
19
20
  })(GuidesType || {});
20
21
  var ZIndex = /* @__PURE__ */ ((ZIndex2) => {
21
22
  ZIndex2["MASK"] = "99999";
23
+ ZIndex2["SELECTED_EL"] = "666";
22
24
  return ZIndex2;
23
25
  })(ZIndex || {});
24
26
  var MouseButton = /* @__PURE__ */ ((MouseButton2) => {
@@ -33,6 +35,7 @@
33
35
  Mode2["SORTABLE"] = "sortable";
34
36
  return Mode2;
35
37
  })(Mode || {});
38
+ const SELECTED_CLASS = "tmagic-stage-selected-area";
36
39
 
37
40
  const getOffset = (el) => {
38
41
  const { transform } = getComputedStyle(el);
@@ -153,6 +156,17 @@
153
156
  el.style.cssText = cssText;
154
157
  return el;
155
158
  };
159
+ const removeSelectedClassName = (doc) => {
160
+ const oldEl = doc.querySelector(`.${SELECTED_CLASS}`);
161
+ if (oldEl) {
162
+ oldEl.classList.remove(SELECTED_CLASS);
163
+ oldEl.parentNode?.classList.remove(`${SELECTED_CLASS}-parent`);
164
+ }
165
+ };
166
+ const addSelectedClassName = (el) => {
167
+ el.classList.add(SELECTED_CLASS);
168
+ el.parentNode?.classList.add(`${SELECTED_CLASS}-parent`);
169
+ };
156
170
 
157
171
  class StageDragResize extends EventEmitter.EventEmitter {
158
172
  core;
@@ -166,6 +180,7 @@
166
180
  dragStatus = "end" /* END */;
167
181
  ghostEl;
168
182
  mode = Mode.ABSOLUTE;
183
+ moveableHelper;
169
184
  constructor(config) {
170
185
  super();
171
186
  this.core = config.core;
@@ -183,6 +198,11 @@
183
198
  this.moveableOptions = await this.getOptions({
184
199
  target: this.dragEl || this.target
185
200
  });
201
+ this.moveableHelper = MoveableHelper__default["default"].create({
202
+ useBeforeRender: true,
203
+ useRender: false,
204
+ createAuto: true
205
+ });
186
206
  this.initMoveable();
187
207
  if (event) {
188
208
  this.moveable?.dragStart(event);
@@ -261,27 +281,32 @@
261
281
  bindDragEvent() {
262
282
  if (!this.moveable)
263
283
  throw new Error("moveable \u4E3A\u521D\u59CB\u5316");
264
- this.moveable.on("dragStart", () => {
284
+ let offset = {
285
+ left: 0,
286
+ top: 0
287
+ };
288
+ this.moveable.on("dragStart", (e) => {
265
289
  if (!this.target)
266
290
  throw new Error("\u672A\u9009\u4E2D\u7EC4\u4EF6");
267
291
  this.dragStatus = "start" /* START */;
292
+ this.moveableHelper?.onDragStart(e);
293
+ offset = getAbsolutePosition(this.target, { left: 0, top: 0 });
268
294
  if (this.mode === Mode.SORTABLE) {
269
295
  this.ghostEl = this.generateGhostEl(this.target);
270
296
  }
271
- }).on("drag", ({ left, top }) => {
297
+ }).on("drag", (e) => {
272
298
  if (!this.target || !this.dragEl)
273
299
  return;
274
300
  this.dragStatus = "ing" /* ING */;
275
- const offset = getAbsolutePosition(this.target, { left, top });
301
+ const { left, top } = e;
276
302
  if (this.ghostEl) {
277
303
  this.dragEl.style.top = `${top}px`;
278
- this.ghostEl.style.top = `${offset.top}px`;
304
+ this.ghostEl.style.top = `${top + offset.top}px`;
279
305
  return;
280
306
  }
281
- this.dragEl.style.left = `${left}px`;
282
- this.dragEl.style.top = `${top}px`;
283
- this.target.style.left = `${offset.left}px`;
284
- this.target.style.top = `${offset.top}px`;
307
+ this.moveableHelper?.onDrag(e);
308
+ this.target.style.left = `${left + offset.left}px`;
309
+ this.target.style.top = `${top + offset.top}px`;
285
310
  }).on("dragEnd", () => {
286
311
  if (this.dragStatus === "ing" /* ING */) {
287
312
  switch (this.mode) {
@@ -384,17 +409,26 @@
384
409
  moveableOptions = moveableOptions(this.core);
385
410
  }
386
411
  return {
387
- scrollable: true,
388
412
  origin: true,
413
+ rootContainer: this.core.container,
389
414
  zoom: 1,
390
- dragArea: true,
415
+ dragArea: false,
391
416
  draggable: true,
392
417
  resizable: true,
393
418
  snappable: isAbsolute,
394
419
  snapGap: isAbsolute,
395
- snapDirections: { center: isAbsolute, middle: isAbsolute },
396
- elementSnapDirections: { center: isAbsolute, middle: isAbsolute },
397
- elementGuidelines: isAbsolute ? await this.getSnapElements(this.target) : [],
420
+ snapThreshold: 5,
421
+ snapDigit: 0,
422
+ throttleDrag: 0,
423
+ isDisplaySnapDigit: isAbsolute,
424
+ snapDirections: {
425
+ top: isAbsolute,
426
+ right: isAbsolute,
427
+ bottom: isAbsolute,
428
+ left: isAbsolute,
429
+ center: isAbsolute,
430
+ middle: isAbsolute
431
+ },
398
432
  horizontalGuidelines: this.horizontalGuidelines,
399
433
  verticalGuidelines: this.verticalGuidelines,
400
434
  bounds: {
@@ -465,6 +499,36 @@
465
499
  };
466
500
  };
467
501
 
502
+ class StageHighlight extends EventEmitter.EventEmitter {
503
+ core;
504
+ container;
505
+ target;
506
+ moveable;
507
+ constructor(config) {
508
+ super();
509
+ this.core = config.core;
510
+ this.container = config.container;
511
+ }
512
+ highlight(el) {
513
+ if (!el || el === this.target)
514
+ return;
515
+ this.target = el;
516
+ this.moveable?.destroy();
517
+ this.moveable = new Moveable__default["default"](this.container, {
518
+ target: this.target
519
+ });
520
+ }
521
+ clearHighlight() {
522
+ if (!this.moveable)
523
+ return;
524
+ this.moveable.target = null;
525
+ this.moveable.updateTarget();
526
+ }
527
+ destroy() {
528
+ this.moveable?.destroy();
529
+ }
530
+ }
531
+
468
532
  class Rule extends EventEmitter__default["default"] {
469
533
  hGuides;
470
534
  vGuides;
@@ -576,6 +640,7 @@
576
640
  }
577
641
 
578
642
  const wrapperClassName = "editor-mask-wrapper";
643
+ const throttleTime = 100;
579
644
  const hideScrollbar = () => {
580
645
  const style = globalThis.document.createElement("style");
581
646
  style.innerHTML = `
@@ -623,6 +688,9 @@
623
688
  mode = Mode.ABSOLUTE;
624
689
  pageResizeObserver = null;
625
690
  wrapperResizeObserver = null;
691
+ highlightHandler = lodashEs.throttle((event) => {
692
+ this.emit("highlight", event);
693
+ }, throttleTime);
626
694
  constructor(config) {
627
695
  const wrapper = createWrapper();
628
696
  super(wrapper);
@@ -631,6 +699,7 @@
631
699
  this.content.addEventListener("mousedown", this.mouseDownHandler);
632
700
  this.wrapper.appendChild(this.content);
633
701
  this.content.addEventListener("wheel", this.mouseWheelHandler);
702
+ this.content.addEventListener("mousemove", this.highlightHandler);
634
703
  }
635
704
  setMode(mode) {
636
705
  this.mode = mode;
@@ -702,7 +771,7 @@
702
771
  this.width = width;
703
772
  this.content.style.width = `${width}px`;
704
773
  }
705
- mouseDownHandler = async (event) => {
774
+ mouseDownHandler = (event) => {
706
775
  event.stopImmediatePropagation();
707
776
  event.stopPropagation();
708
777
  if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT)
@@ -712,9 +781,12 @@
712
781
  }
713
782
  this.emit("beforeSelect", event);
714
783
  globalThis.document.addEventListener("mouseup", this.mouseUpHandler);
784
+ this.content.removeEventListener("mousemove", this.highlightHandler);
785
+ this.emit("clearHighlight");
715
786
  };
716
787
  mouseUpHandler = () => {
717
788
  globalThis.document.removeEventListener("mouseup", this.mouseUpHandler);
789
+ this.content.addEventListener("mousemove", this.highlightHandler);
718
790
  this.emit("select");
719
791
  };
720
792
  mouseWheelHandler = (event) => {
@@ -823,16 +895,29 @@
823
895
  this.iframe?.contentDocument?.body?.appendChild(el);
824
896
  }
825
897
  }
898
+ if (this.contentWindow) {
899
+ const style = this.contentWindow.document.createElement("style");
900
+ style.id = "tmagic-stage-render";
901
+ style.innerHTML = `
902
+ .${SELECTED_CLASS}, .${SELECTED_CLASS}-parent {
903
+ z-index: ${ZIndex.SELECTED_EL};
904
+ }
905
+ `;
906
+ this.contentWindow.document.head.appendChild(style);
907
+ }
826
908
  };
827
909
  }
828
910
 
829
911
  class StageCore extends EventEmitter.EventEmitter {
830
912
  selectedDom;
913
+ highlightedDom;
831
914
  renderer;
832
915
  mask;
833
916
  dr;
917
+ highlightLayer;
834
918
  config;
835
919
  zoom = DEFAULT_ZOOM;
920
+ container;
836
921
  canSelect;
837
922
  constructor(config) {
838
923
  super();
@@ -842,6 +927,7 @@
842
927
  this.renderer = new StageRender({ core: this });
843
928
  this.mask = new StageMask({ core: this });
844
929
  this.dr = new StageDragResize({ core: this, container: this.mask.content });
930
+ this.highlightLayer = new StageHighlight({ core: this, container: this.mask.content });
845
931
  this.renderer.on("runtime-ready", (runtime) => this.emit("runtime-ready", runtime));
846
932
  this.renderer.on("page-el-update", (el) => this.mask?.observe(el));
847
933
  this.mask.on("beforeSelect", (event) => {
@@ -851,6 +937,12 @@
851
937
  }).on("changeGuides", (data) => {
852
938
  this.dr.setGuidelines(data.type, data.guides);
853
939
  this.emit("changeGuides", data);
940
+ }).on("highlight", async (event) => {
941
+ await this.setElementFromPoint(event);
942
+ this.highlightLayer.highlight(this.highlightedDom);
943
+ this.emit("highlight", this.highlightedDom);
944
+ }).on("clearHighlight", async () => {
945
+ this.highlightLayer.clearHighlight();
854
946
  });
855
947
  this.dr.on("update", (data) => {
856
948
  setTimeout(() => this.emit("update", data));
@@ -877,30 +969,32 @@
877
969
  if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.canSelect(el, stop)) {
878
970
  if (stopped)
879
971
  break;
972
+ if (event.type === "mousemove") {
973
+ this.highlight(el);
974
+ break;
975
+ }
880
976
  this.select(el, event);
881
977
  break;
882
978
  }
883
979
  }
884
980
  }
885
981
  async select(idOrEl, event) {
886
- let el;
887
- if (typeof idOrEl === "string" || typeof idOrEl === "number") {
888
- const runtime2 = await this.renderer?.getRuntime();
889
- el = await runtime2?.select?.(`${idOrEl}`);
890
- if (!el)
891
- throw new Error(`\u4E0D\u5B58\u5728ID\u4E3A${idOrEl}\u7684\u5143\u7D20`);
892
- } else {
893
- el = idOrEl;
894
- }
982
+ const el = await this.getTargetElement(idOrEl);
895
983
  if (el === this.selectedDom)
896
984
  return;
897
- const runtime = await this.renderer?.getRuntime();
985
+ const runtime = await this.renderer.getRuntime();
898
986
  if (runtime?.beforeSelect) {
899
987
  await runtime.beforeSelect(el);
900
988
  }
901
989
  this.mask.setLayout(el);
902
990
  this.dr?.select(el, event);
903
991
  this.selectedDom = el;
992
+ if (this.renderer.contentWindow) {
993
+ removeSelectedClassName(this.renderer.contentWindow.document);
994
+ if (this.selectedDom) {
995
+ addSelectedClassName(this.selectedDom);
996
+ }
997
+ }
904
998
  }
905
999
  update(data) {
906
1000
  const { config } = data;
@@ -915,6 +1009,13 @@
915
1009
  }, 0);
916
1010
  });
917
1011
  }
1012
+ async highlight(idOrEl) {
1013
+ const el = await this.getTargetElement(idOrEl);
1014
+ if (el === this.highlightedDom)
1015
+ return;
1016
+ this.highlightLayer.highlight(el);
1017
+ this.highlightedDom = el;
1018
+ }
918
1019
  sortNode(data) {
919
1020
  this.renderer?.getRuntime().then((runtime) => runtime?.sortNode?.(data));
920
1021
  }
@@ -928,6 +1029,7 @@
928
1029
  this.zoom = zoom;
929
1030
  }
930
1031
  mount(el) {
1032
+ this.container = el;
931
1033
  const { mask, renderer } = this;
932
1034
  renderer.mount(el);
933
1035
  mask.mount(el);
@@ -938,11 +1040,25 @@
938
1040
  this.dr.clearGuides();
939
1041
  }
940
1042
  destroy() {
941
- const { mask, renderer, dr } = this;
1043
+ const { mask, renderer, dr, highlightLayer } = this;
942
1044
  renderer.destroy();
943
1045
  mask.destroy();
944
1046
  dr.destroy();
1047
+ highlightLayer.destroy();
945
1048
  this.removeAllListeners();
1049
+ this.container = void 0;
1050
+ }
1051
+ async getTargetElement(idOrEl) {
1052
+ let el;
1053
+ if (typeof idOrEl === "string" || typeof idOrEl === "number") {
1054
+ const runtime = await this.renderer?.getRuntime();
1055
+ el = await runtime?.select?.(`${idOrEl}`);
1056
+ if (!el)
1057
+ throw new Error(`\u4E0D\u5B58\u5728ID\u4E3A${idOrEl}\u7684\u5143\u7D20`);
1058
+ } else {
1059
+ el = idOrEl;
1060
+ }
1061
+ return el;
946
1062
  }
947
1063
  }
948
1064