@tmagic/editor 1.1.0-beta.1 → 1.1.0-beta.12

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 (106) hide show
  1. package/dist/style.css +5 -1
  2. package/dist/{tmagic-editor.es.js → tmagic-editor.mjs} +1449 -1205
  3. package/dist/tmagic-editor.mjs.map +1 -0
  4. package/dist/tmagic-editor.umd.js +1463 -1219
  5. package/dist/tmagic-editor.umd.js.map +1 -1
  6. package/package.json +23 -21
  7. package/src/Editor.vue +24 -15
  8. package/src/components/ContentMenu.vue +87 -99
  9. package/src/components/Icon.vue +1 -1
  10. package/src/components/ScrollViewer.vue +2 -2
  11. package/src/components/ToolButton.vue +150 -167
  12. package/src/fields/UISelect.vue +51 -72
  13. package/src/index.ts +2 -1
  14. package/src/layouts/AddPageBox.vue +2 -2
  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 +6 -17
  20. package/src/layouts/sidebar/LayerMenu.vue +2 -2
  21. package/src/layouts/sidebar/LayerPanel.vue +52 -12
  22. package/src/layouts/sidebar/Sidebar.vue +1 -1
  23. package/src/layouts/sidebar/TabPane.vue +2 -2
  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 +198 -219
  27. package/src/layouts/workspace/ViewerMenu.vue +140 -147
  28. package/src/layouts/workspace/Workspace.vue +14 -12
  29. package/src/services/BaseService.ts +5 -10
  30. package/src/services/componentList.ts +3 -3
  31. package/src/services/editor.ts +208 -147
  32. package/src/services/events.ts +1 -1
  33. package/src/services/history.ts +1 -1
  34. package/src/services/props.ts +74 -49
  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 +25 -7
  41. package/src/utils/config.ts +1 -1
  42. package/src/utils/editor.ts +20 -12
  43. package/src/utils/operator.ts +109 -0
  44. package/src/utils/props.ts +2 -27
  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 +17 -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 +1101 -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 +22 -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/types/services/props.d.ts +97 -0
  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 +18 -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 +6 -3
  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 -23
  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 -16
  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/services/props.d.ts +0 -42
  104. package/dist/types/src/shims-vue.d.ts +0 -6
  105. package/dist/types/src/vite-env.d.ts +0 -1
  106. package/src/vite-env.d.ts +0 -1
@@ -15,6 +15,7 @@
15
15
  v-if="values.length"
16
16
  ref="tree"
17
17
  node-key="id"
18
+ empty-text="页面空荡荡的"
18
19
  draggable
19
20
  :default-expanded-keys="expandedKeys"
20
21
  :load="loadItems"
@@ -29,7 +30,8 @@
29
30
  @node-click="clickHandler"
30
31
  @node-contextmenu="contextmenu"
31
32
  @node-drag-end="handleDragEnd"
32
- empty-text="页面空荡荡的"
33
+ @node-collapse="handleCollapse"
34
+ @node-expand="handleExpand"
33
35
  >
34
36
  <template #default="{ node, data }">
35
37
  <div
@@ -60,12 +62,13 @@ import { computed, defineComponent, inject, Ref, ref, watchEffect } from 'vue';
60
62
  import type { ElTree } from 'element-plus';
61
63
  import { throttle } from 'lodash-es';
62
64
 
63
- import type { MNode, MPage } from '@tmagic/schema';
64
- import { NodeType } from '@tmagic/schema';
65
+ import type { Id, MNode, MPage } from '@tmagic/schema';
66
+ import { MContainer, NodeType } from '@tmagic/schema';
65
67
  import StageCore from '@tmagic/stage';
66
68
 
67
- import type { EditorService } from '@editor/services/editor';
68
- import type { Services } from '@editor/type';
69
+ import type { EditorService } from '../../services/editor';
70
+ import type { Services } from '../../type';
71
+ import { Layout } from '../../type';
69
72
 
70
73
  import LayerMenu from './LayerMenu.vue';
71
74
 
@@ -104,8 +107,16 @@ const useDrop = (tree: Ref<InstanceType<typeof ElTree> | undefined>, editorServi
104
107
  return false;
105
108
  },
106
109
 
