@tmagic/editor 1.0.0-beta.8 → 1.0.0-rc.10

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.
Files changed (73) hide show
  1. package/README.md +1 -0
  2. package/dist/style.css +94 -45
  3. package/dist/tmagic-editor.es.js +1622 -2069
  4. package/dist/tmagic-editor.es.js.map +1 -1
  5. package/dist/tmagic-editor.umd.js +1621 -2071
  6. package/dist/tmagic-editor.umd.js.map +1 -1
  7. package/dist/types/src/Editor.vue.d.ts +50 -2
  8. package/dist/types/src/fields/Code.vue.d.ts +4 -4
  9. package/dist/types/src/fields/CodeLink.vue.d.ts +1 -3
  10. package/dist/types/src/index.d.ts +1 -0
  11. package/dist/types/src/layouts/CodeEditor.vue.d.ts +13 -4
  12. package/dist/types/src/layouts/Framework.vue.d.ts +15 -3
  13. package/dist/types/src/layouts/PropsPanel.vue.d.ts +4 -5
  14. package/dist/types/src/layouts/sidebar/ComponentListPanel.vue.d.ts +2 -1
  15. package/dist/types/src/layouts/sidebar/Sidebar.vue.d.ts +2 -3
  16. package/dist/types/src/layouts/sidebar/TabPane.vue.d.ts +14 -0
  17. package/dist/types/src/layouts/workspace/Workspace.vue.d.ts +5 -31
  18. package/dist/types/src/services/BaseService.d.ts +5 -2
  19. package/dist/types/src/services/editor.d.ts +16 -6
  20. package/dist/types/src/services/history.d.ts +2 -18
  21. package/dist/types/src/services/props.d.ts +8 -2
  22. package/dist/types/src/services/ui.d.ts +2 -0
  23. package/dist/types/src/type.d.ts +25 -9
  24. package/dist/types/src/utils/editor.d.ts +5 -10
  25. package/dist/types/src/utils/polyfills.d.ts +0 -0
  26. package/dist/types/src/utils/props.d.ts +8 -1
  27. package/package.json +35 -12
  28. package/src/Editor.vue +44 -9
  29. package/src/components/ContentMenu.vue +140 -0
  30. package/src/components/ScrollViewer.vue +1 -1
  31. package/src/components/ToolButton.vue +72 -31
  32. package/src/fields/UISelect.vue +14 -6
  33. package/src/index.ts +2 -0
  34. package/src/layouts/AddPageBox.vue +3 -1
  35. package/src/layouts/CodeEditor.vue +20 -13
  36. package/src/layouts/Framework.vue +20 -7
  37. package/src/layouts/PropsPanel.vue +5 -4
  38. package/src/layouts/sidebar/ComponentListPanel.vue +25 -3
  39. package/src/layouts/sidebar/LayerMenu.vue +93 -95
  40. package/src/layouts/sidebar/LayerPanel.vue +80 -59
  41. package/src/layouts/sidebar/Sidebar.vue +13 -52
  42. package/src/layouts/sidebar/TabPane.vue +68 -0
  43. package/src/layouts/workspace/PageBar.vue +145 -17
  44. package/src/layouts/workspace/Stage.vue +65 -91
  45. package/src/layouts/workspace/ViewerMenu.vue +122 -68
  46. package/src/layouts/workspace/Workspace.vue +125 -42
  47. package/src/services/BaseService.ts +71 -23
  48. package/src/services/editor.ts +231 -69
  49. package/src/services/history.ts +7 -0
  50. package/src/services/props.ts +64 -9
  51. package/src/services/ui.ts +35 -5
  52. package/src/theme/common/var.scss +3 -2
  53. package/src/theme/component-list-panel.scss +2 -0
  54. package/src/theme/content-menu.scss +33 -26
  55. package/src/theme/layer-panel.scss +10 -0
  56. package/src/theme/nav-menu.scss +6 -2
  57. package/src/theme/page-bar.scss +42 -2
  58. package/src/theme/props-panel.scss +19 -17
  59. package/src/theme/workspace.scss +4 -0
  60. package/src/type.ts +27 -9
  61. package/src/utils/editor.ts +37 -56
  62. package/src/utils/polyfills.ts +8 -0
  63. package/src/utils/props.ts +50 -8
  64. package/LICENSE +0 -5432
  65. package/dist/types/src/components/ToolButton.vue.d.ts +0 -35
  66. package/dist/types/src/fields/UISelect.vue.d.ts +0 -32
  67. package/dist/types/src/layouts/sidebar/LayerMenu.vue.d.ts +0 -31
  68. package/dist/types/src/layouts/sidebar/LayerPanel.vue.d.ts +0 -973
  69. package/dist/types/src/layouts/workspace/PageBar.vue.d.ts +0 -11
  70. package/dist/types/src/layouts/workspace/Stage.vue.d.ts +0 -192
  71. package/dist/types/src/layouts/workspace/ViewerMenu.vue.d.ts +0 -18
  72. package/tsconfig.json +0 -9
  73. package/vite.config.ts +0 -30
