@tmagic/editor 1.0.0-rc.5 → 1.0.0-rc.8

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 (85) hide show
  1. package/dist/style.css +3 -0
  2. package/dist/tmagic-editor.es.js +160 -118
  3. package/dist/tmagic-editor.es.js.map +1 -1
  4. package/dist/tmagic-editor.umd.js +160 -120
  5. package/dist/tmagic-editor.umd.js.map +1 -1
  6. package/dist/types/src/Editor.vue.d.ts +36 -2
  7. package/dist/types/src/fields/Code.vue.d.ts +4 -4
  8. package/dist/types/src/fields/CodeLink.vue.d.ts +1 -3
  9. package/dist/types/src/layouts/PropsPanel.vue.d.ts +2 -4
  10. package/dist/types/src/layouts/workspace/Workspace.vue.d.ts +3 -31
  11. package/dist/types/src/services/history.d.ts +1 -18
  12. package/dist/types/src/services/props.d.ts +8 -2
  13. package/dist/types/src/type.d.ts +9 -0
  14. package/dist/types/src/utils/editor.d.ts +0 -6
  15. package/dist/types/src/utils/props.d.ts +8 -1
  16. package/package.json +11 -20
  17. package/src/Editor.vue +35 -9
  18. package/src/components/ContentMenu.vue +58 -25
  19. package/src/layouts/sidebar/LayerMenu.vue +3 -0
  20. package/src/layouts/workspace/Stage.vue +11 -31
  21. package/src/layouts/workspace/ViewerMenu.vue +3 -0
  22. package/src/layouts/workspace/Workspace.vue +2 -28
  23. package/src/services/editor.ts +3 -4
  24. package/src/services/props.ts +64 -9
  25. package/src/theme/workspace.scss +4 -0
  26. package/src/type.ts +10 -0
  27. package/src/utils/editor.ts +1 -50
  28. package/src/utils/props.ts +30 -7
  29. package/LICENSE +0 -5432
  30. package/coverage/clover.xml +0 -1593
  31. package/coverage/coverage-final.json +0 -36
  32. package/coverage/lcov-report/base.css +0 -224
  33. package/coverage/lcov-report/block-navigation.js +0 -87
  34. package/coverage/lcov-report/favicon.png +0 -0
  35. package/coverage/lcov-report/index.html +0 -206
  36. package/coverage/lcov-report/prettify.css +0 -1
  37. package/coverage/lcov-report/prettify.js +0 -2
  38. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  39. package/coverage/lcov-report/sorter.js +0 -196
  40. package/coverage/lcov-report/src/Editor.vue.html +0 -814
  41. package/coverage/lcov-report/src/components/ContentMenu.vue.html +0 -406
  42. package/coverage/lcov-report/src/components/Icon.vue.html +0 -172
  43. package/coverage/lcov-report/src/components/ScrollViewer.vue.html +0 -283
  44. package/coverage/lcov-report/src/components/ToolButton.vue.html +0 -772
  45. package/coverage/lcov-report/src/components/index.html +0 -161
  46. package/coverage/lcov-report/src/index.html +0 -131
  47. package/coverage/lcov-report/src/layouts/AddPageBox.vue.html +0 -214
  48. package/coverage/lcov-report/src/layouts/Framework.vue.html +0 -343
  49. package/coverage/lcov-report/src/layouts/NavMenu.vue.html +0 -208
  50. package/coverage/lcov-report/src/layouts/PropsPanel.vue.html +0 -319
  51. package/coverage/lcov-report/src/layouts/Resizer.vue.html +0 -268
  52. package/coverage/lcov-report/src/layouts/index.html +0 -176
  53. package/coverage/lcov-report/src/layouts/sidebar/ComponentListPanel.vue.html +0 -358
  54. package/coverage/lcov-report/src/layouts/sidebar/LayerMenu.vue.html +0 -421
  55. package/coverage/lcov-report/src/layouts/sidebar/LayerPanel.vue.html +0 -775
  56. package/coverage/lcov-report/src/layouts/sidebar/Sidebar.vue.html +0 -226
  57. package/coverage/lcov-report/src/layouts/sidebar/TabPane.vue.html +0 -289
  58. package/coverage/lcov-report/src/layouts/sidebar/index.html +0 -176
  59. package/coverage/lcov-report/src/layouts/workspace/PageBar.vue.html +0 -718
  60. package/coverage/lcov-report/src/layouts/workspace/Stage.vue.html +0 -766
  61. package/coverage/lcov-report/src/layouts/workspace/ViewerMenu.vue.html +0 -568
  62. package/coverage/lcov-report/src/layouts/workspace/Workspace.vue.html +0 -649
  63. package/coverage/lcov-report/src/layouts/workspace/index.html +0 -161
  64. package/coverage/lcov-report/src/services/BaseService.ts.html +0 -643
  65. package/coverage/lcov-report/src/services/componentList.ts.html +0 -229
  66. package/coverage/lcov-report/src/services/editor.ts.html +0 -2167
  67. package/coverage/lcov-report/src/services/events.ts.html +0 -331
  68. package/coverage/lcov-report/src/services/history.ts.html +0 -478
  69. package/coverage/lcov-report/src/services/index.html +0 -206
  70. package/coverage/lcov-report/src/services/props.ts.html +0 -415
  71. package/coverage/lcov-report/src/services/ui.ts.html +0 -580
  72. package/coverage/lcov-report/src/type.ts.html +0 -850
  73. package/coverage/lcov-report/src/utils/compose.ts.html +0 -184
  74. package/coverage/lcov-report/src/utils/config.ts.html +0 -172
  75. package/coverage/lcov-report/src/utils/editor.ts.html +0 -838
  76. package/coverage/lcov-report/src/utils/index.html +0 -221
  77. package/coverage/lcov-report/src/utils/index.ts.html +0 -151
  78. package/coverage/lcov-report/src/utils/logger.ts.html +0 -226
  79. package/coverage/lcov-report/src/utils/props.ts.html +0 -796
  80. package/coverage/lcov-report/src/utils/scroll-viewer.ts.html +0 -733
  81. package/coverage/lcov-report/src/utils/undo-redo.ts.html +0 -313
  82. package/coverage/lcov.info +0 -3846
  83. package/dist/types/src/components/ToolButton.vue.d.ts +0 -46
  84. package/dist/types/src/fields/UISelect.vue.d.ts +0 -35
  85. package/dist/types/src/layouts/workspace/PageBar.vue.d.ts +0 -18
