@tmagic/editor 1.0.6 → 1.1.0-beta.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 (105) hide show
  1. package/dist/style.css +5 -1
  2. package/dist/{tmagic-editor.es.js → tmagic-editor.mjs} +1522 -1177
  3. package/dist/tmagic-editor.mjs.map +1 -0
  4. package/dist/tmagic-editor.umd.js +1606 -1259
  5. package/dist/tmagic-editor.umd.js.map +1 -1
  6. package/package.json +22 -20
  7. package/src/Editor.vue +41 -15
  8. package/src/components/ContentMenu.vue +87 -99
  9. package/src/components/Icon.vue +2 -2
  10. package/src/components/ScrollViewer.vue +2 -2
  11. package/src/components/ToolButton.vue +151 -168
  12. package/src/fields/UISelect.vue +49 -70
  13. package/src/index.ts +2 -1
  14. package/src/layouts/AddPageBox.vue +3 -3
  15. package/src/layouts/Framework.vue +1 -1
  16. package/src/layouts/NavMenu.vue +2 -2
  17. package/src/layouts/PropsPanel.vue +1 -1
  18. package/src/layouts/Resizer.vue +1 -1
  19. package/src/layouts/sidebar/ComponentListPanel.vue +43 -2
  20. package/src/layouts/sidebar/LayerMenu.vue +3 -3
  21. package/src/layouts/sidebar/LayerPanel.vue +13 -4
  22. package/src/layouts/sidebar/Sidebar.vue +1 -1
  23. package/src/layouts/sidebar/TabPane.vue +3 -3
  24. package/src/layouts/workspace/PageBar.vue +63 -192
  25. package/src/layouts/workspace/PageBarScrollContainer.vue +111 -0
  26. package/src/layouts/workspace/Stage.vue +208 -188
  27. package/src/layouts/workspace/ViewerMenu.vue +141 -148
  28. package/src/layouts/workspace/Workspace.vue +11 -11
  29. package/src/services/BaseService.ts +5 -10
  30. package/src/services/componentList.ts +3 -3
  31. package/src/services/editor.ts +247 -140
  32. package/src/services/events.ts +1 -1
  33. package/src/services/history.ts +1 -1
  34. package/src/services/props.ts +63 -11
  35. package/src/services/storage.ts +133 -0
  36. package/src/services/ui.ts +10 -4
  37. package/src/theme/component-list-panel.scss +5 -0
  38. package/src/theme/framework.scss +1 -1
  39. package/src/theme/stage.scss +2 -2
  40. package/src/type.ts +28 -7
  41. package/src/utils/config.ts +1 -1
  42. package/src/utils/editor.ts +53 -35
  43. package/src/utils/operator.ts +109 -0
  44. package/src/utils/props.ts +2 -24
  45. package/src/utils/scroll-viewer.ts +1 -1
  46. package/tsconfig.build.json +13 -0
  47. package/{dist/types/src → types}/Editor.vue.d.ts +44 -9
  48. package/types/components/ContentMenu.vue.d.ts +116 -0
  49. package/types/components/Icon.vue.d.ts +13 -0
  50. package/types/components/ScrollViewer.vue.d.ts +22 -0
  51. package/types/components/ToolButton.vue.d.ts +109 -0
  52. package/types/fields/Code.vue.d.ts +23 -0
  53. package/{dist/types/src → types}/fields/CodeLink.vue.d.ts +4 -6
  54. package/types/fields/UISelect.vue.d.ts +83 -0
  55. package/{dist/types/src → types}/index.d.ts +4 -1
  56. package/types/layouts/AddPageBox.vue.d.ts +4 -0
  57. package/{dist/types/src → types}/layouts/CodeEditor.vue.d.ts +11 -13
  58. package/types/layouts/Framework.vue.d.ts +22 -0
  59. package/types/layouts/NavMenu.vue.d.ts +25 -0
  60. package/types/layouts/PropsPanel.vue.d.ts +245 -0
  61. package/types/layouts/Resizer.vue.d.ts +12 -0
  62. package/types/layouts/sidebar/ComponentListPanel.vue.d.ts +14 -0
  63. package/types/layouts/sidebar/LayerMenu.vue.d.ts +100 -0
  64. package/types/layouts/sidebar/LayerPanel.vue.d.ts +1099 -0
  65. package/{dist/types/src → types}/layouts/sidebar/Sidebar.vue.d.ts +3 -5
  66. package/types/layouts/sidebar/TabPane.vue.d.ts +14 -0
  67. package/types/layouts/workspace/PageBar.vue.d.ts +54 -0
  68. package/types/layouts/workspace/PageBarScrollContainer.vue.d.ts +48 -0
  69. package/types/layouts/workspace/Stage.vue.d.ts +46 -0
  70. package/types/layouts/workspace/ViewerMenu.vue.d.ts +88 -0
  71. package/types/layouts/workspace/Workspace.vue.d.ts +6 -0
  72. package/{dist/types/src → types}/services/BaseService.d.ts +0 -0
  73. package/types/services/componentList.d.ts +14 -0
  74. package/{dist/types/src → types}/services/editor.d.ts +27 -14
  75. package/{dist/types/src → types}/services/events.d.ts +0 -0
  76. package/{dist/types/src → types}/services/history.d.ts +0 -0
  77. package/{dist/types/src → types}/services/props.d.ts +26 -2
  78. package/types/services/storage.d.ts +56 -0
  79. package/{dist/types/src → types}/services/ui.d.ts +1 -1
  80. package/{dist/types/src → types}/type.d.ts +21 -1
  81. package/{dist/types/src → types}/utils/compose.d.ts +1 -1
  82. package/{dist/types/src → types}/utils/config.d.ts +0 -0
  83. package/{dist/types/src → types}/utils/editor.d.ts +11 -4
  84. package/{dist/types/src → types}/utils/index.d.ts +0 -0
  85. package/{dist/types/src → types}/utils/logger.d.ts +0 -0
  86. package/types/utils/operator.d.ts +21 -0
  87. package/{dist/types/src → types}/utils/polyfills.d.ts +0 -0
  88. package/{dist/types/src → types}/utils/props.d.ts +2 -22
  89. package/{dist/types/src → types}/utils/scroll-viewer.d.ts +0 -0
  90. package/{dist/types/src → types}/utils/undo-redo.d.ts +0 -0
  91. package/dist/tmagic-editor.es.js.map +0 -1
  92. package/dist/types/src/components/Icon.vue.d.ts +0 -14
  93. package/dist/types/src/components/ScrollViewer.vue.d.ts +0 -24
  94. package/dist/types/src/fields/Code.vue.d.ts +0 -25
  95. package/dist/types/src/layouts/AddPageBox.vue.d.ts +0 -5
  96. package/dist/types/src/layouts/Framework.vue.d.ts +0 -24
  97. package/dist/types/src/layouts/NavMenu.vue.d.ts +0 -27
  98. package/dist/types/src/layouts/PropsPanel.vue.d.ts +0 -13
  99. package/dist/types/src/layouts/Resizer.vue.d.ts +0 -14
  100. package/dist/types/src/layouts/sidebar/ComponentListPanel.vue.d.ts +0 -14
  101. package/dist/types/src/layouts/sidebar/TabPane.vue.d.ts +0 -16
  102. package/dist/types/src/layouts/workspace/Workspace.vue.d.ts +0 -8
  103. package/dist/types/src/shims-vue.d.ts +0 -6
  104. package/dist/types/src/vite-env.d.ts +0 -1
  105. package/src/vite-env.d.ts +0 -1