@@ -25,6 +25,17 @@ import type { GetColumnWidth, SetColumnWidth, StageRect, UiState } from '@editor
25
25
 
26
26
  import BaseService from './BaseService';
27
27
 
28
+ const DEFAULT_LEFT_COLUMN_WIDTH = 310;
29
+ const DEFAULT_RIGHT_COLUMN_WIDTH = 480;
30
+
31
+ const COLUMN_WIDTH_STORAGE_KEY = '$MagicEditorColumnWidthData';
32
+
33
+ const defaultColumnWidth = {
34
+ left: DEFAULT_LEFT_COLUMN_WIDTH,
35
+ center: globalThis.document.body.clientWidth - DEFAULT_LEFT_COLUMN_WIDTH - DEFAULT_RIGHT_COLUMN_WIDTH,
36
+ right: DEFAULT_RIGHT_COLUMN_WIDTH,
37
+ };
38
+
28
39
  const state = reactive<UiState>({
29
40
  uiSelectMode: false,
30
41
  showSrc: false,
@@ -37,13 +48,10 @@ const state = reactive<UiState>({
37
48
  width: 375,
38
49
  height: 817,
39
50
  },
40
- columnWidth: {
41
- left: 310,
42
- center: globalThis.document.body.clientWidth - 310 - 400,
43
- right: 400,
44
- },
51
+ columnWidth: defaultColumnWidth,
45
52
  showGuides: true,
46
53
  showRule: true,
54
+ propsPanelSize: 'small',
47
55
  });
48
56
 
49
57
  class Ui extends BaseService {
@@ -54,6 +62,16 @@ class Ui extends BaseService {
54
62
  center: 'auto',
55
63
  });
56
64
  });
65
+
66
+ const columnWidthCacheData = globalThis.localStorage.getItem(COLUMN_WIDTH_STORAGE_KEY);
67
+ if (columnWidthCacheData) {
68
+ try {
69
+ const columnWidthCache = JSON.parse(columnWidthCacheData);
70
+ this.setColumnWidth(columnWidthCache);
71
+ } catch (e) {
72
+ console.error(e);
73
+ }
74
+ }
57
75
  }
58
76
 
