@tmagic/editor 1.0.0-beta.9 → 1.0.0-rc.1

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 (117) hide show
  1. package/README.md +1 -0
  2. package/coverage/clover.xml +1560 -0
  3. package/coverage/coverage-final.json +36 -0
  4. package/coverage/lcov-report/base.css +224 -0
  5. package/coverage/lcov-report/block-navigation.js +87 -0
  6. package/coverage/lcov-report/favicon.png +0 -0
  7. package/coverage/lcov-report/index.html +206 -0
  8. package/coverage/lcov-report/prettify.css +1 -0
  9. package/coverage/lcov-report/prettify.js +2 -0
  10. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  11. package/coverage/lcov-report/sorter.js +196 -0
  12. package/coverage/lcov-report/src/Editor.vue.html +787 -0
  13. package/coverage/lcov-report/src/components/ContentMenu.vue.html +406 -0
  14. package/coverage/lcov-report/src/components/Icon.vue.html +172 -0
  15. package/coverage/lcov-report/src/components/ScrollViewer.vue.html +283 -0
  16. package/coverage/lcov-report/src/components/ToolButton.vue.html +772 -0
  17. package/coverage/lcov-report/src/components/index.html +161 -0
  18. package/coverage/lcov-report/src/index.html +131 -0
  19. package/coverage/lcov-report/src/layouts/AddPageBox.vue.html +214 -0
  20. package/coverage/lcov-report/src/layouts/Framework.vue.html +304 -0
  21. package/coverage/lcov-report/src/layouts/NavMenu.vue.html +208 -0
  22. package/coverage/lcov-report/src/layouts/PropsPanel.vue.html +319 -0
  23. package/coverage/lcov-report/src/layouts/Resizer.vue.html +268 -0
  24. package/coverage/lcov-report/src/layouts/index.html +176 -0
  25. package/coverage/lcov-report/src/layouts/sidebar/ComponentListPanel.vue.html +358 -0
  26. package/coverage/lcov-report/src/layouts/sidebar/LayerMenu.vue.html +421 -0
  27. package/coverage/lcov-report/src/layouts/sidebar/LayerPanel.vue.html +775 -0
  28. package/coverage/lcov-report/src/layouts/sidebar/Sidebar.vue.html +226 -0
  29. package/coverage/lcov-report/src/layouts/sidebar/TabPane.vue.html +289 -0
  30. package/coverage/lcov-report/src/layouts/sidebar/index.html +176 -0
  31. package/coverage/lcov-report/src/layouts/workspace/PageBar.vue.html +718 -0
  32. package/coverage/lcov-report/src/layouts/workspace/Stage.vue.html +757 -0
  33. package/coverage/lcov-report/src/layouts/workspace/ViewerMenu.vue.html +532 -0
  34. package/coverage/lcov-report/src/layouts/workspace/Workspace.vue.html +586 -0
  35. package/coverage/lcov-report/src/layouts/workspace/index.html +161 -0
  36. package/coverage/lcov-report/src/services/BaseService.ts.html +643 -0
  37. package/coverage/lcov-report/src/services/componentList.ts.html +229 -0
  38. package/coverage/lcov-report/src/services/editor.ts.html +2077 -0
  39. package/coverage/lcov-report/src/services/events.ts.html +331 -0
  40. package/coverage/lcov-report/src/services/history.ts.html +478 -0
  41. package/coverage/lcov-report/src/services/index.html +206 -0
  42. package/coverage/lcov-report/src/services/props.ts.html +415 -0
  43. package/coverage/lcov-report/src/services/ui.ts.html +580 -0
  44. package/coverage/lcov-report/src/type.ts.html +850 -0
  45. package/coverage/lcov-report/src/utils/compose.ts.html +184 -0
  46. package/coverage/lcov-report/src/utils/config.ts.html +172 -0
  47. package/coverage/lcov-report/src/utils/editor.ts.html +838 -0
  48. package/coverage/lcov-report/src/utils/index.html +221 -0
  49. package/coverage/lcov-report/src/utils/index.ts.html +151 -0
  50. package/coverage/lcov-report/src/utils/logger.ts.html +226 -0
  51. package/coverage/lcov-report/src/utils/props.ts.html +796 -0
  52. package/coverage/lcov-report/src/utils/scroll-viewer.ts.html +733 -0
  53. package/coverage/lcov-report/src/utils/undo-redo.ts.html +313 -0
  54. package/coverage/lcov.info +3708 -0
  55. package/dist/style.css +65 -33
  56. package/dist/tmagic-editor.es.js +1379 -806
  57. package/dist/tmagic-editor.es.js.map +1 -1
  58. package/dist/tmagic-editor.umd.js +1381 -808
  59. package/dist/tmagic-editor.umd.js.map +1 -1
  60. package/dist/types/src/Editor.vue.d.ts +1 -1
  61. package/dist/types/src/components/ToolButton.vue.d.ts +12 -1
  62. package/dist/types/src/fields/UISelect.vue.d.ts +4 -1
  63. package/dist/types/src/index.d.ts +1 -0
  64. package/dist/types/src/layouts/CodeEditor.vue.d.ts +13 -4
  65. package/dist/types/src/layouts/PropsPanel.vue.d.ts +2 -1
  66. package/dist/types/src/layouts/sidebar/ComponentListPanel.vue.d.ts +2 -1
  67. package/dist/types/src/layouts/sidebar/Sidebar.vue.d.ts +2 -3
  68. package/dist/types/src/layouts/sidebar/TabPane.vue.d.ts +14 -0
  69. package/dist/types/src/layouts/workspace/PageBar.vue.d.ts +10 -3
  70. package/dist/types/src/layouts/workspace/Workspace.vue.d.ts +4 -7
  71. package/dist/types/src/services/BaseService.d.ts +4 -1
  72. package/dist/types/src/services/editor.d.ts +5 -2
  73. package/dist/types/src/services/history.d.ts +1 -0
  74. package/dist/types/src/services/props.d.ts +2 -2
  75. package/dist/types/src/services/ui.d.ts +2 -0
  76. package/dist/types/src/type.d.ts +15 -9
  77. package/dist/types/src/utils/editor.d.ts +4 -3
  78. package/dist/types/src/utils/polyfills.d.ts +0 -0
  79. package/package.json +36 -12
  80. package/src/components/ContentMenu.vue +107 -0
  81. package/src/components/ScrollViewer.vue +1 -1
  82. package/src/components/ToolButton.vue +69 -30
  83. package/src/fields/UISelect.vue +14 -6
  84. package/src/index.ts +2 -0
  85. package/src/layouts/CodeEditor.vue +20 -10
  86. package/src/layouts/Framework.vue +6 -6
  87. package/src/layouts/PropsPanel.vue +4 -3
  88. package/src/layouts/sidebar/ComponentListPanel.vue +25 -3
  89. package/src/layouts/sidebar/LayerMenu.vue +91 -96
  90. package/src/layouts/sidebar/LayerPanel.vue +31 -54
  91. package/src/layouts/sidebar/Sidebar.vue +13 -52
  92. package/src/layouts/sidebar/TabPane.vue +68 -0
  93. package/src/layouts/workspace/PageBar.vue +136 -13
  94. package/src/layouts/workspace/Stage.vue +50 -75
  95. package/src/layouts/workspace/ViewerMenu.vue +104 -67
  96. package/src/layouts/workspace/Workspace.vue +106 -23
  97. package/src/services/BaseService.ts +70 -22
  98. package/src/services/editor.ts +148 -39
  99. package/src/services/history.ts +7 -0
  100. package/src/services/props.ts +3 -3
  101. package/src/services/ui.ts +35 -5
  102. package/src/theme/common/var.scss +1 -0
  103. package/src/theme/component-list-panel.scss +2 -0
  104. package/src/theme/content-menu.scss +33 -26
  105. package/src/theme/layer-panel.scss +2 -1
  106. package/src/theme/nav-menu.scss +6 -2
  107. package/src/theme/page-bar.scss +35 -3
  108. package/src/theme/props-panel.scss +13 -13
  109. package/src/type.ts +16 -9
  110. package/src/utils/editor.ts +31 -6
  111. package/{vite.config.ts → src/utils/polyfills.ts} +4 -12
  112. package/src/utils/props.ts +20 -1
  113. package/dist/types/src/layouts/sidebar/LayerMenu.vue.d.ts +0 -31
  114. package/dist/types/src/layouts/sidebar/LayerPanel.vue.d.ts +0 -979
  115. package/dist/types/src/layouts/workspace/Stage.vue.d.ts +0 -193
  116. package/dist/types/src/layouts/workspace/ViewerMenu.vue.d.ts +0 -18
  117. package/tsconfig.json +0 -9