@@ -2,163 +2,156 @@
2
2
  <content-menu :menu-data="menuData" ref="menu"></content-menu>
3
3
  </template>
4
4
 
5
- <script lang="ts">
6
- import { computed, defineComponent, inject, markRaw, onMounted, reactive, ref, watch } from 'vue';
7
- import { Bottom, Delete, DocumentCopy, Top } from '@element-plus/icons';
5
+ <script lang="ts" setup>
6
+ import { computed, inject, markRaw, reactive, ref, watch } from 'vue';
7
+ import { Bottom, Delete, DocumentCopy, Top } from '@element-plus/icons-vue';
8
8
 
9
- import { NodeType } from '@tmagic/schema';
10
- import type StageCore from '@tmagic/stage';
9
+ import { MNode, NodeType } from '@tmagic/schema';
10
+ import StageCore from '@tmagic/stage';
11
+ import { isPage } from '@tmagic/utils';
11
12
 
12
- import ContentMenu from '@editor/components/ContentMenu.vue';
13
- import { LayerOffset, Layout, MenuItem, Services } from '@editor/type';
14
- import { COPY_STORAGE_KEY } from '@editor/utils/editor';
13
+ import ContentMenu from '../../components/ContentMenu.vue';
14
+ import storageService from '../../services/storage';
15
+ import { LayerOffset, Layout, MenuItem, Services } from '../../type';
16
+ import { COPY_STORAGE_KEY } from '../../utils/editor';
15
17
 