59
77
  public set<T = any>(name: keyof UiState, value: T) {
@@ -88,6 +106,11 @@ class Ui extends BaseService {
88
106
  return (state as any)[name];
89
107
  }
90
108
 
109
+ public zoom(zoom: number) {
110
+ this.set('zoom', (this.get<number>('zoom') * 100 + zoom * 100) / 100);
111
+ if (this.get<number>('zoom') < 0.1) this.set('zoom', 0.1);
112
+ }
113
+
91
114
  private setColumnWidth({ left, center, right }: SetColumnWidth) {
92
115
  const columnWidth = {
93
116
  ...toRaw(this.get<GetColumnWidth>('columnWidth')),
@@ -104,10 +127,17 @@ class Ui extends BaseService {
104
127
  if (!center || center === 'auto') {
105
128
  const bodyWidth = globalThis.document.body.clientWidth;
106
129
  columnWidth.center = bodyWidth - (columnWidth?.left || 0) - (columnWidth?.right || 0);
130
+ if (columnWidth.center <= 0) {
131
+ columnWidth.left = defaultColumnWidth.left;
132
+ columnWidth.center = defaultColumnWidth.center;
133
+ columnWidth.right = defaultColumnWidth.right;
134
+ }
107
135
  } else {
108
136
  columnWidth.center = center;
109
137
  }
110
138
 
139
+ globalThis.localStorage.setItem(COLUMN_WIDTH_STORAGE_KEY, JSON.stringify(columnWidth));
140
+
111
141
  state.columnWidth = columnWidth;
112
142
  }
113
143
 
@@ -2,12 +2,13 @@ $--theme-color: #2882e0;
2
2
 
3
3
  $--font-color: #070303;
4
4
  $--border-color: #d9dbdd;
5
+ $--hover-color: #f3f5f9;
5
6
 
6
7
  $--nav-height: 35px;
7
8
  $--nav-color: #070303;
8
- $--nav--background-color: #f8fbff;
9
+ $--nav--background-color: #ffffff;
9
10
 
10
11
  $--sidebar-heder-background-color: $--theme-color;
11
- $--sidebar-content-background-color: #f8fbff;
12
+ $--sidebar-content-background-color: #ffffff;
12
13
 
13
14
  $--page-bar-height: 32px;
@@ -12,6 +12,7 @@
12
12
  top: 0;
13
13
  left: 0;
14
14
  box-sizing: border-box;
15
+ z-index: 1;
15
16
 
16
17
  .el-input__prefix {
17
18
  padding: 10px;
@@ -62,6 +63,7 @@
62
63
  color: $--font-color;
63
64
  flex-direction: column;
64
65
  width: 42px;
66
+ cursor: pointer;
65
67
 
66
68
  i {
67
69
  font-size: 20px;
@@ -2,38 +2,45 @@
2
2
  position: fixed;
3
3
  font-size: 12px;
4
4
  background: #fff;
5
- color: #333;
6
5
  box-shadow: 0 2px 8px 2px rgba(68, 73, 77, 0.16);
7
6
  z-index: 9999;
8
7
  transform-origin: 0% 0%;
9
8
  font-weight: 600;
10
9
  padding: 4px 0px;
10
+ overflow: auto;
11
+ max-height: 100%;
11
12
 
12
- .separation {
13
- width: 100%;
14
- height: 0;
15
- border-color: rgba(155, 155, 155, 0.1);
16
- }
17
-
18
- .subMenu {
19
- position: absolute;
20
- right: 0;
21
- transform: translate(100%, 0);
22
- background-color: #fff;
13
+ .menu-item {
23
14
  color: #333;
24
- box-shadow: 0 2px 8px 2px rgba(68, 73, 77, 0.16);
25
- top: 0;
26
- height: 223px;
27
- }
28
- }
15
+ display: flex;
16
+ -webkit-box-align: center;
17
+ align-items: center;
18
+ cursor: pointer;
19
+ min-width: 140px;
20
+ transition: all 0.2s ease 0s;
21
+ padding: 5px 14px;
22
+ border-left: 2px solid transparent;
23
+
24
+ .el-button {
25
+ width: 100%;
26
+ justify-content: flex-start;
27
+ }
29
28
 
30
- .magic-editor-content-menu-item {
31
- display: flex;
32
- -webkit-box-align: center;
33
- align-items: center;
34
- cursor: pointer;
35
- min-width: 140px;
36
- transition: all 0.2s ease 0s;
37
- padding: 10px 14px;
38
- border-left: 2px solid transparent;
29
+ .el-button--text,
30
+ i {
31
+ color: $--font-color;
32
+ }
33
+
34
+ &.divider {
35
+ padding: 0 14px;
36
+
37
+ .el-divider {
38
+ margin: 0;
39
+ }
40
+ }
41
+
42
+ &:hover {
43
+ background-color: $--hover-color;
44
+ }
45
+ }
39
46
  }
@@ -50,6 +50,16 @@
50
50
  color: #fff;
51
51
  }
52
52
 
53
+ .magic-editor-layer-panel .cus-tree-node {
54
+ width: 100%;
55
+ overflow: hidden;
56
+ }
57
+
58
+ .magic-editor-layer-panel .cus-tree-node-hover {
59
+ background-color: $--hover-color;
60
+ width: 100%;
61
+ }
62
+
53
63
  .magic-editor-layer-panel .el-tree-node:focus > .el-tree-node__content {
54
64
  background-color: $--sidebar-heder-background-color;
55
65
  color: #fff;
@@ -43,13 +43,17 @@
43
43
  display: flex !important;
44
44
  transition: all 0.3s ease 0s;
45
45
  border-bottom: 2px solid transparent;
46
- margin: 0 5px;
46
+ margin: 0;
47
47
 
48
48
  .is-disabled {
49
49
  opacity: 0.5;
50
50
  }
51
51
 
52
- .el-button--text,
52
+ .is-text {
53
+ padding: 5px;
54
+ }
55
+
56
+ .is-text,
53
57
  i {
54
58
  color: $--font-color;
55
59
  }
@@ -6,18 +6,25 @@
6
6
  width: 100%;
7
7
  height: $--page-bar-height;
8
8
  line-height: $--page-bar-height;
9
- background-color: #f3f3f3;
10
9
  color: $--font-color;
10
+ background-color: #f3f3f3;
11
11
  border-top: 1px solid $--border-color;
12
12
  z-index: 2;
13
+ overflow: hidden;
14
+
15
+ &-items {
16
+ display: flex;
17
+ transition: transform 0.3s;
18
+ }
13
19
 
14
- .m-editor-page-bar-item {
20
+ &-item {
15
21
  padding: 0 10px;
16
22
  cursor: pointer;
17
23
  border-right: 1px solid $--border-color;
18
24
  display: flex;
19
25
  justify-items: center;
20
26
  align-items: center;
27
+ background-color: #f3f3f3;
21
28
 
22
29
  &.active {
23
30
  background-color: #fff;
@@ -27,5 +34,38 @@
27
34
  cursor: pointer;
28
35
  }
29
36
  }
37
+
38
+ &-icon {
39
+ position: relative;
40
+ z-index: 1;
41
+ }
42
+
43
+ &-title {
44
+ max-width: 150px;
45
+ text-overflow: ellipsis;
46
+ white-space: nowrap;
47
+ overflow: hidden;
48
+ }
49
+ }
50
+ }
51
+
52
+ .page-bar-popover {
53
+ &.el-popper.el-popover {
54
+ padding: 10px 0;
55
+ }
56
+
57
+ .menu-item {
58
+ cursor: pointer;
59
+ transition: all 0.2s ease 0s;
60
+ padding: 5px 14px;
61
+
62
+ .el-button--text,
63
+ i {
64
+ color: $--font-color;
65
+ }
66
+
67
+ &:hover {
68
+ background-color: $--hover-color;
69
+ }
30
70
  }
31
71
  }
@@ -1,31 +1,33 @@
1
1
  .m-editor-props-panel {
2
2
  padding: 0 10px;
3
3
 
4
- .el-form-item__label {
5
- font-size: 12px;
6
- }
7
-
8
- .m-fieldset {
9
- legend {
4
+ &.small {
5
+ .el-form-item__label {
10
6
  font-size: 12px;
11
7
  }
12
- }
13
8
 
14
- .el-tabs__item {
15
- font-size: 12px;
9
+ .m-fieldset {
10
+ legend {
11
+ font-size: 12px;
12
+ }
13
+ }
14
+
15
+ .el-tabs__item {
16
+ font-size: 12px;
17
+ }
16
18
  }
17
19
 
18
- span,
19
- a,
20
- p {
21
- font-size: 12px;
20
+ .el-input__wrapper {
21
+ border-radius: 0;
22
22
  }
23
23
  }
24
24
 
25
25
  .m-editor-props-panel-popper {
26
- span,
27
- a,
28
- p {
29
- font-size: 12px;
26
+ &.small {
27
+ span,
28
+ a,
29
+ p {
30
+ font-size: 12px;
31
+ }
30
32
  }
31
33
  }
@@ -2,4 +2,8 @@
2
2
  height: 100%;
3
3
  width: 100%;
4
4
  user-select: none;
5
+
6
+ &:focus-visible {
7
+ outline: 0;
8
+ }
5
9
  }
package/src/type.ts CHANGED
@@ -21,6 +21,7 @@ import type { Component } from 'vue';
21
21
  import type { FormConfig } from '@tmagic/form';
22
22
  import type { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
23
23
  import type StageCore from '@tmagic/stage';
24
+ import type { MoveableOptions } from '@tmagic/stage';
24
25
 
25
26
  import type { ComponentListService } from '@editor/services/componentList';
26
27
  import type { EditorService } from '@editor/services/editor';
@@ -45,13 +46,24 @@ export interface Services {
45
46
  uiService: UiService;
46
47
  }
47
48
 
49
+ export interface StageOptions {
50
+ runtimeUrl: string;
51
+ autoScrollIntoView: boolean;
52
+ render: () => HTMLDivElement;
53
+ moveableOptions: MoveableOptions | ((core?: StageCore) => MoveableOptions);
54
+ canSelect: (el: HTMLElement) => boolean | Promise<boolean>;
55
+ updateDragEl: (el: HTMLDivElement) => void;
56
+ }
57
+
48
58
  export interface StoreState {
49
59
  root: MApp | null;
50
60
  page: MPage | null;
51
61
  parent: MContainer | null;
52
62
  node: MNode | null;
63
+ highlightNode: MNode | null;
53
64
  stage: StageCore | null;
54
65
  modifiedNodeIds: Map<Id, Id>;
66
+ pageLength: number;
55
67
  }
56
68
 
57
69
  export interface PropsState {
@@ -97,6 +109,8 @@ export interface UiState {
97
109
  showGuides: boolean;
98
110
  /** 是否显示标尺,true: 显示,false: 不显示,默认为true */
99
111
  showRule: boolean;
112
+ /** 用于控制该属性配置表单内组件的尺寸 */
113
+ propsPanelSize: 'large' | 'default' | 'small';
100
114
  }
101
115
 
102
116
  export interface EditorNodeInfo {
@@ -124,6 +138,8 @@ export interface MenuButton {
124
138
  * zoom: 放大缩小
125
139
  */
126
140
  type: 'button' | 'dropdown' | 'text' | 'divider' | 'zoom';
141
+ /** 当type为divider时有效,分割线方向, 默认vertical */
142
+ direction?: 'horizontal' | 'vertical';
127
143
  /** 展示的文案 */
128
144
  text?: string;
129
145
  /** 鼠标悬浮是显示的气泡中的文案 */
@@ -135,14 +151,9 @@ export interface MenuButton {
135
151
  /** 是否显示,默认为true */
136
152
  display?: boolean | ((data?: Services) => boolean);
137
153
  /** type为button/dropdown时点击运行的方法 */
138
- handler?: (data?: Services) => Promise<any> | any;
139
- /** type为dropdown时,下拉的菜单列表 */
140
- items?: {
141
- /** 展示的文案 */
142
- text: string;
143
- /** 点击运行的方法 */
144
- handler(data: Services): any;
145
- }[];
154
+ handler?: (data: Services, event: MouseEvent) => Promise<any> | any;
155
+ /** type为dropdown时,下拉的菜单列表, 或者有子菜单时 */
156
+ items?: MenuButton[];
146
157
  }
147
158
 
148
159
  export interface MenuComponent {
@@ -219,7 +230,9 @@ export interface ComponentItem {
219
230
  type: string;
220
231
  /** element-plus icon class */
221
232
  icon?: string | Component;
222
- [key: string]: any;
233
+ data?: {
234
+ [key: string]: any;
235
+ };
223
236
  }
224
237
 
225
238
  export interface ComponentGroup {
@@ -229,6 +242,11 @@ export interface ComponentGroup {
229
242
  items: ComponentItem[];
230
243
  }
231
244
 
245
+ export interface UpdateData {
246
+ id: Id;
247
+ [key: string]: any;
248
+ }
249
+
232
250
  export enum LayerOffset {
233
251
  TOP = 'top',
234
252
  BOTTOM = 'bottom',
@@ -16,17 +16,15 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
- import { random } from 'lodash-es';
20
-
21
- import { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
22
- import { getNodePath, isPop } from '@tmagic/utils';
19
+ import type { MApp, MContainer, MNode, MPage } from '@tmagic/schema';
20
+ import { NodeType } from '@tmagic/schema';
21
+ import type StageCore from '@tmagic/stage';
22
+ import { getNodePath, isNumber, isPage, isPop } from '@tmagic/utils';
23
23
 
24
24
  import { Layout } from '@editor/type';
25
25
 
26
26
  export const COPY_STORAGE_KEY = '$MagicEditorCopyData';
27
27
 
28
- export const generateId = (type: string | number): string => `${type}_${random(10000, false)}`;
29
-
30
28
  /**
31
29
  * 获取所有页面配置
32
30
  * @param app DSL跟节点
@@ -34,7 +32,7 @@ export const generateId = (type: string | number): string => `${type}_${random(1
34
32
  */
35
33
  export const getPageList = (app: MApp): MPage[] => {
36
34
  if (app.items && Array.isArray(app.items)) {
37
- return app.items.filter((item: MPage) => item.type === 'page');
35
+ return app.items.filter((item: MPage) => item.type === NodeType.PAGE);
38
36
  }
39
37
  return [];
40
38
  };
@@ -72,58 +70,13 @@ export const generatePageName = (pageNameList: string[]): string => {
72
70
  */
73
71
  export const generatePageNameByApp = (app: MApp): string => generatePageName(getPageNameList(getPageList(app)));
74
72
 
75
- /**
76
- * 复制页面时,需要把组件下关联的弹窗id换测复制出来的弹窗的id
77
- * @param {number} oldId 复制的源弹窗id
78
- * @param {number} popId 新的弹窗id
79
- * @param {Object} pageConfig 页面配置
80
- */
81
- const updatePopId = (oldId: Id, popId: Id, pageConfig: MPage) => {
82
- pageConfig.items?.forEach((config) => {
83
- if (config.pop === oldId) {
84
- config.pop = popId;
85
- return;
86
- }
87
-
88
- if (config.popId === oldId) {
89
- config.popId = popId;
90
- return;
91
- }
92
-
93
- if (Array.isArray(config.items)) {
94
- updatePopId(oldId, popId, config as MPage);
95
- }
96
- });
97
- };
98
-
99
- /**
100
- * 将组件与组件的子元素配置中的id都设置成一个新的ID
101
- * @param {Object} config 组件配置
102
- */
103
- /* eslint no-param-reassign: ["error", { "props": false }] */
104
- export const setNewItemId = (config: MNode, parent?: MPage) => {
105
- const oldId = config.id;
106
-
107
- config.id = generateId(config.type);
108
- config.name = `${config.name?.replace(/_(\d+)$/, '')}_${config.id}`;
109
-
110
- // 只有弹窗在页面下的一级子元素才有效
111
- if (isPop(config) && parent?.type === 'page') {
112
- updatePopId(oldId, config.id, parent);
113
- }
114
-
115
- if (config.items && Array.isArray(config.items)) {
116
- config.items.forEach((item) => setNewItemId(item, config as MPage));
117
- }
118
- };
119
-
120
73
  /**
121
74
  * @param {Object} node
122
75
  * @returns {boolean}
123
76
  */
124
77
  export const isFixed = (node: MNode): boolean => node.style?.position === 'fixed';
125
78
 
126
- export const getNodeIndex = (node: MNode, parent: MContainer): number => {
79
+ export const getNodeIndex = (node: MNode, parent: MContainer | MApp): number => {
127
80
  const items = parent?.items || [];
128
81
  return items.findIndex((item: MNode) => `${item.id}` === `${node.id}`);
129
82
  };
@@ -138,11 +91,33 @@ export const toRelative = (node: MNode) => {
138
91
  return node;
139
92
  };
140
93
 
141
- export const initPosition = (node: MNode, layout: Layout) => {
94
+ const setTop2Middle = (node: MNode, parentNode: MNode, stage: StageCore) => {
95
+ const style = node.style || {};
96
+ let height = style.height || 0;
97
+
98
+ if (!stage || typeof style.top !== 'undefined' || !parentNode.style) return style;
99
+
100
+ if (!isNumber(height)) {
101
+ height = 0;
102
+ }
103
+
104
+ const { height: parentHeight } = parentNode.style;
105
+
106
+ if (isPage(parentNode)) {
107
+ const { scrollTop = 0, wrapperHeight } = stage.mask;
108
+ style.top = (wrapperHeight - height) / 2 + scrollTop;
109
+ } else {
110
+ style.top = (parentHeight - height) / 2;
111
+ }
112
+
113
+ return style;
114
+ };
115
+
116
+ export const initPosition = (node: MNode, layout: Layout, parentNode: MNode, stage: StageCore) => {
142
117
  if (layout === Layout.ABSOLUTE) {
143
118
  node.style = {
144
119
  position: 'absolute',
145
- ...(node.style || {}),
120
+ ...setTop2Middle(node, parentNode, stage),
146
121
  };
147
122
  return node;
148
123
  }
@@ -193,12 +168,18 @@ export const change2Fixed = (node: MNode, root: MApp) => {
193
168
  return node;
194
169
  };
195
170
 
196
- export const Fixed2Other = async (node: MNode, root: MApp, getLayout: (node: MNode) => Promise<Layout>) => {
171
+ export const Fixed2Other = async (
172
+ node: MNode,
173
+ root: MApp,
174
+ getLayout: (parent: MNode, node?: MNode) => Promise<Layout>,
175
+ ) => {
197
176
  const path = getNodePath(node.id, root.items);
198
177
  const cur = path.pop();
199
178
  const offset = {
200
179
  left: cur?.style?.left || 0,
201
180
  top: cur?.style?.top || 0,
181
+ right: '',
182
+ bottom: '',
202
183
  };
203
184
 
204
185
  path.forEach((value) => {
@@ -0,0 +1,8 @@
1
+ // serialize-javascript 依赖的 randombytes 依赖全局的 global 对象,因此此处需添加 global polyfill
2
+ if (typeof global === 'undefined') {
3
+ (window as any).global = window;
4
+ }
5
+
6
+ if (typeof globalThis === 'undefined') {
7
+ (window as any).globalThis = window;
8
+ }
@@ -20,7 +20,6 @@ import { FormConfig, FormState } from '@tmagic/form';
20
20
 
21
21
  import editorService from '@editor/services/editor';
22
22
  import eventsService from '@editor/services/events';
23
- import { generateId } from '@editor/utils/editor';
24
23
 
25
24
  /**
26
25
  * 统一为组件属性表单加上事件、高级、样式配置
@@ -142,6 +141,40 @@ export const fillConfig = (config: FormConfig = []) => [
142
141
  },
143
142
  ],
144
143
  },
144
+ {
145
+ type: 'fieldset',
146
+ legend: '字体',
147
+ items: [
148
+ {
149
+ name: 'color',
150
+ text: '颜色',
151
+ type: 'colorPicker',
152
+ },
153
+ {
154
+ name: 'fontSize',
155
+ text: '大小',
156
+ },
157
+ {
158
+ name: 'fontWeight',
159
+ text: '粗细',
160
+ },
161
+ ],
162
+ },
163
+ {
164
+ type: 'fieldset',
165
+ legend: '变形',
166
+ name: 'transform',
167
+ items: [
168
+ {
169
+ name: 'rotate',
170
+ text: '旋转角度',
171
+ },
172
+ {
173
+ name: 'scale',
174
+ text: '缩放',
175
+ },
176
+ ],
177
+ },
145
178
  ],
146
179
  },
147
180
  ],
@@ -174,7 +207,7 @@ export const fillConfig = (config: FormConfig = []) => [
174
207
  type: 'select',
175
208
  options: (mForm: FormState, { model }: any) => {
176
209
  const node = editorService.getNodeById(model.to);
177
- if (!node) return [];
210
+ if (!node?.type) return [];
178
211
 
179
212
  return eventsService.getMethod(node.type).map((option) => ({
180
213
  text: option.label,
@@ -210,9 +243,18 @@ export const DEFAULT_CONFIG: FormConfig = fillConfig([]);
210
243
  * @param type 组件类型
211
244
  * @returns Object
212
245
  */
213
- export const getDefaultPropsValue = (type: string) => ({
214
- type,
215
- id: generateId(type),
216
- style: {},
217
- name: type,
218
- });
246
+ export const getDefaultPropsValue = (type: string, id: string) =>
247
+ ['page', 'container'].includes(type)
248
+ ? {
249
+ type,
250
+ id,
251
+ style: {},
252
+ name: type,
253
+ items: [],
254
+ }
255
+ : {
256
+ type,
257
+ id,
258
+ style: {},
259
+ name: type,
260
+ };