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

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 (121) hide show
  1. package/README.md +1 -0
  2. package/coverage/clover.xml +1556 -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 +802 -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 +343 -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 +760 -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 +598 -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 +3747 -0
  55. package/dist/style.css +91 -45
  56. package/dist/tmagic-editor.es.js +1462 -2003
  57. package/dist/tmagic-editor.es.js.map +1 -1
  58. package/dist/tmagic-editor.umd.js +1461 -2003
  59. package/dist/tmagic-editor.umd.js.map +1 -1
  60. package/dist/types/src/Editor.vue.d.ts +10 -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/Framework.vue.d.ts +15 -3
  66. package/dist/types/src/layouts/PropsPanel.vue.d.ts +2 -1
  67. package/dist/types/src/layouts/sidebar/ComponentListPanel.vue.d.ts +2 -1
  68. package/dist/types/src/layouts/sidebar/Sidebar.vue.d.ts +2 -3
  69. package/dist/types/src/layouts/sidebar/TabPane.vue.d.ts +14 -0
  70. package/dist/types/src/layouts/workspace/PageBar.vue.d.ts +10 -3
  71. package/dist/types/src/layouts/workspace/Workspace.vue.d.ts +4 -6
  72. package/dist/types/src/services/BaseService.d.ts +4 -1
  73. package/dist/types/src/services/editor.d.ts +16 -6
  74. package/dist/types/src/services/history.d.ts +1 -0
  75. package/dist/types/src/services/props.d.ts +2 -2
  76. package/dist/types/src/services/ui.d.ts +2 -0
  77. package/dist/types/src/type.d.ts +16 -9
  78. package/dist/types/src/utils/editor.d.ts +5 -4
  79. package/dist/types/src/utils/polyfills.d.ts +0 -0
  80. package/package.json +44 -12
  81. package/src/Editor.vue +6 -1
  82. package/src/components/ContentMenu.vue +107 -0
  83. package/src/components/ScrollViewer.vue +1 -1
  84. package/src/components/ToolButton.vue +72 -31
  85. package/src/fields/UISelect.vue +14 -6
  86. package/src/index.ts +2 -0
  87. package/src/layouts/AddPageBox.vue +3 -1
  88. package/src/layouts/CodeEditor.vue +20 -13
  89. package/src/layouts/Framework.vue +20 -7
  90. package/src/layouts/PropsPanel.vue +5 -4
  91. package/src/layouts/sidebar/ComponentListPanel.vue +25 -3
  92. package/src/layouts/sidebar/LayerMenu.vue +91 -96
  93. package/src/layouts/sidebar/LayerPanel.vue +80 -59
  94. package/src/layouts/sidebar/Sidebar.vue +13 -52
  95. package/src/layouts/sidebar/TabPane.vue +68 -0
  96. package/src/layouts/workspace/PageBar.vue +145 -17
  97. package/src/layouts/workspace/Stage.vue +56 -64
  98. package/src/layouts/workspace/ViewerMenu.vue +107 -68
  99. package/src/layouts/workspace/Workspace.vue +110 -18
  100. package/src/services/BaseService.ts +70 -22
  101. package/src/services/editor.ts +197 -64
  102. package/src/services/history.ts +7 -0
  103. package/src/services/props.ts +3 -3
  104. package/src/services/ui.ts +35 -5
  105. package/src/theme/common/var.scss +3 -2
  106. package/src/theme/component-list-panel.scss +2 -0
  107. package/src/theme/content-menu.scss +33 -26
  108. package/src/theme/layer-panel.scss +10 -0
  109. package/src/theme/nav-menu.scss +6 -2
  110. package/src/theme/page-bar.scss +42 -2
  111. package/src/theme/props-panel.scss +19 -17
  112. package/src/type.ts +17 -9
  113. package/src/utils/editor.ts +35 -9
  114. package/src/utils/polyfills.ts +8 -0
  115. package/src/utils/props.ts +20 -1
  116. package/dist/types/src/layouts/sidebar/LayerMenu.vue.d.ts +0 -31
  117. package/dist/types/src/layouts/sidebar/LayerPanel.vue.d.ts +0 -973
  118. package/dist/types/src/layouts/workspace/Stage.vue.d.ts +0 -192
  119. package/dist/types/src/layouts/workspace/ViewerMenu.vue.d.ts +0 -18
  120. package/tsconfig.json +0 -9
  121. package/vite.config.ts +0 -30