107
- handleDragEnd() {
110
+ async handleDragEnd(e: any) {
108
111
  if (!tree.value) return;
112
+ const { data: node } = e;
113
+ const parent = editorService?.getParentById(node.id, false) as MContainer;
114
+ const layout = await editorService?.getLayout(parent);
115
+ node.style.position = layout;
116
+ if (layout === Layout.RELATIVE) {
117
+ node.style.top = 0;
118
+ node.style.left = 0;
119
+ }
109
120
  const { data } = tree.value;
110
121
  const [page] = data as [MPage];
111
122
  editorService?.update(page);
@@ -113,22 +124,41 @@ const useDrop = (tree: Ref<InstanceType<typeof ElTree> | undefined>, editorServi
113
124
  });
114
125
 
115
126
  const useStatus = (tree: Ref<InstanceType<typeof ElTree> | undefined>, editorService?: EditorService) => {
116
- const highlightNode = ref<MNode>();
117
127
  const node = ref<MNode>();
118
128
  const page = computed(() => editorService?.get('page'));
129
+ const expandedKeys = new Map<Id, Id>();
130
+
131
+ const expandNodes = () => {
132
+ expandedKeys.forEach((key) => {
133
+ if (!tree.value) return;
134
+ tree.value.getNode(key)?.expand();
135
+ });
136
+ };
119
137
 
120
138
  watchEffect(() => {
121
139
  if (!tree.value) return;
122
- node.value = editorService?.get('node');
123
- node.value && tree.value.setCurrentKey(node.value.id, true);
140
+ if (!editorService) return;
141
+ node.value = editorService.get('node');
142
+
143
+ if (!node.value) return;
124
144
 
125
- const parent = editorService?.get('parent');
145
+ tree.value.setCurrentKey(node.value.id, true);
146
+
147
+ const parent = editorService.get('parent');
126
148
  if (!parent?.id) return;
127
149
 
128
150
  const treeNode = tree.value.getNode(parent.id);
129
151
  treeNode?.updateChildren();
130
152
 
131
- highlightNode.value = editorService?.get('highlightNode');
153
+ setTimeout(() => {
154
+ tree.value &&
155
+ Object.entries(tree.value.store.nodesMap).forEach(([id, node]) => {
156
+ if (node.expanded && node.data.items) {
157
+ expandedKeys.set(id, id);
158
+ }
159
+ });
160
+ expandNodes();
161
+ });
132
162
  });
133
163
 
134
164
  return {
@@ -144,9 +174,19 @@ const useStatus = (tree: Ref<InstanceType<typeof ElTree> | undefined>, editorSer
144
174
  resolve([]);
145
175
  },
146
176
 
147
- highlightNode,
177
+ highlightNode: computed(() => editorService?.get('highlightNode')),
148
178
  clickNode: node,
149
179
  expandedKeys: computed(() => (node.value ? [node.value.id] : [])),
180
+
181
+ handleCollapse: (data: MNode) => {
182
+ expandedKeys.delete(data.id);
183
+ },
184
+
185
+ handleExpand: (data: MNode) => {
186
+ const parent = editorService?.getParentById(data.id);
187
+ if (!parent?.id) return;
188
+ expandedKeys.set(parent.id, parent.id);
189
+ },
150
190
  };
151
191
  };
152
192
 
@@ -21,7 +21,7 @@
21
21
  <script lang="ts">
22
22
  import { defineComponent, PropType, ref, watch } from 'vue';
23
23
 
24
- import { SideBarData } from '@editor/type';
24
+ import { SideBarData } from '../../type';
25
25
 
26
26
  import TabPane from './TabPane.vue';
27
27
 
@@ -29,8 +29,8 @@
29
29
  import { computed, defineComponent, PropType } from 'vue';
30
30
  import { Coin, Files } from '@element-plus/icons-vue';
31
31
 
32
- import MIcon from '@editor/components/Icon.vue';
33
- import { SideComponent, SideItem } from '@editor/type';
32
+ import MIcon from '../../components/Icon.vue';
33
+ import { SideComponent, SideItem } from '../../type';
34
34
 
35
35
  import ComponentListPanel from './ComponentListPanel.vue';
36
36
  import LayerPanel from './LayerPanel.vue';
@@ -1,211 +1,82 @@
1
1
  <template>
2
- <div class="m-editor-page-bar" ref="pageBar">
3
- <div id="m-editor-page-bar-add-icon" class="m-editor-page-bar-item m-editor-page-bar-item-icon" @click="addPage">
4
- <el-icon><plus></plus></el-icon>
5
- </div>
6
- <div v-if="canScroll" class="m-editor-page-bar-item m-editor-page-bar-item-icon" @click="scroll('left')">
7
- <el-icon><arrow-left-bold></arrow-left-bold></el-icon>
8
- </div>
9
- <div v-if="root" class="m-editor-page-bar-items" ref="itemsContainer" :style="`width: ${itemsContainerWidth}px`">
10
- <div
11
- v-for="item in root.items"
12
- :key="item.key"
13
- class="m-editor-page-bar-item"
14
- :class="{ active: page?.id === item.id }"
15
- @click="switchPage(item)"
16
- >
17
- <div class="m-editor-page-bar-title">
18
- <slot name="page-bar-title" :page="item">
19
- <el-tooltip effect="dark" placement="top-start" :content="item.name">
20
- <span>{{ item.name }}</span>
21
- </el-tooltip>
2
+ <PageBarScrollContainer>
3
+ <div
4
+ v-for="item in (root && root.items) || []"
5
+ class="m-editor-page-bar-item"
6
+ :key="item.key"
7
+ :class="{ active: page?.id === item.id }"
8
+ @click="switchPage(item)"
9
+ >
10
+ <div class="m-editor-page-bar-title">
11
+ <slot name="page-bar-title" :page="item">
12
+ <el-tooltip effect="dark" placement="top-start" :content="item.name">
13
+ <span>{{ item.name || item.id }}</span>
14
+ </el-tooltip>
15
+ </slot>
16
+ </div>
17
+
18
+ <el-popover popper-class="page-bar-popover" placement="top" :width="160" trigger="hover">
19
+ <div>
20
+ <slot name="page-bar-popover" :page="item">
21
+ <tool-button
22
+ :data="{
23
+ type: 'button',
24
+ text: '复制',
25
+ icon: DocumentCopy,
26
+ handler: () => copy(item),
27
+ }"
28
+ ></tool-button>
29
+ <tool-button
30
+ :data="{
31
+ type: 'button',
32
+ text: '删除',
33
+ icon: Delete,
34
+ handler: () => remove(item),
35
+ }"
36
+ ></tool-button>
22
37
  </slot>
