@tmagic/editor 1.5.7 → 1.5.8

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 (72) hide show
  1. package/dist/style.css +17 -0
  2. package/dist/tmagic-editor.js +463 -470
  3. package/dist/tmagic-editor.umd.cjs +471 -469
  4. package/package.json +7 -7
  5. package/src/components/CodeBlockEditor.vue +4 -4
  6. package/src/components/FloatingBox.vue +4 -4
  7. package/src/components/ToolButton.vue +6 -4
  8. package/src/components/TreeNode.vue +2 -2
  9. package/src/fields/CodeSelect.vue +6 -6
  10. package/src/fields/CodeSelectCol.vue +5 -4
  11. package/src/fields/CondOpSelect.vue +5 -4
  12. package/src/fields/DataSourceFieldSelect/FieldSelect.vue +6 -5
  13. package/src/fields/DataSourceFieldSelect/Index.vue +4 -3
  14. package/src/fields/DataSourceFields.vue +3 -3
  15. package/src/fields/DataSourceInput.vue +4 -4
  16. package/src/fields/DataSourceMethodSelect.vue +8 -9
  17. package/src/fields/DataSourceMocks.vue +3 -3
  18. package/src/fields/DataSourceSelect.vue +6 -5
  19. package/src/fields/DisplayConds.vue +4 -4
  20. package/src/fields/EventSelect.vue +17 -23
  21. package/src/fields/PageFragmentSelect.vue +6 -5
  22. package/src/fields/UISelect.vue +16 -19
  23. package/src/hooks/index.ts +1 -0
  24. package/src/hooks/use-code-block-edit.ts +5 -10
  25. package/src/hooks/use-data-source-edit.ts +6 -6
  26. package/src/hooks/use-editor-content-height.ts +5 -5
  27. package/src/hooks/use-float-box.ts +5 -5
  28. package/src/hooks/use-next-float-box-position.ts +9 -9
  29. package/src/hooks/use-services.ts +13 -0
  30. package/src/hooks/use-stage.ts +2 -6
  31. package/src/layouts/AddPageBox.vue +3 -7
  32. package/src/layouts/Framework.vue +27 -27
  33. package/src/layouts/NavMenu.vue +16 -16
  34. package/src/layouts/page-bar/AddButton.vue +4 -7
  35. package/src/layouts/page-bar/PageBar.vue +10 -10
  36. package/src/layouts/page-bar/PageBarScrollContainer.vue +7 -8
  37. package/src/layouts/page-bar/PageList.vue +6 -8
  38. package/src/layouts/props-panel/FormPanel.vue +6 -4
  39. package/src/layouts/props-panel/PropsPanel.vue +39 -49
  40. package/src/layouts/props-panel/use-style-panel.ts +35 -19
  41. package/src/layouts/sidebar/ComponentListPanel.vue +5 -5
  42. package/src/layouts/sidebar/Sidebar.vue +15 -9
  43. package/src/layouts/sidebar/code-block/CodeBlockList.vue +13 -18
  44. package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +4 -3
  45. package/src/layouts/sidebar/code-block/useContentMenu.ts +3 -3
  46. package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +5 -5
  47. package/src/layouts/sidebar/data-source/DataSourceList.vue +13 -17
  48. package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +6 -12
  49. package/src/layouts/sidebar/data-source/useContentMenu.ts +3 -3
  50. package/src/layouts/sidebar/layer/LayerMenu.vue +11 -8
  51. package/src/layouts/sidebar/layer/LayerNodeTool.vue +2 -6
  52. package/src/layouts/sidebar/layer/LayerPanel.vue +6 -12
  53. package/src/layouts/sidebar/layer/use-click.ts +16 -15
  54. package/src/layouts/sidebar/layer/use-drag.ts +6 -6
  55. package/src/layouts/sidebar/layer/use-keybinding.ts +6 -8
  56. package/src/layouts/sidebar/layer/use-node-status.ts +16 -7
  57. package/src/layouts/workspace/Breadcrumb.vue +8 -9
  58. package/src/layouts/workspace/Workspace.vue +4 -10
  59. package/src/layouts/workspace/viewer/NodeListMenu.vue +9 -8
  60. package/src/layouts/workspace/viewer/Stage.vue +24 -24
  61. package/src/layouts/workspace/viewer/StageOverlay.vue +15 -16
  62. package/src/layouts/workspace/viewer/ViewerMenu.vue +15 -14
  63. package/src/services/dep.ts +23 -8
  64. package/src/services/ui.ts +6 -2
  65. package/src/theme/common/var.scss +1 -0
  66. package/src/theme/sidebar.scss +20 -1
  67. package/src/type.ts +3 -9
  68. package/src/utils/const.ts +11 -0
  69. package/src/utils/content-menu.ts +28 -30
  70. package/src/utils/idle-task.ts +11 -0
  71. package/src/utils/index.ts +1 -0
  72. package/types/index.d.ts +28 -10