16
- export default defineComponent({
17
- components: { ContentMenu },
18
+ const props = withDefaults(defineProps<{ isMultiSelect?: boolean }>(), { isMultiSelect: false });
18
19
 
19
- setup() {
20
- const services = inject<Services>('services');
21
- const editorService = services?.editorService;
22
- const menu = ref<InstanceType<typeof ContentMenu>>();
23
- const canPaste = ref(false);
24
- const canCenter = ref(false);
20
+ const services = inject<Services>('services');
21
+ const editorService = services?.editorService;
22
+ const menu = ref<InstanceType<typeof ContentMenu>>();
23
+ const canPaste = ref(false);
24
+ const canCenter = ref(false);
25
25
 
26
- const node = computed(() => editorService?.get('node'));
27
- const parent = computed(() => editorService?.get('parent'));
28
- const isPage = computed(() => node.value?.type === NodeType.PAGE);
26
+ const node = computed(() => editorService?.get<MNode>('node'));
27
+ const nodes = computed(() => editorService?.get<MNode[]>('nodes'));
28
+ const parent = computed(() => editorService?.get('parent'));
29
+ const stage = computed(() => editorService?.get<StageCore>('stage'));
29
30
 
30
- const stageContentMenu = inject<MenuItem[]>('stageContentMenu', []);
31
+ const stageContentMenu = inject<MenuItem[]>('stageContentMenu', []);
31
32
 
32
- onMounted(() => {
33
- const data = globalThis.localStorage.getItem(COPY_STORAGE_KEY);
34
- canPaste.value = data !== 'undefined' && !!data;
35
- });
36
-
37
- watch(
38
- parent,
39
- async () => {
40
- if (!parent.value || !editorService) return (canCenter.value = false);
41
- const layout = await editorService.getLayout(parent.value);
42
- canCenter.value =
43
- [Layout.ABSOLUTE, Layout.FIXED].includes(layout) &&
44
- ![NodeType.ROOT, NodeType.PAGE, 'pop'].includes(`${node.value?.type}`);
45
- },
46
- { immediate: true },
47
- );
48
-
49
- return {
50
- menu,
51
- menuData: reactive<MenuItem[]>([
52
- {
53
- type: 'button',
54
- text: '水平居中',
55
- display: () => canCenter.value,
56
- handler: () => {
57
- node.value && editorService?.alignCenter(node.value);
58
- },
59
- },
60
- {
61
- type: 'button',
62
- text: '复制',
63
- icon: markRaw(DocumentCopy),
64
- handler: () => {
65
- node.value && editorService?.copy(node.value);
66
- canPaste.value = true;
67
- },
68
- },
69
- {
70
- type: 'button',
71
- text: '粘贴',
72
- display: () => canPaste.value,
73
- handler: () => {
74
- const stage = editorService?.get<StageCore>('stage');
33
+ const menuData = reactive<MenuItem[]>([
34
+ {
35
+ type: 'button',
36
+ text: '水平居中',
37
+ display: () => canCenter.value,
38
+ handler: () => {
39
+ if (!nodes.value) return;
40
+ editorService?.alignCenter(nodes.value);
41
+ },
42
+ },
43
+ {
44
+ type: 'button',
45
+ text: '复制',
46
+ icon: markRaw(DocumentCopy),
47
+ handler: () => {
48
+ nodes.value && editorService?.copy(nodes.value);
49
+ canPaste.value = true;
50
+ },
51
+ },
52
+ {
53
+ type: 'button',
54
+ text: '粘贴',
55
+ display: () => canPaste.value,
56
+ handler: () => {
57
+ const rect = menu.value?.$el.getBoundingClientRect();
58
+ const parentRect = stage.value?.container?.getBoundingClientRect();
59
+ const initialLeft = (rect?.left || 0) - (parentRect?.left || 0);
60
+ const initialTop = (rect?.top || 0) - (parentRect?.top || 0);
75
61
 
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);
62
+ if (!nodes.value || nodes.value.length === 0) return;
63
+ editorService?.paste({ left: initialLeft, top: initialTop });
64
+ },
65
+ },
66
+ {
67
+ type: 'divider',
68
+ direction: 'horizontal',
69
+ display: () => {
70
+ if (!node.value) return false;
71
+ return !isPage(node.value);
72
+ },
73
+ },
74
+ {
75
+ type: 'button',
76
+ text: '上移一层',
77
+ icon: markRaw(Top),
78
+ display: () => !isPage(node.value) && !props.isMultiSelect,
79
+ handler: () => {
80
+ editorService?.moveLayer(1);
81
+ },
82
+ },
83
+ {
84
+ type: 'button',
85
+ text: '下移一层',
86
+ icon: markRaw(Bottom),
87
+ display: () => !isPage(node.value) && !props.isMultiSelect,
88
+ handler: () => {
89
+ editorService?.moveLayer(-1);
90
+ },
91
+ },
92
+ {
93
+ type: 'button',
94
+ text: '置顶',
95
+ display: () => !isPage(node.value) && !props.isMultiSelect,
96
+ handler: () => {
97
+ editorService?.moveLayer(LayerOffset.TOP);
98
+ },
99
+ },
100
+ {
101
+ type: 'button',
102
+ text: '置底',
103
+ display: () => !isPage(node.value) && !props.isMultiSelect,
104
+ handler: () => {
105
+ editorService?.moveLayer(LayerOffset.BOTTOM);
106
+ },
107
+ },
108
+ {
109
+ type: 'divider',
110
+ direction: 'horizontal',
111
+ display: () => !isPage(node.value) && !props.isMultiSelect,
112
+ },
113
+ {
114
+ type: 'button',
115
+ text: '删除',
116
+ icon: Delete,
117
+ display: () => !isPage(node.value),
118
+ handler: () => {
119
+ nodes.value && editorService?.remove(nodes.value);
120
+ },
121
+ },
122
+ {
123
+ type: 'divider',
124
+ direction: 'horizontal',
125
+ },
126
+ {
127
+ type: 'button',
128
+ text: '清空参考线',
129
+ handler: () => {
130
+ editorService?.get<StageCore>('stage').clearGuides();
131
+ },
132
+ },
133
+ ...stageContentMenu,
134
+ ]);
80
135
 
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
- }
136
+ watch(
137
+ parent,
138
+ async () => {
139
+ if (!parent.value || !editorService) return (canCenter.value = false);
140
+ const layout = await editorService.getLayout(parent.value);
141
+ const isLayoutConform = [Layout.ABSOLUTE, Layout.FIXED].includes(layout);
142
+ const isTypeConform = nodes.value?.every(
143
+ (selectedNode) => ![NodeType.ROOT, NodeType.PAGE, 'pop'].includes(`${selectedNode?.type}`),
144
+ );
145
+ canCenter.value = isLayoutConform && !!isTypeConform;
146
+ },
147
+ { immediate: true },
148
+ );
87
149
 
88
- editorService?.paste({ left, top });
89
- },
90
- },
91
- {
92
- type: 'divider',
93
- direction: 'horizontal',
94
- display: () => !isPage.value,
95
- },
96
- {
97
- type: 'button',
98
- text: '上移一层',
99
- icon: markRaw(Top),
100
- display: () => !isPage.value,
101
- handler: () => {
102
- editorService?.moveLayer(1);
103
- },
104
- },
105
- {
106
- type: 'button',
107
- text: '下移一层',
108
- icon: markRaw(Bottom),
109
- display: () => !isPage.value,
110
- handler: () => {
111
- editorService?.moveLayer(-1);
112
- },
113
- },
114
- {
115
- type: 'button',
116
- text: '置顶',
117
- display: () => !isPage.value,
118
- handler: () => {
119
- editorService?.moveLayer(LayerOffset.TOP);
120
- },
121
- },
122
- {
123
- type: 'button',
124
- text: '置底',
125
- display: () => !isPage.value,
126
- handler: () => {
127
- editorService?.moveLayer(LayerOffset.BOTTOM);
128
- },
129
- },
130
- {
131
- type: 'divider',
132
- direction: 'horizontal',
133
- display: () => !isPage.value,
134
- },
135
- {
136
- type: 'button',
137
- text: '删除',
138
- icon: Delete,
139
- display: () => !isPage.value,
140
- handler: () => {
141
- node.value && editorService?.remove(node.value);
142
- },
143
- },
144
- {
145
- type: 'divider',
146
- direction: 'horizontal',
147
- },
148
- {
149
- type: 'button',
150
- text: '清空参考线',
151
- handler: () => {
152
- editorService?.get<StageCore>('stage').clearGuides();
153
- },
154
- },
155
- ...stageContentMenu,
156
- ]),
150
+ const show = async (e: MouseEvent) => {
151
+ menu.value?.show(e);
152
+ const data = await storageService.getItem(COPY_STORAGE_KEY);
153
+ canPaste.value = data !== 'undefined' && !!data;
154
+ };
157
155
 
158
- show(e: MouseEvent) {
159
- menu.value?.show(e);
160
- },
161
- };
162
- },
163
- });
156
+ defineExpose({ show });
164
157
  </script>
