@tmagic/stage 1.1.0-beta.2 → 1.1.0-beta.5

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.
@@ -23,12 +23,13 @@ import type { MoveableOptions } from 'moveable';
23
23
  import Moveable from 'moveable';
24
24
  import MoveableHelper from 'moveable-helper';
25
25
 
26
- import { addClassName, removeClassNameByClassName } from '@tmagic/utils';
26
+ import { removeClassNameByClassName } from '@tmagic/utils';
27
27
 
28
28
  import { DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, GuidesType, Mode, ZIndex } from './const';
29
29
  import StageCore from './StageCore';
30
- import type { SortEventData, StageDragResizeConfig } from './types';
31
- import { calcValueByFontsize, getAbsolutePosition, getMode, getOffset } from './util';
30
+ import StageMask from './StageMask';
31
+ import type { StageDragResizeConfig } from './types';
32
+ import { calcValueByFontsize, down, getAbsolutePosition, getMode, getOffset, getTargetElStyle, up } from './util';
32
33
 
33
34
  /** 拖动状态 */
34
35
  enum ActionStatus {
@@ -45,12 +46,13 @@ enum ActionStatus {
45
46
  */
46
47
  export default class StageDragResize extends EventEmitter {
47
48
  public core: StageCore;
49
+ public mask: StageMask;
48
50
  /** 画布容器 */
49
51
  public container: HTMLElement;
50
52
  /** 目标节点 */
51
53
  public target?: HTMLElement;
52
54
  /** 目标节点在蒙层中的占位节点 */
53
- public dragEl: HTMLDivElement;
55
+ public dragEl?: HTMLDivElement;
54
56
  /** Moveable拖拽类实例 */
55
57
  public moveable?: Moveable;
56
58
  /** 水平参考线 */
@@ -74,9 +76,7 @@ export default class StageDragResize extends EventEmitter {
74
76
 
75
77
  this.core = config.core;
76
78
  this.container = config.container;
77
-
78
- this.dragEl = globalThis.document.createElement('div');
79
- this.container.append(this.dragEl);
79
+ this.mask = config.mask;
80
80
  }
81
81
 
82
82
  /**
@@ -147,6 +147,17 @@ export default class StageDragResize extends EventEmitter {
147
147
  this.updateMoveable();
148
148
  }
149
149
 
150
+ public clearSelectStatus(): void {
151
+ if (!this.moveable) return;
152
+ this.destroyDragEl();
153
+ this.moveable.target = null;
154
+ this.moveable.updateTarget();
155
+ }
156
+
157
+ public destroyDragEl(): void {
158
+ this.dragEl?.remove();
159
+ }
160
+
150
161
  /**
151
162
  * 销毁实例
152
163
  */
@@ -166,9 +177,15 @@ export default class StageDragResize extends EventEmitter {
166
177
  this.mode = getMode(el);
167
178
 
168
179
  this.destroyGhostEl();
180
+ this.destroyDragEl();
181
+ this.dragEl = globalThis.document.createElement('div');
182
+ this.container.append(this.dragEl);
183
+ this.dragEl.style.cssText = getTargetElStyle(el);
184
+ this.dragEl.id = `${DRAG_EL_ID_PREFIX}${el.id}`;
169
185
 
170
- this.updateDragEl(el);
171
-
186
+ if (typeof this.core.config.updateDragEl === 'function') {
187
+ this.core.config.updateDragEl(this.dragEl, el);
188
+ }
172
189
  this.moveableOptions = this.getOptions({
173
190
  target: this.dragEl,
174
191
  });
@@ -294,20 +311,7 @@ export default class StageDragResize extends EventEmitter {
294
311
  timeout = undefined;
295
312
  }
296
313
 
297
- timeout = globalThis.setTimeout(async () => {
298
- const els = this.core.getElementsFromPoint(e.inputEvent);
299
- for (const el of els) {
300
- if (
301
- doc &&
302
- !el.id.startsWith(GHOST_EL_ID_PREFIX) &&
303
- el !== this.target &&
304
- (await this.core.isContainer(el))
305
- ) {
306
- addClassName(el, doc, this.core.containerHighlightClassName);
307
- break;
308
- }
309
- }
310
- }, this.core.containerHighlightDuration);
314
+ timeout = this.core.getAddContainerHighlightClassNameTimeout(e.inputEvent, [this.target]);
311
315
 
312
316
  this.dragStatus = ActionStatus.ING;
313
317
 
@@ -467,6 +471,7 @@ export default class StageDragResize extends EventEmitter {
467
471
  }
468
472
 
469
473
  const ghostEl = el.cloneNode(true) as HTMLElement;
474
+ this.setGhostElChildrenId(ghostEl);
470
475
  const { top, left } = getAbsolutePosition(el, getOffset(el));
471
476
  ghostEl.id = `${GHOST_EL_ID_PREFIX}${el.id}`;
472
477
  ghostEl.style.zIndex = ZIndex.GHOST_EL;
@@ -478,34 +483,21 @@ export default class StageDragResize extends EventEmitter {
478
483
  return ghostEl;
479
484
  }
480
485
 
481
- private destroyGhostEl(): void {
482
- this.ghostEl?.remove();
483
- this.ghostEl = undefined;
484
- }
485
-
486
- private updateDragEl(el: HTMLElement) {
487
- const offset = getOffset(el);
488
- const { transform } = getComputedStyle(el);
489
-
490
- this.dragEl.style.cssText = `
491
- position: absolute;
492
- transform: ${transform};
493
- left: ${offset.left}px;
494
- top: ${offset.top}px;
495
- width: ${el.clientWidth}px;
496
- height: ${el.clientHeight}px;
497
- z-index: ${ZIndex.DRAG_EL};
498
- `;
499
-
500
- this.dragEl.id = `${DRAG_EL_ID_PREFIX}${el.id}`;
486
+ private setGhostElChildrenId(el: Element) {
487
+ for (const child of el.children) {
488
+ if (child.id) {
489
+ child.id = `${GHOST_EL_ID_PREFIX}${child.id}`;
490
+ }
501
491
 
502
- if (typeof this.core.config.updateDragEl === 'function') {
503
- this.core.config.updateDragEl(this.dragEl, el);
492
+ if (child.children.length) {
493
+ this.setGhostElChildrenId(child);
494
+ }
504
495
  }
505
496
  }
506
497
 
507
- private destroyDragEl(): void {
508
- this.dragEl?.remove();
498
+ private destroyGhostEl(): void {
499
+ this.ghostEl?.remove();
500
+ this.ghostEl = undefined;
509
501
  }
510
502
 
511
503
  private getOptions(options: MoveableOptions = {}): MoveableOptions {
@@ -566,7 +558,7 @@ export default class StageDragResize extends EventEmitter {
566
558
  top: 0,
567
559
  // 设置0的话无法移动到left为0,所以只能设置为-1
568
560
  left: -1,
569
- right: this.container.clientWidth,
561
+ right: this.container.clientWidth - 1,
570
562
  bottom: this.container.clientHeight,
571
563
  ...(moveableOptions.bounds || {}),
572
564
  },
@@ -575,73 +567,3 @@ export default class StageDragResize extends EventEmitter {
575
567
  };
576
568
  }
577
569
  }
578
-
579
- /**
580
- * 下移组件位置
581
- * @param {number} deltaTop 偏移量
582
- * @param {Object} detail 当前选中的组件配置
583
- */
584
- export const down = (deltaTop: number, target: HTMLElement | SVGElement): SortEventData | void => {
585
- let swapIndex = 0;
586
- let addUpH = target.clientHeight;
587
- const brothers = Array.from(target.parentNode?.children || []).filter(
588
- (node) => !node.id.startsWith(GHOST_EL_ID_PREFIX),
589
- );
590
- const index = brothers.indexOf(target);
591
- // 往下移动
592
- const downEls = brothers.slice(index + 1) as HTMLElement[];
593
-
594
- for (let i = 0; i < downEls.length; i++) {
595
- const ele = downEls[i];
596
- // 是 fixed 不做处理
597
- if (ele.style?.position === 'fixed') {
598
- continue;
599
- }
600
- addUpH += ele.clientHeight / 2;
601
- if (deltaTop <= addUpH) {
602
- break;
603
- }
604
- addUpH += ele.clientHeight / 2;
605
- swapIndex = i;
606
- }
607
- return {
608
- src: target.id,
609
- dist: downEls.length && swapIndex > -1 ? downEls[swapIndex].id : target.id,
610
- };
611
- };
612
-
613
- /**
614
- * 上移组件位置
615
- * @param {Array} brothers 处于同一容器下的所有子组件配置
616
- * @param {number} index 当前组件所处的位置
617
- * @param {number} deltaTop 偏移量
618
- * @param {Object} detail 当前选中的组件配置
619
- */
620
- export const up = (deltaTop: number, target: HTMLElement | SVGElement): SortEventData | void => {
621
- const brothers = Array.from(target.parentNode?.children || []).filter(
622
- (node) => !node.id.startsWith(GHOST_EL_ID_PREFIX),
623
- );
624
- const index = brothers.indexOf(target);
625
- // 往上移动
626
- const upEls = brothers.slice(0, index) as HTMLElement[];
627
-
628
- let addUpH = target.clientHeight;
629
- let swapIndex = upEls.length - 1;
630
-
631
- for (let i = upEls.length - 1; i >= 0; i--) {
632
- const ele = upEls[i];
633
- if (!ele) continue;
634
- // 是 fixed 不做处理
635
- if (ele.style.position === 'fixed') continue;
636
-
637
- addUpH += ele.clientHeight / 2;
638
- if (-deltaTop <= addUpH) break;
639
- addUpH += ele.clientHeight / 2;
640
-
641
- swapIndex = i;
642
- }
643
- return {
644
- src: target.id,
645
- dist: upEls.length && swapIndex > -1 ? upEls[swapIndex].id : target.id,
646
- };
647
- };
@@ -57,7 +57,7 @@ export default class StageHighlight extends EventEmitter {
57
57
  target: this.calibrationTarget.update(el, HIGHLIGHT_EL_ID_PREFIX),
58
58
  origin: false,
59
59
  rootContainer: this.core.container,
60
- zoom: 1,
60
+ zoom: 2,
61
61
  });
62
62
  }
63
63
 
package/src/StageMask.ts CHANGED
@@ -16,6 +16,7 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
+ import KeyController from 'keycon';
19
20
  import { throttle } from 'lodash-es';
20
21
 
21
22
  import { createDiv, injectStyle } from '@tmagic/utils';
@@ -82,6 +83,7 @@ export default class StageMask extends Rule {
82
83
  public maxScrollTop = 0;
83
84
  public maxScrollLeft = 0;
84
85
  public intersectionObserver: IntersectionObserver | null = null;
86
+ public isMultiSelectStatus: Boolean = false;
85
87
 
86
88
  private mode: Mode = Mode.ABSOLUTE;
87
89
  private pageResizeObserver: ResizeObserver | null = null;
@@ -106,6 +108,14 @@ export default class StageMask extends Rule {
106
108
  this.content.addEventListener('wheel', this.mouseWheelHandler);
107
109
  this.content.addEventListener('mousemove', this.highlightHandler);
108
110
  this.content.addEventListener('mouseleave', this.mouseLeaveHandler);
111
+ KeyController.global.keydown('shift', (e) => {
112
+ e.inputEvent.preventDefault();
113
+ this.isMultiSelectStatus = true;
114
+ });
115
+ KeyController.global.keyup('shift', (e) => {
116
+ e.inputEvent.preventDefault();
117
+ this.isMultiSelectStatus = false;
118
+ });
109
119
  }
110
120
 
111
121
  public setMode(mode: Mode) {
@@ -292,21 +302,28 @@ export default class StageMask extends Rule {
292
302
  */
293
303
  private mouseDownHandler = (event: MouseEvent): void => {
294
304
  this.emit('clearHighlight');
295
-
296
305
  event.stopImmediatePropagation();
297
306
  event.stopPropagation();
298
307
 
299
308
  if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT) return;
300
309
 
301
- // 点击的对象如果是选中框,则不需要再触发选中了,而可能是拖动行为
310
+ // 如果单击多选选中区域,则不需要再触发选中了,而可能是拖动行为
311
+ if (!this.isMultiSelectStatus && (event.target as HTMLDivElement).className.indexOf('moveable-area') !== -1) {
312
+ return;
313
+ }
314
+ // 点击对象如果是边框锚点,则可能是resize
302
315
  if ((event.target as HTMLDivElement).className.indexOf('moveable-control') !== -1) {
303
316
  return;
304
317
  }
305
318
 
306
319
  this.content.removeEventListener('mousemove', this.highlightHandler);
307
320
 
308
- this.emit('beforeSelect', event);
309
-
321
+ // 判断触发多选还是单选
322
+ if (this.isMultiSelectStatus) {
323
+ this.emit('beforeMultiSelect', event);
324
+ } else {
325
+ this.emit('beforeSelect', event);
326
+ }
310
327
  // 如果是右键点击,这里的mouseup事件监听没有效果
311
328
  globalThis.document.addEventListener('mouseup', this.mouseUpHandler);
312
329
  };
@@ -0,0 +1,231 @@
1
+ /*
2
+ * Tencent is pleased to support the open source community by making TMagicEditor available.
3
+ *
4
+ * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ import { EventEmitter } from 'events';
20
+
21
+ import type { MoveableOptions } from 'moveable';
22
+ import Moveable from 'moveable';
23
+ import MoveableHelper from 'moveable-helper';
24
+
25
+ import { DRAG_EL_ID_PREFIX, PAGE_CLASS } from './const';
26
+ import StageCore from './StageCore';
27
+ import StageMask from './StageMask';
28
+ import { StageDragResizeConfig } from './types';
29
+ import { calcValueByFontsize, getMode, getTargetElStyle } from './util';
30
+ export default class StageMultiDragResize extends EventEmitter {
31
+ public core: StageCore;
32
+ public mask: StageMask;
33
+ /** 画布容器 */
34
+ public container: HTMLElement;
35
+ /** 多选:目标节点组 */
36
+ public targetList: HTMLElement[] = [];
37
+ /** 多选:目标节点在蒙层中的占位节点组 */
38
+ public dragElList: HTMLDivElement[] = [];
39
+ /** Moveable多选拖拽类实例 */
40
+ public moveableForMulti?: Moveable;
41
+ private multiMoveableHelper?: MoveableHelper;
42
+
43
+ constructor(config: StageDragResizeConfig) {
44
+ super();
45
+
46
+ this.core = config.core;
47
+ this.container = config.container;
48
+ this.mask = config.mask;
49
+ }
50
+
51
+ /**
52
+ * 多选
53
+ * @param els
54
+ */
55
+ public multiSelect(els: HTMLElement[]): void {
56
+ this.targetList = els;
57
+ this.core.dr.destroyDragEl();
58
+ this.destroyDragElList();
59
+ // 生成虚拟多选节点
60
+ this.dragElList = els.map((elItem) => {
61
+ const dragElDiv = globalThis.document.createElement('div');
62
+ this.container.append(dragElDiv);
63
+ dragElDiv.style.cssText = getTargetElStyle(elItem);
64
+ dragElDiv.id = `${DRAG_EL_ID_PREFIX}${elItem.id}`;
65
+ // 业务方校准
66
+ if (typeof this.core.config.updateDragEl === 'function') {
67
+ this.core.config.updateDragEl(dragElDiv, elItem);
68
+ }
69
+ return dragElDiv;
70
+ });
71
+ this.moveableForMulti?.destroy();
72
+ this.multiMoveableHelper?.clear();
73
+
74
+ this.moveableForMulti = new Moveable(
75
+ this.container,
76
+ this.getOptions({
77
+ target: this.dragElList,
78
+ }),
79
+ );
80
+ this.multiMoveableHelper = MoveableHelper.create({
81
+ useBeforeRender: true,
82
+ useRender: false,
83
+ createAuto: true,
84
+ });
85
+ const frames: { left: number; top: number; id: string }[] = [];
86
+ this.moveableForMulti
87
+ .on('dragGroupStart', (params) => {
88
+ const { events } = params;
89
+ this.multiMoveableHelper?.onDragGroupStart(params);
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
+ .on('dragGroup', (params) => {
105
+ const { events } = params;
106
+ // 拖动过程更新
107
+ events.forEach((ev) => {
108
+ const frameSnapShot = frames.find(
109
+ (frameItem) => frameItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ''),
110
+ );
111
+ if (!frameSnapShot) return;
112
+ const targeEl = this.targetList.find(
113
+ (targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ''),
114
+ );
115
+ if (!targeEl) return;
116
+ // 元素与其所属组同时加入多选列表时,只更新父元素
117
+ const isParentIncluded = this.targetList.find((targetItem) => targetItem.id === targeEl.parentElement?.id);
118
+ if (!isParentIncluded) {
119
+ // 更新页面元素位置
120
+ targeEl.style.left = `${frameSnapShot.left + ev.beforeTranslate[0]}px`;
121
+ targeEl.style.top = `${frameSnapShot.top + ev.beforeTranslate[1]}px`;
122
+ }
123
+ });
124
+ this.multiMoveableHelper?.onDragGroup(params);
125
+ })
126
+ .on('dragGroupEnd', () => {
127
+ this.update();
128
+ });
129
+ }
130
+
131
+ public canSelect(el: HTMLElement): Boolean {
132
+ // 多选不可以选中magic-ui-page
133
+ if (el.className.includes(PAGE_CLASS)) {
134
+ this.core.highlightedDom = undefined;
135
+ this.core.highlightLayer.clearHighlight();
136
+ return false;
137
+ }
138
+ const currentTargetMode = getMode(el);
139
+ let selectedDomMode = '';
140
+
141
+ if (this.targetList.length === 0 && this.core.selectedDom) {
142
+ // 单选后添加到多选的情况
143
+ selectedDomMode = getMode(this.core.selectedDom);
144
+ } else if (this.targetList.length > 0) {
145
+ // 已加入多选列表的布局模式是一样的,取第一个判断
146
+ selectedDomMode = getMode(this.targetList[0]);
147
+ }
148
+ // 定位模式不同,不可混选
149
+ if (currentTargetMode !== selectedDomMode) {
150
+ return false;
151
+ }
152
+ return true;
153
+ }
154
+
155
+ /**
156
+ * 清除多选状态
157
+ */
158
+ public clearSelectStatus(): void {
159
+ if (!this.moveableForMulti) return;
160
+ this.destroyDragElList();
161
+ this.moveableForMulti.target = null;
162
+ this.moveableForMulti.updateTarget();
163
+ this.targetList = [];
164
+ }
165
+
166
+ /**
167
+ * 销毁实例
168
+ */
169
+ public destroy(): void {
170
+ this.moveableForMulti?.destroy();
171
+ this.destroyDragElList();
172
+ }
173
+
174
+ /**
175
+ * 清除蒙层占位节点
176
+ */
177
+ public destroyDragElList(): void {
178
+ this.dragElList.forEach((dragElItem) => dragElItem?.remove());
179
+ }
180
+
181
+ /**
182
+ * 拖拽完成后将更新的位置信息暴露给上层业务方,业务方可以接收事件进行保存
183
+ * @param isResize 是否进行大小缩放
184
+ */
185
+ private update(isResize = false): void {
186
+ if (this.targetList.length === 0) return;
187
+
188
+ const { contentWindow } = this.core.renderer;
189
+ const doc = contentWindow?.document;
190
+ if (!doc) return;
191
+
192
+ this.targetList.forEach((targetItem) => {
193
+ const offset = { left: targetItem.offsetLeft, top: targetItem.offsetTop };
194
+ const left = calcValueByFontsize(doc, offset.left);
195
+ const top = calcValueByFontsize(doc, offset.top);
196
+ const width = calcValueByFontsize(doc, targetItem.clientWidth);
197
+ const height = calcValueByFontsize(doc, targetItem.clientHeight);
198
+ this.emit('update', {
199
+ el: targetItem,
200
+ style: isResize ? { left, top, width, height } : { left, top },
201
+ });
202
+ });
203
+ }
204
+
205
+ /**
206
+ * 获取moveable options参数
207
+ * @param {MoveableOptions} options
208
+ * @return {MoveableOptions} moveable options参数
209
+ */
210
+ private getOptions(options: MoveableOptions = {}): MoveableOptions {
211
+ let { moveableOptions = {} } = this.core.config;
212
+
213
+ if (typeof moveableOptions === 'function') {
214
+ moveableOptions = moveableOptions(this.core);
215
+ }
216
+ return {
217
+ defaultGroupRotate: 0,
218
+ defaultGroupOrigin: '50% 50%',
219
+ draggable: true,
220
+ resizable: true,
221
+ throttleDrag: 0,
222
+ startDragRotate: 0,
223
+ throttleDragRotate: 0,
224
+ zoom: 1,
225
+ origin: true,
226
+ padding: { left: 0, top: 0, right: 0, bottom: 0 },
227
+ ...options,
228
+ ...moveableOptions,
229
+ };
230
+ }
231
+ }
@@ -72,20 +72,22 @@ export default class StageRender extends EventEmitter {
72
72
  * @param el 将页面挂载到该Dom节点上
73
73
  */
74
74
  public async mount(el: HTMLDivElement) {
75
- if (this.iframe) {
76
- if (!isSameDomain(this.runtimeUrl) && this.runtimeUrl) {
77
- // 不同域,使用srcdoc发起异步请求,需要目标地址支持跨域
78
- let html = await fetch(this.runtimeUrl).then((res) => res.text());
79
- // 使用base, 解决相对路径或绝对路径的问题
80
- const base = `${location.protocol}//${getHost(this.runtimeUrl)}`;
81
- html = html.replace('<head>', `<head>\n<base href="${base}">`);
82
- this.iframe.srcdoc = html;
83
- }
84
-
85
- el.appendChild<HTMLIFrameElement>(this.iframe);
86
- } else {
75
+ if (!this.iframe) {
87
76
  throw Error('mount 失败');
88
77
  }
78
+
79
+ if (!isSameDomain(this.runtimeUrl) && this.runtimeUrl) {
80
+ // 不同域,使用srcdoc发起异步请求,需要目标地址支持跨域
81
+ let html = await fetch(this.runtimeUrl).then((res) => res.text());
82
+ // 使用base, 解决相对路径或绝对路径的问题
83
+ const base = `${location.protocol}//${getHost(this.runtimeUrl)}`;
84
+ html = html.replace('<head>', `<head>\n<base href="${base}">`);
85
+ this.iframe.srcdoc = html;
86
+ }
87
+
88
+ el.appendChild<HTMLIFrameElement>(this.iframe);
89
+
90
+ this.postTmagicRuntimeReady();
89
91
  }
90
92
 
91
93
  public getRuntime = (): Promise<Runtime> => {
@@ -111,26 +113,34 @@ export default class StageRender extends EventEmitter {
111
113
  }
112
114
 
113
115
  private loadHandler = async () => {
114
- this.contentWindow = this.iframe?.contentWindow as RuntimeWindow;
116
+ if (!this.contentWindow?.magic) {
117
+ this.postTmagicRuntimeReady();
118
+ }
115
119
 
116
- this.contentWindow.magic = this.getMagicApi();
120
+ if (!this.contentWindow) return;
117
121
 
118
122
  if (this.render) {
119
123
  const el = await this.render(this.core);
120
124
  if (el) {
121
- this.iframe?.contentDocument?.body?.appendChild(el);
125
+ this.contentWindow.document?.body?.appendChild(el);
122
126
  }
123
127
  }
124
128
 
125
129
  this.emit('onload');
126
130
 
131
+ injectStyle(this.contentWindow.document, style);
132
+ };
133
+
134
+ private postTmagicRuntimeReady() {
135
+ this.contentWindow = this.iframe?.contentWindow as RuntimeWindow;
136
+
137
+ this.contentWindow.magic = this.getMagicApi();
138
+
127
139
  this.contentWindow.postMessage(
128
140
  {
129
141
  tmagicRuntimeReady: true,
130
142
  },
131
143
  '*',
132
144
  );
133
-
134
- injectStyle(this.contentWindow.document, style);
135
- };
145
+ }
136
146
  }
@@ -18,7 +18,7 @@
18
18
 
19
19
  import { EventEmitter } from 'events';
20
20
 
21
- import { Mode } from './const';
21
+ import { Mode, ZIndex } from './const';
22
22
  import StageCore from './StageCore';
23
23
  import StageDragResize from './StageDragResize';
24
24
  import StageMask from './StageMask';
@@ -57,6 +57,7 @@ export default class TargetCalibrate extends EventEmitter {
57
57
  top: ${top}px;
58
58
  width: ${el.clientWidth}px;
59
59
  height: ${el.clientHeight}px;
60
+ z-index: ${ZIndex.DRAG_EL};
60
61
  `;
61
62
 
62
63
  this.operationEl.id = `${prefix}${el.id}`;
package/src/const.ts CHANGED
@@ -27,6 +27,8 @@ export const HIGHLIGHT_EL_ID_PREFIX = 'highlight_el_';
27
27
 
28
28
  export const CONTAINER_HIGHLIGHT_CLASS = 'tmagic-stage-container-highlight';
29
29
 
30
+ export const PAGE_CLASS = 'magic-ui-page';
31
+
30
32
  /** 默认放到缩小倍数 */
31
33
  export const DEFAULT_ZOOM = 1;
32
34
 
package/src/style.css CHANGED
@@ -7,4 +7,5 @@
7
7
  left: 0;
8
8
  background-color: #000;
9
9
  opacity: .1;
10
+ pointer-events: none;
10
11
  }
package/src/types.ts CHANGED
@@ -19,7 +19,7 @@
19
19
  import { MoveableOptions } from 'moveable';
20
20
 
21
21
  import Core from '@tmagic/core';
22
- import type { Id, MApp, MNode } from '@tmagic/schema';
22
+ import type { Id, MApp, MContainer, MNode } from '@tmagic/schema';
23
23
 
24
24
  import { GuidesType } from './const';
25
25
  import StageCore from './StageCore';
@@ -57,6 +57,7 @@ export interface StageMaskConfig {
57
57
  export interface StageDragResizeConfig {
58
58
  core: StageCore;
59
59
  container: HTMLElement;
60
+ mask: StageMask;
60
61
  }
61
62
 
62
63
  export type Rect = {
@@ -98,6 +99,7 @@ export interface SortEventData {
98
99
 
99
100
  export interface UpdateData {
100
101
  config: MNode;
102
+ parent?: MContainer;
101
103
  root: MApp;
102
104
  }
103
105