@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.
@@ -1,21 +1,46 @@
1
+ /** 流式布局下拖动时需要clone一个镜像节点,镜像节点的id前缀 */
1
2
  export declare const GHOST_EL_ID_PREFIX = "ghost_el_";
3
+ /** 拖动的时候需要在蒙层中创建一个占位节点,该节点的id前缀 */
4
+ export declare const DRAG_EL_ID_PREFIX = "drag_el_";
5
+ /** 高亮事需要在蒙层中创建一个占位节点,该节点的id前缀 */
6
+ export declare const HIGHLIGHT_EL_ID_PREFIX = "highlight_el_";
7
+ /** 默认放到缩小倍数 */
2
8
  export declare const DEFAULT_ZOOM = 1;
9
+ /** 参考线类型 */
3
10
  export declare enum GuidesType {
11
+ /** 水平 */
4
12
  HORIZONTAL = "horizontal",
13
+ /** 垂直 */
5
14
  VERTICAL = "vertical"
6
15
  }
16
+ /** css z-index */
7
17
  export declare enum ZIndex {
18
+ /** 蒙层,用于监听用户操作,需要置于顶层 */
8
19
  MASK = "99999",
9
- SELECTED_EL = "666"
20
+ /** 选中的节点 */
21
+ SELECTED_EL = "666",
22
+ GHOST_EL = "700",
23
+ DRAG_EL = "9"
10
24
  }
25
+ /** 鼠标按键 */
11
26
  export declare enum MouseButton {
27
+ /** 左键 */
12
28
  LEFT = 0,
29
+ /** z中健 */
13
30
  MIDDLE = 1,
31
+ /** 右键 */
14
32
  RIGHT = 2
15
33
  }
34
+ /** 布局方式 */
16
35
  export declare enum Mode {
36
+ /** 绝对定位布局 */
17
37
  ABSOLUTE = "absolute",
38
+ /** 固定定位布局 */
18
39
  FIXED = "fixed",
40
+ /** 流式布局 */
19
41
  SORTABLE = "sortable"
20
42
  }
43
+ /** 选中节点的class name */
21
44
  export declare const SELECTED_CLASS = "tmagic-stage-selected-area";
45
+ export declare const H_GUIDE_LINE_STORAGE_KEY = "$MagicStageHorizontalGuidelinesData";
46
+ export declare const V_GUIDE_LINE_STORAGE_KEY = "$MagicStageVerticalGuidelinesData";
@@ -1,8 +1,11 @@
1
- import { MoveableOptions } from 'react-moveable/declaration/types';
1
+ import { MoveableOptions } from 'moveable';
2
+ import Core from '@tmagic/core';
2
3
  import { Id, MApp, MNode } from '@tmagic/schema';
3
4
  import { GuidesType } from './const';
4
5
  import StageCore from './StageCore';
