@tmagic/editor 1.3.6 → 1.3.7

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 (75) hide show
  1. package/LICENSE +5432 -0
  2. package/dist/style.css +15 -11
  3. package/dist/tmagic-editor.js +1312 -949
  4. package/dist/tmagic-editor.js.map +1 -1
  5. package/dist/tmagic-editor.umd.cjs +1334 -969
  6. package/dist/tmagic-editor.umd.cjs.map +1 -1
  7. package/package.json +17 -17
  8. package/src/Editor.vue +10 -7
  9. package/src/components/CodeBlockEditor.vue +2 -2
  10. package/src/components/ContentMenu.vue +5 -5
  11. package/src/components/ScrollBar.vue +2 -2
  12. package/src/components/ScrollViewer.vue +2 -2
  13. package/src/components/SplitView.vue +2 -2
  14. package/src/components/TreeNode.vue +3 -3
  15. package/src/editorProps.ts +14 -4
  16. package/src/fields/PageFragmentSelect.vue +55 -0
  17. package/src/hooks/use-getso.ts +2 -2
  18. package/src/hooks/use-stage.ts +18 -1
  19. package/src/index.ts +3 -0
  20. package/src/initService.ts +15 -5
  21. package/src/layouts/AddPageBox.vue +16 -4
  22. package/src/layouts/CodeEditor.vue +2 -2
  23. package/src/layouts/Framework.vue +17 -3
  24. package/src/layouts/PropsPanel.vue +2 -2
  25. package/src/layouts/page-bar/AddButton.vue +48 -0
  26. package/src/layouts/page-bar/PageBar.vue +158 -0
  27. package/src/layouts/{workspace → page-bar}/PageBarScrollContainer.vue +61 -35
  28. package/src/layouts/page-bar/SwitchTypeButton.vue +45 -0
  29. package/src/layouts/sidebar/Sidebar.vue +2 -0
  30. package/src/layouts/sidebar/layer/LayerMenu.vue +39 -27
  31. package/src/layouts/sidebar/layer/LayerPanel.vue +7 -1
  32. package/src/layouts/sidebar/layer/use-click.ts +5 -3
  33. package/src/layouts/sidebar/layer/use-keybinding.ts +8 -8
  34. package/src/layouts/sidebar/layer/use-node-status.ts +3 -3
  35. package/src/layouts/workspace/Workspace.vue +6 -7
  36. package/src/layouts/workspace/viewer/NodeListMenu.vue +2 -2
  37. package/src/layouts/workspace/viewer/Stage.vue +12 -5
  38. package/src/layouts/workspace/viewer/ViewerMenu.vue +93 -80
  39. package/src/services/editor.ts +65 -34
  40. package/src/services/history.ts +6 -2
  41. package/src/services/keybinding.ts +48 -13
  42. package/src/theme/code-block.scss +0 -16
  43. package/src/theme/page-bar.scss +18 -1
  44. package/src/type.ts +22 -7
  45. package/src/utils/content-menu.ts +2 -2
  46. package/src/utils/editor.ts +22 -15
  47. package/src/utils/operator.ts +4 -4
  48. package/types/components/ToolButton.vue.d.ts +2 -2
  49. package/types/editorProps.d.ts +11 -2
  50. package/types/fields/PageFragmentSelect.vue.d.ts +31 -0
  51. package/types/index.d.ts +1 -0
  52. package/types/layouts/AddPageBox.vue.d.ts +14 -1
  53. package/types/layouts/Framework.vue.d.ts +14 -1
  54. package/types/layouts/PropsPanel.vue.d.ts +9 -9
  55. package/types/layouts/page-bar/AddButton.vue.d.ts +16 -0
  56. package/types/layouts/page-bar/PageBar.vue.d.ts +28 -0
  57. package/types/layouts/page-bar/PageBarScrollContainer.vue.d.ts +24 -0
  58. package/types/layouts/page-bar/SwitchTypeButton.vue.d.ts +20 -0
  59. package/types/layouts/sidebar/Sidebar.vue.d.ts +2 -0
  60. package/types/layouts/sidebar/layer/LayerMenu.vue.d.ts +22 -3
  61. package/types/layouts/sidebar/layer/LayerPanel.vue.d.ts +2 -0
  62. package/types/layouts/sidebar/layer/use-click.d.ts +25 -3
  63. package/types/layouts/sidebar/layer/use-keybinding.d.ts +1 -1
  64. package/types/layouts/workspace/Workspace.vue.d.ts +2 -0
  65. package/types/layouts/workspace/viewer/Stage.vue.d.ts +2 -0
  66. package/types/layouts/workspace/viewer/ViewerMenu.vue.d.ts +8 -0
  67. package/types/services/dataSource.d.ts +1 -0
  68. package/types/services/editor.d.ts +3 -2
  69. package/types/services/history.d.ts +3 -2
  70. package/types/services/keybinding.d.ts +21 -1
  71. package/types/type.d.ts +25 -12
  72. package/types/utils/editor.d.ts +9 -7
  73. package/src/layouts/workspace/PageBar.vue +0 -87
  74. package/types/layouts/workspace/PageBar.vue.d.ts +0 -15
  75. package/types/layouts/workspace/PageBarScrollContainer.vue.d.ts +0 -9
