@tmagic/editor 1.0.0-rc.1 → 1.0.0-rc.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/dist/style.css +6 -3
  2. package/dist/tmagic-editor.es.js +292 -1394
  3. package/dist/tmagic-editor.es.js.map +1 -1
  4. package/dist/tmagic-editor.umd.js +292 -1396
  5. package/dist/tmagic-editor.umd.js.map +1 -1
  6. package/dist/types/src/Editor.vue.d.ts +49 -1
  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/Framework.vue.d.ts +15 -3
  10. package/dist/types/src/layouts/PropsPanel.vue.d.ts +2 -4
  11. package/dist/types/src/layouts/workspace/Workspace.vue.d.ts +3 -27
  12. package/dist/types/src/services/BaseService.d.ts +1 -1
  13. package/dist/types/src/services/history.d.ts +1 -18
  14. package/dist/types/src/services/props.d.ts +8 -2
  15. package/dist/types/src/type.d.ts +9 -0
  16. package/dist/types/src/utils/editor.d.ts +0 -6
  17. package/dist/types/src/utils/props.d.ts +8 -1
  18. package/package.json +17 -18
  19. package/src/Editor.vue +44 -9
  20. package/src/components/ContentMenu.vue +59 -26
  21. package/src/layouts/CodeEditor.vue +1 -4
  22. package/src/layouts/Framework.vue +14 -1
  23. package/src/layouts/PropsPanel.vue +1 -1
  24. package/src/layouts/sidebar/LayerMenu.vue +3 -0
  25. package/src/layouts/sidebar/TabPane.vue +1 -1
  26. package/src/layouts/workspace/Stage.vue +12 -29
  27. package/src/layouts/workspace/ViewerMenu.vue +17 -2
  28. package/src/layouts/workspace/Workspace.vue +21 -26
  29. package/src/services/BaseService.ts +1 -1
  30. package/src/services/editor.ts +34 -5
  31. package/src/services/props.ts +64 -9
  32. package/src/theme/props-panel.scss +6 -4
  33. package/src/theme/workspace.scss +4 -0
  34. package/src/type.ts +10 -0
  35. package/src/utils/editor.ts +7 -52
  36. package/src/utils/polyfills.ts +5 -19
  37. package/src/utils/props.ts +30 -7
  38. package/LICENSE +0 -5432
  39. package/coverage/clover.xml +0 -1560
  40. package/coverage/coverage-final.json +0 -36
  41. package/coverage/lcov-report/base.css +0 -224
  42. package/coverage/lcov-report/block-navigation.js +0 -87
  43. package/coverage/lcov-report/favicon.png +0 -0
  44. package/coverage/lcov-report/index.html +0 -206
  45. package/coverage/lcov-report/prettify.css +0 -1
  46. package/coverage/lcov-report/prettify.js +0 -2
  47. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  48. package/coverage/lcov-report/sorter.js +0 -196
  49. package/coverage/lcov-report/src/Editor.vue.html +0 -787
  50. package/coverage/lcov-report/src/components/ContentMenu.vue.html +0 -406
  51. package/coverage/lcov-report/src/components/Icon.vue.html +0 -172
  52. package/coverage/lcov-report/src/components/ScrollViewer.vue.html +0 -283
  53. package/coverage/lcov-report/src/components/ToolButton.vue.html +0 -772
  54. package/coverage/lcov-report/src/components/index.html +0 -161
  55. package/coverage/lcov-report/src/index.html +0 -131
  56. package/coverage/lcov-report/src/layouts/AddPageBox.vue.html +0 -214
  57. package/coverage/lcov-report/src/layouts/Framework.vue.html +0 -304
  58. package/coverage/lcov-report/src/layouts/NavMenu.vue.html +0 -208
  59. package/coverage/lcov-report/src/layouts/PropsPanel.vue.html +0 -319
  60. package/coverage/lcov-report/src/layouts/Resizer.vue.html +0 -268
  61. package/coverage/lcov-report/src/layouts/index.html +0 -176
  62. package/coverage/lcov-report/src/layouts/sidebar/ComponentListPanel.vue.html +0 -358
  63. package/coverage/lcov-report/src/layouts/sidebar/LayerMenu.vue.html +0 -421
  64. package/coverage/lcov-report/src/layouts/sidebar/LayerPanel.vue.html +0 -775
  65. package/coverage/lcov-report/src/layouts/sidebar/Sidebar.vue.html +0 -226
  66. package/coverage/lcov-report/src/layouts/sidebar/TabPane.vue.html +0 -289
  67. package/coverage/lcov-report/src/layouts/sidebar/index.html +0 -176
  68. package/coverage/lcov-report/src/layouts/workspace/PageBar.vue.html +0 -718
  69. package/coverage/lcov-report/src/layouts/workspace/Stage.vue.html +0 -757
  70. package/coverage/lcov-report/src/layouts/workspace/ViewerMenu.vue.html +0 -532
  71. package/coverage/lcov-report/src/layouts/workspace/Workspace.vue.html +0 -586
  72. package/coverage/lcov-report/src/layouts/workspace/index.html +0 -161
  73. package/coverage/lcov-report/src/services/BaseService.ts.html +0 -643
  74. package/coverage/lcov-report/src/services/componentList.ts.html +0 -229
  75. package/coverage/lcov-report/src/services/editor.ts.html +0 -2077
  76. package/coverage/lcov-report/src/services/events.ts.html +0 -331
  77. package/coverage/lcov-report/src/services/history.ts.html +0 -478
  78. package/coverage/lcov-report/src/services/index.html +0 -206
  79. package/coverage/lcov-report/src/services/props.ts.html +0 -415
  80. package/coverage/lcov-report/src/services/ui.ts.html +0 -580
  81. package/coverage/lcov-report/src/type.ts.html +0 -850
  82. package/coverage/lcov-report/src/utils/compose.ts.html +0 -184
  83. package/coverage/lcov-report/src/utils/config.ts.html +0 -172
  84. package/coverage/lcov-report/src/utils/editor.ts.html +0 -838
  85. package/coverage/lcov-report/src/utils/index.html +0 -221
  86. package/coverage/lcov-report/src/utils/index.ts.html +0 -151
  87. package/coverage/lcov-report/src/utils/logger.ts.html +0 -226
  88. package/coverage/lcov-report/src/utils/props.ts.html +0 -796
  89. package/coverage/lcov-report/src/utils/scroll-viewer.ts.html +0 -733
  90. package/coverage/lcov-report/src/utils/undo-redo.ts.html +0 -313
  91. package/coverage/lcov.info +0 -3708
  92. package/dist/types/src/components/ToolButton.vue.d.ts +0 -46
  93. package/dist/types/src/fields/UISelect.vue.d.ts +0 -35
  94. package/dist/types/src/layouts/workspace/PageBar.vue.d.ts +0 -18