5
- export declare type CanSelect = (el: HTMLElement, stop: () => boolean) => boolean | Promise<boolean>;
6
+ import StageDragResize from './StageDragResize';
7
+ import StageMask from './StageMask';
8
+ export declare type CanSelect = (el: HTMLElement, event: MouseEvent, stop: () => boolean) => boolean | Promise<boolean>;
6
9
  export declare type StageCoreConfig = {
7
10
  /** 需要对齐的dom节点的CSS选择器字符串 */
8
11
  snapElementQuerySelector?: string;
@@ -13,6 +16,8 @@ export declare type StageCoreConfig = {
13
16
  /** runtime 的HTML地址,可以是一个HTTP地址,如果和编辑器不同域,需要设置跨域,也可以是一个相对或绝对路径 */
14
17
  runtimeUrl?: string;
15
18
  render?: (renderer: StageCore) => Promise<HTMLElement> | HTMLElement;
19
+ autoScrollIntoView?: boolean;
20
+ updateDragEl?: (el: HTMLDivElement, target: HTMLElement) => void;
16
21
  };
17
22
  export interface StageRenderConfig {
18
23
  core: StageCore;
@@ -40,10 +45,14 @@ export interface UpdateEventData {
40
45
  el: HTMLElement;
41
46
  ghostEl: HTMLElement;
42
47
  style: {
43
- width: number;
44
- height: number;
48
+ width?: number;
49
+ height?: number;
45
50
  left?: number;
46
51
  top?: number;
52
+ transform?: {
53
+ rotate?: string;
54
+ scale?: string;
55
+ };
47
56
  };
48
57
  }
49
58
  export interface SortEventData {
@@ -60,9 +69,10 @@ export interface RemoveData {
60
69
  root: MApp;
61
70
  }
62
71
  export interface Runtime {
72
+ getApp?: () => Core;
63
73
  beforeSelect?: (el: HTMLElement) => Promise<boolean> | boolean;
64
- getSnapElements?: (el: HTMLElement) => HTMLElement[];
65
- updateRootConfig: (config: MApp) => void;
74
+ getSnapElements?: (el?: HTMLElement) => HTMLElement[];
75
+ updateRootConfig?: (config: MApp) => void;
66
76
  updatePageId?: (id: Id) => void;
67
77
  select?: (id: Id) => Promise<HTMLElement> | HTMLElement;
68
78
  add?: (data: UpdateData) => void;
@@ -82,3 +92,9 @@ export interface StageHighlightConfig {
82
92
  core: StageCore;
83
93
  container: HTMLElement;
84
94
  }
95
+ export interface TargetCalibrateConfig {
96
+ parent: HTMLElement;
97
+ mask: StageMask;
98
+ dr: StageDragResize;
99
+ core: StageCore;
100
+ }
@@ -1,4 +1,4 @@
1
- import { Mode } from './const';
1
+ import { GuidesType, Mode } from './const';
2
2
  import type { Offset } from './types';
3
3
  export declare const getOffset: (el: HTMLElement) => Offset;
4
4
  export declare const getAbsolutePosition: (el: HTMLElement, { top, left }: Offset) => {
@@ -19,4 +19,5 @@ export declare const createDiv: ({ className, cssText }: {
19
19
  cssText: string;
20
20
  }) => HTMLDivElement;
21
21
  export declare const removeSelectedClassName: (doc: Document) => void;
22
- export declare const addSelectedClassName: (el: Element) => void;
22
+ export declare const addSelectedClassName: (el: Element, doc: Document) => void;
23
+ export declare const getGuideLineFromCache: (type: GuidesType) => number[];
package/package.json CHANGED
@@ -1,7 +1,9 @@
1
1
  {
2
- "version": "1.0.0-beta.9",
2
+ "version": "1.0.0-rc.11",
3
3
  "name": "@tmagic/stage",
4
- "sideEffects": false,
4
+ "sideEffects": [
5
+ "dist/*"
6
+ ],
5
7
  "main": "dist/tmagic-stage.umd.js",
6
8
  "module": "dist/tmagic-stage.es.js",
7
9
  "types": "dist/types/src/index.d.ts",
@@ -9,8 +11,10 @@
9
11
  ".": {
10
12
  "import": "./dist/tmagic-stage.es.js",
11
13
  "require": "./dist/tmagic-stage.umd.js"
12
- }
14
+ },
15
+ "./*": "./*"
13
16
  },
17
+ "license": "Apache-2.0",
14
18
  "scripts": {
15
19
  "build": "vite build"
16
20
  },
@@ -23,11 +27,12 @@
23
27
  },
24
28
  "dependencies": {
25
29
  "@scena/guides": "^0.17.0",
26
- "@tmagic/schema": "^1.0.0-beta.9",
27
- "@tmagic/utils": "^1.0.0-beta.8",
30
+ "@tmagic/core": "1.0.0-rc.11",
31
+ "@tmagic/schema": "1.0.0-rc.11",
32
+ "@tmagic/utils": "1.0.0-rc.11",
28
33
  "events": "^3.3.0",
29
34
  "lodash-es": "^4.17.21",
30
- "moveable": "^0.28.0",
35
+ "moveable": "^0.29.4",
31
36
  "moveable-helper": "^0.4.0"
32
37
  },
33
38
  "devDependencies": {
@@ -38,6 +43,5 @@
38
43
  "typescript": "^4.3.4",
39
44
  "vite": "^2.3.7",
40
45
  "vite-plugin-dts": "^0.9.6"
41
- },
42
- "gitHead": "6314078c100ddcf513eb5581b38e2292f9b93eb9"
46
+ }
43
47
  }
package/src/Rule.ts CHANGED
@@ -2,13 +2,14 @@ import EventEmitter from 'events';
2
2
 
3
3
  import Guides, { GuidesEvents } from '@scena/guides';
4
4
 
5
- import { GuidesType } from './const';
5
+ import { GuidesType, H_GUIDE_LINE_STORAGE_KEY, V_GUIDE_LINE_STORAGE_KEY } from './const';
6
+ import { getGuideLineFromCache } from './util';
6
7
 
7
8
  export default class Rule extends EventEmitter {
8
9
  public hGuides: Guides;
9
10
  public vGuides: Guides;
10
- public horizontalGuidelines: number[] = [];
11
- public verticalGuidelines: number[] = [];
11
+ public horizontalGuidelines: number[] = getGuideLineFromCache(GuidesType.HORIZONTAL);
12
+ public verticalGuidelines: number[] = getGuideLineFromCache(GuidesType.VERTICAL);
12
13
 
13
14
  private container: HTMLDivElement;
14
15
  private containerResizeObserver: ResizeObserver;
@@ -17,8 +18,8 @@ export default class Rule extends EventEmitter {
17
18
  super();
18
19
 
19
20
  this.container = container;
20
- this.hGuides = this.createGuides(GuidesType.HORIZONTAL);
21
- this.vGuides = this.createGuides(GuidesType.VERTICAL);
21
+ this.hGuides = this.createGuides(GuidesType.HORIZONTAL, this.horizontalGuidelines);
22
+ this.vGuides = this.createGuides(GuidesType.VERTICAL, this.verticalGuidelines);
22
23
 
23
24
  this.hGuides.on('changeGuides', this.hGuidesChangeGuidesHandler);
24
25
  this.vGuides.on('changeGuides', this.vGuidesChangeGuidesHandler);
@@ -68,6 +69,9 @@ export default class Rule extends EventEmitter {
68
69
  type: GuidesType.HORIZONTAL,
69
70
  guides: [],
70
71
  });
72
+
73
+ globalThis.localStorage.setItem(V_GUIDE_LINE_STORAGE_KEY, '[]');
74
+ globalThis.localStorage.setItem(H_GUIDE_LINE_STORAGE_KEY, '[]');
71
75
  }
72
76
 
73
77
  /**
@@ -138,6 +142,8 @@ export default class Rule extends EventEmitter {
138
142
  type: GuidesType.HORIZONTAL,
139
143
  guides: this.horizontalGuidelines,
140
144
  });
145
+
146
+ globalThis.localStorage.setItem(H_GUIDE_LINE_STORAGE_KEY, JSON.stringify(e.guides));
141
147
  };
142
148
 
143
149
  private vGuidesChangeGuidesHandler = (e: GuidesEvents['changeGuides']) => {
@@ -146,5 +152,7 @@ export default class Rule extends EventEmitter {
146
152
  type: GuidesType.VERTICAL,
147
153
  guides: this.verticalGuidelines,
148
154
  });
155
+
156
+ globalThis.localStorage.setItem(V_GUIDE_LINE_STORAGE_KEY, JSON.stringify(e.guides));
149
157
  };
150
158
  }
package/src/StageCore.ts CHANGED
@@ -61,10 +61,14 @@ export default class StageCore extends EventEmitter {
61
61
  this.renderer = new StageRender({ core: this });
62
62
  this.mask = new StageMask({ core: this });
63
63
  this.dr = new StageDragResize({ core: this, container: this.mask.content });
64
- this.highlightLayer = new StageHighlight({ core: this, container: this.mask.content });
64
+ this.highlightLayer = new StageHighlight({ core: this, container: this.mask.wrapper });
65
65
 
66
- this.renderer.on('runtime-ready', (runtime: Runtime) => this.emit('runtime-ready', runtime));
67
- this.renderer.on('page-el-update', (el: HTMLElement) => this.mask?.observe(el));
66
+ this.renderer.on('runtime-ready', (runtime: Runtime) => {
67
+ this.emit('runtime-ready', runtime);
68
+ });
69
+ this.renderer.on('page-el-update', (el: HTMLElement) => {
70
+ this.mask?.observe(el);
71
+ });
68
72
 
69
73
  this.mask
70
74
  .on('beforeSelect', (event: MouseEvent) => {
@@ -79,6 +83,10 @@ export default class StageCore extends EventEmitter {
79
83
  })
80
84
  .on('highlight', async (event: MouseEvent) => {
81
85
  await this.setElementFromPoint(event);
86
+ if (this.highlightedDom === this.selectedDom) {
87
+ this.highlightLayer.clearHighlight();
88
+ return;
89
+ }
82
90
  this.highlightLayer.highlight(this.highlightedDom as HTMLElement);
83
91
  this.emit('highlight', this.highlightedDom);
84
92
  })
@@ -116,7 +124,7 @@ export default class StageCore extends EventEmitter {
116
124
  let stopped = false;
117
125
  const stop = () => (stopped = true);
118
126
  for (const el of els) {
119
- if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && (await this.canSelect(el, stop))) {
127
+ if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && (await this.canSelect(el, event, stop))) {
120
128
  if (stopped) break;
121
129
  if (event.type === 'mousemove') {
122
130
  this.highlight(el);
@@ -139,18 +147,25 @@ export default class StageCore extends EventEmitter {
139
147
 
140
148
  const runtime = await this.renderer.getRuntime();
141
149
 
150
+ await runtime?.select?.(el.id);
151
+
142
152
  if (runtime?.beforeSelect) {
143
153
  await runtime.beforeSelect(el);
144
154
  }
145
155
 
146
156
  this.mask.setLayout(el);
147
- this.dr?.select(el, event);
157
+ this.dr.select(el, event);
158
+
159
+ if (this.config.autoScrollIntoView || el.dataset.autoScrollIntoView) {
160
+ this.mask.intersectionObserver?.observe(el);
161
+ }
162
+
148
163
  this.selectedDom = el;
149
164
 
150
165
  if (this.renderer.contentWindow) {
151
166
  removeSelectedClassName(this.renderer.contentWindow.document);
152
167
  if (this.selectedDom) {
153
- addSelectedClassName(this.selectedDom);
168
+ addSelectedClassName(this.selectedDom, this.renderer.contentWindow.document);
154
169
  }
155
170
  }
156
171
  }
@@ -159,18 +174,20 @@ export default class StageCore extends EventEmitter {
159
174
  * 更新选中的节点
160
175
  * @param data 更新的数据
161
176
  */
162
- public update(data: UpdateData): void {
177
+ public update(data: UpdateData): Promise<void> {
163
178
  const { config } = data;
164
179
 
165
- this.renderer?.getRuntime().then((runtime) => {
180
+ return this.renderer?.getRuntime().then((runtime) => {
166
181
  runtime?.update?.(data);
167
182
  // 更新配置后,需要等组件渲染更新
168
183
  setTimeout(() => {
169
184
  const el = this.renderer.contentWindow?.document.getElementById(`${config.id}`);
170
- if (el) {
185
+ // 有可能dom已经重新渲染,不再是原来的dom了,所以这里判断id,而不是判断el === this.selectedDom
186
+ if (el && el.id === this.selectedDom?.id) {
187
+ this.selectedDom = el;
171
188
  // 更新了组件的布局,需要重新设置mask是否可以滚动
172
189
  this.mask.setLayout(el);
173
- this.dr?.select(el);
190
+ this.dr.updateMoveable(el);
174
191
  }
175
192
  }, 0);
176
193
  });
@@ -181,22 +198,28 @@ export default class StageCore extends EventEmitter {
181
198
  * @param el 页面Dom节点
182
199
  */
183
200
  public async highlight(idOrEl: HTMLElement | Id): Promise<void> {
184
- const el = await this.getTargetElement(idOrEl);
201
+ let el;
202
+ try {
203
+ el = await this.getTargetElement(idOrEl);
204
+ } catch (error) {
205
+ this.highlightLayer.clearHighlight();
206
+ return;
207
+ }
185
208
  if (el === this.highlightedDom) return;
186
209
  this.highlightLayer.highlight(el);
187
210
  this.highlightedDom = el;
188
211
  }
189
212
 
190
- public sortNode(data: SortEventData): void {
191
- this.renderer?.getRuntime().then((runtime) => runtime?.sortNode?.(data));
213
+ public sortNode(data: SortEventData): Promise<void> {
214
+ return this.renderer?.getRuntime().then((runtime) => runtime?.sortNode?.(data));
192
215
  }
193
216
 
194
- public add(data: UpdateData): void {
195
- this.renderer?.getRuntime().then((runtime) => runtime?.add?.(data));
217
+ public add(data: UpdateData): Promise<void> {
218
+ return this.renderer?.getRuntime().then((runtime) => runtime?.add?.(data));
196
219
  }
197
220
 
198
- public remove(data: RemoveData): void {
199
- this.renderer?.getRuntime().then((runtime) => runtime?.remove?.(data));
221
+ public remove(data: RemoveData): Promise<void> {
222
+ return this.renderer?.getRuntime().then((runtime) => runtime?.remove?.(data));
200
223
  }
201
224
 
202
225
  public setZoom(zoom: number = DEFAULT_ZOOM): void {
@@ -242,14 +265,11 @@ export default class StageCore extends EventEmitter {
242
265
  }
243
266
 
244
267
  private async getTargetElement(idOrEl: Id | HTMLElement): Promise<HTMLElement> {
245
- let el;
246
268
  if (typeof idOrEl === 'string' || typeof idOrEl === 'number') {
247
- const runtime = await this.renderer?.getRuntime();
248
- el = await runtime?.select?.(`${idOrEl}`);
269
+ const el = this.renderer.contentWindow?.document.getElementById(`${idOrEl}`);
249
270
  if (!el) throw new Error(`不存在ID为${idOrEl}的元素`);
250
- } else {
251
- el = idOrEl;
271
+ return el;
252
272
  }
253
- return el;
273
+ return idOrEl;
254
274
  }
255
275
  }