@@ -7,13 +7,14 @@
7
7
  </template>
8
8
 
9
9
  <script lang="ts" setup>
10
- import { computed, inject, markRaw, onBeforeUnmount, onMounted, useTemplateRef } from 'vue';
10
+ import { computed, markRaw, onBeforeUnmount, onMounted, useTemplateRef } from 'vue';
11
11
  import { Back, Delete, FullScreen, Grid, Memo, Right, ScaleToOriginal, ZoomIn, ZoomOut } from '@element-plus/icons-vue';
12
12
 
13
13
  import { NodeType } from '@tmagic/core';
14
14
 
15
15
  import ToolButton from '@editor/components/ToolButton.vue';
16
- import { ColumnLayout, MenuBarData, MenuButton, MenuComponent, MenuItem, Services } from '@editor/type';
16
+ import { useServices } from '@editor/hooks/use-services';
17
+ import { ColumnLayout, MenuBarData, MenuButton, MenuComponent, MenuItem } from '@editor/type';
17
18
 
18
19
  defineOptions({
19
20
  name: 'MEditorNavMenu',
@@ -30,15 +31,14 @@ const props = withDefaults(
30
31
  },
31
32
  );
32
33
 
33
- const services = inject<Services>('services');
34
- const uiService = services?.uiService;
34
+ const { uiService, editorService, historyService } = useServices();
35
35
 
36
- const columnWidth = computed(() => services?.uiService.get('columnWidth'));
36
+ const columnWidth = computed(() => uiService.get('columnWidth'));
37
37
  const keys = Object.values(ColumnLayout);
38
38
 
39
- const showGuides = computed((): boolean => uiService?.get('showGuides') ?? true);
40
- const showRule = computed((): boolean => uiService?.get('showRule') ?? true);
41
- const zoom = computed((): number => uiService?.get('zoom') ?? 1);
39
+ const showGuides = computed((): boolean => uiService.get('showGuides'));
40
+ const showRule = computed((): boolean => uiService.get('showRule'));
41
+ const zoom = computed((): number => uiService.get('zoom'));
42
42
 
43
43
  const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
44
44
  const ctrl = isMac ? 'Command' : 'Ctrl';
@@ -70,10 +70,10 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
70
70
  className: 'delete',
71
71
  icon: markRaw(Delete),
72
72
  tooltip: `刪除(Delete)`,
73
- disabled: () => services?.editorService.get('node')?.type === NodeType.PAGE,
73
+ disabled: () => editorService.get('node')?.type === NodeType.PAGE,
74
74
  handler: () => {
75
- const node = services?.editorService.get('node');
76
- node && services?.editorService.remove(node);
75
+ const node = editorService.get('node');
76
+ node && editorService.remove(node);
77
77
  },
78
78
  });
79
79
  break;
@@ -83,8 +83,8 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
83
83
  className: 'undo',
84
84
  icon: markRaw(Back),
85
85
  tooltip: `后退(${ctrl}+z)`,
86
- disabled: () => !services?.historyService.state.canUndo,
87
- handler: () => services?.editorService.undo(),
86
+ disabled: () => !historyService.state.canUndo,
87
+ handler: () => editorService.undo(),
88
88
  });
89
89
  break;
90
90
  case 'redo':
@@ -93,8 +93,8 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
93
93
  className: 'redo',
94
94
  icon: markRaw(Right),
95
95
  tooltip: `前进(${ctrl}+Shift+z)`,
96
- disabled: () => !services?.historyService.state.canRedo,
97
- handler: () => services?.editorService.redo(),
96
+ disabled: () => !historyService.state.canRedo,
97
+ handler: () => editorService.redo(),
98
98
  });
99
99
  break;
100
100
  case 'zoom-in':