@@ -94,11 +94,7 @@ export default defineComponent({
94
94
  const options = {
95
95
  value: values.value,
96
96
  language: props.language,
97
- tabSize: 2,
98
97
  theme: 'vs-dark',
99
- fontFamily: 'dm, Menlo, Monaco, "Courier New", monospace',
100
- fontSize: 14,
101
- formatOnPaste: true,
102
98
  ...props.options,
103
99
  };
104
100
 
@@ -117,6 +113,7 @@ export default defineComponent({
117
113
  codeEditor.value.addEventListener('keydown', (e) => {
118
114
  if (e.keyCode === 83 && (navigator.platform.match('Mac') ? e.metaKey : e.ctrlKey)) {
119
115
  e.preventDefault();
116
+ e.stopPropagation();
120
117
  emit('save', getEditorValue());
121
118
  }
122
119
  });
@@ -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,6 +54,13 @@ 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
65
  const { editorService, uiService } = inject<Services>('services') || {};
53
66
 
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <m-form
3
3
  :class="`m-editor-props-panel ${propsPanelSize}`"
4
- popper-class="m-editor-props-panel-popper"
4
+ :popper-class="`m-editor-props-panel-popper ${propsPanelSize}`"
5
5
  ref="configForm"
6
6
  :size="propsPanelSize"
7
7
  :init-values="values"
@@ -22,6 +22,8 @@ export default defineComponent({
22
22
  const isPage = computed(() => node.value?.type === NodeType.PAGE);
23
23
  const componentList = computed(() => services?.componentListService.getList() || []);
24
24
 
25
+ const layerContentMenu = inject<MenuItem[]>('layerContentMenu', []);
26
+
25
27
  const createMenuItems = (group: ComponentGroup): MenuButton[] =>
26
28
  group.items.map((component) => ({
27
29
  text: component.text,
@@ -101,6 +103,7 @@ export default defineComponent({
101
103
  node.value && services?.editorService.remove(node.value);
102
104
  },
103
105
  },
106
+ ...layerContentMenu,
104
107
  ]),
105
108
 
106
109
  show(e: MouseEvent) {
@@ -30,7 +30,7 @@ export default defineComponent({
30
30
 
31
31
  props: {
32
32
  data: {
33
- type: Object as PropType<SideItem>,
33
+ type: [Object, String] as PropType<SideItem>,
34
34
  },
35
35
  },
36
36
 
@@ -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,28 +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
-
63
- canSelect: {
64
- type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
65
- default: (el: HTMLElement) => Boolean(el.id),
66
- },
67
-
68
- moveableOptions: {
69
- type: [Object, Function] as PropType<MoveableOptions | ((core?: StageCore) => MoveableOptions)>,
70
- default: () => (core?: StageCore) => ({
71
- container: core?.renderer?.contentWindow?.document.getElementById('app'),
72
- }),
73
- },
74
- },
75
-
76
- setup(props) {
55
+ setup() {
77
56
  const services = inject<Services>('services');
57
+ const stageOptions = inject<StageOptions>('stageOptions');
78
58
 
79
59
  const stageWrap = ref<InstanceType<typeof ScrollViewer>>();
80
60
  const stageContainer = ref<HTMLDivElement>();
@@ -94,14 +74,15 @@ export default defineComponent({
94
74
  if (stage) return;
95
75
 
96
76
  if (!stageContainer.value) return;
97
- if (!(props.runtimeUrl || props.render) || !root.value) return;
77
+ if (!(stageOptions?.runtimeUrl || stageOptions?.render) || !root.value) return;
98
78
 
99
79
  stage = new StageCore({
100
- render: props.render,
101
- runtimeUrl: props.runtimeUrl,
80
+ render: stageOptions.render,
81
+ runtimeUrl: stageOptions.runtimeUrl,
102
82
  zoom: zoom.value,
83
+ autoScrollIntoView: stageOptions.autoScrollIntoView,
103
84
  canSelect: (el, event, stop) => {
104
- const elCanSelect = props.canSelect(el);
85
+ const elCanSelect = stageOptions.canSelect(el);
105
86
  // 在组件联动过程中不能再往下选择,返回并触发 ui-select
106
87
  if (uiSelectMode.value && elCanSelect && event.type === 'mousedown') {
107
88
  document.dispatchEvent(new CustomEvent('ui-select', { detail: el }));
@@ -110,7 +91,8 @@ export default defineComponent({
110
91
 
111
92
  return elCanSelect;
112
93
  },
113
- moveableOptions: props.moveableOptions,
94
+ moveableOptions: stageOptions.moveableOptions,
95
+ updateDragEl: stageOptions.updateDragEl,
114
96
  });
115
97
 
116
98
  services?.editorService.set('stage', markRaw(stage));
@@ -209,6 +191,7 @@ export default defineComponent({
209
191
  const { scrollTop, scrollLeft } = stage.mask;
210
192
  if (layout === Layout.ABSOLUTE) {
211
193
  config.style = {
194
+ ...(config.style || {}),
212
195
  position: 'absolute',
213
196
  top: e.clientY - containerRect.top + scrollTop,
214
197
  left: e.clientX - containerRect.left + scrollLeft,
@@ -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;
@@ -69,8 +71,20 @@ export default defineComponent({
69
71
  text: '粘贴',
70
72
  display: () => canPaste.value,
71
73
  handler: () => {
72
- const top = menu.value?.$el.offsetTop || 0;
73
- const left = menu.value?.$el.offsetLeft || 0;
74
+ const stage = editorService?.get<StageCore>('stage');
75
+
76
+ const rect = menu.value?.$el.getBoundingClientRect();
77
+ const parentRect = stage?.container?.getBoundingClientRect();
78
+ let left = (rect?.left || 0) - (parentRect?.left || 0);
79
+ let top = (rect?.top || 0) - (parentRect?.top || 0);
80
+
81
+ if (node.value?.items && stage) {
82
+ const parentEl = stage.renderer.contentWindow?.document.getElementById(`${node.value.id}`);
83
+ const parentElRect = parentEl?.getBoundingClientRect();
84
+ left = left - (parentElRect?.left || 0);
85
+ top = top - (parentElRect?.top || 0);
86
+ }
87
+
74
88
  editorService?.paste({ left, top });
75
89
  },
76
90
  },
@@ -138,6 +152,7 @@ export default defineComponent({
138
152
  editorService?.get<StageCore>('stage').clearGuides();
139
153
  },
140
154
  },
155
+ ...stageContentMenu,
141
156
  ]),
142
157
 
143
158
  show(e: MouseEvent) {
@@ -1,12 +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
- :render="render"
7
- :moveable-options="moveableOptions"
8
- :can-select="canSelect"
9
- ></magic-stage>
3
+ <magic-stage :key="page?.id"></magic-stage>
10
4
 
11
5
  <slot name="workspace-content"></slot>
12
6
 
@@ -18,12 +12,10 @@
18
12
  </template>
19
13
 
20
14
  <script lang="ts">
21
- import { computed, defineComponent, inject, onMounted, onUnmounted, PropType, ref } from 'vue';
15
+ import { computed, defineComponent, inject, onMounted, onUnmounted, ref } from 'vue';
22
16
  import KeyController from 'keycon';
23
17
 
24
18
  import type { MNode, MPage } from '@tmagic/schema';
25
- import type { MoveableOptions } from '@tmagic/stage';
26
- import StageCore from '@tmagic/stage';
27
19
  import { isPage } from '@tmagic/utils';
28
20
 
29
21
  import type { Services } from '@editor/type';
@@ -39,22 +31,6 @@ export default defineComponent({
39
31
  MagicStage,
40
32
  },
41
33
 
42
- props: {
43
- runtimeUrl: String,
44
-
45
- render: {
46
- type: Function as PropType<() => HTMLDivElement>,
47
- },
48
-
49
- moveableOptions: {
50
- type: [Object, Function] as PropType<MoveableOptions | ((core?: StageCore) => MoveableOptions)>,
51
- },
52
-
53
- canSelect: {
54
- type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
55
- },
56
- },
57
-
58
34
  setup() {
59
35
  const services = inject<Services>('services');
60
36
  const workspace = ref<HTMLDivElement>();
@@ -65,8 +41,13 @@ export default defineComponent({
65
41
  workspace.value?.focus();
66
42
  };
67
43
 
44
+ const mouseleaveHandler = () => {
45
+ workspace.value?.blur();
46
+ };
47
+
68
48
  onMounted(() => {
69
49
  workspace.value?.addEventListener('mouseenter', mouseenterHandler);
50
+ workspace.value?.addEventListener('mouseleave', mouseleaveHandler);
70
51
 
71
52
  keycon = new KeyController(workspace.value);
72
53
 
@@ -80,6 +61,11 @@ export default defineComponent({
80
61
  if (!node.value || isPage(node.value)) return;
81
62
  services?.editorService.remove(node.value);
82
63
  })
64
+ .keyup('backspace', (e) => {
65
+ e.inputEvent.preventDefault();
66
+ if (!node.value || isPage(node.value)) return;
67
+ services?.editorService.remove(node.value);
68
+ })
83
69
  .keydown([ctrl, 'c'], (e) => {
84
70
  e.inputEvent.preventDefault();
85
71
  node.value && services?.editorService.copy(node.value);
@@ -146,14 +132,23 @@ export default defineComponent({
146
132
  e.inputEvent.preventDefault();
147
133
  services?.uiService.zoom(0.1);
148
134
  })
135
+ .keydown([ctrl, 'numpadplus'], (e) => {
136
+ e.inputEvent.preventDefault();
137
+ services?.uiService.zoom(0.1);
138
+ })
149
139
  .keydown([ctrl, '-'], (e) => {
150
140
  e.inputEvent.preventDefault();
151
141
  services?.uiService.zoom(-0.1);
142
+ })
143
+ .keydown([ctrl, 'numpad-'], (e) => {
144
+ e.inputEvent.preventDefault();
145
+ services?.uiService.zoom(-0.1);
152
146
  });
153
147
  });
154
148
 
155
149
  onUnmounted(() => {
156
150
  workspace.value?.removeEventListener('mouseenter', mouseenterHandler);
151
+ workspace.value?.removeEventListener('mouseleave', mouseleaveHandler);
157
152
  keycon.destroy();
158
153
  });
159
154
 
@@ -91,7 +91,7 @@ const doAction = async (
91
91
  * editorService.afterAdd();
92
92
  * }
93
93
  *
94
- * 调用时的参数会透传到before方法的参数中, 然后before的return 会作为原方法的参数和after的参数,after最后一个参数则是原方法的return值;
94
+ * 调用时的参数会透传到before方法的参数中, 然后before的return 会作为原方法的参数和after的参数,after第一个参数则是原方法的return值;
95
95
  * 如需终止后续方法调用可以return new Error();
96
96
  *
97
97
  * 方法2:
@@ -33,11 +33,11 @@ import {
33
33
  change2Fixed,
34
34
  COPY_STORAGE_KEY,
35
35
  Fixed2Other,
36
+ generatePageNameByApp,
36
37
  getNodeIndex,
37
38
  initPosition,
38
39
  isFixed,
39
40
  setLayout,
40
- setNewItemId,
41
41
  } from '@editor/utils/editor';
42
42
  import { log } from '@editor/utils/logger';
43
43
 
@@ -194,6 +194,20 @@ class Editor extends BaseService {
194
194
  historyService.empty();
195
195
  }
196
196
 
197
+ if (node?.id) {
198
+ this.get<StageCore>('stage')
199
+ ?.renderer.runtime?.getApp?.()
200
+ ?.emit(
201
+ 'editor:select',
202
+ {
203
+ node,
204
+ page,
205
+ parent,
206
+ },
207
+ getNodePath(node.id, this.get<MApp>('root').items),
208
+ );
209
+ }
210
+
197
211
  this.emit('select', node);
198
212
 
199
213
  return node!;
@@ -480,7 +494,7 @@ class Editor extends BaseService {
480
494
  return;
481
495
  }
482
496
 
483
- setNewItemId(config, this.get('root'));
497
+ await propsService.setNewItemId(config, this.get('root'));
484
498
  if (config.style) {
485
499
  config.style = {
486
500
  ...config.style,
@@ -488,6 +502,10 @@ class Editor extends BaseService {
488
502
  };
489
503
  }
490
504
 
505
+ if (isPage(config)) {
506
+ config.name = generatePageNameByApp(this.get('root'));
507
+ }
508
+
491
509
  return await this.add(config);
492
510
  }
493
511
 
@@ -504,7 +522,18 @@ class Editor extends BaseService {
504
522
  return;
505
523
  }
506
524
 
507
- if (parent.style?.width && node.style?.width) {
525
+ if (!node.style) return;
526
+
527
+ const stage = this.get<StageCore>('stage');
528
+ const doc = stage?.renderer.contentWindow?.document;
529
+
530
+ if (doc) {
531
+ const parentEl = doc.getElementById(`${parent.id}`);
532
+ const el = doc.getElementById(`${node.id}`);
533
+ if (parentEl && el) {
534
+ node.style.left = (parentEl.clientWidth - el.clientWidth) / 2;
535
+ }
536
+ } else if (parent.style && isNumber(parent.style?.width) && isNumber(node.style?.width)) {
508
537
  node.style.left = (parent.style.width - node.style.width) / 2;
509
538
  }
510
539
 
@@ -526,9 +555,9 @@ class Editor extends BaseService {
526
555
  const brothers: MNode[] = parent?.items || [];
527
556
  const index = brothers.findIndex((item) => `${item.id}` === `${node?.id}`);
528
557
 
529
- if (offset === LayerOffset.BOTTOM) {
558
+ if (offset === LayerOffset.TOP) {
530
559
  brothers.splice(brothers.length - 1, 0, brothers.splice(index, 1)[0]);
531
- } else if (offset === LayerOffset.TOP) {
560
+ } else if (offset === LayerOffset.BOTTOM) {
532
561
  brothers.splice(0, 0, brothers.splice(index, 1)[0]);
533
562
  } else {
534
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();
@@ -23,9 +23,11 @@
23
23
  }
24
24
 
25
25
  .m-editor-props-panel-popper {
26
- span,
27
- a,
28
- p {
29
- font-size: 12px;
26
+ &.small {
27
+ span,
28
+ a,
29
+ p {
30
+ font-size: 12px;
31
+ }
30
32
  }
31
33
  }
@@ -2,4 +2,8 @@
2
2
  height: 100%;
3
3
  width: 100%;
4
4
  user-select: none;
5
+
6
+ &:focus-visible {
7
+ outline: 0;
8
+ }
5
9
  }
package/src/type.ts CHANGED
@@ -21,6 +21,7 @@ import type { Component } from 'vue';
21
21
  import type { FormConfig } from '@tmagic/form';
22
22
  import type { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
23
23
  import type StageCore from '@tmagic/stage';
24
+ import type { MoveableOptions } from '@tmagic/stage';
24
25
 
25
26
  import type { ComponentListService } from '@editor/services/componentList';
26
27
  import type { EditorService } from '@editor/services/editor';
@@ -45,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}
@@ -142,9 +93,13 @@ export const toRelative = (node: MNode) => {
142
93
 
143
94
  const setTop2Middle = (node: MNode, parentNode: MNode, stage: StageCore) => {
144
95
  const style = node.style || {};
145
- const height = style.height || 0;
96
+ let height = style.height || 0;
146
97
 
147
- if (!stage || typeof style.top !== 'undefined' || !parentNode.style || !isNumber(height)) return style;
98
+ if (!stage || typeof style.top !== 'undefined' || !parentNode.style) return style;
99
+
100
+ if (!isNumber(height)) {
101
+ height = 0;
102
+ }
148
103
 
149
104
  const { height: parentHeight } = parentNode.style;
150
105
 
@@ -1,22 +1,8 @@
1
- /*
2
- * Tencent is pleased to support the open source community by making TMagicEditor available.
3
- *
4
- * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
5
- *
6
- * Licensed under the Apache License, Version 2.0 (the "License");
7
- * you may not use this file except in compliance with the License.
8
- * You may obtain a copy of the License at
9
- *
10
- * http://www.apache.org/licenses/LICENSE-2.0
11
- *
12
- * Unless required by applicable law or agreed to in writing, software
13
- * distributed under the License is distributed on an "AS IS" BASIS,
14
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- * See the License for the specific language governing permissions and
16
- * limitations under the License.
17
- */
18
-
19
1
  // serialize-javascript 依赖的 randombytes 依赖全局的 global 对象,因此此处需添加 global polyfill
20
- if (typeof (window as any).global === 'undefined') {
2
+ if (typeof global === 'undefined') {
21
3
  (window as any).global = window;
22
4
  }
5
+
6
+ if (typeof globalThis === 'undefined') {
7
+ (window as any).globalThis = window;
8
+ }