@@ -1,24 +1,37 @@
1
1
  <template>
2
- <div v-if="display" class="menu-item">
3
- <el-divider v-if="item.type === 'divider'" direction="vertical"></el-divider>
2
+ <div
3
+ v-if="display"
4
+ class="menu-item"
5
+ :class="item.type"
6
+ @click="clickHandler(item, $event)"
7
+ @mousedown="mousedownHandler(item, $event)"
8
+ @mouseup="mouseupHandler(item, $event)"
9
+ >
10
+ <el-divider v-if="item.type === 'divider'" :direction="item.direction || 'vertical'"></el-divider>
4
11
  <div v-else-if="item.type === 'text'" class="menu-item-text">{{ item.text }}</div>
5
12
 
6
13
  <template v-else-if="item.type === 'zoom'">
7
- <m-icon :icon="ZoomIn" @click="zoomInHandler"></m-icon>
14
+ <tool-button
15
+ :data="{ type: 'button', icon: ZoomOut, handler: zoomOutHandler, tooltip: '缩小' }"
16
+ :event-type="eventType"
17
+ ></tool-button>
8
18
  <span class="menu-item-text" style="margin: 0 5px">{{ parseInt(`${zoom * 100}`, 10) }}%</span>
9
- <m-icon :icon="ZoomOut" @click="zoomOutHandler"></m-icon>
19
+ <tool-button
20
+ :data="{ type: 'button', icon: ZoomIn, handler: zoomInHandler, tooltip: '放大' }"
21
+ :event-type="eventType"
22
+ ></tool-button>
10
23
  </template>