@@ -184,7 +184,7 @@ const navMenuEl = useTemplateRef<HTMLDivElement>('navMenu');
184
184
  const resizeObserver = new ResizeObserver(() => {
185
185
  const rect = navMenuEl.value?.getBoundingClientRect();
186
186
  if (rect) {
187
- uiService?.set('navMenuRect', {
187
+ uiService.set('navMenuRect', {
188
188
  left: rect.left,
189
189
  top: rect.top,
190
190
  width: rect.width,
@@ -33,7 +33,7 @@
33
33
  </template>
34
34
 
35
35
  <script setup lang="ts">
36
- import { computed, inject, toRaw } from 'vue';
36
+ import { computed, toRaw } from 'vue';
37
37
  import { Plus } from '@element-plus/icons-vue';
38
38
 
39
39
  import { NodeType } from '@tmagic/core';
@@ -41,21 +41,18 @@ import { TMagicPopover } from '@tmagic/design';
41
41
 
42
42
  import Icon from '@editor/components/Icon.vue';
43
43
  import ToolButton from '@editor/components/ToolButton.vue';
44
- import type { Services } from '@editor/type';
44
+ import { useServices } from '@editor/hooks/use-services';
45
45
  import { generatePageNameByApp } from '@editor/utils/editor';
46
46
 
47
47
  defineOptions({
48
48
  name: 'MEditorPageBarAddButton',
49
49
  });
50
50
 
51
- const services = inject<Services>('services');
52
- const uiService = services?.uiService;
53
- const editorService = services?.editorService;
51
+ const { editorService, uiService } = useServices();
54
52
 
55
- const showAddPageButton = computed(() => uiService?.get('showAddPageButton'));
53
+ const showAddPageButton = computed(() => uiService.get('showAddPageButton'));
56
54
 
57
55
  const addPage = (type: NodeType.PAGE | NodeType.PAGE_FRAGMENT) => {
58
- if (!editorService) return;
59
56
  const root = toRaw(editorService.get('root'));
60
57
  if (!root) throw new Error('root 不能为空');
61
58
  const pageConfig = {
@@ -68,14 +68,15 @@
68
68
  </template>
69
69
 
70
70
  <script lang="ts" setup>
71
- import { computed, inject, ref, useTemplateRef, watch } from 'vue';
71
+ import { computed, ref, useTemplateRef, watch } from 'vue';
72
72
  import { CaretBottom, Delete, DocumentCopy } from '@element-plus/icons-vue';
73
73
 
74
74
  import { type Id, type MPage, type MPageFragment, NodeType } from '@tmagic/core';
75
75
  import { TMagicIcon, TMagicPopover } from '@tmagic/design';
76
76
 
77
77
  import ToolButton from '@editor/components/ToolButton.vue';
78
- import type { PageBarSortOptions, Services } from '@editor/type';
78
+ import { useServices } from '@editor/hooks/use-services';
79
+ import type { PageBarSortOptions } from '@editor/type';
79
80
 
80
81
  import AddButton from './AddButton.vue';
81
82
  import PageBarScrollContainer from './PageBarScrollContainer.vue';
@@ -97,11 +98,10 @@ const props = withDefaults(
97
98
  },
98
99
  );
99
100
 
100
- const services = inject<Services>('services');
101
- const editorService = services?.editorService;
101
+ const { editorService } = useServices();
102
102
 
103
- const root = computed(() => editorService?.get('root'));
104
- const page = computed(() => editorService?.get('page'));
103
+ const root = computed(() => editorService.get('root'));
104
+ const page = computed(() => editorService.get('page'));
105
105
 
106
106
  const query = ref<{
107
107
  pageType: NodeType[];
@@ -129,19 +129,19 @@ const list = computed(() => {
129
129
  });
130
130
 
131
131
  const switchPage = (id: Id) => {
132
- editorService?.select(id);
132
+ editorService.select(id);
133
133
  };
134
134
 
135
135
  const copy = (node: MPage | MPageFragment) => {
136
- node && editorService?.copy(node);
137
- editorService?.paste({
136
+ node && editorService.copy(node);
137
+ editorService.paste({
138
138
  left: 0,
139
139
  top: 0,
140
140
  });
141
141
  };
142
142
 
143
143
  const remove = (node: MPage | MPageFragment) => {
144
- editorService?.remove(node);
144
+ editorService.remove(node);
145
145
  };
146
146
 
147
147
  const pageBarScrollContainerRef = useTemplateRef<InstanceType<typeof PageBarScrollContainer>>('pageBarScrollContainer');
@@ -24,14 +24,15 @@
24
24
  </template>
25
25
 
26
26
  <script setup lang="ts">
27
- import { computed, inject, nextTick, onBeforeUnmount, onMounted, ref, useTemplateRef, watch } from 'vue';
27
+ import { computed, nextTick, onBeforeUnmount, onMounted, ref, useTemplateRef, watch } from 'vue';
28
28
  import { ArrowLeftBold, ArrowRightBold } from '@element-plus/icons-vue';
29
29
  import Sortable, { type SortableEvent } from 'sortablejs';
30
30
 
31
31
  import type { Id } from '@tmagic/core';
32
32
 
33
33
  import Icon from '@editor/components/Icon.vue';
34
- import type { PageBarSortOptions, Services } from '@editor/type';
34
+ import { useServices } from '@editor/hooks/use-services';
35
+ import type { PageBarSortOptions } from '@editor/type';
35
36
 
36
37
  defineOptions({
37
38
  name: 'MEditorPageBarScrollContainer',
@@ -42,15 +43,13 @@ const props = defineProps<{
42
43
  length: number;
43
44
  }>();
44
45
 
45
- const services = inject<Services>('services');
46
- const editorService = services?.editorService;
47
- const uiService = services?.uiService;
46
+ const { editorService, uiService } = useServices();
48
47
 
49
48
  const itemsContainerEl = useTemplateRef<HTMLElement>('itemsContainer');
50
49
  const canScroll = ref(false);
51
50
 
52
- const showAddPageButton = computed(() => uiService?.get('showAddPageButton'));
53
- const showPageListButton = computed(() => uiService?.get('showPageListButton'));
51
+ const showAddPageButton = computed(() => uiService.get('showAddPageButton'));
52
+ const showPageListButton = computed(() => uiService.get('showPageListButton'));
54
53
 
55
54
  const itemsContainerWidth = ref(0);
56
55
 
@@ -145,7 +144,7 @@ watch(
145
144
  beforeDragList = sortable.toArray();
146
145
  },
147
146
  onUpdate: async (event: SortableEvent) => {
148
- await editorService?.sort(
147
+ await editorService.sort(
149
148
  beforeDragList[event.oldIndex as number],
150
149
  beforeDragList[event.newIndex as number],
151
150
  );
@@ -35,14 +35,14 @@
35
35
  </template>
36
36
 
37
37
  <script setup lang="ts">
38
- import { computed, inject } from 'vue';
38
+ import { computed } from 'vue';
39
39
  import { Files } from '@element-plus/icons-vue';
40
40
 
41
41
  import { Id, MPage, MPageFragment } from '@tmagic/core';
42
42
  import { TMagicIcon, TMagicPopover } from '@tmagic/design';
43
43
 
44
44
  import ToolButton from '@editor/components/ToolButton.vue';
45
- import type { Services } from '@editor/type';
45
+ import { useServices } from '@editor/hooks/use-services';
46
46
  defineOptions({
47
47
  name: 'MEditorPageList',
48
48
  });
@@ -51,13 +51,11 @@ defineProps<{
51
51
  list: (MPage | MPageFragment)[];
52
52
  }>();
53
53
 
54
- const services = inject<Services>('services');
55
- const uiService = services?.uiService;
56
- const editorService = services?.editorService;
54
+ const { editorService, uiService } = useServices();
57
55
 
58
- const showPageListButton = computed(() => uiService?.get('showPageListButton'));
59
- const page = computed(() => editorService?.get('page'));
56
+ const showPageListButton = computed(() => uiService.get('showPageListButton'));
57
+ const page = computed(() => editorService.get('page'));
60
58
  const switchPage = async (id: Id) => {
61
- await editorService?.select(id);
59
+ await editorService.select(id);
62
60
  };
63
61
  </script>
@@ -51,7 +51,7 @@ import { MForm } from '@tmagic/form';
51
51
 
52
52
  import MIcon from '@editor/components/Icon.vue';
53
53
  import { useEditorContentHeight } from '@editor/hooks/use-editor-content-height';
54
- import type { Services } from '@editor/type';
54
+ import { useServices } from '@editor/hooks/use-services';
55
55
 
56
56
  import CodeEditor from '../CodeEditor.vue';
57
57
 
@@ -80,13 +80,15 @@ const emit = defineEmits<{
80
80
  mounted: [internalInstance: any];
81
81
  }>();
82
82
 
83
- const services = inject<Services>('services');
83
+ const services = useServices();
84
+ const { editorService, uiService } = services;
85
+
84
86
  const codeOptions = inject('codeOptions', {});
85
87
 
86
88
  const showSrc = ref(false);
87
- const propsPanelSize = computed(() => services?.uiService.get('propsPanelSize') || 'small');
89
+ const propsPanelSize = computed(() => uiService.get('propsPanelSize') || 'small');
88
90
  const { height: editorContentHeight } = useEditorContentHeight();
89
- const stage = computed(() => services?.editorService.get('stage'));
91
+ const stage = computed(() => editorService.get('stage'));
90
92
 
91
93
  const configFormRef = useTemplateRef<InstanceType<typeof MForm>>('configForm');
92
94
 
@@ -34,7 +34,9 @@
34
34
  <div class="m-editor-props-style-panel-title">
35
35
  <span>样式</span>
36
36
  <div>
37
- <TMagicButton link size="small" @click="closeStylePanelHandler"><MIcon :icon="Close"></MIcon></TMagicButton>
37
+ <TMagicButton link size="small" @click="toggleStylePanel(false)"
38
+ ><MIcon :icon="Close"></MIcon
39
+ ></TMagicButton>
38
40
  </div>
39
41
  </div>
40
42
  </template>
@@ -44,7 +46,7 @@
44
46
  v-if="showStylePanelToggleButton && !showStylePanel"
45
47
  class="m-editor-props-panel-style-icon"
46
48
  circle
47
- @click="showStylePanelHandler"
49
+ @click="toggleStylePanel(true)"
48
50
  >
49
51
  <MIcon :icon="Sugar"></MIcon>
50
52
  </TMagicButton>
@@ -52,7 +54,7 @@
52
54
  </template>
53
55
 
54
56
  <script lang="ts" setup>
55
- import { computed, inject, onBeforeUnmount, ref, useTemplateRef, watch, watchEffect } from 'vue';
57
+ import { computed, onBeforeUnmount, onMounted, ref, useTemplateRef, watch, watchEffect } from 'vue';
56
58
  import { Close, Sugar } from '@element-plus/icons-vue';
57
59
  import type { OnDrag } from 'gesto';
58
60
 
@@ -63,9 +65,11 @@ import { setValueByKeyPath } from '@tmagic/utils';
63
65
 
64
66
  import MIcon from '@editor/components/Icon.vue';
65
67
  import Resizer from '@editor/components/Resizer.vue';
66
- import type { PropsPanelSlots, Services } from '@editor/type';
68
+ import { useServices } from '@editor/hooks/use-services';
69
+ import { Protocol } from '@editor/services/storage';
70
+ import type { PropsPanelSlots } from '@editor/type';
67
71
  import { styleTabConfig } from '@editor/utils';
68
- import { RIGHT_COLUMN_WIDTH_STORAGE_KEY } from '@editor/utils/const';
72
+ import { PROPS_PANEL_WIDTH_STORAGE_KEY } from '@editor/utils/const';
69
73
 
70
74
  import FormPanel from './FormPanel.vue';
71
75
  import { useStylePanel } from './use-style-panel';
@@ -87,13 +91,13 @@ const emit = defineEmits<{
87
91
  mounted: [internalInstance: InstanceType<typeof FormPanel>];
88
92
  }>();
89
93
 
90
- const services = inject<Services>('services');
94
+ const { editorService, uiService, propsService, storageService } = useServices();
91
95
 
92
96
  const values = ref<FormValue>({});
93
97
  // ts类型应该是FormConfig, 但是打包时会出错,所以暂时用any
94
98
  const curFormConfig = ref<any>([]);
95
- const node = computed(() => services?.editorService.get('node'));
96
- const nodes = computed(() => services?.editorService.get('nodes') || []);
99
+ const node = computed(() => editorService.get('node'));
100
+ const nodes = computed(() => editorService.get('nodes'));
97
101
 
98
102
  const styleFormConfig = [
99
103
  {
@@ -109,15 +113,15 @@ const init = async () => {
109
113
  }
110
114
 
111
115
  const type = node.value.type || (node.value.items ? 'container' : 'text');
112
- curFormConfig.value = (await services?.propsService.getPropsConfig(type)) || [];
116
+ curFormConfig.value = await propsService.getPropsConfig(type);
113
117
  values.value = node.value;
114
118
  };
115
119
 
116
120
  watchEffect(init);
117
- services?.propsService.on('props-configs-change', init);
121
+ propsService.on('props-configs-change', init);
118
122
 
119
123
  onBeforeUnmount(() => {
120
- services?.propsService.off('props-configs-change', init);
124
+ propsService.off('props-configs-change', init);
121
125
  });
122
126
 
123
127
  const submit = async (v: MNode, eventData?: ContainerChangeEventData) => {
@@ -145,7 +149,7 @@ const submit = async (v: MNode, eventData?: ContainerChangeEventData) => {
145
149
  });
146
150
  }
147
151
 
148
- services?.editorService.update(newValue, { changeRecords: eventData?.changeRecords });
152
+ editorService.update(newValue, { changeRecords: eventData?.changeRecords });
149
153
  } catch (e: any) {
150
154
  emit('submit-error', e);
151
155
  }
@@ -162,8 +166,16 @@ const mountedHandler = () => {
162
166
  };
163
167
 
164
168
  const propsPanelEl = useTemplateRef('propsPanel');
169
+ const propsPanelWidth = ref(
170
+ storageService.getItem(PROPS_PANEL_WIDTH_STORAGE_KEY, { protocol: Protocol.NUMBER }) || 300,
171
+ );
172
+
173
+ onMounted(() => {
174
+ propsPanelEl.value?.style.setProperty('--props-style-panel-width', `${propsPanelWidth.value}px`);
175
+ });
176
+
165
177
  const widthChange = ({ deltaX }: OnDrag) => {
166
- if (!propsPanelEl.value || !services) {
178
+ if (!propsPanelEl.value) {
167
179
  return;
168
180
  }
169
181
 
@@ -172,47 +184,25 @@ const widthChange = ({ deltaX }: OnDrag) => {
172
184
  );
173
185
 
174
186
  let value = width - deltaX;
175
- if (value > services.uiService.get('columnWidth').right) {
176
- value = services.uiService.get('columnWidth').right - 40;
187
+ if (value > uiService.get('columnWidth').right) {
188
+ value = uiService.get('columnWidth').right - 40;
177
189
  }
178
- propsPanelEl.value.style.setProperty('--props-style-panel-width', `${value}px`);
190
+ propsPanelWidth.value = value;
179
191
  };
180
192
 
181
- const { showStylePanel, showStylePanelToggleButton, showStylePanelHandler, closeStylePanelHandler } =
182
- useStylePanel(services);
183
-
184
- watch(showStylePanel, (showStylePanel) => {
185
- if (!propsPanelEl.value || !services) {
186
- return;
187
- }
188
-
189
- const columnWidth = {
190
- ...services.uiService.get('columnWidth'),
191
- };
192
-
193
- const width = globalThis.parseFloat(
194
- getComputedStyle(propsPanelEl.value).getPropertyValue('--props-style-panel-width'),
195
- );
196
-
197
- if (showStylePanel) {
198
- columnWidth.right += width;
199
- columnWidth.center -= width;
200
- } else {
201
- columnWidth.right -= width;
202
- columnWidth.center += width;
203
- }
204
-
205
- if (columnWidth.center < 0) {
206
- columnWidth.right = columnWidth.right + columnWidth.center - 400;
207
- columnWidth.center = 400;
208
-
209
- propsPanelEl.value.style.setProperty('--props-style-panel-width', `${columnWidth.right / 2}px`);
210
- }
211
-
212
- globalThis.localStorage.setItem(RIGHT_COLUMN_WIDTH_STORAGE_KEY, `${columnWidth.right}`);
213
- services.uiService.set('columnWidth', columnWidth);
193
+ watch(propsPanelWidth, (value) => {
194
+ propsPanelEl.value?.style.setProperty('--props-style-panel-width', `${value}px`);
195
+ storageService.setItem(PROPS_PANEL_WIDTH_STORAGE_KEY, value, { protocol: Protocol.NUMBER });
214
196
  });
215
197
 
198
+ const { showStylePanel, showStylePanelToggleButton, toggleStylePanel } = useStylePanel(
199
+ {
200
+ storageService,
201
+ uiService,
202
+ },
203
+ propsPanelWidth,
204
+ );
205
+
216
206
  const propertyFormPanelRef = useTemplateRef<InstanceType<typeof FormPanel>>('propertyFormPanel');
217
207
  defineExpose({
218
208
  getFormState() {
@@ -1,40 +1,56 @@
1
- import { computed } from 'vue';
1
+ import { computed, type Ref } from 'vue';
2
2
 
3
3
  import { Protocol } from '@editor/services/storage';
4
4
  import { Services } from '@editor/type';
5
+ import { MIN_CENTER_COLUMN_WIDTH, RIGHT_COLUMN_WIDTH_STORAGE_KEY } from '@editor/utils/const';
5
6
 
6
- export const useStylePanel = (services?: Services) => {
7
+ export const useStylePanel = (
8
+ { uiService, storageService }: Pick<Services, 'uiService' | 'storageService'>,
9
+ propsPanelWidth: Ref<number>,
10
+ ) => {
7
11
  const showStylePanelStorageKey = 'props-panel-show-style-panel';
8
- const showStylePanelStorageValue = services?.storageService.getItem(showStylePanelStorageKey, {
12
+ const showStylePanelStorageValue = storageService.getItem(showStylePanelStorageKey, {
9
13
  protocol: Protocol.BOOLEAN,
10
14
  });
11
15
 
12
16
  if (typeof showStylePanelStorageValue === 'boolean') {
13
- services?.uiService.set('showStylePanel', showStylePanelStorageValue);
17
+ uiService.set('showStylePanel', showStylePanelStorageValue);
14
18
  }
15
19
 
16
- const showStylePanel = computed(
17
- () => showStylePanelToggleButton.value && (services?.uiService.get('showStylePanel') ?? true),
18
- );
20
+ const showStylePanel = computed(() => showStylePanelToggleButton.value && (uiService.get('showStylePanel') ?? true));
19
21
 
20
- const showStylePanelToggleButton = computed(
21
- () => !(services && services.uiService.get('frameworkRect').width < 1280),
22
- );
22
+ const showStylePanelToggleButton = computed(() => uiService.get('frameworkRect').width >= 1280);
23
23
 
24
- const showStylePanelHandler = () => {
25
- services?.uiService.set('showStylePanel', true);
26
- services?.storageService.setItem(showStylePanelStorageKey, true, { protocol: Protocol.BOOLEAN });
27
- };
24
+ const toggleStylePanel = (showStylePanel: boolean) => {
25
+ uiService.set('showStylePanel', showStylePanel);
26
+ storageService.setItem(showStylePanelStorageKey, showStylePanel, { protocol: Protocol.BOOLEAN });
27
+
28
+ const columnWidth = {
29
+ ...uiService.get('columnWidth'),
30
+ };
31
+
32
+ if (showStylePanel) {
33
+ columnWidth.right += propsPanelWidth.value;
34
+ columnWidth.center -= propsPanelWidth.value;
35
+ } else {
36
+ columnWidth.right -= propsPanelWidth.value;
37
+ columnWidth.center += propsPanelWidth.value;
38
+ }
39
+
40
+ if (columnWidth.center < 0) {
41
+ columnWidth.right = columnWidth.right + columnWidth.center - MIN_CENTER_COLUMN_WIDTH;
42
+ columnWidth.center = MIN_CENTER_COLUMN_WIDTH;
43
+
44
+ propsPanelWidth.value = columnWidth.right / 2;
45
+ }
28
46
 
29
- const closeStylePanelHandler = () => {
30
- services?.uiService.set('showStylePanel', false);
31
- services?.storageService.setItem(showStylePanelStorageKey, false, { protocol: Protocol.BOOLEAN });
47
+ storageService.setItem(RIGHT_COLUMN_WIDTH_STORAGE_KEY, columnWidth.right, { protocol: Protocol.NUMBER });
48
+ uiService.set('columnWidth', columnWidth);
32
49
  };
33
50
 
34
51
  return {
35
52
  showStylePanel,
36
53
  showStylePanelToggleButton,
37
- showStylePanelHandler,
38
- closeStylePanelHandler,
54
+ toggleStylePanel,
39
55
  };
40
56
  };
@@ -43,12 +43,12 @@ import { removeClassNameByClassName } from '@tmagic/utils';
43
43
 
44
44
  import MIcon from '@editor/components/Icon.vue';
45
45
  import SearchInput from '@editor/components/SearchInput.vue';
46
+ import { useServices } from '@editor/hooks/use-services';
46
47
  import {
47
48
  type ComponentGroup,
48
49
  type ComponentItem,
49
50
  ComponentListPanelSlots,
50
51
  DragType,
51
- type Services,
52
52
  type StageOptions,
53
53
  } from '@editor/type';
54
54
 
@@ -64,12 +64,12 @@ const filterTextChangeHandler = (v: string) => {
64
64
  searchText.value = v;
65
65
  };
66
66
 
67
- const services = inject<Services>('services');
67
+ const { editorService, componentListService } = useServices();
68
68
  const stageOptions = inject<StageOptions>('stageOptions');
69
69
 
70
- const stage = computed(() => services?.editorService.get('stage'));
70
+ const stage = computed(() => editorService.get('stage'));
71
71
  const list = computed<ComponentGroup[]>(() =>
72
- (services?.componentListService.getList() || []).map((group: ComponentGroup) => ({
72
+ componentListService.getList().map((group: ComponentGroup) => ({
73
73
  ...group,
74
74
  items: group.items.filter((item: ComponentItem) => item.text.includes(searchText.value)),
75
75
  })),
@@ -85,7 +85,7 @@ let clientX: number;
85
85
  let clientY: number;
86
86
 
87
87
  const appendComponent = ({ text, type, data = {} }: ComponentItem): void => {
88
- services?.editorService.add({
88
+ editorService.add({
89
89
  name: text,
90
90
  type,
91
91
  ...data,
@@ -117,6 +117,10 @@
117
117
  </template>
118
118
  </component>
119
119
  </div>
120
+ <div class="m-editor-sidebar-tips" v-if="tipsBarVisible && collecting && taskLength > 0">
121
+ <span>依赖收集中(剩余任务:{{ taskLength }})</span>
122
+ <MIcon :icon="Close" class="close-icon" @click.stop="tipsBarVisible = false"></MIcon>
123
+ </div>
120
124
  </div>
121
125
 
122
126
  <Teleport to="body">
@@ -149,19 +153,19 @@
149
153
  </template>
150
154
 
151
155
  <script setup lang="ts">
152
- import { computed, inject, nextTick, ref, watch } from 'vue';
153
- import { Coin, EditPen, Goods, List } from '@element-plus/icons-vue';
156
+ import { computed, nextTick, ref, watch } from 'vue';
157
+ import { Close, Coin, EditPen, Goods, List } from '@element-plus/icons-vue';
154
158
 
155
159
  import FloatingBox from '@editor/components/FloatingBox.vue';
156
160
  import MIcon from '@editor/components/Icon.vue';
157
161
  import { useEditorContentHeight } from '@editor/hooks/use-editor-content-height';
158
162
  import { useFloatBox } from '@editor/hooks/use-float-box';
163
+ import { useServices } from '@editor/hooks/use-services';
159
164
  import {
160
165
  ColumnLayout,
161
166
  CustomContentMenuFunction,
162
167
  type MenuButton,
163
168
  type MenuComponent,
164
- type Services,
165
169
  type SideBarData,
166
170
  type SidebarSlots,
167
171
  type SideComponent,
@@ -197,11 +201,13 @@ const props = withDefaults(
197
201
  },
198
202
  );
199
203
 
200
- const services = inject<Services>('services');
204
+ const { depService, uiService } = useServices();
201
205
 
202
- const collecting = computed(() => services?.depService.get('collecting'));
206
+ const collecting = computed(() => depService.get('collecting'));
207
+ const taskLength = computed(() => depService.get('taskLength'));
208
+ const tipsBarVisible = ref(true);
203
209
 
204
- const columnLeftWidth = computed(() => services?.uiService.get('columnWidth')[ColumnLayout.LEFT] || 0);
210
+ const columnLeftWidth = computed(() => uiService.get('columnWidth')[ColumnLayout.LEFT]);
205
211
  const { height: editorContentHeight } = useEditorContentHeight();
206
212
  const columnLeftHeight = ref(0);
207
213
 
@@ -282,7 +288,7 @@ const sideBarItems = computed(() => props.data.items.map((item) => getItemConfig
282
288
  watch(
283
289
  sideBarItems,
284
290
  (items) => {
285
- services?.uiService.set('sideBarItems', items);
291
+ uiService.set('sideBarItems', items);
286
292
  },
287
293
  {
288
294
  immediate: true,
@@ -310,10 +316,10 @@ watch(
310
316
  const nextSlideBarItem = sideBarItems.value.find((sideBarItem) => !showingBoxKeys.value.includes(sideBarItem.$key));
311
317
  if (!nextSlideBarItem) {
312
318
  activeTabName.value = '';
313
- services?.uiService.set('hideSlideBar', true);
319
+ uiService.set('hideSlideBar', true);
314
320
  return;
315
321
  }
316
- services?.uiService.set('hideSlideBar', false);
322
+ uiService.set('hideSlideBar', false);
317
323
  activeTabName.value = nextSlideBarItem?.text;
318
324
  },
319
325
  );