@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
|
@@ -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
|
-
|
|
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 '
|
|
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
|
-
|
|
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
|
|
44
|
-
height
|
|
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
|
|
65
|
-
updateRootConfig
|
|
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
|
+
}
|
package/dist/types/src/util.d.ts
CHANGED
|
@@ -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-
|
|
2
|
+
"version": "1.0.0-rc.11",
|
|
3
3
|
"name": "@tmagic/stage",
|
|
4
|
-
"sideEffects":
|
|
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/
|
|
27
|
-
"@tmagic/
|
|
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.
|
|
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.
|
|
64
|
+
this.highlightLayer = new StageHighlight({ core: this, container: this.mask.wrapper });
|
|
65
65
|
|
|
66
|
-
this.renderer.on('runtime-ready', (runtime: Runtime) =>
|
|
67
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
251
|
-
el = idOrEl;
|
|
271
|
+
return el;
|
|
252
272
|
}
|
|
253
|
-
return
|
|
273
|
+
return idOrEl;
|
|
254
274
|
}
|
|
255
275
|
}
|