11
24
 
12
- <el-tooltip
13
- v-else-if="item.type === 'button'"
14
- effect="dark"
15
- placement="bottom-start"
16
- :content="item.tooltip || item.text"
17
- >
18
- <el-button size="small" type="text" :disabled="disabled" @click="buttonHandler(item)"
19
- ><m-icon :icon="item.icon"></m-icon><span>{{ item.text }}</span></el-button
25
+ <template v-else-if="item.type === 'button'">
26
+ <el-tooltip v-if="item.tooltip" effect="dark" placement="bottom-start" :content="item.tooltip">
27
+ <el-button size="small" text :disabled="disabled"
28
+ ><m-icon v-if="item.icon" :icon="item.icon"></m-icon><span>{{ item.text }}</span></el-button
29
+ >
30
+ </el-tooltip>
31
+ <el-button v-else size="small" text :disabled="disabled"
32
+ ><m-icon v-if="item.icon" :icon="item.icon"></m-icon><span>{{ item.text }}</span></el-button
20
33
  >
21
- </el-tooltip>
34
+ </template>
22
35
 
23
36
  <el-dropdown v-else-if="item.type === 'dropdown'" trigger="click" :disabled="disabled" @command="dropdownHandler">
24
37
  <span class="el-dropdown-link menubar-menu-button">
@@ -38,7 +51,7 @@
38
51
  </template>
39
52
 
40
53
  <script lang="ts">
41
- import { computed, defineComponent, inject, PropType } from 'vue';
54
+ import { computed, defineComponent, inject, markRaw, PropType } from 'vue';
42
55
  import { ArrowDown, Back, Delete, Grid, Right, ScaleToOriginal, ZoomIn, ZoomOut } from '@element-plus/icons';
43
56
 
44
57
  import { NodeType } from '@tmagic/schema';
@@ -58,19 +71,24 @@ export default defineComponent({
58
71
  display: false,
59
72
  }),
60
73
  },
74
+
75
+ eventType: {
76
+ type: String as PropType<'mousedown' | 'mouseup' | 'click'>,
77
+ default: 'click',
78
+ },
61
79
  },
62
80
 