23
38
  </div>
24
-
25
- <el-popover popper-class="page-bar-popover" placement="top" :width="160" trigger="hover">
26
- <div>
27
- <slot name="page-bar-popover" :page="item">
28
- <tool-button
29
- :data="{
30
- type: 'button',
31
- text: '复制',
32
- icon: DocumentCopy,
33
- handler: () => copy(item),
34
- }"
35
- ></tool-button>
36
- <tool-button
37
- :data="{
38
- type: 'button',
39
- text: '删除',
40
- icon: Delete,
41
- handler: () => remove(item),
42
- }"
43
- ></tool-button>
44
- </slot>
45
- </div>
46
- <template #reference>
47
- <el-icon class="m-editor-page-bar-menu-icon">
48
- <caret-bottom></caret-bottom>
49
- </el-icon>
50
- </template>
51
- </el-popover>
52
- </div>
39
+ <template #reference>
40
+ <el-icon class="m-editor-page-bar-menu-icon">
41
+ <caret-bottom></caret-bottom>
42
+ </el-icon>
43
+ </template>
44
+ </el-popover>
53
45
  </div>
54
- <div v-if="canScroll" class="m-editor-page-bar-item m-editor-page-bar-item-icon" @click="scroll('right')">
55
- <el-icon><arrow-right-bold></arrow-right-bold></el-icon>
56
- </div>
57
- </div>
46
+ </PageBarScrollContainer>
58
47
  </template>
59
48
 
60
- <script lang="ts">
61
- import {
62
- computed,
63
- ComputedRef,
64
- defineComponent,
65
- inject,
66
- markRaw,
67
- onMounted,
68
- onUnmounted,
69
- ref,
70
- toRaw,
71
- watch,
72
- } from 'vue';
73
- import { ArrowLeftBold, ArrowRightBold, CaretBottom, Delete, DocumentCopy, Plus } from '@element-plus/icons-vue';
49
+ <script lang="ts" setup>
50
+ import { computed, inject } from 'vue';
51
+ import { CaretBottom, Delete, DocumentCopy } from '@element-plus/icons-vue';
74
52
 
75
53
  import type { MApp, MPage } from '@tmagic/schema';
