@tmagic/editor 1.2.0-beta.8 → 1.2.0

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 (98) hide show
  1. package/dist/style.css +59 -35
  2. package/dist/{tmagic-editor.mjs → tmagic-editor.js} +1473 -1161
  3. package/dist/tmagic-editor.js.map +1 -0
  4. package/dist/{tmagic-editor.umd.js → tmagic-editor.umd.cjs} +1483 -1166
  5. package/dist/tmagic-editor.umd.cjs.map +1 -0
  6. package/package.json +16 -14
  7. package/src/Editor.vue +66 -40
  8. package/src/components/CodeDraftEditor.vue +145 -0
  9. package/src/components/ContentMenu.vue +2 -2
  10. package/src/components/FunctionEditor.vue +145 -0
  11. package/src/components/Icon.vue +1 -1
  12. package/src/{layouts → components}/Layout.vue +54 -15
  13. package/src/components/ScrollBar.vue +1 -1
  14. package/src/components/ScrollViewer.vue +10 -1
  15. package/src/components/ToolButton.vue +1 -1
  16. package/src/fields/Code.vue +1 -1
  17. package/src/fields/CodeLink.vue +1 -1
  18. package/src/fields/CodeSelect.vue +84 -110
  19. package/src/fields/UISelect.vue +1 -1
  20. package/src/index.ts +1 -0
  21. package/src/layouts/AddPageBox.vue +1 -1
  22. package/src/layouts/CodeEditor.vue +2 -3
  23. package/src/layouts/Framework.vue +2 -2
  24. package/src/layouts/NavMenu.vue +2 -2
  25. package/src/layouts/PropsPanel.vue +13 -6
  26. package/src/layouts/Resizer.vue +1 -1
  27. package/src/layouts/sidebar/ComponentListPanel.vue +1 -1
  28. package/src/layouts/sidebar/LayerMenu.vue +9 -7
  29. package/src/layouts/sidebar/LayerPanel.vue +127 -174
  30. package/src/layouts/sidebar/Sidebar.vue +110 -26
  31. package/src/layouts/sidebar/code-block/CodeBlockEditor.vue +27 -83
  32. package/src/layouts/sidebar/code-block/CodeBlockList.vue +90 -122
  33. package/src/layouts/workspace/Breadcrumb.vue +1 -1
  34. package/src/layouts/workspace/PageBar.vue +1 -1
  35. package/src/layouts/workspace/PageBarScrollContainer.vue +1 -1
  36. package/src/layouts/workspace/Stage.vue +26 -9
  37. package/src/layouts/workspace/ViewerMenu.vue +11 -9
  38. package/src/layouts/workspace/Workspace.vue +7 -3
  39. package/src/services/BaseService.ts +10 -1
  40. package/src/services/codeBlock.ts +124 -125
  41. package/src/services/componentList.ts +6 -1
  42. package/src/services/editor.ts +54 -18
  43. package/src/services/events.ts +6 -1
  44. package/src/services/history.ts +7 -16
  45. package/src/services/props.ts +7 -2
  46. package/src/services/storage.ts +1 -0
  47. package/src/services/ui.ts +12 -0
  48. package/src/theme/code-block.scss +43 -24
  49. package/src/theme/component-list-panel.scss +8 -5
  50. package/src/type.ts +77 -50
  51. package/src/utils/editor.ts +9 -1
  52. package/src/utils/index.ts +1 -0
  53. package/src/utils/props.ts +2 -2
  54. package/src/utils/scroll-viewer.ts +18 -2
  55. package/src/utils/stage.ts +4 -3
  56. package/types/Editor.vue.d.ts +47 -27
  57. package/types/components/CodeDraftEditor.vue.d.ts +56 -0
  58. package/types/components/ContentMenu.vue.d.ts +11 -87
  59. package/types/components/FunctionEditor.vue.d.ts +43 -0
  60. package/types/components/Icon.vue.d.ts +4 -50
  61. package/types/{layouts → components}/Layout.vue.d.ts +12 -1
  62. package/types/components/ScrollBar.vue.d.ts +7 -65
  63. package/types/components/ScrollViewer.vue.d.ts +45 -1
  64. package/types/components/ToolButton.vue.d.ts +12 -78
  65. package/types/fields/Code.vue.d.ts +11 -77
  66. package/types/fields/CodeLink.vue.d.ts +12 -82
  67. package/types/fields/CodeSelect.vue.d.ts +13 -77
  68. package/types/fields/UISelect.vue.d.ts +7 -65
  69. package/types/index.d.ts +1 -0
  70. package/types/layouts/AddPageBox.vue.d.ts +1 -43
  71. package/types/layouts/CodeEditor.vue.d.ts +22 -130
  72. package/types/layouts/NavMenu.vue.d.ts +9 -69
  73. package/types/layouts/sidebar/LayerMenu.vue.d.ts +16 -48
  74. package/types/layouts/sidebar/LayerPanel.vue.d.ts +24 -7
  75. package/types/layouts/sidebar/Sidebar.vue.d.ts +10 -5
  76. package/types/layouts/sidebar/code-block/CodeBlockEditor.vue.d.ts +1 -1
  77. package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +6 -5
  78. package/types/layouts/workspace/Breadcrumb.vue.d.ts +1 -43
  79. package/types/layouts/workspace/Stage.vue.d.ts +15 -43
  80. package/types/layouts/workspace/ViewerMenu.vue.d.ts +11 -66
  81. package/types/layouts/workspace/Workspace.vue.d.ts +23 -5
  82. package/types/services/BaseService.d.ts +2 -1
  83. package/types/services/codeBlock.d.ts +57 -36
  84. package/types/services/componentList.d.ts +1 -0
  85. package/types/services/editor.d.ts +5 -6
  86. package/types/services/events.d.ts +1 -0
  87. package/types/services/history.d.ts +5 -15
  88. package/types/services/props.d.ts +3 -2
  89. package/types/services/ui.d.ts +2 -1
  90. package/types/type.d.ts +65 -48
  91. package/types/utils/editor.d.ts +1 -0
  92. package/types/utils/index.d.ts +1 -0
  93. package/types/utils/props.d.ts +1 -1
  94. package/types/utils/scroll-viewer.d.ts +5 -0
  95. package/dist/tmagic-editor.mjs.map +0 -1
  96. package/dist/tmagic-editor.umd.js.map +0 -1
  97. package/src/layouts/sidebar/TabPane.vue +0 -118
  98. package/types/layouts/sidebar/TabPane.vue.d.ts +0 -82
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div ref="el" class="m-editor-layout">
3
- <template v-if="typeof props.left !== 'undefined'">
3
+ <template v-if="hasLeft">
4
4
  <div class="m-editor-layout-left" :class="leftClass" :style="`width: ${left}px`">
