@tmagic/stage 1.3.5 → 1.3.7

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,7 +23,15 @@ import { getHost, injectStyle, isSameDomain } from '@tmagic/utils';
23
23
 
24
24
  import { DEFAULT_ZOOM } from './const';
25
25
  import style from './style.css?raw';
26
- import type { Point, RemoveData, Runtime, RuntimeWindow, StageRenderConfig, UpdateData } from './types';
26
+ import {
27
+ type Point,
28
+ type RemoveData,
29
+ RenderType,
30
+ type Runtime,
31
+ type RuntimeWindow,
32
+ type StageRenderConfig,
33
+ type UpdateData,
34
+ } from './types';
27
35
  import { addSelectedClassName, removeSelectedClassName } from './util';
28
36
 
29
37
  export default class StageRender extends EventEmitter {
@@ -31,28 +39,26 @@ export default class StageRender extends EventEmitter {
31
39
  public contentWindow: RuntimeWindow | null = null;
32
40
  public runtime: Runtime | null = null;
33
41
  public iframe?: HTMLIFrameElement;
42
+ public nativeContainer?: HTMLDivElement;
34
43
 
35
44
  private runtimeUrl?: string;
36
45
  private zoom = DEFAULT_ZOOM;
46
+ private renderType: RenderType;
37
47
  private customizedRender?: () => Promise<HTMLElement | null>;
38
48
 
39
- constructor({ runtimeUrl, zoom, customizedRender }: StageRenderConfig) {
49
+ constructor({ runtimeUrl, zoom, customizedRender, renderType = RenderType.IFRAME }: StageRenderConfig) {
40
50
  super();
41
51
 
52
+ this.renderType = renderType;
42
53
  this.runtimeUrl = runtimeUrl || '';
43
54
  this.customizedRender = customizedRender;
44
55
  this.setZoom(zoom);
45
56
 
46
- this.iframe = globalThis.document.createElement('iframe');
47
- // 同源,直接加载
48
- this.iframe.src = isSameDomain(this.runtimeUrl) ? this.runtimeUrl : '';
49
- this.iframe.style.cssText = `
50
- border: 0;
51
- width: 100%;
52
- height: 100%;
53
- `;
54
-
55
- this.iframe.addEventListener('load', this.loadHandler);
57
+ if (this.renderType === RenderType.IFRAME) {
58
+ this.createIframe();
59
+ } else if (this.renderType === RenderType.NATIVE) {
60
+ this.createNativeContainer();
61
+ }
56
62
  }
57
63
 
58
64
  public getMagicApi = () => ({
@@ -102,22 +108,22 @@ export default class StageRender extends EventEmitter {
102
108
  * @param el 将页面挂载到该Dom节点上
103
109
  */
104
110
  public async mount(el: HTMLDivElement) {
105
- if (!this.iframe) {
106
- throw Error('mount 失败');
107
- }
108
-
109
- if (!isSameDomain(this.runtimeUrl) && this.runtimeUrl) {
110
- // 不同域,使用srcdoc发起异步请求,需要目标地址支持跨域
111
- let html = await fetch(this.runtimeUrl).then((res) => res.text());
112
- // 使用base, 解决相对路径或绝对路径的问题
113
- const base = `${location.protocol}//${getHost(this.runtimeUrl)}`;
114
- html = html.replace('<head>', `<head>\n<base href="${base}">`);
115
- this.iframe.srcdoc = html;
116
- }
111
+ if (this.iframe) {
112
+ if (!isSameDomain(this.runtimeUrl) && this.runtimeUrl) {
113
+ // 不同域,使用srcdoc发起异步请求,需要目标地址支持跨域
114
+ let html = await fetch(this.runtimeUrl).then((res) => res.text());
115
+ // 使用base, 解决相对路径或绝对路径的问题
116
+ const base = `${location.protocol}//${getHost(this.runtimeUrl)}`;
117
+ html = html.replace('<head>', `<head>\n<base href="${base}">`);
118
+ this.iframe.srcdoc = html;
119
+ }
117
120
 
118
- el.appendChild<HTMLIFrameElement>(this.iframe);
121
+ el.appendChild<HTMLIFrameElement>(this.iframe);
119
122
 
120
- this.postTmagicRuntimeReady();
123
+ this.postTmagicRuntimeReady();
124
+ } else if (this.nativeContainer) {
125
+ el.appendChild(this.nativeContainer);
126
+ }
121
127
  }
122
128
 
123
129
  public getRuntime = (): Promise<Runtime> => {
@@ -168,13 +174,42 @@ export default class StageRender extends EventEmitter {
168
174
  * 销毁实例
169
175
  */
170
176
  public destroy(): void {
171
- this.iframe?.removeEventListener('load', this.loadHandler);
177
+ this.iframe?.removeEventListener('load', this.iframeLoadHandler);
172
178
  this.contentWindow = null;
173
179
  this.iframe?.remove();
174
180
  this.iframe = undefined;
175
181
  this.removeAllListeners();
176
182
  }
177
183
 
184
+ private createIframe(): HTMLIFrameElement {
185
+ this.iframe = globalThis.document.createElement('iframe');
186
+ // 同源,直接加载
187
+ this.iframe.src = this.runtimeUrl && isSameDomain(this.runtimeUrl) ? this.runtimeUrl : '';
188
+ this.iframe.style.cssText = `
189
+ border: 0;
190
+ width: 100%;
191
+ height: 100%;
192
+ `;
193
+
194
+ this.iframe.addEventListener('load', this.iframeLoadHandler);
195
+
196
+ return this.iframe;
197
+ }
198
+
199
+ private async createNativeContainer() {
200
+ this.contentWindow = globalThis as unknown as RuntimeWindow;
201
+ this.nativeContainer = globalThis.document.createElement('div');
202
+
203
+ this.contentWindow.magic = this.getMagicApi();
204
+
205
+ if (this.customizedRender) {
206
+ const el = await this.customizedRender();
207
+ if (el) {
208
+ this.nativeContainer.appendChild(el);
209
+ }
210
+ }
211
+ }
212
+
178
213
  /**
179
214
  * 在runtime中对被选中的元素进行标记,部分组件有对选中态进行特殊显示的需求
180
215
  * @param el 被选中的元素
@@ -187,7 +222,7 @@ export default class StageRender extends EventEmitter {
187
222
  }
188
223
  }
189
224
 
190
- private loadHandler = async () => {
225
+ private iframeLoadHandler = async () => {
191
226
  if (!this.contentWindow?.magic) {
192
227
  this.postTmagicRuntimeReady();
193
228
  }
@@ -96,7 +96,7 @@ export default class TargetShadow {
96
96
  el.style.cssText = getTargetElStyle(target, this.zIndex);
97
97
 
98
98
  if (typeof this.updateDragEl === 'function') {
99
- this.updateDragEl(el, target);
99
+ this.updateDragEl(el, target, this.container);
100
100
  }
101
101
  const isFixed = isFixedParent(target);
102
102
  const mode = this.container.dataset.mode || Mode.ABSOLUTE;
package/src/const.ts CHANGED
@@ -73,3 +73,8 @@ export enum Mode {
73
73
 
74
74
  /** 选中节点的class name */
75
75
  export const SELECTED_CLASS = 'tmagic-stage-selected-area';
76
+
77
+ export enum AbleActionEventType {
78
+ SELECT_PARENT = 'select-parent',
79
+ REMOVE = 'remove',
80
+ }
package/src/index.ts CHANGED
@@ -19,6 +19,7 @@
19
19
  import StageCore from './StageCore';
20
20
 
21
21
  export type { MoveableOptions, OnDragStart } from 'moveable';
22
+ export type { GuidesOptions } from '@scena/guides';
22
23
  export { default as StageRender } from './StageRender';
23
24
  export { default as StageMask } from './StageMask';
24
25
  export { default as StageDragResize } from './StageDragResize';
package/src/types.ts CHANGED
@@ -16,6 +16,7 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
+ import type { GuidesOptions } from '@scena/guides';
19
20
  import type { MoveableOptions } from 'moveable';
20
21
 
21
22
  import Core from '@tmagic/core';
@@ -52,7 +53,12 @@ export enum ContainerHighlightType {
52
53
  ALT = 'alt',
53
54
  }
54
55
 
55
- export type UpdateDragEl = (el: TargetElement, target: TargetElement) => void;
56
+ export enum RenderType {
57
+ IFRAME = 'iframe',
58
+ NATIVE = 'native',
59
+ }
60
+
61
+ export type UpdateDragEl = (el: TargetElement, target: TargetElement, container: HTMLElement) => void;
56
62
 
57
63
  export interface StageCoreConfig {
58
64
  /** 需要对齐的dom节点的CSS选择器字符串 */
@@ -71,6 +77,9 @@ export interface StageCoreConfig {
71
77
  autoScrollIntoView?: boolean;
72
78
  updateDragEl?: UpdateDragEl;
73
79
  disabledDragStart?: boolean;
80
+ renderType?: RenderType;
81
+ guidesOptions?: Partial<GuidesOptions>;
82
+ disabledMultiSelect?: boolean;
74
83
  }
75
84
 
76
85
  export interface ActionManagerConfig {
@@ -80,6 +89,7 @@ export interface ActionManagerConfig {
80
89
  containerHighlightType?: ContainerHighlightType;
81
90
  moveableOptions?: CustomizeMoveableOptions;
82
91
  disabledDragStart?: boolean;
92
+ disabledMultiSelect?: boolean;
83
93
  canSelect?: CanSelect;
84
94
  isContainer: IsContainer;
85
95
  getRootContainer: GetRootContainer;
@@ -107,6 +117,7 @@ export interface CustomizeMoveableOptionsCallbackConfig {
107
117
  export interface StageRenderConfig {
108
118
  runtimeUrl?: string;
109
119
  zoom: number | undefined;
120
+ renderType?: RenderType;
110
121
  customizedRender?: () => Promise<HTMLElement | null>;
111
122
  }
112
123
 
@@ -257,7 +268,6 @@ export interface TargetShadowConfig {
257
268
  idPrefix?: string;
258
269
  }
259
270
 
260
- export enum AbleActionEventType {
261
- SELECT_PARENT = 'select-parent',
262
- REMOVE = 'remove',
271
+ export interface RuleOptions {
272
+ guidesOptions?: Partial<GuidesOptions>;
263
273
  }
@@ -11,7 +11,7 @@ import { ActionManagerConfig, SelectStatus, StageDragStatus } from './types';
11
11
  */
12
12
  export default class ActionManager extends EventEmitter {
13
13
  private dr;
14
- private multiDr;
14
+ private multiDr?;
15
15
  private highlightLayer;
16
16
  /** 单选、多选、高亮的容器(蒙层的content) */
17
17
  private container;
@@ -35,8 +35,12 @@ export default class ActionManager extends EventEmitter {
35
35
  private canSelect;
36
36
  private isContainer;
37
37
  private getRenderDocument;
38
+ private disabledMultiSelect;
39
+ private config;
38
40
  private mouseMoveHandler;
39
41
  constructor(config: ActionManagerConfig);
42
+ disableMultiSelect(): void;
43
+ enableMultiSelect(): void;
40
44
  /**
41
45
  * 设置水平/垂直参考线
42
46
  * @param type 参考线类型
@@ -56,7 +60,7 @@ export default class ActionManager extends EventEmitter {
56
60
  * 判断是否单选选中的元素
57
61
  */
58
62
  isSelectedEl(el: HTMLElement): boolean;
59
- setSelectedEl(el: HTMLElement): void;
63
+ setSelectedEl(el?: HTMLElement): void;
60
64
  getSelectedEl(): HTMLElement | undefined;
61
65
  getSelectedElList(): HTMLElement[];
62
66
  getMoveableOption<K extends keyof MoveableOptions>(key: K): MoveableOptions[K] | undefined;
@@ -105,6 +109,8 @@ export default class ActionManager extends EventEmitter {
105
109
  delayedMarkContainer(event: MouseEvent, excludeElList?: Element[]): NodeJS.Timeout | undefined;
106
110
  getDragStatus(): StageDragStatus;
107
111
  destroy(): void;
112
+ private createDr;
113
+ private createMultiDr;
108
114
  private changeCallback;
109
115
  /**
110
116
  * 在执行多选逻辑前,先准备好多选选中元素
@@ -126,10 +132,6 @@ export default class ActionManager extends EventEmitter {
126
132
  * 初始化键盘事件监听
127
133
  */
128
134
  private initKeyEvent;
129
- /**
130
- * 处理单选、多选抛出来的事件
131
- */
132
- private initActionEvent;
133
135
  /**
134
136
  * 在down事件中集中cpu处理画布中选中操作渲染,在up事件中再通知外面的编辑器更新
135
137
  */
@@ -1,5 +1,5 @@
1
1
  import { MoveableManagerInterface, Renderer } from 'moveable';
2
- import { AbleActionEventType } from './types';
2
+ import { AbleActionEventType } from './const';
3
3
  declare const _default: (handler: (type: AbleActionEventType) => void) => {
4
4
  name: string;
5
5
  props: never[];
@@ -2,7 +2,7 @@
2
2
  import EventEmitter from 'events';
3
3
  import type { MoveableOptions } from 'moveable';
4
4
  import { GuidesType, Mode } from './const';
5
- import { MoveableOptionsManagerConfig } from './types';
5
+ import type { MoveableOptionsManagerConfig } from './types';
6
6
  /**
7
7
  * 单选和多选的父类,用于管理moveableOptions
8
8
  * @extends EventEmitter
package/types/Rule.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  import EventEmitter from 'events';
3
3
  import Guides from '@scena/guides';
4
+ import type { RuleOptions } from './types';
4
5
  export default class Rule extends EventEmitter {
5
6
  hGuides: Guides;
6
7
  vGuides: Guides;
@@ -9,7 +10,8 @@ export default class Rule extends EventEmitter {
9
10
  private container;
10
11
  private containerResizeObserver;
11
12
  private isShowGuides;
12
- constructor(container: HTMLDivElement);
13
+ private guidesOptions?;
14
+ constructor(container: HTMLDivElement, options?: RuleOptions);
13
15
  /**
14
16
  * 是否显示辅助线
15
17
  * @param isShowGuides 是否显示
@@ -73,6 +73,8 @@ export default class StageCore extends EventEmitter {
73
73
  delayedMarkContainer(event: MouseEvent, excludeElList?: Element[]): NodeJS.Timeout | undefined;
74
74
  getMoveableOption<K extends keyof MoveableOptions>(key: K): MoveableOptions[K] | undefined;
75
75
  getDragStatus(): import("./types").StageDragStatus;
76
+ disableMultiSelect(): void;
77
+ enableMultiSelect(): void;
76
78
  /**
77
79
  * 销毁实例
78
80
  */
@@ -1,5 +1,6 @@
1
1
  import { Mode } from './const';
2
2
  import Rule from './Rule';
3
+ import type { RuleOptions } from './types';
3
4
  /**
4
5
  * 蒙层
5
6
  * @description 用于拦截页面的点击动作,避免点击时触发组件自身动作;在编辑器中点击组件应当是选中组件;
@@ -20,7 +21,7 @@ export default class StageMask extends Rule {
20
21
  private pageScrollParent;
21
22
  private intersectionObserver;
22
23
  private wrapperResizeObserver;
23
- constructor();
24
+ constructor(options?: RuleOptions);
24
25
  setMode(mode: Mode): void;
25
26
  /**
26
27
  * 初始化视窗和蒙层监听,监听元素是否在视窗区域、监听mask蒙层所在的wrapper大小变化
@@ -1,16 +1,18 @@
1
1
  /// <reference types="node" />
2
2
  import { EventEmitter } from 'events';
3
3
  import { Id } from '@tmagic/schema';
4
- import type { Point, RemoveData, Runtime, RuntimeWindow, StageRenderConfig, UpdateData } from './types';
4
+ import { type Point, type RemoveData, type Runtime, type RuntimeWindow, type StageRenderConfig, type UpdateData } from './types';
5
5
  export default class StageRender extends EventEmitter {
6
6
  /** 组件的js、css执行的环境,直接渲染为当前window,iframe渲染则为iframe.contentWindow */
7
7
  contentWindow: RuntimeWindow | null;
8
8
  runtime: Runtime | null;
9
9
  iframe?: HTMLIFrameElement;
10
+ nativeContainer?: HTMLDivElement;
10
11
  private runtimeUrl?;
11
12
  private zoom;
13
+ private renderType;
12
14
  private customizedRender?;
13
- constructor({ runtimeUrl, zoom, customizedRender }: StageRenderConfig);
15
+ constructor({ runtimeUrl, zoom, customizedRender, renderType }: StageRenderConfig);
14
16
  getMagicApi: () => {
15
17
  onPageElUpdate: (el: HTMLElement) => boolean;
16
18
  onRuntimeReady: (runtime: Runtime) => void;
@@ -38,11 +40,13 @@ export default class StageRender extends EventEmitter {
38
40
  * 销毁实例
39
41
  */
40
42
  destroy(): void;
43
+ private createIframe;
44
+ private createNativeContainer;
41
45
  /**
42
46
  * 在runtime中对被选中的元素进行标记,部分组件有对选中态进行特殊显示的需求
43
47
  * @param el 被选中的元素
44
48
  */
45
49
  private flagSelectedEl;
46
- private loadHandler;
50
+ private iframeLoadHandler;
47
51
  private postTmagicRuntimeReady;
48
52
  }
package/types/const.d.ts CHANGED
@@ -45,3 +45,7 @@ export declare enum Mode {
45
45
  }
46
46
  /** 选中节点的class name */
47
47
  export declare const SELECTED_CLASS = "tmagic-stage-selected-area";
48
+ export declare enum AbleActionEventType {
49
+ SELECT_PARENT = "select-parent",
50
+ REMOVE = "remove"
51
+ }
package/types/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import StageCore from './StageCore';
2
2
  export type { MoveableOptions, OnDragStart } from 'moveable';
3
+ export type { GuidesOptions } from '@scena/guides';
3
4
  export { default as StageRender } from './StageRender';
4
5
  export { default as StageMask } from './StageMask';
5
6
  export { default as StageDragResize } from './StageDragResize';
package/types/types.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  /// <reference types="node" />
2
+ import type { GuidesOptions } from '@scena/guides';
2
3
  import type { MoveableOptions } from 'moveable';
3
4
  import Core from '@tmagic/core';
4
5
  import type { Id, MApp, MContainer, MNode } from '@tmagic/schema';
@@ -26,7 +27,11 @@ export declare enum ContainerHighlightType {
26
27
  /** 按住alt键,并在容器上方悬停一段时间后加入 */
27
28
  ALT = "alt"
28
29
  }
29
- export type UpdateDragEl = (el: TargetElement, target: TargetElement) => void;
30
+ export declare enum RenderType {
31
+ IFRAME = "iframe",
32
+ NATIVE = "native"
33
+ }
34
+ export type UpdateDragEl = (el: TargetElement, target: TargetElement, container: HTMLElement) => void;
30
35
  export interface StageCoreConfig {
31
36
  /** 需要对齐的dom节点的CSS选择器字符串 */
32
37
  snapElementQuerySelector?: string;
@@ -44,6 +49,9 @@ export interface StageCoreConfig {
44
49
  autoScrollIntoView?: boolean;
45
50
  updateDragEl?: UpdateDragEl;
46
51
  disabledDragStart?: boolean;
52
+ renderType?: RenderType;
53
+ guidesOptions?: Partial<GuidesOptions>;
54
+ disabledMultiSelect?: boolean;
47
55
  }
48
56
  export interface ActionManagerConfig {
49
57
  container: HTMLElement;
@@ -52,6 +60,7 @@ export interface ActionManagerConfig {
52
60
  containerHighlightType?: ContainerHighlightType;
53
61
  moveableOptions?: CustomizeMoveableOptions;
54
62
  disabledDragStart?: boolean;
63
+ disabledMultiSelect?: boolean;
55
64
  canSelect?: CanSelect;
56
65
  isContainer: IsContainer;
57
66
  getRootContainer: GetRootContainer;
@@ -76,6 +85,7 @@ export interface CustomizeMoveableOptionsCallbackConfig {
76
85
  export interface StageRenderConfig {
77
86
  runtimeUrl?: string;
78
87
  zoom: number | undefined;
88
+ renderType?: RenderType;
79
89
  customizedRender?: () => Promise<HTMLElement | null>;
80
90
  }
81
91
  export interface StageMaskConfig {
@@ -204,7 +214,6 @@ export interface TargetShadowConfig {
204
214
  updateDragEl?: UpdateDragEl;
205
215
  idPrefix?: string;
206
216
  }
207
- export declare enum AbleActionEventType {
208
- SELECT_PARENT = "select-parent",
209
- REMOVE = "remove"
217
+ export interface RuleOptions {
218
+ guidesOptions?: Partial<GuidesOptions>;
210
219
  }