76
- import { NodeType } from '@tmagic/schema';
77
-
78
- import ToolButton from '@editor/components/ToolButton.vue';
79
- import type { Services } from '@editor/type';
80
- import { generatePageNameByApp } from '@editor/utils/editor';
81
-
82
- const useScroll = (root: ComputedRef<MApp | undefined>) => {
83
- const pageBar = ref<HTMLDivElement>();
84
- const itemsContainer = ref<HTMLDivElement>();
85
-
86
- const pageBarWidth = ref(0);
87
- const canScroll = ref(false);
88
-
89
- const itemsContainerWidth = computed(() => pageBarWidth.value - 105);
90
-
91
- let translateLeft = 0;
92
- const resizeObserver = new ResizeObserver((entries) => {
93
- for (const { contentRect } of entries) {
94
- const { width } = contentRect;
95
- pageBarWidth.value = width || 0;
96
-
97
- setCanScroll();
98
- }
99
- });
100
-
101
- const setCanScroll = () => {
102
- if (itemsContainer.value) {
103
- canScroll.value = itemsContainer.value.scrollWidth > pageBarWidth.value - 105;
104
- }
105
- };
106
-
107
- const scroll = (type: 'left' | 'right' | 'start' | 'end') => {
108
- if (!itemsContainer.value) return;
109
54
 
110
- const maxScrollLeft = itemsContainer.value.scrollWidth - itemsContainerWidth.value;
55
+ import ToolButton from '../../components/ToolButton.vue';
56
+ import type { Services } from '../../type';
111
57
 
112
- if (type === 'left') {
113
- translateLeft += 100;
58
+ import PageBarScrollContainer from './PageBarScrollContainer.vue';
114
59
 
115
- if (translateLeft > 0) {
116
- translateLeft = 0;
117
- }
118
- } else if (type === 'right') {
119
- translateLeft -= 100;
60
+ const services = inject<Services>('services');
61
+ const editorService = services?.editorService;
120
62
 
121
- if (-translateLeft > maxScrollLeft) {
122
- translateLeft = -maxScrollLeft;
123
- }
124
- } else if (type === 'start') {
125
- translateLeft = 0;
126
- } else if (type === 'end') {
127
- translateLeft = -maxScrollLeft;
128
- }
63
+ const root = computed(() => editorService?.get<MApp>('root'));
129
64
 
130
- itemsContainer.value.style.transform = `translate(${translateLeft}px, 0px)`;
131
- };
65
+ const page = computed(() => editorService?.get('page'));
132
66
 
133
- onMounted(() => {
134
- pageBar.value && resizeObserver.observe(pageBar.value);
135
- });
67
+ const switchPage = (page: MPage) => {
68
+ editorService?.select(page);
69
+ };
136
70
 
137
- onUnmounted(() => {
138
- resizeObserver.disconnect();
71
+ const copy = (node: MPage) => {
72
+ node && editorService?.copy(node);
73
+ editorService?.paste({
74
+ left: 0,
75
+ top: 0,
139
76
  });
140
-
141
- watch(
142
- () => root.value?.items.length,
143
- (length = 0, preLength = 0) => {
144
- setTimeout(() => {
145
- setCanScroll();
146
- if (length < preLength) {
147
- scroll('start');
148
- } else {
149
- scroll('end');
150
- }
151
- });
152
- },
153
- );
154
-
155
- return {
156
- pageBar,
157
- itemsContainer,
158
- canScroll,
159
-
160
- itemsContainerWidth,
161
-
162
- scroll,
163
- };
164
77
  };
165
78
 
166
- export default defineComponent({
167
- components: { ArrowLeftBold, ArrowRightBold, CaretBottom, Plus, ToolButton },
168
-
169
- setup() {
170
- const services = inject<Services>('services');
171
- const editorService = services?.editorService;
172
-
173
- const root = computed(() => editorService?.get<MApp>('root'));
174
-
175
- return {
176
- Delete: markRaw(Delete),
177
- DocumentCopy: markRaw(DocumentCopy),
178
-
179
- ...useScroll(root),
180
-
181
- root,
182
- page: computed(() => editorService?.get('page')),
183
-
184
- switchPage(page: MPage) {
185
- editorService?.select(page);
186
- },
187
-
188
- addPage() {
189
- if (!editorService) return;
190
- const pageConfig = {
191
- type: NodeType.PAGE,
192
- name: generatePageNameByApp(toRaw(editorService.get('root'))),
193
- };
194
- editorService.add(pageConfig);
195
- },
196
-
197
- copy(node: MPage) {
198
- node && editorService?.copy(node);
199
- editorService?.paste({
200
- left: 0,
201
- top: 0,
202
- });
203
- },
204
-
205
- remove(node: MPage) {
206
- editorService?.remove(node);
207
- },
208
- };
209
- },
210
- });
79
+ const remove = (node: MPage) => {
80
+ editorService?.remove(node);
81
+ };
211
82
  </script>
@@ -0,0 +1,111 @@
1
+ <template>
2
+ <div class="m-editor-page-bar" ref="pageBar">
3
+ <div id="m-editor-page-bar-add-icon" class="m-editor-page-bar-item m-editor-page-bar-item-icon" @click="addPage">
4
+ <el-icon><plus></plus></el-icon>
5
+ </div>
6
+ <div v-if="canScroll" class="m-editor-page-bar-item m-editor-page-bar-item-icon" @click="scroll('left')">
7
+ <el-icon><arrow-left-bold></arrow-left-bold></el-icon>
8
+ </div>
9
+ <div v-if="root" class="m-editor-page-bar-items" ref="itemsContainer" :style="`width: ${itemsContainerWidth}px`">
10
+ <slot></slot>
11
+ </div>
12
+ <div v-if="canScroll" class="m-editor-page-bar-item m-editor-page-bar-item-icon" @click="scroll('right')">
13
+ <el-icon><arrow-right-bold></arrow-right-bold></el-icon>
14
+ </div>
15
+ </div>
16
+ </template>
17
+
18
+ <script setup lang="ts">
19
+ import { computed, inject, onMounted, onUnmounted, ref, toRaw, watch } from 'vue';
20
+ import { ArrowLeftBold, ArrowRightBold, Plus } from '@element-plus/icons-vue';
21
+
22
+ import { MApp, NodeType } from '@tmagic/schema';
23
+
24
+ import type { Services } from '../../type';
25
+ import { generatePageNameByApp } from '../../utils/editor';
26
+
27
+ const services = inject<Services>('services');
28
+ const editorService = services?.editorService;
29
+
30
+ const pageBar = ref<HTMLDivElement>();
31
+ const itemsContainer = ref<HTMLDivElement>();
32
+ const pageBarWidth = ref(0);
33
+ const canScroll = ref(false);
34
+
35
+ const itemsContainerWidth = computed(() => pageBarWidth.value - 105);
36
+
37
+ let translateLeft = 0;
38
+ const resizeObserver = new ResizeObserver((entries) => {
39
+ for (const { contentRect } of entries) {
40
+ const { width } = contentRect;
41
+ pageBarWidth.value = width || 0;
42
+
43
+ setCanScroll();
44
+ }
45
+ });
46
+
47
+ const setCanScroll = () => {
48
+ if (itemsContainer.value) {
49
+ canScroll.value = itemsContainer.value.scrollWidth > pageBarWidth.value - 105;
50
+ }
51
+ };
52
+
53
+ const scroll = (type: 'left' | 'right' | 'start' | 'end') => {
54
+ if (!itemsContainer.value) return;
55
+
56
+ const maxScrollLeft = itemsContainer.value.scrollWidth - itemsContainerWidth.value;
57
+
58
+ if (type === 'left') {
59
+ translateLeft += 100;
60
+
61
+ if (translateLeft > 0) {
62
+ translateLeft = 0;
63
+ }
64
+ } else if (type === 'right') {
65
+ translateLeft -= 100;
66
+
67
+ if (-translateLeft > maxScrollLeft) {
68
+ translateLeft = -maxScrollLeft;
69
+ }
70
+ } else if (type === 'start') {
71
+ translateLeft = 0;
72
+ } else if (type === 'end') {
73
+ translateLeft = -maxScrollLeft;
74
+ }
75
+
76
+ itemsContainer.value.style.transform = `translate(${translateLeft}px, 0px)`;
77
+ };
78
+
79
+ onMounted(() => {
80
+ pageBar.value && resizeObserver.observe(pageBar.value);
81
+ });
82
+
83
+ onUnmounted(() => {
84
+ resizeObserver.disconnect();
85
+ });
86
+
87
+ const root = computed(() => editorService?.get<MApp>('root'));
88
+
89
+ watch(
90
+ () => root.value?.items.length,
91
+ (length = 0, preLength = 0) => {
92
+ setTimeout(() => {
93
+ setCanScroll();
94
+ if (length < preLength) {
95
+ scroll('start');
96
+ } else {
97
+ scroll('end');
98
+ }
99
+ });
100
+ },
101
+ );
102
+
103
+ const addPage = () => {
104
+ if (!editorService) return;
105
+ const pageConfig = {
106
+ type: NodeType.PAGE,
107
+ name: generatePageNameByApp(toRaw(editorService.get('root'))),
108
+ };
109
+ editorService.add(pageConfig);
110
+ };
111
+ </script>