5
5
  <slot name="left"></slot>
6
6
  </div>
@@ -11,7 +11,7 @@
11
11
  <slot name="center"></slot>
12
12
  </div>
13
13
 
14
- <template v-if="typeof props.right !== 'undefined'">
14
+ <template v-if="hasRight">
15
15
  <Resizer @change="changeRight"></Resizer>
16
16
  <div class="m-editor-layout-right" :class="rightClass" :style="`width: ${right}px`">
17
17
  <slot name="right"></slot>
@@ -20,10 +20,10 @@
20
20
  </div>
21
21
  </template>
22
22
 
23
- <script lang="ts" setup>
24
- import { onMounted, onUnmounted, ref } from 'vue';
23
+ <script lang="ts" setup name="MEditorLayout">
24
+ import { computed, onMounted, onUnmounted, ref } from 'vue';
25
25
 
26
- import Resizer from './Resizer.vue';
26
+ import Resizer from '../layouts/Resizer.vue';
27
27
 
28
28
  const emit = defineEmits(['update:left', 'change', 'update:right']);
29
29
 
@@ -33,29 +33,64 @@ const props = withDefaults(
33
33
  right?: number;
34
34
  minLeft?: number;
35
35
  minRight?: number;
36
+ minCenter?: number;
36
37
  leftClass?: string;
37
38
  rightClass?: string;
38
39
  centerClass?: string;
39
40
  }>(),