@@ -0,0 +1,107 @@
1
+ <template>
2
+ <div v-if="menuData.length" v-show="visible" class="magic-editor-content-menu" ref="menu" :style="menuStyle">
3
+ <div>
4
+ <tool-button
5
+ v-for="(item, index) in menuData"
6
+ event-type="mouseup"
7
+ :data="item"
8
+ :key="index"
9
+ @mouseup="hide"
10
+ @mouseenter="showSubMenu(item)"
11
+ ></tool-button>
12
+ </div>
13
+ <teleport to="body">
14
+ <content-menu class="sub-menu" ref="subMenu" :menu-data="subMenuData"></content-menu>
15
+ </teleport>
16
+ </div>
17
+ </template>
18
+
19
+ <script lang="ts">
20
+ import { defineComponent, nextTick, onMounted, PropType, ref } from 'vue';
21
+
22
+ import { MenuButton, MenuItem } from '@editor/type';
23
+
24
+ import ToolButton from './ToolButton.vue';
25
+
26
+ export default defineComponent({
27
+ components: { ToolButton },
28
+
29
+ props: {
30
+ menuData: {
31
+ type: Array as PropType<MenuItem[]>,
32
+ default: () => [],
33
+ },
34
+ },
35
+
36
+ setup() {
37
+ const menu = ref<HTMLDivElement>();
38
+ const subMenu = ref<any>();
39
+ const visible = ref(false);
40
+ const subMenuData = ref<MenuItem[]>([]);
41
+ const menuStyle = ref({
42
+ left: '0',
43
+ top: '0',
44
+ });
45
+
46
+ const hide = () => {
47
+ visible.value = false;
48
+ };
49
+
50
+ onMounted(() => {
51
+ globalThis.addEventListener(
52
+ 'mousedown',
53
+ (e: MouseEvent) => {
54
+ if (!visible.value || (e.target && menu.value?.contains(e.target as HTMLElement))) {
55
+ return;
56
+ }
57
+ hide();
58
+ },
59
+ true,
60
+ );
61
+ });
62
+
63
+ return {
64
+ menu,
65
+ subMenu,
66
+ visible,
67
+ menuStyle,
68
+ subMenuData,
69
+
70
+ hide,
71
+
72
+ show(e: MouseEvent) {
73
+ visible.value = true;
74
+
75
+ nextTick(() => {
76
+ const menuHeight = menu.value?.clientHeight || 0;
77
+
78
+ let top = e.clientY;
79
+ if (menuHeight + e.clientY > document.body.clientHeight) {
80
+ top = document.body.clientHeight - menuHeight;
81
+ }
82
+
83
+ menuStyle.value = {
84
+ top: `${top}px`,
85
+ left: `${e.clientX}px`,
86
+ };
87
+ });
88
+ },
89
+
90
+ showSubMenu(item: MenuItem) {
91
+ const menuItem = item as MenuButton;
92
+ if (typeof item !== 'object' || !menuItem.items?.length) {
93
+ return;
94
+ }
95
+
96
+ subMenuData.value = menuItem.items;
97
+ if (menu.value) {
98
+ subMenu.value.show({
99
+ clientX: menu.value.offsetLeft + menu.value.clientWidth,
100
+ clientY: menu.value.offsetTop,
101
+ });
102
+ }
103
+ },
104
+ };
105
+ },
106
+ });
107
+ </script>
@@ -55,7 +55,7 @@ export default defineComponent({
55
55
  style: computed(
56
56
  () => `
57
57
  width: ${props.width}px;
58
- height: ${props.height}px;
58
+ height: ${(props.height || 0) - 40}px;
59
59
  position: absolute;
60
60
  margin-top: 30px;
61
61
  `,
@@ -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,9 +51,11 @@
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
 
57
+ import { NodeType } from '@tmagic/schema';
58
+
44
59
  import MIcon from '@editor/components/Icon.vue';
45
60
  import type { MenuButton, MenuComponent, MenuItem, Services } from '@editor/type';
46
61
 
@@ -56,19 +71,24 @@ export default defineComponent({
56
71
  display: false,
57
72
  }),
58
73
  },
74
+
75
+ eventType: {
76
+ type: String as PropType<'mousedown' | 'mouseup' | 'click'>,
77
+ default: 'click',
78
+ },
59
79
  },
60
80
 
61
81
  setup(props) {
62
82
  const services = inject<Services>('services');
63
83
  const uiService = services?.uiService;
64
84
 
65
- const zoomInHandler = () => uiService?.set('zoom', zoom.value + 0.1);
66
- const zoomOutHandler = () => uiService?.set('zoom', zoom.value - 0.1);
67
-
68
85
  const zoom = computed((): number => uiService?.get<number>('zoom') ?? 1);
69
86
  const showGuides = computed((): boolean => uiService?.get<boolean>('showGuides') ?? true);
70
87
  const showRule = computed((): boolean => uiService?.get<boolean>('showRule') ?? true);
71
88
 
89
+ const zoomInHandler = () => uiService?.zoom(0.1);
90
+ const zoomOutHandler = () => uiService?.zoom(-0.1);
91
+
72
92
  const item = computed((): MenuButton | MenuComponent => {
73
93
  if (typeof props.data !== 'string') {
74
94
  return props.data;
@@ -85,15 +105,15 @@ export default defineComponent({
85
105
  case 'delete':
86
106
  return {
87
107
  type: 'button',
88
- icon: Delete,
108
+ icon: markRaw(Delete),
89
109
  tooltip: '刪除',
90
- disabled: () => services?.editorService.get('node')?.type === 'page',
110
+ disabled: () => services?.editorService.get('node')?.type === NodeType.PAGE,
91
111
  handler: () => services?.editorService.remove(services?.editorService.get('node')),
92
112
  };
93
113
  case 'undo':
94
114
  return {
95
115
  type: 'button',
96
- icon: Back,
116
+ icon: markRaw(Back),
97
117
  tooltip: '后退',
98
118
  disabled: () => !services?.historyService.state.canUndo,
99
119
  handler: () => services?.editorService.undo(),
@@ -101,7 +121,7 @@ export default defineComponent({
101
121
  case 'redo':
102
122
  return {
103
123
  type: 'button',
104
- icon: Right,
124
+ icon: markRaw(Right),
105
125
  tooltip: '前进',
106
126
  disabled: () => !services?.historyService.state.canRedo,
107
127
  handler: () => services?.editorService.redo(),
@@ -109,28 +129,28 @@ export default defineComponent({
109
129
  case 'zoom-in':
110
130
  return {
111
131
  type: 'button',
112
- icon: ZoomIn,
132
+ icon: markRaw(ZoomIn),
113
133
  tooltip: '放大',
114
134
  handler: zoomInHandler,
115
135
  };
116
136
  case 'zoom-out':
117
137
  return {
118
138
  type: 'button',
119
- icon: ZoomOut,
139
+ icon: markRaw(ZoomOut),
120
140
  tooltip: '縮小',
121
141
  handler: zoomOutHandler,
122
142
  };
123
143
  case 'rule':
124
144
  return {
125
145
  type: 'button',
126
- icon: ScaleToOriginal,
146
+ icon: markRaw(ScaleToOriginal),
127
147
  tooltip: showRule.value ? '隐藏标尺' : '显示标尺',
128
148
  handler: () => uiService?.set('showRule', !showRule.value),
129
149
  };
130
150
  case 'guides':
131
151
  return {
132
152
  type: 'button',
133
- icon: Grid,
153
+ icon: markRaw(Grid),
134
154
  tooltip: showGuides.value ? '隐藏参考线' : '显示参考线',
135
155
  handler: () => uiService?.set('showGuides', !showGuides.value),
136
156
  };
@@ -151,9 +171,16 @@ export default defineComponent({
151
171
  return item.value.disabled;
152
172
  });
153
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
+
154
181
  return {
155
- ZoomIn,
156
- ZoomOut,
182
+ ZoomIn: markRaw(ZoomIn),
183
+ ZoomOut: markRaw(ZoomOut),
157
184
 
158
185
  item,
159
186
  zoom,
@@ -176,10 +203,24 @@ export default defineComponent({
176
203
  }
177
204
  },
178
205
 
179
- buttonHandler(item: MenuButton | MenuComponent) {
180
- if (disabled.value) return;
181
- if (typeof (item as MenuButton).handler === 'function') {
182
- (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);
183
224
  }
184
225
  },
185
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, 自定义图片上传方法等编辑器依赖的外部选项
@@ -15,6 +15,8 @@
15
15
  import { defineComponent, inject, toRaw } from 'vue';
16
16
  import { Plus } from '@element-plus/icons';
17
17
 
18
+ import { NodeType } from '@tmagic/schema';
19
+
18
20
  import { Services } from '@editor/type';
19
21
  import { generatePageNameByApp } from '@editor/utils';
20
22
 
@@ -31,7 +33,7 @@ export default defineComponent({
31
33
  if (!editorService) return;
32
34
 
33
35
  editorService.add({
34
- type: 'page',
36
+ type: NodeType.PAGE,
35
37
  name: generatePageNameByApp(toRaw(editorService.get('root'))),
36
38
  });
37
39
  },
@@ -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
 
@@ -85,11 +94,8 @@ export default defineComponent({
85
94
  const options = {
86
95
  value: values.value,
87
96
  language: props.language,
88
- tabSize: 2,
89
97
  theme: 'vs-dark',
90
- fontFamily: 'dm, Menlo, Monaco, "Courier New", monospace',
91
- fontSize: 15,
92
- formatOnPaste: true,
98
+ ...props.options,
93
99
  };
94
100
 
95
101
  if (props.type === 'diff') {
@@ -107,6 +113,7 @@ export default defineComponent({
107
113
  codeEditor.value.addEventListener('keydown', (e) => {
108
114
  if (e.keyCode === 83 && (navigator.platform.match('Mac') ? e.metaKey : e.ctrlKey)) {
109
115
  e.preventDefault();
116
+ e.stopPropagation();
110
117
  emit('save', getEditorValue());
111
118
  }
112
119
  });
@@ -117,7 +124,7 @@ export default defineComponent({
117
124
  });
118
125
  }
119
126
 
120
- globalThis.addEventListener('resize', resizeHandler);
127
+ resizeObserver.observe(codeEditor.value);
121
128
  };
122
129
 
123
130
  watch(
@@ -140,7 +147,7 @@ export default defineComponent({
140
147
  });
141
148
 
142
149
  onUnmounted(() => {
143
- globalThis.removeEventListener('resize', resizeHandler);
150
+ resizeObserver.disconnect();
144
151
  });
145
152
 
146
153
  return {
@@ -2,7 +2,13 @@
2
2
  <div class="m-editor">
3
3
  <slot name="nav" class="m-editor-nav-menu"></slot>
4
4
 
5
- <magic-code-editor v-if="showSrc" class="m-editor-content" :init-values="root" @save="saveCode"></magic-code-editor>
5
+ <magic-code-editor
6
+ v-if="showSrc"
7
+ class="m-editor-content"
8
+ :init-values="root"
9
+ :options="codeOptions"
10
+ @save="saveCode"
11
+ ></magic-code-editor>
6
12
 
7
13
  <div class="m-editor-content" v-else>
8
14
  <div class="m-editor-framework-left" :style="`width: ${columnWidth?.left}px`">
@@ -48,21 +54,28 @@ export default defineComponent({
48
54
  Resizer,
49
55
  },
50
56
 
57
+ props: {
58
+ codeOptions: {
59
+ type: Object,
60
+ default: () => ({}),
61
+ },
62
+ },
63
+
51
64
  setup() {
52
- const services = inject<Services>('services');
65
+ const { editorService, uiService } = inject<Services>('services') || {};
53
66
 
54
- const root = computed(() => services?.editorService.get<MApp>('root'));
67
+ const root = computed(() => editorService?.get<MApp>('root'));
55
68
 
56
69
  return {
57
70
  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')),
71
+ pageLength: computed(() => editorService?.get<number>('pageLength') || 0),
72
+ showSrc: computed(() => uiService?.get<boolean>('showSrc')),
73
+ columnWidth: computed(() => uiService?.get<GetColumnWidth>('columnWidth')),
61
74
 
62
75
  saveCode(value: string) {
63
76
  try {
64
77
  // eslint-disable-next-line no-eval
65
- services?.editorService.set('root', eval(value));
78
+ editorService?.set('root', eval(value));
66
79
  } catch (e: any) {
67
80
  console.error(e);
68
81
  }
@@ -1,9 +1,9 @@
1
1
  <template>
2
2
  <m-form
3
- class="m-editor-props-panel"
4
- popper-class="m-editor-props-panel-popper"
3
+ :class="`m-editor-props-panel ${propsPanelSize}`"
4
+ :popper-class="`m-editor-props-panel-popper ${propsPanelSize}`"
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
  });