63
81
  setup(props) {
64
82
  const services = inject<Services>('services');
65
83
  const uiService = services?.uiService;
66
84
 
67
- const zoomInHandler = () => uiService?.set('zoom', zoom.value + 0.1);
68
- const zoomOutHandler = () => uiService?.set('zoom', zoom.value - 0.1);
69
-
70
85
  const zoom = computed((): number => uiService?.get<number>('zoom') ?? 1);
71
86
  const showGuides = computed((): boolean => uiService?.get<boolean>('showGuides') ?? true);
72
87
  const showRule = computed((): boolean => uiService?.get<boolean>('showRule') ?? true);
73
88
 
89
+ const zoomInHandler = () => uiService?.zoom(0.1);
90
+ const zoomOutHandler = () => uiService?.zoom(-0.1);
91
+
74
92
  const item = computed((): MenuButton | MenuComponent => {
75
93
  if (typeof props.data !== 'string') {
76
94
  return props.data;
@@ -87,7 +105,7 @@ export default defineComponent({
87
105
  case 'delete':
88
106
  return {
89
107
  type: 'button',
90
- icon: Delete,
108
+ icon: markRaw(Delete),
91
109
  tooltip: '刪除',
92
110
  disabled: () => services?.editorService.get('node')?.type === NodeType.PAGE,
93
111
  handler: () => services?.editorService.remove(services?.editorService.get('node')),
@@ -95,7 +113,7 @@ export default defineComponent({
95
113
  case 'undo':
96
114
  return {
97
115
  type: 'button',
98
- icon: Back,
116
+ icon: markRaw(Back),
99
117
  tooltip: '后退',
100
118
  disabled: () => !services?.historyService.state.canUndo,
101
119
  handler: () => services?.editorService.undo(),
@@ -103,7 +121,7 @@ export default defineComponent({
103
121
  case 'redo':
104
122
  return {
105
123
  type: 'button',
106
- icon: Right,
124
+ icon: markRaw(Right),
107
125
  tooltip: '前进',
108
126
  disabled: () => !services?.historyService.state.canRedo,
109
127
  handler: () => services?.editorService.redo(),
@@ -111,28 +129,28 @@ export default defineComponent({
111
129
  case 'zoom-in':
112
130
  return {
113
131
  type: 'button',
114
- icon: ZoomIn,
132
+ icon: markRaw(ZoomIn),
115
133
  tooltip: '放大',
116
134
  handler: zoomInHandler,
117
135
  };
118
136
  case 'zoom-out':
119
137
  return {
120
138
  type: 'button',
121
- icon: ZoomOut,
139
+ icon: markRaw(ZoomOut),
122
140
  tooltip: '縮小',
123
141
  handler: zoomOutHandler,
124
142
  };
125
143
  case 'rule':
126
144
  return {
127
145
  type: 'button',
128
- icon: ScaleToOriginal,
146
+ icon: markRaw(ScaleToOriginal),
129
147
  tooltip: showRule.value ? '隐藏标尺' : '显示标尺',
130
148
  handler: () => uiService?.set('showRule', !showRule.value),
131
149
  };
132
150
  case 'guides':
133
151
  return {
134
152
  type: 'button',
135
- icon: Grid,
153
+ icon: markRaw(Grid),
136
154
  tooltip: showGuides.value ? '隐藏参考线' : '显示参考线',
137
155
  handler: () => uiService?.set('showGuides', !showGuides.value),
138
156
  };
@@ -153,9 +171,16 @@ export default defineComponent({
153
171
  return item.value.disabled;
154
172
  });
155
173
 
174
+ const buttonHandler = (item: MenuButton | MenuComponent, event: MouseEvent) => {
175
+ if (disabled.value) return;
176
+ if (typeof (item as MenuButton).handler === 'function' && services) {
177
+ (item as MenuButton).handler?.(services, event);
178
+ }
179
+ };
180
+
156
181
  return {
157
- ZoomIn,
158
- ZoomOut,
182
+ ZoomIn: markRaw(ZoomIn),
183
+ ZoomOut: markRaw(ZoomOut),
159
184
 
160
185
  item,
161
186
  zoom,
@@ -178,10 +203,24 @@ export default defineComponent({
178
203
  }
179
204
  },
180
205
 
181
- buttonHandler(item: MenuButton | MenuComponent) {
182
- if (disabled.value) return;
183
- if (typeof (item as MenuButton).handler === 'function') {
184
- (item as MenuButton).handler?.(services);
206
+ clickHandler(item: MenuButton | MenuComponent, event: MouseEvent) {
207
+ if (props.eventType !== 'click') return;
208
+ if (item.type === 'button') {
209
+ buttonHandler(item, event);
210
+ }
211
+ },
212
+
213
+ mousedownHandler(item: MenuButton | MenuComponent, event: MouseEvent) {
214
+ if (props.eventType !== 'mousedown') return;
215
+ if (item.type === 'button') {
216
+ buttonHandler(item, event);
217
+ }
218
+ },
219
+
220
+ mouseupHandler(item: MenuButton | MenuComponent, event: MouseEvent) {
221
+ if (props.eventType !== 'mouseup') return;
222
+ if (item.type === 'button') {
223
+ buttonHandler(item, event);
185
224
  }
186
225
  },
187
226
  };
@@ -1,16 +1,20 @@
1
1
  <template>
2
2
  <div class="m-fields-ui-select" v-if="uiSelectMode" @click="cancelHandler">
3
- <i class="el-icon-delete" style="color: rgb(221, 75, 57)">取消</i>
3
+ <el-button type="danger" :icon="Delete" text style="padding: 0">取消</el-button>
4
4
  </div>
5
- <div class="m-fields-ui-select" v-else @click="startSelect">
6
- <i class="el-icon-thumb"></i>
7
- <span>{{ val ? toName + '_' + val : '点击此处选择' }}</span>
8
- <i class="el-icon-delete" @click.stop="deleteHandler" v-if="val"></i>
5
+ <div class="m-fields-ui-select" v-else @click="startSelect" style="display: flex">
6
+ <el-tooltip content="清除">
7
+ <el-button v-if="val" style="padding: 0" type="danger" :icon="Close" text @click.stop="deleteHandler"></el-button>
8
+ </el-tooltip>
9
+ <el-tooltip :content="val ? toName + '_' + val : '点击此处选择'">
10
+ <el-button text style="padding: 0; margin: 0">{{ val ? toName + '_' + val : '点击此处选择' }}</el-button>
11
+ </el-tooltip>
9
12
  </div>
10
13
  </template>
11
14
 
12
15
  <script lang="ts">
13
- import { computed, defineComponent, inject, ref } from 'vue';
16
+ import { computed, defineComponent, inject, markRaw, ref } from 'vue';
17
+ import { Close, Delete, Pointer } from '@element-plus/icons';
14
18
 
15
19
  import { FormState } from '@tmagic/form';
16
20
 
@@ -60,6 +64,10 @@ export default defineComponent({
60
64
  };
61
65
 
62
66
  return {
67
+ Delete: markRaw(Delete),
68
+ Pointer: markRaw(Pointer),
69
+ Close: markRaw(Close),
70
+
63
71
  val,
64
72
  uiSelectMode,
65
73
  toName: computed(() => {
package/src/index.ts CHANGED
@@ -15,6 +15,7 @@
15
15
  * See the License for the specific language governing permissions and
16
16
  * limitations under the License.
17
17
  */
18
+ import './utils/polyfills';
18
19
 
19
20
  import { App } from 'vue';
20
21
 
@@ -41,6 +42,7 @@ export { default as uiService } from './services/ui';
41
42
  export { default as ComponentListPanel } from './layouts/sidebar/ComponentListPanel.vue';
42
43
  export { default as LayerPanel } from './layouts/sidebar/LayerPanel.vue';
43
44
  export { default as PropsPanel } from './layouts/PropsPanel.vue';
45
+ export { default as ToolButton } from './components/ToolButton.vue';
44
46
 
45
47
  const defaultInstallOpt: InstallOptions = {
46
48
  // @todo, 自定义图片上传方法等编辑器依赖的外部选项
@@ -4,6 +4,7 @@
4
4
 
5
5
  <script lang="ts">
6
6
  import { defineComponent, onMounted, onUnmounted, ref, watch } from 'vue';
7
+ import { throttle } from 'lodash-es';
7
8
  import * as monaco from 'monaco-editor';
8
9
  import serialize from 'serialize-javascript';
9
10
 
@@ -36,14 +37,19 @@ export default defineComponent({
36
37
  },
37
38
 
38
39
  type: {
39
- type: [String],
40
+ type: String,
40
41
  default: () => '',
41
42
  },
42
43
 
43
44
  language: {
44
- type: [String],
45
+ type: String,
45
46
  default: () => 'javascript',
46
47
  },
48
+
49
+ options: {
50
+ type: Object,
51
+ default: () => ({}),
52
+ },
47
53
  },
48
54
 
49
55
  emits: ['initd', 'save'],
@@ -51,10 +57,18 @@ export default defineComponent({
51
57
  setup(props, { emit }) {
52
58
  let vsEditor: monaco.editor.IStandaloneCodeEditor | null = null;
53
59
  let vsDiffEditor: monaco.editor.IStandaloneDiffEditor | null = null;
60
+
54
61
  const values = ref('');
55
62
  const loading = ref(false);
56
63
  const codeEditor = ref<HTMLDivElement>();
57
64
 
65
+ const resizeObserver = new globalThis.ResizeObserver(
66
+ throttle((): void => {
67
+ vsEditor?.layout();
68
+ vsDiffEditor?.layout();
69
+ }, 300),
70
+ );
71
+
58
72
  const setEditorValue = (v: string | any, m: string | any) => {
59
73
  values.value = toString(v, props.language);
60
74
 
@@ -71,11 +85,6 @@ export default defineComponent({
71
85
  return vsEditor?.setValue(values.value);
72
86
  };
73
87
 
74
- const resizeHandler = () => {
75
- vsEditor?.layout();
76
- vsDiffEditor?.layout();
77
- };
78
-
79
88
  const getEditorValue = () =>
80
89
  props.type === 'diff' ? vsDiffEditor?.getModifiedEditor().getValue() : vsEditor?.getValue();
81
90
 
@@ -88,8 +97,9 @@ export default defineComponent({
88
97
  tabSize: 2,
89
98
  theme: 'vs-dark',
90
99
  fontFamily: 'dm, Menlo, Monaco, "Courier New", monospace',
91
- fontSize: 15,
100
+ fontSize: 14,
92
101
  formatOnPaste: true,
102
+ ...props.options,
93
103
  };
94
104
 
95
105
  if (props.type === 'diff') {
@@ -117,7 +127,7 @@ export default defineComponent({
117
127
  });
118
128
  }
119
129
 
120
- globalThis.addEventListener('resize', resizeHandler);
130
+ resizeObserver.observe(codeEditor.value);
121
131
  };
122
132
 
123
133
  watch(
@@ -140,7 +150,7 @@ export default defineComponent({
140
150
  });
141
151
 
142
152
  onUnmounted(() => {
143
- globalThis.removeEventListener('resize', resizeHandler);
153
+ resizeObserver.disconnect();
144
154
  });
145
155
 
146
156
  return {
@@ -49,20 +49,20 @@ export default defineComponent({
49
49
  },
50
50
 
51
51
  setup() {
52
- const services = inject<Services>('services');
52
+ const { editorService, uiService } = inject<Services>('services') || {};
53
53
 
54
- const root = computed(() => services?.editorService.get<MApp>('root'));
54
+ const root = computed(() => editorService?.get<MApp>('root'));
55
55
 
56
56
  return {
57
57
  root,
58
- pageLength: computed(() => root.value?.items?.length || 0),
59
- showSrc: computed(() => services?.uiService.get<boolean>('showSrc')),
60
- columnWidth: computed(() => services?.uiService.get<GetColumnWidth>('columnWidth')),
58
+ pageLength: computed(() => editorService?.get<number>('pageLength') || 0),
59
+ showSrc: computed(() => uiService?.get<boolean>('showSrc')),
60
+ columnWidth: computed(() => uiService?.get<GetColumnWidth>('columnWidth')),
61
61
 
62
62
  saveCode(value: string) {
63
63
  try {
64
64
  // eslint-disable-next-line no-eval
65
- services?.editorService.set('root', eval(value));
65
+ editorService?.set('root', eval(value));
66
66
  } catch (e: any) {
67
67
  console.error(e);
68
68
  }
@@ -1,9 +1,9 @@
1
1
  <template>
2
2
  <m-form
3
- class="m-editor-props-panel"
3
+ :class="`m-editor-props-panel ${propsPanelSize}`"
4
4
  popper-class="m-editor-props-panel-popper"
5
5
  ref="configForm"
6
- size="small"
6
+ :size="propsPanelSize"
7
7
  :init-values="values"
8
8
  :config="curFormConfig"
9
9
  @change="submit"
@@ -39,9 +39,9 @@ export default defineComponent({
39
39
  return;
40
40
  }
41
41
 
42
- values.value = node.value;
43
42
  const type = node.value.type || (node.value.items ? 'container' : 'text');
44
43
  curFormConfig.value = (await services?.propsService.getPropsConfig(type)) || [];
44
+ values.value = node.value;
45
45
  };
46
46
 
47
47
  watchEffect(init);
@@ -55,6 +55,7 @@ export default defineComponent({
55
55
  values,
56
56
  configForm,
57
57
  curFormConfig,
58
+ propsPanelSize: computed(() => services?.uiService.get('propsPanelSize') || 'small'),
58
59
 
59
60
  async submit() {
60
61
  try {
@@ -12,7 +12,14 @@
12
12
  <template v-for="(group, index) in list">
13
13
  <el-collapse-item v-if="group.items && group.items.length" :key="index" :name="index">
14
14
  <template #title><i class="el-icon-s-grid"></i>{{ group.title }}</template>
15
- <div class="component-item" v-for="item in group.items" :key="item.type" @click="appendComponent(item)">
15
+ <div
16
+ class="component-item"
17
+ v-for="item in group.items"
18
+ draggable="true"
19
+ :key="item.type"
20
+ @click="appendComponent(item)"
21
+ @dragstart="dragstartHandler(item, $event)"
22
+ >
16
23
  <m-icon :icon="item.icon"></m-icon>
17
24
 
18
25
  <el-tooltip effect="dark" placement="bottom" :content="item.text">
@@ -27,6 +34,7 @@
27
34
 
28
35
  <script lang="ts">
29
36
  import { computed, defineComponent, inject, ref } from 'vue';
37
+ import serialize from 'serialize-javascript';
30
38
 
31
39
  import MIcon from '@editor/components/Icon.vue';
32
40
  import type { ComponentGroup, ComponentItem, Services } from '@editor/type';
@@ -56,13 +64,27 @@ export default defineComponent({
56
64
  collapseValue,
57
65
  list,
58
66
 
59
- appendComponent({ text, type, ...config }: ComponentItem): void {
67
+ appendComponent({ text, type, data = {} }: ComponentItem): void {
60
68
  services?.editorService.add({
61
69
  name: text,
62
70
  type,
63
- ...config,
71
+ ...data,
64
72
  });
65
73
  },
74
+
75
+ dragstartHandler({ text, type, data = {} }: ComponentItem, e: DragEvent) {
76
+ if (e.dataTransfer) {
77
+ e.dataTransfer.effectAllowed = 'move';
78
+ e.dataTransfer.setData(
79
+ 'data',
80
+ serialize({
81
+ name: text,
82
+ type,
83
+ ...data,
84
+ }).replace(/"(\w+)":\s/g, '$1: '),
85
+ );
86
+ }
87
+ },
66
88
  };
67
89
  },
68
90
  });
@@ -1,115 +1,110 @@
1
1
  <template>
2
- <div v-if="node" class="magic-editor-content-menu">
3
- <div
4
- v-if="node.items"
5
- class="magic-editor-content-menu-item"
6
- @mouseenter="setSubVisiable(true)"
7
- @mouseleave="setSubVisiable(false)"
8
- >
9
- 新增
10
- </div>
11
- <div v-if="node.type !== 'app'" class="magic-editor-content-menu-item" @click="() => copy(node)">复制</div>
12
- <div
13
- v-if="node.type !== 'app' && node.type !== 'page'"
14
- class="magic-editor-content-menu-item"
15
- @click="() => remove()"
16
- >
17
- 删除
18
- </div>
19
- <div class="subMenu" v-show="subVisible" @mouseenter="setSubVisiable(true)" @mouseleave="setSubVisiable(false)">
20
- <el-scrollbar>
21
- <template v-if="node.type === 'tabs'">
22
- <div
23
- class="magic-editor-content-menu-item"
24
- @click="
25
- () =>
26
- append({
27
- type: 'tab-pane',
28
- })
29
- "
30
- >
31
- 标签
32
- </div>
33
- </template>
34
-
35
- <template v-else-if="node.type === 'app'">
36
- <div
37
- class="magic-editor-content-menu-item"
38
- v-for="item in menu.app"
39
- :key="item.type"
40
- @click="() => append(item)"
41
- >
42
- {{ item.text }}
43
- </div>
44
- </template>
45
-
46
- <template v-else-if="node.items">
47
- <div v-for="list in menu.component" :key="list.title">
48
- <template v-for="item in list.items">
49
- <div class="magic-editor-content-menu-item" v-if="item" :key="item.type" @click="() => append(item)">
50
- {{ item.text }}
51
- </div>
52
- </template>
53
- <div class="separation"></div>
54
- </div>
55
- </template>
56
- </el-scrollbar>
57
- </div>
58
- </div>
2
+ <content-menu :menu-data="menuData" ref="menu" style="overflow: initial"></content-menu>
59
3
  </template>
60
4
 
61
5
  <script lang="ts">
62
- import { computed, defineComponent, inject, PropType, ref } from 'vue';
6
+ import { computed, defineComponent, inject, markRaw, ref } from 'vue';
7
+ import { Delete, DocumentCopy, Files, Plus } from '@element-plus/icons';
63
8
 
64
- import type { ComponentGroup, Services } from '@editor/type';
9
+ import { NodeType } from '@tmagic/schema';
65
10
 
66
- export default defineComponent({
67
- name: 'magic-editor-content-menu',
11
+ import ContentMenu from '@editor/components/ContentMenu.vue';
12
+ import type { ComponentGroup, MenuButton, MenuItem, Services } from '@editor/type';
68
13
 
69
- props: {
70
- componentGroupList: {
71
- type: Array as PropType<ComponentGroup[]>,
72
- default: () => [],
73
- },
74
- },
14
+ export default defineComponent({
15
+ components: { ContentMenu },
75
16
 
76
- setup(props) {
17
+ setup() {
77
18
  const services = inject<Services>('services');
78
- const subVisible = ref(false);
19
+ const menu = ref<InstanceType<typeof ContentMenu>>();
79
20
  const node = computed(() => services?.editorService.get('node'));
21
+ const isRoot = computed(() => node.value?.type === NodeType.ROOT);
22
+ const isPage = computed(() => node.value?.type === NodeType.PAGE);
23
+ const componentList = computed(() => services?.componentListService.getList() || []);
80
24
 
81
- return {
82
- subVisible,
83
-
84
- node,
25
+ const createMenuItems = (group: ComponentGroup): MenuButton[] =>
26
+ group.items.map((component) => ({
27
+ text: component.text,
28
+ type: 'button',
29
+ icon: component.icon,
30
+ handler: () => {
31
+ services?.editorService.add({
32
+ name: component.text,
33
+ type: component.type,
34
+ ...(component.data || {}),
35
+ });
36
+ },
37
+ }));
85
38
 
86
- menu: computed(() => ({
87
- app: [
39
+ const getSubMenuData = computed<MenuButton[]>(() => {
40
+ if (node.value?.type === 'tabs') {
41
+ return [
88
42
  {
89
- type: 'page',
90
- text: '页面',
43
+ text: '标签页',
44
+ type: 'button',
45
+ icon: Files,
46
+ handler: () => {
47
+ services?.editorService.add({
48
+ type: 'tab-pane',
49
+ });
50
+ },
91
51
  },
92
- ],
93
- component: props.componentGroupList,
94
- })),
52
+ ];
53
+ }
54
+ if (node.value?.items) {
55
+ return (
56
+ componentList.value.reduce(
57
+ (subMenuData: MenuButton[], group: ComponentGroup, index) =>
58
+ subMenuData.concat(
59
+ createMenuItems(group),
60
+ index < componentList.value.length - 1
61
+ ? [
62
+ {
63
+ type: 'divider',
64
+ direction: 'horizontal',
65
+ },
66
+ ]
67
+ : [],
68
+ ),
69
+ [],
70
+ ) || []
71
+ );
72
+ }
73
+ return [];
74
+ });
95
75
 
96
- append(config: any) {
97
- services?.editorService.add({
98
- name: config.text,
99
- type: config.type,
100
- });
101
- },
102
-
103
- remove() {
104
- node.value && services?.editorService.remove(node.value);
105
- },
106
-
107
- copy(node: any) {
108
- services?.editorService.copy(node);
109
- },
76
+ return {
77
+ menu,
78
+ menuData: computed<MenuItem[]>(() => [
79
+ {
80
+ type: 'button',
81
+ text: '新增',
82
+ icon: markRaw(Plus),
83
+ display: () => node.value?.items,
84
+ items: getSubMenuData.value,
85
+ },
86
+ {
87
+ type: 'button',
88
+ text: '复制',
89
+ icon: markRaw(DocumentCopy),
90
+ display: () => !isRoot.value,
91
+ handler: () => {
92
+ node.value && services?.editorService.copy(node.value);
93
+ },
94
+ },
95
+ {
96
+ type: 'button',
97
+ text: '删除',
98
+ icon: markRaw(Delete),
99
+ display: () => !isRoot.value && !isPage.value,
100
+ handler: () => {
101
+ node.value && services?.editorService.remove(node.value);
102
+ },
103
+ },
104
+ ]),
110
105
 
111
- setSubVisiable(v: any) {
112
- subVisible.value = v;
106
+ show(e: MouseEvent) {
107
+ menu.value?.show(e);
113
108
  },
114
109
  };
115
110
  },