40
41
  {
41
- minLeft: 1,
42
+ minLeft: 46,
42
43
  minRight: 1,
44
+ minCenter: 1,
43
45
  },
44
46
  );
45
47
 
46
48
  const el = ref<HTMLElement>();
47
49
 
50
+ const hasLeft = computed(() => typeof props.left !== 'undefined');
51
+ const hasRight = computed(() => typeof props.right !== 'undefined');
52
+
53
+ const getCenterWidth = (clientWidth: number, left: number, right: number) => {
54
+ let center = clientWidth - left - right;
55
+ if (center < props.minCenter) {
56
+ center = props.minCenter;
57
+ if (left < right) {
58
+ right = clientWidth - left - props.minCenter;
59
+ } else {
60
+ left = clientWidth - right - props.minCenter;
61
+ }
62
+ }
63
+ return {
64
+ center,
65
+ left,
66
+ right,
67
+ };
68
+ };
69
+
48
70
  let clientWidth = 0;
49
71
  const resizerObserver = new ResizeObserver((entries) => {
50
72
  for (const { contentRect } of entries) {
51
73
  clientWidth = contentRect.width;
52
74
 
53
- center.value = clientWidth - (props.left || 0) - (props.right || 0);
75
+ let left = props.left || 0;
76
+ let right = props.right || 0;
77
+
78
+ if (left > clientWidth) {
79
+ left = clientWidth / 3;
80
+ }
81
+
82
+ if (right > clientWidth) {
83
+ right = clientWidth / 3;
84
+ }
85
+
86
+ const columnWidth = getCenterWidth(clientWidth, left, right);
87
+
88
+ center.value = columnWidth.center;
54
89
 
55
90
  emit('change', {
56
- left: props.left,
91
+ left: columnWidth.left,
57
92
  center: center.value,
58
- right: props.right,
93
+ right: columnWidth.right,
59
94
  });
60
95
  }
61
96
  });
@@ -81,12 +116,14 @@ const changeLeft = (deltaX: number) => {
81
116
  left = props.left;
82
117
  }
83
118
 
84
- center.value = clientWidth - left - (props.right || 0);
119
+ const columnWidth = getCenterWidth(clientWidth, left, props.right || 0);
120
+
121
+ center.value = columnWidth.center;
85
122
 
86
123
  emit('change', {
87
- left,
124
+ left: columnWidth.left,
88
125
  center: center.value,
89
- right: props.right,
126
+ right: columnWidth.right,
90
127
  });
91
128
  };
92
129
 
@@ -99,12 +136,14 @@ const changeRight = (deltaX: number) => {
99
136
  right = props.right;
100
137
  }
101
138
 
102
- center.value = clientWidth - (props.left || 0) - right;
139
+ const columnWidth = getCenterWidth(clientWidth, props.left || 0, right);
140
+
141
+ center.value = columnWidth.center;
103
142
 
104
143
  emit('change', {
105
- left: props.left,
144
+ left: columnWidth.left,
106
145
  center: center.value,
107
- right,
146
+ right: columnWidth.right,
108
147
  });
109
148
  };
110
149
  </script>
@@ -4,7 +4,7 @@
4
4
  </div>
5
5
  </template>
6
6
 
7
- <script lang="ts" setup>
7
+ <script lang="ts" setup name="MEditorScrollBar">
8
8
  import { computed, onMounted, onUnmounted, ref } from 'vue';
9
9
  import Gesto from 'gesto';
10
10
 
@@ -22,7 +22,7 @@
22
22
  </div>
23
23
  </template>
24
24
 
25
- <script lang="ts" setup>
25
+ <script lang="ts" setup name="MEditorScrollViewer">
26
26
  import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
27
27
 
28
28
  import { ScrollViewerEvent } from '../type';
@@ -37,6 +37,10 @@ const props = withDefaults(
37
37
  wrapWidth?: number;
38
38
  wrapHeight?: number;
39
39
  zoom?: number;
40
+ correctionScrollSize?: {
41
+ width: number;
42
+ height: number;
43
+ };
40
44
  }>(),