@@ -28,7 +28,6 @@ import {
28
28
  markRaw,
29
29
  onMounted,
30
30
  onUnmounted,
31
- PropType,
32
31
  ref,
33
32
  toRaw,
34
33
  watch,
@@ -37,11 +36,11 @@ import {
37
36
  import { cloneDeep } from 'lodash-es';
38
37
 
39
38
  import type { MApp, MNode, MPage } from '@tmagic/schema';
40
- import type { MoveableOptions, Runtime, SortEventData, UpdateEventData } from '@tmagic/stage';
39
+ import type { Runtime, SortEventData, UpdateEventData } from '@tmagic/stage';
41
40
  import StageCore from '@tmagic/stage';
42
41
 
43
42
  import ScrollViewer from '@editor/components/ScrollViewer.vue';
44
- import { Layout, Services, StageRect } from '@editor/type';
43
+ import { Layout, Services, StageOptions, StageRect } from '@editor/type';
45
44
 
46
45
  import ViewerMenu from './ViewerMenu.vue';
47
46
 
@@ -53,29 +52,9 @@ export default defineComponent({
53
52
  ScrollViewer,
54
53
  },
55
54
 
56
- props: {
57
- render: {
58
- type: Function as PropType<() => HTMLDivElement>,
59
- },
60
-
61
- runtimeUrl: String,
62
- autoScrollIntoView: Boolean,
63
-
64
- canSelect: {
65
- type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
66
- default: (el: HTMLElement) => Boolean(el.id),
67
- },
68
-
69
- moveableOptions: {
70
- type: [Object, Function] as PropType<MoveableOptions | ((core?: StageCore) => MoveableOptions)>,
71
- default: () => (core?: StageCore) => ({
72
- container: core?.renderer?.contentWindow?.document.getElementById('app'),
73
- }),
74
- },
75
- },
76
-
77
- setup(props) {
55
+ setup() {
78
56
  const services = inject<Services>('services');
57
+ const stageOptions = inject<StageOptions>('stageOptions');
79
58
 
80
59
  const stageWrap = ref<InstanceType<typeof ScrollViewer>>();
81
60
  const stageContainer = ref<HTMLDivElement>();
@@ -95,15 +74,15 @@ export default defineComponent({
95
74
  if (stage) return;
96
75
 
97
76
  if (!stageContainer.value) return;
98
- if (!(props.runtimeUrl || props.render) || !root.value) return;
77
+ if (!(stageOptions?.runtimeUrl || stageOptions?.render) || !root.value) return;
99
78
 
100
79
  stage = new StageCore({
101
- render: props.render,
102
- runtimeUrl: props.runtimeUrl,
80
+ render: stageOptions.render,
81
+ runtimeUrl: stageOptions.runtimeUrl,
103
82
  zoom: zoom.value,
104
- autoScrollIntoView: props.autoScrollIntoView,
83
+ autoScrollIntoView: stageOptions.autoScrollIntoView,
105
84
  canSelect: (el, event, stop) => {
106
- const elCanSelect = props.canSelect(el);
85
+ const elCanSelect = stageOptions.canSelect(el);
107
86
  // 在组件联动过程中不能再往下选择,返回并触发 ui-select
108
87
  if (uiSelectMode.value && elCanSelect && event.type === 'mousedown') {
109
88
  document.dispatchEvent(new CustomEvent('ui-select', { detail: el }));
@@ -112,7 +91,8 @@ export default defineComponent({
112
91
 
113
92
  return elCanSelect;
114
93
  },
115
- moveableOptions: props.moveableOptions,
94
+ moveableOptions: stageOptions.moveableOptions,
95
+ updateDragEl: stageOptions.updateDragEl,
116
96
  });
117
97
 
118
98
  services?.editorService.set('stage', markRaw(stage));
@@ -27,6 +27,8 @@ export default defineComponent({
27
27
  const parent = computed(() => editorService?.get('parent'));
28
28
  const isPage = computed(() => node.value?.type === NodeType.PAGE);
29
29
 
30
+ const stageContentMenu = inject<MenuItem[]>('stageContentMenu', []);
31
+
30
32
  onMounted(() => {
31
33
  const data = globalThis.localStorage.getItem(COPY_STORAGE_KEY);
32
34
  canPaste.value = data !== 'undefined' && !!data;
@@ -150,6 +152,7 @@ export default defineComponent({
150
152
  editorService?.get<StageCore>('stage').clearGuides();
151
153
  },
152
154
  },
155
+ ...stageContentMenu,
153
156
  ]),
154
157
 
155
158
  show(e: MouseEvent) {
@@ -1,13 +1,6 @@
1
1
  <template>
2
2
  <div class="m-editor-workspace" tabindex="1" ref="workspace">
3
- <magic-stage
4
- :key="page?.id"
5
- :runtime-url="runtimeUrl"
6
- :auto-scroll-into-view="autoScrollIntoView"
7
- :render="render"
8
- :moveable-options="moveableOptions"
9
- :can-select="canSelect"
10
- ></magic-stage>
3
+ <magic-stage :key="page?.id"></magic-stage>
11
4
 
12
5
  <slot name="workspace-content"></slot>
13
6
 
@@ -19,12 +12,10 @@
19
12
  </template>
20
13
 
21
14
  <script lang="ts">
22
- import { computed, defineComponent, inject, onMounted, onUnmounted, PropType, ref } from 'vue';
15
+ import { computed, defineComponent, inject, onMounted, onUnmounted, ref } from 'vue';
23
16
  import KeyController from 'keycon';
24
17
 
25
18
  import type { MNode, MPage } from '@tmagic/schema';
26
- import type { MoveableOptions } from '@tmagic/stage';
27
- import StageCore from '@tmagic/stage';
28
19
  import { isPage } from '@tmagic/utils';
29
20
 
30
21
  import type { Services } from '@editor/type';
@@ -40,23 +31,6 @@ export default defineComponent({
40
31
  MagicStage,
41
32
  },
42
33
 
43
- props: {
44
- runtimeUrl: String,
45
- autoScrollIntoView: Boolean,
46
-
47
- render: {
48
- type: Function as PropType<() => HTMLDivElement>,
49
- },
50
-
51
- moveableOptions: {
52
- type: [Object, Function] as PropType<MoveableOptions | ((core?: StageCore) => MoveableOptions)>,
53
- },
54
-
55
- canSelect: {
56
- type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
57
- },
58
- },
59
-
60
34
  setup() {
61
35
  const services = inject<Services>('services');
62
36
  const workspace = ref<HTMLDivElement>();
@@ -38,7 +38,6 @@ import {
38
38
  initPosition,
39
39
  isFixed,
40
40
  setLayout,
41
- setNewItemId,
42
41
  } from '@editor/utils/editor';
43
42
  import { log } from '@editor/utils/logger';
44
43
 
@@ -495,7 +494,7 @@ class Editor extends BaseService {
495
494
  return;
496
495
  }
497
496
 
498
- setNewItemId(config, this.get('root'));
497
+ await propsService.setNewItemId(config, this.get('root'));
499
498
  if (config.style) {
500
499
  config.style = {
501
500
  ...config.style,
@@ -556,9 +555,9 @@ class Editor extends BaseService {
556
555
  const brothers: MNode[] = parent?.items || [];
557
556
  const index = brothers.findIndex((item) => `${item.id}` === `${node?.id}`);
558
557
 
559
- if (offset === LayerOffset.BOTTOM) {
558
+ if (offset === LayerOffset.TOP) {
560
559
  brothers.splice(brothers.length - 1, 0, brothers.splice(index, 1)[0]);
561
- } else if (offset === LayerOffset.TOP) {
560
+ } else if (offset === LayerOffset.BOTTOM) {
562
561
  brothers.splice(0, 0, brothers.splice(index, 1)[0]);
563
562
  } else {
564
563
  brothers.splice(index + parseInt(`${offset}`, 10), 0, brothers.splice(index, 1)[0]);
@@ -17,11 +17,12 @@
17
17
  */
18
18
 
19
19
  import { reactive } from 'vue';
20
- import { cloneDeep, mergeWith } from 'lodash-es';
20
+ import { cloneDeep, mergeWith, random } from 'lodash-es';
21
21
 
22
22
  import type { FormConfig } from '@tmagic/form';
23
- import type { MComponent, MNode } from '@tmagic/schema';
24
- import { toLine } from '@tmagic/utils';
23
+ import type { Id, MComponent, MNode, MPage } from '@tmagic/schema';
24
+ import { NodeType } from '@tmagic/schema';
25
+ import { isPop, toLine } from '@tmagic/utils';
25
26
 
26
27
  import type { PropsState } from '@editor/type';
27
28
  import { DEFAULT_CONFIG, fillConfig, getDefaultPropsValue } from '@editor/utils/props';
@@ -35,7 +36,7 @@ class Props extends BaseService {
35
36
  });
36
37
 
37
38
  constructor() {
38
- super(['setPropsConfig', 'getPropsConfig', 'setPropsValue', 'getPropsValue']);
39
+ super(['setPropsConfig', 'getPropsConfig', 'setPropsValue', 'getPropsValue', 'createId', 'setNewItemId']);
39
40
  }
40
41
 
41
42
  public setPropsConfigs(configs: Record<string, FormConfig>) {
@@ -87,7 +88,7 @@ class Props extends BaseService {
87
88
  * @param type 组件类型
88
89
  * @returns 组件初始值
89
90
  */
90
- public async getPropsValue(type: string, defaultValue = {}) {
91
+ public async getPropsValue(type: string, defaultValue: Record<string, any> = {}) {
91
92
  if (type === 'area') {
92
93
  const value = (await this.getPropsValue('button')) as MComponent;
93
94
  value.className = 'action-area';
@@ -98,13 +99,67 @@ class Props extends BaseService {
98
99
  return value;
99
100
  }
100
101
 
101
- return cloneDeep({
102
- ...getDefaultPropsValue(type),
103
- ...mergeWith(this.state.propsValueMap[type] || {}, defaultValue),
104
- });
102
+ const data = cloneDeep(defaultValue as any);
103
+
104
+ await this.setNewItemId(data);
105
+
106
+ return {
107
+ ...getDefaultPropsValue(type, await this.createId(type)),
108
+ ...mergeWith(cloneDeep(this.state.propsValueMap[type] || {}), data),
109
+ };
110
+ }
111
+
112
+ public async createId(type: string | number): Promise<string> {
113
+ return `${type}_${random(10000, false)}`;
114
+ }
115
+
116
+ /**
117
+ * 将组件与组件的子元素配置中的id都设置成一个新的ID
118
+ * @param {Object} config 组件配置
119
+ */
120
+ /* eslint no-param-reassign: ["error", { "props": false }] */
121
+ public async setNewItemId(config: MNode, parent?: MPage) {
122
+ const oldId = config.id;
123
+
124
+ config.id = await this.createId(config.type || 'component');
125
+
126
+ // 只有弹窗在页面下的一级子元素才有效
127
+ if (isPop(config) && parent?.type === NodeType.PAGE) {
128
+ updatePopId(oldId, config.id, parent);
129
+ }
130
+
131
+ if (config.items && Array.isArray(config.items)) {
132
+ for (const item of config.items) {
133
+ await this.setNewItemId(item, config as MPage);
134
+ }
135
+ }
105
136
  }
106
137
  }
107
138
 
139
+ /**
140
+ * 复制页面时,需要把组件下关联的弹窗id换测复制出来的弹窗的id
141
+ * @param {number} oldId 复制的源弹窗id
142
+ * @param {number} popId 新的弹窗id
143
+ * @param {Object} pageConfig 页面配置
144
+ */
145
+ const updatePopId = (oldId: Id, popId: Id, pageConfig: MPage) => {
146
+ pageConfig.items?.forEach((config) => {
147
+ if (config.pop === oldId) {
148
+ config.pop = popId;
149
+ return;
150
+ }
151
+
152
+ if (config.popId === oldId) {
153
+ config.popId = popId;
154
+ return;
155
+ }
156
+
157
+ if (Array.isArray(config.items)) {
158
+ updatePopId(oldId, popId, config as MPage);
159
+ }
160
+ });
161
+ };
162
+
108
163
  export type PropsService = Props;
109
164
 
110
165
  export default new Props();
@@ -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,6 +46,15 @@ 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;
@@ -16,9 +16,7 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
- import { random } from 'lodash-es';
20
-
21
- import type { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
19
+ import type { MApp, MContainer, MNode, MPage } from '@tmagic/schema';
22
20
  import { NodeType } from '@tmagic/schema';
23
21
  import type StageCore from '@tmagic/stage';
24
22
  import { getNodePath, isNumber, isPage, isPop } from '@tmagic/utils';
@@ -27,8 +25,6 @@ import { Layout } from '@editor/type';
27
25
 
28
26
  export const COPY_STORAGE_KEY = '$MagicEditorCopyData';
29
27
 
30
- export const generateId = (type: string | number): string => `${type}_${random(10000, false)}`;
31
-
32
28
  /**
33
29
  * 获取所有页面配置
34
30
  * @param app DSL跟节点
@@ -74,51 +70,6 @@ export const generatePageName = (pageNameList: string[]): string => {
74
70
  */
75
71
  export const generatePageNameByApp = (app: MApp): string => generatePageName(getPageNameList(getPageList(app)));
76
72
 
77
- /**
78
- * 复制页面时,需要把组件下关联的弹窗id换测复制出来的弹窗的id
79
- * @param {number} oldId 复制的源弹窗id
80
- * @param {number} popId 新的弹窗id
81
- * @param {Object} pageConfig 页面配置
82
- */
83
- const updatePopId = (oldId: Id, popId: Id, pageConfig: MPage) => {
84
- pageConfig.items?.forEach((config) => {
85
- if (config.pop === oldId) {
86
- config.pop = popId;
87
- return;
88
- }
89
-
90
- if (config.popId === oldId) {
91
- config.popId = popId;
92
- return;
93
- }
94
-
95
- if (Array.isArray(config.items)) {
96
- updatePopId(oldId, popId, config as MPage);
97
- }
98
- });
99
- };
100
-
101
- /**
102
- * 将组件与组件的子元素配置中的id都设置成一个新的ID
103
- * @param {Object} config 组件配置
104
- */
105
- /* eslint no-param-reassign: ["error", { "props": false }] */
106
- export const setNewItemId = (config: MNode, parent?: MPage) => {
107
- const oldId = config.id;
108
-
109
- config.id = generateId(config.type || 'component');
110
- config.name = `${config.name?.replace(/_(\d+)$/, '')}_${config.id}`;
111
-
112
- // 只有弹窗在页面下的一级子元素才有效
113
- if (isPop(config) && parent?.type === NodeType.PAGE) {
114
- updatePopId(oldId, config.id, parent);
115
- }
116
-
117
- if (config.items && Array.isArray(config.items)) {
118
- config.items.forEach((item) => setNewItemId(item, config as MPage));
119
- }
120
- };
121
-
122
73
  /**
123
74
  * @param {Object} node
124
75
  * @returns {boolean}
@@ -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
  * 统一为组件属性表单加上事件、高级、样式配置
@@ -161,6 +160,21 @@ export const fillConfig = (config: FormConfig = []) => [
161
160
  },
162
161
  ],
163
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
+ },
164
178
  ],
165
179
  },
166
180
  ],
@@ -229,9 +243,18 @@ export const DEFAULT_CONFIG: FormConfig = fillConfig([]);
229
243
  * @param type 组件类型
230
244
  * @returns Object
231
245
  */
232
- export const getDefaultPropsValue = (type: string) => ({
233
- type,
234
- id: generateId(type),
235
- style: {},
236
- name: type,
237
- });
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
+ };