@@ -25,13 +25,18 @@
25
25
  <NodeListMenu></NodeListMenu>
26
26
 
27
27
  <Teleport to="body">
28
- <ViewerMenu ref="menu" :is-multi-select="isMultiSelect" :stage-content-menu="stageContentMenu"></ViewerMenu>
28
+ <ViewerMenu
29
+ ref="menu"
30
+ :is-multi-select="isMultiSelect"
31
+ :stage-content-menu="stageContentMenu"
32
+ :custom-content-menu="customContentMenu"
33
+ ></ViewerMenu>
29
34
  </Teleport>
30
35
  </ScrollViewer>
31
36
  </template>
32
37
 
33
38
  <script lang="ts" setup>
34
- import { computed, inject, markRaw, nextTick, onMounted, onUnmounted, ref, toRaw, watch, watchEffect } from 'vue';
39
+ import { computed, inject, markRaw, nextTick, onBeforeUnmount, onMounted, ref, toRaw, watch, watchEffect } from 'vue';
35
40
  import { cloneDeep } from 'lodash-es';
36
41
 
37
42
  import type { MApp, MContainer } from '@tmagic/schema';
@@ -52,6 +57,7 @@ defineOptions({
52
57
 
53
58
  defineProps<{
54
59
  stageContentMenu: (MenuButton | MenuComponent)[];
60
+ customContentMenu?: (menus: (MenuButton | MenuComponent)[], type: string) => (MenuButton | MenuComponent)[];
55
61
  }>();
56
62
 
57
63
  let stage: StageCore | null = null;
@@ -108,6 +114,7 @@ watch(zoom, (zoom) => {
108
114
 
109
115
  watch(page, (page) => {
110
116
  if (runtime && page) {
117
+ services?.editorService.set('stageLoading', true);
111
118
  runtime.updatePageId?.(page.id);
112
119
  nextTick(() => {
113
120
  stage?.select(page.id);
@@ -135,15 +142,15 @@ const resizeObserver = new ResizeObserver((entries) => {
135
142
  onMounted(() => {
136
143
  if (stageWrap.value?.container) {
137
144
  resizeObserver.observe(stageWrap.value.container);
138
- services?.keybindingService.registeEl(KeyBindingContainerKey.STAGE, stageWrap.value.container);
145
+ services?.keybindingService.registerEl(KeyBindingContainerKey.STAGE, stageWrap.value.container);
139
146
  }
140
147
  });
141
148
 
142
- onUnmounted(() => {
149
+ onBeforeUnmount(() => {
143
150
  stage?.destroy();
144
151
  resizeObserver.disconnect();
145
152
  services?.editorService.set('stage', null);
146
- services?.keybindingService.unregisteEl('stage');
153
+ services?.keybindingService.unregisterEl('stage');
147
154
  services?.editorService.off('root-change', rootChangeHandler);
148
155
  });
149
156
 
@@ -7,7 +7,7 @@ import { computed, inject, markRaw, ref, watch } from 'vue';
7
7
  import { Bottom, Top } from '@element-plus/icons-vue';
8
8
 
9
9
  import { NodeType } from '@tmagic/schema';
10
- import { isPage } from '@tmagic/utils';
10
+ import { isPage, isPageFragment } from '@tmagic/utils';
11
11
 
12
12
  import ContentMenu from '@editor/components/ContentMenu.vue';
13
13
  import CenterIcon from '@editor/icons/CenterIcon.vue';
@@ -19,8 +19,16 @@ defineOptions({
19
19
  });
20
20
 
21
21
  const props = withDefaults(
22
- defineProps<{ isMultiSelect?: boolean; stageContentMenu: (MenuButton | MenuComponent)[] }>(),
23
- { isMultiSelect: false },
22
+ defineProps<{
23
+ isMultiSelect?: boolean;
24
+ stageContentMenu: (MenuButton | MenuComponent)[];
25
+ customContentMenu?: (menus: (MenuButton | MenuComponent)[], type: string) => (MenuButton | MenuComponent)[];
26
+ }>(),
27
+ {
28
+ isMultiSelect: false,
29
+ stageContentMenu: () => [],
30
+ customContentMenu: (menus: (MenuButton | MenuComponent)[]) => menus,
31
+ },
24
32
  );
25
33
 
26
34
  const services = inject<Services>('services');
@@ -32,83 +40,88 @@ const node = computed(() => editorService?.get('node'));
32
40
  const nodes = computed(() => editorService?.get('nodes'));
33
41
  const parent = computed(() => editorService?.get('parent'));
34
42
 
35
- const menuData = computed<(MenuButton | MenuComponent)[]>(() => [
36
- {
37
- type: 'button',
38
- text: '水平居中',
39
- icon: markRaw(CenterIcon),
40
- display: () => canCenter.value,
41
- handler: () => {
42
- if (!nodes.value) return;
43
- editorService?.alignCenter(nodes.value);
44
- },
45
- },
46
- useCopyMenu(),
47
- usePasteMenu(menu),
48
- {
49
- type: 'divider',
50
- direction: 'horizontal',
51
- display: () => {
52
- if (!node.value) return false;
53
- return !isPage(node.value);
54
- },
55
- },
56
- {
57
- type: 'button',
58
- text: '上移一层',
59
- icon: markRaw(Top),
60
- display: () => !isPage(node.value) && !props.isMultiSelect,
61
- handler: () => {
62
- editorService?.moveLayer(1);
63
- },
64
- },
65
- {
66
- type: 'button',
67
- text: '下移一层',
68
- icon: markRaw(Bottom),
69
- display: () => !isPage(node.value) && !props.isMultiSelect,
70
- handler: () => {
71
- editorService?.moveLayer(-1);
72
- },
73
- },
74
- {
75
- type: 'button',
76
- text: '置顶',
77
- icon: markRaw(Top),
78
- display: () => !isPage(node.value) && !props.isMultiSelect,
79
- handler: () => {
80
- editorService?.moveLayer(LayerOffset.TOP);
81
- },
82
- },
83
- {
84
- type: 'button',
85
- text: '置底',
86
- icon: markRaw(Bottom),
87
- display: () => !isPage(node.value) && !props.isMultiSelect,
88
- handler: () => {
89
- editorService?.moveLayer(LayerOffset.BOTTOM);
90
- },
91
- },
92
- useMoveToMenu(services),
93
- {
94
- type: 'divider',
95
- direction: 'horizontal',
96
- display: () => !isPage(node.value) && !props.isMultiSelect,
97
- },
98
- useDeleteMenu(),
99
- {
100
- type: 'divider',
101
- direction: 'horizontal',
102
- },
103
- {
104
- type: 'button',
105
- text: '清空参考线',
106
- handler: () => {
107
- editorService?.get('stage')?.clearGuides();
108
- },
109
- },
110
- ...props.stageContentMenu,
111
- ]);
43
+ const menuData = computed<(MenuButton | MenuComponent)[]>(() =>
44
+ props.customContentMenu(
45
+ [
46
+ {
47
+ type: 'button',
48
+ text: '水平居中',
49
+ icon: markRaw(CenterIcon),
50
+ display: () => canCenter.value,
51
+ handler: () => {
52
+ if (!nodes.value) return;
53
+ editorService?.alignCenter(nodes.value);
54
+ },
55
+ },
56
+ useCopyMenu(),
57
+ usePasteMenu(menu),
58
+ {
59
+ type: 'divider',
60
+ direction: 'horizontal',
61
+ display: () => {
62
+ if (!node.value) return false;
63
+ return !isPage(node.value) && !isPageFragment(node.value);
64
+ },
65
+ },
66
+ {
67
+ type: 'button',
68
+ text: '上移一层',
69
+ icon: markRaw(Top),
70
+ display: () => !isPage(node.value) && !isPageFragment(node.value) && !props.isMultiSelect,
71
+ handler: () => {
72
+ editorService?.moveLayer(1);
73
+ },
74
+ },
75
+ {
76
+ type: 'button',
77
+ text: '下移一层',
78
+ icon: markRaw(Bottom),
79
+ display: () => !isPage(node.value) && !isPageFragment(node.value) && !props.isMultiSelect,
80
+ handler: () => {
81
+ editorService?.moveLayer(-1);
82
+ },
83
+ },
84
+ {
85
+ type: 'button',
86
+ text: '置顶',
87
+ icon: markRaw(Top),
88
+ display: () => !isPage(node.value) && !isPageFragment(node.value) && !props.isMultiSelect,
89
+ handler: () => {
90
+ editorService?.moveLayer(LayerOffset.TOP);
91
+ },
92
+ },
93
+ {
94
+ type: 'button',
95
+ text: '置底',
96
+ icon: markRaw(Bottom),
97
+ display: () => !isPage(node.value) && !isPageFragment(node.value) && !props.isMultiSelect,
98
+ handler: () => {
99
+ editorService?.moveLayer(LayerOffset.BOTTOM);
100
+ },
101
+ },
102
+ useMoveToMenu(services),
103
+ {
104
+ type: 'divider',
105
+ direction: 'horizontal',
106
+ display: () => !isPage(node.value) && !isPageFragment(node.value) && !props.isMultiSelect,
107
+ },
108
+ useDeleteMenu(),
109
+ {
110
+ type: 'divider',
111
+ direction: 'horizontal',
112
+ },
113
+ {
114
+ type: 'button',
115
+ text: '清空参考线',
116
+ handler: () => {
117
+ editorService?.get('stage')?.clearGuides();
118
+ },
119
+ },
120
+ ...props.stageContentMenu,
121
+ ],
122
+ 'viewer',
123
+ ),
124
+ );
112
125
 
113
126
  watch(
114
127
  parent,
@@ -20,10 +20,9 @@ import { reactive, toRaw } from 'vue';
20
20
  import { cloneDeep, get, isObject, mergeWith, uniq } from 'lodash-es';
21
21
 
22
22
  import { DepTargetType } from '@tmagic/dep';
23
- import type { Id, MApp, MComponent, MContainer, MNode, MPage } from '@tmagic/schema';
23
+ import type { Id, MApp, MComponent, MContainer, MNode, MPage, MPageFragment } from '@tmagic/schema';
24
24
  import { NodeType } from '@tmagic/schema';
25
- import StageCore from '@tmagic/stage';
26
- import { getNodePath, isNumber, isPage, isPop } from '@tmagic/utils';
25
+ import { getNodePath, isNumber, isPage, isPageFragment, isPop } from '@tmagic/utils';
27
26
 
28
27
  import depService from '@editor/services/dep';
29
28
  import historyService from '@editor/services/history';
@@ -37,8 +36,10 @@ import {
37
36
  fixNodePosition,
38
37
  getInitPositionStyle,
39
38
  getNodeIndex,
39
+ getPageFragmentList,
40
+ getPageList,
40
41
  isFixed,
41
- setChilrenLayout,
42
+ setChildrenLayout,
42
43
  setLayout,
43
44
  } from '@editor/utils/editor';
44
45
  import { beforePaste, getAddParent } from '@editor/utils/operator';
@@ -54,9 +55,12 @@ class Editor extends BaseService {
54
55
  node: null,
55
56
  nodes: [],
56
57
  stage: null,
58
+ stageLoading: true,
57
59
  highlightNode: null,
58
60
  modifiedNodeIds: new Map(),
59
61
  pageLength: 0,
62
+ pageFragmentLength: 0,
63
+ disabledMultiSelect: false,
60
64
  });
61
65
  private isHistoryStateChange = false;
62
66
 
@@ -92,7 +96,7 @@ class Editor extends BaseService {
92
96
 
93
97
  /**
94
98
  * 设置当前指点节点配置
95
- * @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength'
99
+ * @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength' | 'pageFragmentLength
96
100
  * @param value MNode
97
101
  */
98
102
  public set<K extends StoreStateKey, T extends StoreState[K]>(name: K, value: T) {
@@ -109,10 +113,15 @@ class Editor extends BaseService {
109
113
  throw new Error('root 不能为数组');
110
114
  }
111
115
 
112
- if (value && isObject(value) && !(value instanceof StageCore) && !(value instanceof Map)) {
113
- this.state.pageLength = value.items?.length || 0;
116
+ if (value && isObject(value)) {
117
+ const app = value as MApp;
118
+ this.state.pageLength = getPageList(app).length || 0;
119
+ this.state.pageFragmentLength = getPageFragmentList(app).length || 0;
120
+ this.state.stageLoading = this.state.pageLength !== 0;
114
121
  } else {
115
122
  this.state.pageLength = 0;
123
+ this.state.pageFragmentLength = 0;
124
+ this.state.stageLoading = false;
116
125
  }
117
126
 
118
127
  this.emit('root-change', value, preValue);
@@ -121,7 +130,7 @@ class Editor extends BaseService {
121
130
 
122
131
  /**
123
132
  * 获取当前指点节点配置
124
- * @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength'
133
+ * @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength' | 'pageFragmentLength'
125
134
  * @returns MNode
126
135
  */
127
136
  public get<K extends StoreStateKey>(name: K): StoreState[K] {
@@ -163,8 +172,8 @@ class Editor extends BaseService {
163
172
  info.parent = path[path.length - 2] as MContainer;
164
173
 
165
174
  path.forEach((item) => {
166
- if (item.type === NodeType.PAGE) {
167
- info.page = item as MPage;
175
+ if (isPage(item) || isPageFragment(item)) {
176
+ info.page = item as MPage | MPageFragment;
168
177
  return;
169
178
  }
170
179
  });
@@ -312,6 +321,17 @@ class Editor extends BaseService {
312
321
  this.set('nodes', nodes);
313
322
  }
314
323
 
324
+ public selectRoot() {
325
+ const root = this.get('root');
326
+ if (!root) return;
327
+
328
+ this.set('nodes', [root]);
329
+ this.set('parent', null);
330
+ this.set('page', null);
331
+ this.set('stage', null);
332
+ this.set('highlightNode', null);
333
+ }
334
+
315
335
  public async doAdd(node: MNode, parent: MContainer): Promise<MNode> {
316
336
  const root = this.get('root');
317
337
 
@@ -322,11 +342,11 @@ class Editor extends BaseService {
322
342
 
323
343
  if (!curNode) throw new Error('当前选中节点为空');
324
344
 
325
- if ((parent.type === NodeType.ROOT || curNode?.type === NodeType.ROOT) && node.type !== NodeType.PAGE) {
345
+ if ((parent.type === NodeType.ROOT || curNode?.type === NodeType.ROOT) && !(isPage(node) || isPageFragment(node))) {
326
346
  throw new Error('app下不能添加组件');
327
347
  }
328
348
 
329
- if (parent.id !== curNode.id && node.type !== NodeType.PAGE) {
349
+ if (parent.id !== curNode.id && !(isPage(node) || isPageFragment(node))) {
330
350
  const index = parent.items.indexOf(curNode);
331
351
  parent.items?.splice(index + 1, 0, node);
332
352
  } else {
@@ -380,7 +400,7 @@ class Editor extends BaseService {
380
400
  const newNodes = await Promise.all(
381
401
  addNodes.map((node) => {
382
402
  const root = this.get('root');
383
- if (isPage(node) && root) {
403
+ if ((isPage(node) || isPageFragment(node)) && root) {
384
404
  return this.doAdd(node, root);
385
405
  }
386
406
  const parentNode = parent && typeof parent !== 'function' ? parent : getAddParent(node);
@@ -399,13 +419,15 @@ class Editor extends BaseService {
399
419
 
400
420
  if (isPage(newNodes[0])) {
401
421
  this.state.pageLength += 1;
422
+ } else if (isPageFragment(newNodes[0])) {
423
+ this.state.pageFragmentLength += 1;
402
424
  } else {
403
425
  // 新增页面,这个时候页面还有渲染出来,此时select会出错,在runtime-ready的时候回去select
404
426
  stage?.select(newNodes[0].id);
405
427
  }
406
428
  }
407
429
 
408
- if (!isPage(newNodes[0])) {
430
+ if (!(isPage(newNodes[0]) || isPageFragment(newNodes[0]))) {
409
431
  this.pushHistoryState();
410
432
  }
411
433
 
@@ -418,7 +440,7 @@ class Editor extends BaseService {
418
440
  const root = this.get('root');
419
441
  if (!root) throw new Error('root不能为空');
420
442
 
421
- const { parent, node: curNode } = this.getNodeInfo(node.id);
443
+ const { parent, node: curNode } = this.getNodeInfo(node.id, false);
422
444
 
423
445
  if (!parent || !curNode) throw new Error('找不要删除的节点');
424
446
 
@@ -430,29 +452,38 @@ class Editor extends BaseService {
430
452
  const stage = this.get('stage');
431
453
  stage?.remove({ id: node.id, parentId: parent.id, root: cloneDeep(root) });
432
454
 
433
- if (node.type === NodeType.PAGE) {
434
- this.state.pageLength -= 1;
435
-
436
- if (root.items[0]) {
437
- await this.select(root.items[0]);
438
- stage?.select(root.items[0].id);
455
+ const selectDefault = async (pages: MNode[]) => {
456
+ if (pages[0]) {
457
+ await this.select(pages[0]);
458
+ stage?.select(pages[0].id);
439
459
  } else {
440
- this.set('nodes', [root]);
441
- this.set('parent', null);
442
- this.set('page', null);
443
- this.set('stage', null);
444
- this.set('highlightNode', null);
445
- this.resetModifiedNodeId();
446
- historyService.reset();
460
+ this.selectRoot();
447
461
 
448
- return;
462
+ historyService.resetPage();
449
463
  }
464
+ };
465
+
466
+ const rootItems = root.items || [];
467
+
468
+ if (isPage(node)) {
469
+ this.state.pageLength -= 1;
470
+
471
+ await selectDefault(getPageList(root));
472
+ } else if (isPageFragment(node)) {
473
+ this.state.pageFragmentLength -= 1;
474
+
475
+ await selectDefault(getPageFragmentList(root));
450
476
  } else {
451
477
  await this.select(parent);
452
478
  stage?.select(parent.id);
479
+
480
+ this.addModifiedNodeId(parent.id);
453
481
  }
454
482
 
455
- this.addModifiedNodeId(parent.id);
483
+ if (!rootItems.length) {
484
+ this.resetModifiedNodeId();
485
+ historyService.reset();
486
+ }
456
487
  }
457
488
 
458
489
  /**
@@ -464,7 +495,7 @@ class Editor extends BaseService {
464
495
 
465
496
  await Promise.all(nodes.map((node) => this.doRemove(node)));
466
497
 
467
- if (!isPage(nodes[0])) {
498
+ if (!(isPage(nodes[0]) || isPageFragment(nodes[0]))) {
468
499
  // 更新历史记录
469
500
  this.pushHistoryState();
470
501
  }
@@ -514,7 +545,7 @@ class Editor extends BaseService {
514
545
  const newLayout = await this.getLayout(newConfig);
515
546
  const layout = await this.getLayout(node);
516
547
  if (Array.isArray(newConfig.items) && newLayout !== layout) {
517
- newConfig = setChilrenLayout(newConfig as MContainer, newLayout);
548
+ newConfig = setChildrenLayout(newConfig as MContainer, newLayout);
518
549
  }
519
550
 
520
551
  parentNodeItems[index] = newConfig;
@@ -531,8 +562,8 @@ class Editor extends BaseService {
531
562
  root: cloneDeep(root),
532
563
  });
533
564
 
534
- if (newConfig.type === NodeType.PAGE) {
535
- this.set('page', newConfig as MPage);
565
+ if (isPage(newConfig) || isPageFragment(newConfig)) {
566
+ this.set('page', newConfig as MPage | MPageFragment);
536
567
  }
537
568
 
538
569
  this.addModifiedNodeId(newConfig.id);
@@ -18,7 +18,7 @@
18
18
 
19
19
  import { reactive } from 'vue';
20
20
 
21
- import type { MPage } from '@tmagic/schema';
21
+ import type { MPage, MPageFragment } from '@tmagic/schema';
22
22
 
23
23
  import type { HistoryState, StepValue } from '@editor/type';
24
24
  import { UndoRedo } from '@editor/utils/undo-redo';
@@ -41,12 +41,16 @@ class History extends BaseService {
41
41
 
42
42
  public reset() {
43
43
  this.state.pageSteps = {};
44
+ this.resetPage();
45
+ }
46
+
47
+ public resetPage() {
44
48
  this.state.pageId = undefined;
45
49
  this.state.canRedo = false;
46
50
  this.state.canUndo = false;
47
51
  }
48
52
 
49
- public changePage(page: MPage): void {
53
+ public changePage(page: MPage | MPageFragment): void {
50
54
  if (!page) return;
51
55
 
52
56
  this.state.pageId = page.id;
@@ -1,6 +1,6 @@
1
1
  import KeyController, { KeyControllerEvent } from 'keycon';
2
2
 
3
- import { isPage } from '@tmagic/utils';
3
+ import { isPage, isPageFragment } from '@tmagic/utils';
4
4
 
5
5
  import { KeyBindingCacheItem, KeyBindingCommand, KeyBindingItem } from '@editor/type';
6
6
 
@@ -19,7 +19,7 @@ class Keybinding extends BaseService {
19
19
  [KeyBindingCommand.DELETE_NODE]: () => {
20
20
  const nodes = editorService.get('nodes');
21
21
 
22
- if (!nodes || isPage(nodes[0])) return;
22
+ if (!nodes || isPage(nodes[0]) || isPageFragment(nodes[0])) return;
23
23
  editorService.remove(nodes);
24
24
  },
25
25
  [KeyBindingCommand.COPY_NODE]: () => {
@@ -29,7 +29,7 @@ class Keybinding extends BaseService {
29
29
  [KeyBindingCommand.CUT_NODE]: () => {
30
30
  const nodes = editorService.get('nodes');
31
31
 
32
- if (!nodes || isPage(nodes[0])) return;
32
+ if (!nodes || isPage(nodes[0]) || isPageFragment(nodes[0])) return;
33
33
  editorService.copy(nodes);
34
34
  editorService.remove(nodes);
35
35
  },
@@ -84,15 +84,29 @@ class Keybinding extends BaseService {
84
84
  },
85
85
  };
86
86
 
87
- public registeCommand(command: string, handler: (e: KeyboardEvent) => void | Promise<void>) {
87
+ public registerCommand(command: string, handler: (e: KeyboardEvent) => void | Promise<void>) {
88
88
  this.commands[command] = handler;
89
89
  }
90
90
 
91
- public unregisteCommand(command: string) {
91
+ /**
92
+ * @deprecated
93
+ */
94
+ public registeCommand(command: string, handler: (e: KeyboardEvent) => void | Promise<void>) {
95
+ this.registerCommand(command, handler);
96
+ }
97
+
98
+ public unregisterCommand(command: string) {
92
99
  delete this.commands[command];
93
100
  }
94
101
 
95
- public registeEl(name: string, el?: HTMLElement) {
102
+ /**
103
+ * @deprecated
104
+ */
105
+ public unregisteCommand(command: string) {
106
+ this.unregisterCommand(command);
107
+ }
108
+
109
+ public registerEl(name: string, el?: HTMLElement) {
96
110
  if (name !== 'global' && !el) {
97
111
  throw new Error('只有name为global可以不传el');
98
112
  }
@@ -102,20 +116,34 @@ class Keybinding extends BaseService {
102
116
  this.bind(name);
103
117
  }
104
118
 
105
- public unregisteEl(name: string) {
119
+ /**
120
+ * @deprecated
121
+ */
122
+ public registeEl(name: string, el?: HTMLElement) {
123
+ this.registerEl(name, el);
124
+ }
125
+
126
+ public unregisterEl(name: string) {
106
127
  this.controllers.get(name)?.destroy();
107
128
  this.controllers.delete(name);
108
129
  this.bindingList.forEach((item) => {
109
- item.binded = false;
130
+ item.bound = false;
110
131
  });
111
132
  }
112
133
 
113
- public registe(maps: KeyBindingItem[]) {
134
+ /**
135
+ * @deprecated
136
+ */
137
+ public unregisteEl(name: string) {
138
+ this.unregisterEl(name);
139
+ }
140
+
141
+ public register(maps: KeyBindingItem[]) {
114
142
  for (const keybindingItem of maps) {
115
143
  const { command, keybinding, when } = keybindingItem;
116
144
 
117
145
  for (const [type = '', eventType = 'keydown'] of when) {
118
- const cacheItem: KeyBindingCacheItem = { type, command, keybinding, eventType, binded: false };
146
+ const cacheItem: KeyBindingCacheItem = { type, command, keybinding, eventType, bound: false };
119
147
 
120
148
  this.bindingList.push(cacheItem);
121
149
  }
@@ -124,6 +152,13 @@ class Keybinding extends BaseService {
124
152
  this.bind();
125
153
  }
126
154
 
155
+ /**
156
+ * @deprecated
157
+ */
158
+ public registe(map: KeyBindingItem[]) {
159
+ this.register(map);
160
+ }
161
+
127
162
  public reset() {
128
163
  this.controllers.forEach((keycon) => {
129
164
  keycon.destroy();
@@ -138,13 +173,13 @@ class Keybinding extends BaseService {
138
173
 
139
174
  private bind(name?: string) {
140
175
  for (const item of this.bindingList) {
141
- const { type, eventType, command, keybinding, binded } = item;
176
+ const { type, eventType, command, keybinding, bound } = item;
142
177
 
143
178
  if (name && name !== type) {
144
179
  continue;
145
180
  }
146
181
 
147
- if (binded) {
182
+ if (bound) {
148
183
  continue;
149
184
  }
150
185
 
@@ -166,7 +201,7 @@ class Keybinding extends BaseService {
166
201
  }
167
202
  });
168
203
 
169
- item.binded = true;
204
+ item.bound = true;
170
205
  }
171
206
  }
172
207
 
@@ -1,21 +1,5 @@
1
1
  .m-editor-code-block-list {
2
2
  height: 100%;
3
-
4
- .list-container {
5
- .list-item {
6
- .codeIcon {
7
- width: 22px;
8
- height: 22px;
9
- margin-right: 5px;
10
- }
11
-
12
- .compIcon {
13
- width: 22px;
14
- height: 22px;
15
- margin-right: 5px;
16
- }
17
- }
18
- }
19
3
  }
20
4
 
21
5
  .m-fields-code-select {