@@ -18,7 +18,7 @@ import KeyController from 'keycon';
18
18
  import type { MNode, MPage } from '@tmagic/schema';
19
19
  import { isPage } from '@tmagic/utils';
20
20
 
21
- import type { Services } from '@editor/type';
21
+ import type { Services } from '../../type';
22
22
 
23
23
  import PageBar from './PageBar.vue';
24
24
  import MagicStage from './Stage.vue';
@@ -34,7 +34,7 @@ export default defineComponent({
34
34
  setup() {
35
35
  const services = inject<Services>('services');
36
36
  const workspace = ref<HTMLDivElement>();
37
- const node = computed(() => services?.editorService.get<MNode>('node'));
37
+ const nodes = computed(() => services?.editorService.get<MNode[]>('nodes'));
38
38
  let keycon: KeyController;
39
39
 
40
40
  const mouseenterHandler = () => {
@@ -58,27 +58,27 @@ export default defineComponent({
58
58
  keycon
59
59
  .keyup('delete', (e) => {
60
60
  e.inputEvent.preventDefault();
61
- if (!node.value || isPage(node.value)) return;
62
- services?.editorService.remove(node.value);
61
+ if (!nodes.value || isPage(nodes.value[0])) return;
62
+ services?.editorService.remove(nodes.value);
63
63
  })
64
64
  .keyup('backspace', (e) => {
65
65
  e.inputEvent.preventDefault();
66
- if (!node.value || isPage(node.value)) return;
67
- services?.editorService.remove(node.value);
66
+ if (!nodes.value || isPage(nodes.value[0])) return;
67
+ services?.editorService.remove(nodes.value);
68
68
  })
69
69
  .keydown([ctrl, 'c'], (e) => {
70
70
  e.inputEvent.preventDefault();
71
- node.value && services?.editorService.copy(node.value);
71
+ nodes.value && services?.editorService.copy(nodes.value);
72
72
  })
73
73
  .keydown([ctrl, 'v'], (e) => {
74
74
  e.inputEvent.preventDefault();
75
- node.value && services?.editorService.paste();
75
+ nodes.value && services?.editorService.paste({ offsetX: 10, offsetY: 10 });
76
76
  })
77
77
  .keydown([ctrl, 'x'], (e) => {
78
78
  e.inputEvent.preventDefault();
79
- if (!node.value || isPage(node.value)) return;
80
- services?.editorService.copy(node.value);
81
- services?.editorService.remove(node.value);
79
+ if (!nodes.value || isPage(nodes.value[0])) return;
80
+ services?.editorService.copy(nodes.value);
81
+ services?.editorService.remove(nodes.value);
82
82
  })
83
83
  .keydown([ctrl, 'z'], (e) => {
84
84
  e.inputEvent.preventDefault();
@@ -18,7 +18,7 @@
18
18
 
19
19
  import { EventEmitter } from 'events';
20
20
 
21
- import { compose } from '@editor/utils/compose';
21
+ import { compose } from '../utils/compose';
22
22
 
23
23
  const methodName = (prefix: string, name: string) => `${prefix}${name[0].toUpperCase()}${name.substring(1)}`;
24
24
 
@@ -36,18 +36,13 @@ const doAction = async (
36
36
  let beforeArgs = args;
37
37
 
38
38
  for (const beforeMethod of scope.pluginOptionsList[beforeMethodName]) {
39
- let beforeReturnValue = (await beforeMethod(...beforeArgs)) || [];
39
+ beforeArgs = (await beforeMethod(...beforeArgs)) || [];
40
40
 
41
- if (isError(beforeReturnValue)) throw beforeReturnValue;
41
+ if (isError(beforeArgs)) throw beforeArgs;
42
42
 
43
- if (!Array.isArray(beforeReturnValue)) {
44
- beforeReturnValue = [beforeReturnValue];
43
+ if (!Array.isArray(beforeArgs)) {
44
+ beforeArgs = [beforeArgs];
45
45
  }
46
-
47
- beforeArgs = beforeArgs.map((v: any, index: number) => {
48
- if (typeof beforeReturnValue[index] === 'undefined') return v;
49
- return beforeReturnValue[index];
50
- });
51
46
  }
52
47
 
53
48
  let returnValue: any = await fn(beforeArgs, sourceMethod.bind(scope));
@@ -18,7 +18,7 @@
18
18
 
19
19
  import { reactive } from 'vue';
20
20
 
21
- import type { ComponentGroup, ComponentGroupState } from '@editor/type';
21
+ import type { ComponentGroup, ComponentGroupState } from '../type';
22
22
 
23
23
  import BaseService from './BaseService';
24
24
 
@@ -34,11 +34,11 @@ class ComponentList extends BaseService {
34
34
  /**
35
35
  * @param componentGroupList 组件列表配置
36
36
  */
37
- public setList(componentGroupList: ComponentGroup[]) {
37
+ public setList(componentGroupList: ComponentGroup[]): void {
38
38
  this.state.list = componentGroupList;
39
39
  }
40
40
 
41
- public getList() {
41
+ public getList(): ComponentGroup[] {
42
42
  return this.state.list;
43
43
  }
44
44
  }