41
45
  {
42
46
  width: 0,
@@ -44,6 +48,10 @@ const props = withDefaults(
44
48
  wrapWidth: 0,
45
49
  wrapHeight: 0,
46
50
  zoom: 1,
51
+ correctionScrollSize: () => ({
52
+ width: 0,
53
+ height: 0,
54
+ }),
47
55
  },
48
56
  );
49
57
 
@@ -69,6 +77,7 @@ onMounted(() => {
69
77
  container: container.value,
70
78
  target: el.value,
71
79
  zoom: props.zoom,
80
+ correctionScrollSize: props.correctionScrollSize,
72
81
  });
73
82
 
74
83
  scrollViewer.on('scroll', (data: ScrollViewerEvent) => {
@@ -43,7 +43,7 @@
43
43
  </div>
44
44
  </template>
45
45
 
46
- <script lang="ts" setup>
46
+ <script lang="ts" setup name="MEditorToolButton">
47
47
  import { computed, inject } from 'vue';
48
48
  import { ArrowDown } from '@element-plus/icons-vue';
49
49
 
@@ -8,7 +8,7 @@
8
8
  ></magic-code-editor>
9
9
  </template>
10
10
 
11
- <script lang="ts" setup>
11
+ <script lang="ts" setup name="MEditorCode">
12
12
  import { computed } from 'vue';
13
13
 
14
14
  const emit = defineEmits(['change']);
@@ -2,7 +2,7 @@
2
2
  <m-fields-link :config="formConfig" :model="modelValue" name="form" @change="changeHandler"></m-fields-link>
3
3
  </template>
4
4
 
5
- <script lang="ts" setup>
5
+ <script lang="ts" setup name="MEditorCodeLink">
6
6
  import { computed, reactive, watch } from 'vue';
7
7
  import serialize from 'serialize-javascript';
8
8
 
@@ -1,144 +1,118 @@
1
1
  <template>
2
- <div class="m-fields-code-select" :key="fieldKey">
3
- <TMagicCard shadow="never">
4
- <template #header>
5
- <m-fields-select
6
- :config="selectConfig"
7
- :model="model"
8
- :prop="prop"
9
- :name="name"
10
- :size="size"
11
- @change="changeHandler"
12
- ></m-fields-select>
13
- </template>
14
- <div class="tool-bar">
15
- <TMagicTooltip class="tool-item" effect="dark" content="查看代码块" placement="top">
16
- <svg
17
- @click="viewHandler"
18
- preserveAspectRatio="xMidYMid meet"
19
- viewBox="0 0 24 24"
20
- width="15px"
21
- height="15px"
22
- data-v-65a7fb6c=""
23
- >
24
- <path
25
- fill="currentColor"
26
- d="m23 12l-7.071 7.071l-1.414-1.414L20.172 12l-5.657-5.657l1.414-1.414L23 12zM3.828 12l5.657 5.657l-1.414 1.414L1 12l7.071-7.071l1.414 1.414L3.828 12z"
27
- ></path>
28
- </svg>
29
- </TMagicTooltip>
30
- </div>
31
- </TMagicCard>
2
+ <div class="m-fields-code-select">
3
+ <m-form-table
4
+ :config="tableConfig"
5
+ :model="model[name]"
6
+ name="hookData"
7
+ :enableToggleMode="false"
8
+ :prop="prop"
9
+ :size="size"
10
+ @change="changeHandler"
11
+ >
12
+ </m-form-table>
32
13
  </div>
33
14
  </template>
34
15
 
35
- <script lang="ts" setup>
36
- import { computed, defineEmits, defineProps, inject, ref, watch, watchEffect } from 'vue';
37
- import { cloneDeep, map, xor } from 'lodash-es';
16
+ <script lang="ts" setup name="MEditorCodeSelect">
17
+ import { computed, defineEmits, defineProps, inject, watch } from 'vue';
18
+ import { isEmpty, map } from 'lodash-es';
38
19
 
39
- import { TMagicCard, tMagicMessage, TMagicTooltip } from '@tmagic/design';
40
- import { SelectConfig } from '@tmagic/form';
20
+ import { createValues, FormItem, FormState, TableConfig } from '@tmagic/form';
21
+ import { HookType, Id } from '@tmagic/schema';
41
22
 
42
- import type { Services } from '../type';
43
- import { CodeEditorMode, CodeSelectOp } from '../type';
23
+ import { CodeParamStatement, HookData, Services } from '../type';
44
24
  const services = inject<Services>('services');
45
-
25
+ const mForm = inject<FormState>('mForm');
46
26
  const emit = defineEmits(['change']);
47
27
 
48
28
  const props = defineProps<{
49
29
  config: {
50
- selectConfig?: SelectConfig;
30
+ tableConfig?: TableConfig;
51
31
  };
52
32
  model: any;
53
33
  prop: string;
54
34
  name: string;
55
- size: string;
35
+ size: 'mini' | 'small' | 'medium';
56
36
  }>();
37
+ const codeDsl = computed(() => services?.codeBlockService.getCodeDslSync());
57
38
 
58
- const selectConfig = computed(() => {
39
+ const tableConfig = computed<FormItem>(() => {
59
40
  const defaultConfig = {
60
- multiple: true,
61
- options: async () => {
62
- const codeDsl = await services?.codeBlockService.getCodeDsl();
63
- if (codeDsl) {
64
- return map(codeDsl, (value, key) => ({
65
- text: `${value.name}(${key})`,
66
- label: `${value.name}(${key})`,
67
- value: key,
68
- }));
69
- }
70
- return [];
71
- },
41
+ dropSort: true,
42
+ enableFullscreen: false,
43
+ border: true,
44
+ items: [
45
+ {
46
+ type: 'select',
47
+ label: '代码块',
48
+ name: 'codeId',
49
+ width: '200px',
50
+ options: () => {
51
+ if (codeDsl.value) {
52
+ return map(codeDsl.value, (value, key) => ({
53
+ text: `${value.name}(${key})`,
54
+ label: `${value.name}(${key})`,
55
+ value: key,
56
+ }));
57
+ }
58
+ return [];
59
+ },
60
+ onChange: (formState: any, codeId: Id, { model }: any) => {
61
+ // 参数的items是根据函数生成的,当codeId变化后修正model的值,避免写入其他codeId的params
62
+ model.params = {};
63
+ },
64
+ },
65
+ {
66
+ name: 'params',
67
+ label: '参数',
68
+ defaultValue: {},
69
+ itemsFunction: (row: HookData) => {
70
+ const paramsConfig = getParamsConfig(row.codeId);
71
+ if (!row.params) row.params = {};
72
+ if (isEmpty(row.params)) {
73
+ createValues(mForm, paramsConfig, {}, row.params);
74
+ }
75
+ return paramsConfig;
76
+ },
77
+ },
78
+ ],
72
79
  };
73
80
  return {
74
81
  ...defaultConfig,
75
- ...props.config.selectConfig,
82
+ ...props.config.tableConfig,
76
83
  };
77
84
  });
78
- const fieldKey = ref('');
79
- const multiple = ref(true);
80
- let lastTagSnapshot = cloneDeep(props.model[props.name]) || [];
81
- let shouldWatch = true;
82
85
 
83
- // 管理端和editor有表现不一致的地方,管理端切换组件表单不会重新渲染,因此增加shouldWatch控制lastTagSnapshot的记录
84
86
  watch(
85
87
  () => props.model[props.name],
86
- (selectValue) => {
87
- if (shouldWatch) {
88
- lastTagSnapshot = cloneDeep(selectValue) || [];
88
+ (value) => {
89
+ // 兼容旧的数据结构
90
+ if (isEmpty(value)) {
91
+ // 空值或者空数组
92
+ props.model[props.name] = {
93
+ hookType: HookType.CODE,
94
+ hookData: [],
95
+ };
89
96
  }
90
97
  },
98
+ {
99
+ immediate: true,
100
+ },
91
101
  );
92
102
 
93
- watchEffect(async () => {
94
- const combineNames = await Promise.all(
95
- props.model[props.name].map(async (id: string) => {
96
- const { name = '' } = (await services?.codeBlockService.getCodeContentById(id)) || {};
97
- return name;
98
- }),
99
- );
100
- fieldKey.value = combineNames.join('-');
101
- });
102
-
103
- const changeHandler = async (value: any) => {
104
- shouldWatch = false;
105
- let codeIds = value;
106
- if (typeof value === 'string') {
107
- multiple.value = false;
108
- lastTagSnapshot = [lastTagSnapshot];
109
- codeIds = value ? [value] : [];
110
- }
111
- await setCombineRelation(codeIds);
112
- emit('change', value);
113
- };
114
-
115
- // 同步绑定关系
116
- const setCombineRelation = async (codeIds: string[]) => {
117
- // 组件id
118
- const { id = '' } = services?.editorService.get('node') || {};
119
-
120
- // 兼容单选
121
- let opFlag = CodeSelectOp.CHANGE;
122
- let diffValues = codeIds;
123
- if (multiple.value) {
124
- opFlag = codeIds.length < lastTagSnapshot.length ? CodeSelectOp.DELETE : CodeSelectOp.ADD;
125
- diffValues = xor(codeIds, lastTagSnapshot) as string[];
126
- }
127
-
128
- // 记录绑定关系
129
- await services?.codeBlockService.setCombineRelation(id, diffValues, opFlag, props.prop);
130
- lastTagSnapshot = codeIds;
131
- shouldWatch = true;
103
+ const changeHandler = async () => {
104
+ emit('change', props.model[props.name]);
132
105
  };
133
106
 
134
- const viewHandler = async () => {
135
- if (props.model[props.name].length === 0) {
136
- tMagicMessage.error('请先绑定代码块');
137
- return;
138
- }
139
- // 记录当前已被绑定的代码块,为查看弹窗的展示内容
140
- await services?.codeBlockService.setCombineIds(props.model[props.name]);
141
- await services?.codeBlockService.setMode(CodeEditorMode.LIST);
142
- services?.codeBlockService.setCodeEditorContent(true, props.model[props.name][0]);
107
+ const getParamsConfig = (codeId: Id) => {
108
+ if (!codeDsl.value) return [];
109
+ const paramStatements = codeDsl.value[codeId]?.params;
110
+ if (isEmpty(paramStatements)) return [];
111
+ return paramStatements.map((paramState: CodeParamStatement) => ({
112
+ name: paramState.name,
113
+ text: paramState.name,
114
+ labelWidth: '100px',
115
+ type: 'text',
116
+ }));
143
117
  };
144
118
  </script>
@@ -12,7 +12,7 @@
12
12
  </div>
13
13
  </template>
14
14
 
15
- <script lang="ts" setup>
15
+ <script lang="ts" setup name="MEditorUISelect">
16
16
  import { computed, inject, ref } from 'vue';
17
17
  import { Close, Delete } from '@element-plus/icons-vue';
18
18
 
package/src/index.ts CHANGED
@@ -48,6 +48,7 @@ export { default as PropsPanel } from './layouts/PropsPanel.vue';
48
48
  export { default as ToolButton } from './components/ToolButton.vue';
49
49
  export { default as ContentMenu } from './components/ContentMenu.vue';
50
50
  export { default as Icon } from './components/Icon.vue';
51
+ export { default as LayoutContainer } from './components/Layout.vue';
51
52
 
52
53
  const defaultInstallOpt: InstallOptions = {
53
54
  // @todo, 自定义图片上传方法等编辑器依赖的外部选项
@@ -11,7 +11,7 @@
11
11
  </div>
12
12
  </template>
13
13
 
14
- <script lang="ts" setup>
14
+ <script lang="ts" setup name="MEditorAddPageBox">
15
15
  import { inject, toRaw } from 'vue';
16
16
  import { Plus } from '@element-plus/icons-vue';
17
17
 
@@ -2,7 +2,7 @@
2
2
  <div ref="codeEditor" class="magic-code-editor"></div>
3
3
  </template>
4
4
 
5
- <script lang="ts" setup>
5
+ <script lang="ts" setup name="MEditorCodeEditor">
6
6
  import { onMounted, onUnmounted, ref, watch } from 'vue';
7
7
  import { throttle } from 'lodash-es';
8
8
  import * as monaco from 'monaco-editor';
@@ -12,7 +12,7 @@ const props = withDefaults(
12
12
  defineProps<{
13
13
  initValues?: string | Object;
14
14
  modifiedValues?: string | Object;
15
- type?: string;
15
+ type?: 'diff';
16
16
  language?: string;
17
17
  options?: {
18
18
  [key: string]: any;
@@ -20,7 +20,6 @@ const props = withDefaults(
20
20
  autoSave?: boolean;
21
21
  }>(),
22
22
  {
23
- type: '',
24
23
  autoSave: true,
25
24
  language: 'javascript',
26
25
  options: () => ({
@@ -42,16 +42,16 @@
42
42
  </div>
43
43
  </template>
44
44
 
45
- <script lang="ts" setup>
45
+ <script lang="ts" setup name="MEditorFramework">
46
46
  import { computed, inject, ref, watch } from 'vue';
47
47
 
48
48
  import { TMagicScrollbar } from '@tmagic/design';
49
49
  import type { MApp } from '@tmagic/schema';
50
50
 
51
+ import Layout from '../components/Layout.vue';
51
52
  import { GetColumnWidth, Services } from '../type';
52
53
 
53
54
  import AddPageBox from './AddPageBox.vue';
54
- import Layout from './Layout.vue';
55
55
 
56
56
  const DEFAULT_LEFT_COLUMN_WIDTH = 310;
57
57
  const DEFAULT_RIGHT_COLUMN_WIDTH = 480;
@@ -1,12 +1,12 @@
1
1
  <template>
2
2
  <div class="m-editor-nav-menu" :style="{ height: `${height}px` }">
3
3
  <div v-for="key in keys" :class="`menu-${key}`" :key="key" :style="`width: ${columnWidth?.[key]}px`">
4
- <tool-button :data="item" v-for="(item, index) in buttons[key]" :key="index"></tool-button>
4
+ <ToolButton :data="item" v-for="(item, index) in buttons[key]" :key="index"></ToolButton>
5
5
  </div>
6
6
  </div>
7
7
  </template>
8
8
 
9
- <script lang="ts" setup>
9
+ <script lang="ts" setup name="MEditorNavMenu">
10
10
  import { computed, inject, markRaw } from 'vue';
11
11
  import { Back, Delete, FullScreen, Grid, Memo, Right, ScaleToOriginal, ZoomIn, ZoomOut } from '@element-plus/icons-vue';
12
12
 
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div class="m-editor-props-panel">
3
3
  <slot name="props-panel-header"></slot>
4
- <m-form
4
+ <MForm
5
5
  ref="configForm"
6
6
  :class="`m-editor-props-panel ${propsPanelSize}`"
7
7
  :popper-class="`m-editor-props-panel-popper ${propsPanelSize}`"
@@ -9,15 +9,16 @@
9
9
  :init-values="values"
10
10
  :config="curFormConfig"
11
11
  @change="submit"
12
- ></m-form>
12
+ ></MForm>
13
13
  </div>
14
14
  </template>
15
15
 
16
- <script lang="ts" setup>
17
- import { computed, getCurrentInstance, inject, onMounted, ref, watchEffect } from 'vue';
16
+ <script lang="ts" setup name="MEditorPropsPanel">
17
+ import { computed, getCurrentInstance, inject, onMounted, onUnmounted, ref, watchEffect } from 'vue';
18
18
 
19
19
  import { tMagicMessage } from '@tmagic/design';
20
- import type { FormValue, MForm } from '@tmagic/form';
20
+ import type { FormValue } from '@tmagic/form';
21
+ import { MForm } from '@tmagic/form';
21
22
  import type { MNode } from '@tmagic/schema';
22
23
  import type StageCore from '@tmagic/stage';
23
24
 
@@ -32,7 +33,9 @@ const configForm = ref<InstanceType<typeof MForm>>();
32
33
  const curFormConfig = ref<any>([]);
33
34
  const services = inject<Services>('services');
34
35
  const node = computed(() => services?.editorService.get<MNode | null>('node'));
35
- const propsPanelSize = computed(() => services?.uiService.get('propsPanelSize') || 'small');
36
+ const propsPanelSize = computed(
37
+ () => services?.uiService.get<'large' | 'default' | 'small'>('propsPanelSize') || 'small',
38
+ );
36
39
  const stage = computed(() => services?.editorService.get<StageCore>('stage'));
37
40
 
38
41
  const init = async () => {
@@ -53,6 +56,10 @@ onMounted(() => {
53
56
  emit('mounted', internalInstance);
54
57
  });
55
58
 
59
+ onUnmounted(() => {
60
+ services?.propsService.off('props-configs-change', init);
61
+ });
62
+
56
63
  watchEffect(() => {
57
64
  if (configForm.value && stage.value) {
58
65
  configForm.value.formState.stage = stage.value;
@@ -4,7 +4,7 @@
4
4
  </span>
5
5
  </template>
6
6
 
7
- <script lang="ts" setup>
7
+ <script lang="ts" setup name="MEditorResizer">
8
8
  import { onMounted, onUnmounted, ref } from 'vue';
9
9
  import Gesto from 'gesto';
10
10
 
@@ -38,7 +38,7 @@
38
38
  </TMagicScrollbar>
39
39
  </template>
40
40
 
41
- <script lang="ts" setup>
41
+ <script lang="ts" setup name="MEditorComponentListPanel">
42
42
  import { computed, inject, ref } from 'vue';
43
43
  import { Grid, Search } from '@element-plus/icons-vue';
44
44
  import serialize from 'serialize-javascript';
@@ -1,16 +1,20 @@
1
1
  <template>
2
- <content-menu :menu-data="menuData" ref="menu" style="overflow: initial"></content-menu>
2
+ <ContentMenu :menu-data="menuData" ref="menu" style="overflow: initial"></ContentMenu>
3
3
  </template>
4
4
 
5
- <script lang="ts" setup>
5
+ <script lang="ts" setup name="MEditorLayerMenu">
6
6
  import { computed, inject, markRaw, ref } from 'vue';
7
- import { Delete, DocumentCopy, Files, Plus } from '@element-plus/icons-vue';
7
+ import { CopyDocument, Delete, Files, Plus } from '@element-plus/icons-vue';
8
8
 
9
9
  import { NodeType } from '@tmagic/schema';
10
10
 
11
11
  import ContentMenu from '../../components/ContentMenu.vue';
12
12
  import type { ComponentGroup, MenuButton, MenuComponent, Services } from '../../type';
13
13
 
14
+ const props = defineProps<{
15
+ layerContentMenu: (MenuButton | MenuComponent)[];
16
+ }>();
17
+
14
18
  const services = inject<Services>('services');
15
19
  const menu = ref<InstanceType<typeof ContentMenu>>();
16
20
  const node = computed(() => services?.editorService.get('node'));
@@ -18,8 +22,6 @@ const isRoot = computed(() => node.value?.type === NodeType.ROOT);
18
22
  const isPage = computed(() => node.value?.type === NodeType.PAGE);
19
23
  const componentList = computed(() => services?.componentListService.getList() || []);
20
24
 
21
- const layerContentMenu = inject<(MenuComponent | MenuButton)[]>('layerContentMenu', []);
22
-
23
25
  const createMenuItems = (group: ComponentGroup): MenuButton[] =>
24
26
  group.items.map((component) => ({
25
27
  text: component.text,
@@ -82,7 +84,7 @@ const menuData = computed<(MenuButton | MenuComponent)[]>(() => [
82
84
  {
83
85
  type: 'button',
84
86
  text: '复制',
85
- icon: markRaw(DocumentCopy),
87
+ icon: markRaw(CopyDocument),
86
88
  display: () => !isRoot.value,
87
89
  handler: () => {
88
90
  node.value && services?.editorService.copy(node.value);
@@ -97,7 +99,7 @@ const menuData = computed<(MenuButton | MenuComponent)[]>(() => [
97
99
  node.value && services?.editorService.remove(node.value);
98
100
  },
99
101
  },
100
- ...layerContentMenu,
102
+ ...props.layerContentMenu,
101
103
  ]);
102
104
 
103
105
  const show = (e: MouseEvent) => {