@tmagic/editor 1.3.5 → 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 (142) hide show
  1. package/LICENSE +5432 -0
  2. package/dist/style.css +88 -62
  3. package/dist/tmagic-editor.js +2448 -2016
  4. package/dist/tmagic-editor.js.map +1 -1
  5. package/dist/tmagic-editor.umd.cjs +2453 -2019
  6. package/dist/tmagic-editor.umd.cjs.map +1 -1
  7. package/package.json +23 -23
  8. package/src/Editor.vue +15 -7
  9. package/src/components/CodeBlockEditor.vue +2 -2
  10. package/src/components/ContentMenu.vue +5 -5
  11. package/src/components/FloatingBox.vue +117 -0
  12. package/src/components/ScrollBar.vue +2 -2
  13. package/src/components/ScrollViewer.vue +2 -2
  14. package/src/components/SplitView.vue +2 -2
  15. package/src/components/Tree.vue +5 -0
  16. package/src/components/TreeNode.vue +10 -4
  17. package/src/editorProps.ts +20 -3
  18. package/src/fields/PageFragmentSelect.vue +55 -0
  19. package/src/hooks/use-filter.ts +55 -0
  20. package/src/hooks/use-getso.ts +2 -2
  21. package/src/hooks/use-node-status.ts +48 -0
  22. package/src/hooks/use-stage.ts +19 -1
  23. package/src/index.ts +3 -0
  24. package/src/initService.ts +43 -17
  25. package/src/layouts/AddPageBox.vue +16 -4
  26. package/src/layouts/CodeEditor.vue +2 -2
  27. package/src/layouts/Framework.vue +17 -3
  28. package/src/layouts/PropsPanel.vue +2 -2
  29. package/src/layouts/page-bar/AddButton.vue +48 -0
  30. package/src/layouts/page-bar/PageBar.vue +158 -0
  31. package/src/layouts/{workspace → page-bar}/PageBarScrollContainer.vue +61 -35
  32. package/src/layouts/page-bar/SwitchTypeButton.vue +45 -0
  33. package/src/layouts/sidebar/Sidebar.vue +9 -2
  34. package/src/layouts/sidebar/code-block/CodeBlockList.vue +55 -65
  35. package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +2 -1
  36. package/src/layouts/sidebar/data-source/DataSourceList.vue +63 -59
  37. package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +1 -1
  38. package/src/layouts/sidebar/layer/LayerMenu.vue +39 -27
  39. package/src/layouts/sidebar/layer/LayerPanel.vue +31 -8
  40. package/src/layouts/sidebar/layer/use-click.ts +5 -3
  41. package/src/layouts/sidebar/layer/use-keybinding.ts +8 -8
  42. package/src/layouts/sidebar/layer/use-node-status.ts +10 -13
  43. package/src/layouts/workspace/Workspace.vue +6 -7
  44. package/src/layouts/workspace/viewer/NodeListMenu.vue +68 -129
  45. package/src/layouts/workspace/viewer/Stage.vue +14 -6
  46. package/src/layouts/workspace/viewer/ViewerMenu.vue +94 -86
  47. package/src/services/BaseService.ts +63 -26
  48. package/src/services/codeBlock.ts +7 -1
  49. package/src/services/dep.ts +12 -8
  50. package/src/services/editor.ts +131 -64
  51. package/src/services/history.ts +6 -2
  52. package/src/services/keybinding.ts +48 -13
  53. package/src/services/props.ts +70 -12
  54. package/src/services/storage.ts +23 -13
  55. package/src/services/ui.ts +4 -1
  56. package/src/theme/code-block.scss +0 -16
  57. package/src/theme/floating-box.scss +30 -0
  58. package/src/theme/layer-panel.scss +19 -0
  59. package/src/theme/page-bar.scss +18 -1
  60. package/src/theme/stage.scss +24 -0
  61. package/src/theme/theme.scss +1 -1
  62. package/src/theme/tree.scss +12 -1
  63. package/src/type.ts +28 -10
  64. package/src/utils/compose.ts +25 -6
  65. package/src/utils/content-menu.ts +6 -7
  66. package/src/utils/editor.ts +34 -18
  67. package/src/utils/operator.ts +5 -6
  68. package/types/components/CodeBlockEditor.vue.d.ts +6 -2
  69. package/types/components/CodeParams.vue.d.ts +3 -1
  70. package/types/components/ContentMenu.vue.d.ts +13 -5
  71. package/types/components/FloatingBox.vue.d.ts +78 -0
  72. package/types/components/Resizer.vue.d.ts +6 -1
  73. package/types/components/ScrollBar.vue.d.ts +3 -1
  74. package/types/components/ScrollViewer.vue.d.ts +3 -3
  75. package/types/components/SearchInput.vue.d.ts +3 -1
  76. package/types/components/SplitView.vue.d.ts +8 -4
  77. package/types/components/ToolButton.vue.d.ts +3 -3
  78. package/types/components/Tree.vue.d.ts +27 -8
  79. package/types/components/TreeNode.vue.d.ts +24 -7
  80. package/types/editorProps.d.ts +16 -1
  81. package/types/fields/Code.vue.d.ts +6 -2
  82. package/types/fields/CodeLink.vue.d.ts +5 -3
  83. package/types/fields/CodeSelect.vue.d.ts +3 -1
  84. package/types/fields/CodeSelectCol.vue.d.ts +3 -1
  85. package/types/fields/DataSourceFieldSelect.vue.d.ts +3 -1
  86. package/types/fields/DataSourceFields.vue.d.ts +5 -3
  87. package/types/fields/DataSourceInput.vue.d.ts +8 -4
  88. package/types/fields/DataSourceMethodSelect.vue.d.ts +3 -1
  89. package/types/fields/DataSourceMethods.vue.d.ts +5 -3
  90. package/types/fields/DataSourceMocks.vue.d.ts +5 -3
  91. package/types/fields/DataSourceSelect.vue.d.ts +5 -3
  92. package/types/fields/EventSelect.vue.d.ts +3 -1
  93. package/types/fields/KeyValue.vue.d.ts +2 -2
  94. package/types/fields/PageFragmentSelect.vue.d.ts +31 -0
  95. package/types/fields/UISelect.vue.d.ts +3 -1
  96. package/types/hooks/use-code-block-edit.d.ts +14 -5
  97. package/types/hooks/use-data-source-method.d.ts +14 -5
  98. package/types/hooks/use-filter.d.ts +7 -0
  99. package/types/hooks/use-node-status.d.ts +6 -0
  100. package/types/index.d.ts +1 -0
  101. package/types/layouts/AddPageBox.vue.d.ts +14 -1
  102. package/types/layouts/CodeEditor.vue.d.ts +4 -1
  103. package/types/layouts/Framework.vue.d.ts +14 -1
  104. package/types/layouts/PropsPanel.vue.d.ts +19 -13
  105. package/types/layouts/{workspace/viewer/NodeListMenuTitle.vue.d.ts → page-bar/AddButton.vue.d.ts} +3 -2
  106. package/types/layouts/page-bar/PageBar.vue.d.ts +28 -0
  107. package/types/layouts/page-bar/PageBarScrollContainer.vue.d.ts +24 -0
  108. package/types/layouts/page-bar/SwitchTypeButton.vue.d.ts +20 -0
  109. package/types/layouts/sidebar/ComponentListPanel.vue.d.ts +1 -1
  110. package/types/layouts/sidebar/Sidebar.vue.d.ts +7 -5
  111. package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +9 -3
  112. package/types/layouts/sidebar/code-block/CodeBlockListPanel.vue.d.ts +1 -1
  113. package/types/layouts/sidebar/data-source/DataSourceConfigPanel.vue.d.ts +3 -1
  114. package/types/layouts/sidebar/data-source/DataSourceList.vue.d.ts +8 -2
  115. package/types/layouts/sidebar/data-source/DataSourceListPanel.vue.d.ts +1 -1
  116. package/types/layouts/sidebar/layer/LayerMenu.vue.d.ts +26 -3
  117. package/types/layouts/sidebar/layer/LayerPanel.vue.d.ts +3 -1
  118. package/types/layouts/sidebar/layer/use-click.d.ts +37 -6
  119. package/types/layouts/sidebar/layer/use-keybinding.d.ts +1 -1
  120. package/types/layouts/sidebar/layer/use-node-status.d.ts +3 -4
  121. package/types/layouts/workspace/Workspace.vue.d.ts +3 -1
  122. package/types/layouts/workspace/viewer/NodeListMenu.vue.d.ts +1 -14
  123. package/types/layouts/workspace/viewer/Stage.vue.d.ts +2 -0
  124. package/types/layouts/workspace/viewer/ViewerMenu.vue.d.ts +9 -1
  125. package/types/services/BaseService.d.ts +4 -1
  126. package/types/services/dataSource.d.ts +1 -0
  127. package/types/services/dep.d.ts +6 -5
  128. package/types/services/editor.d.ts +12 -5
  129. package/types/services/history.d.ts +3 -2
  130. package/types/services/keybinding.d.ts +21 -1
  131. package/types/services/props.d.ts +25 -1
  132. package/types/services/storage.d.ts +7 -7
  133. package/types/type.d.ts +32 -17
  134. package/types/utils/compose.d.ts +1 -1
  135. package/types/utils/editor.d.ts +14 -8
  136. package/src/layouts/sidebar/layer/use-filter.ts +0 -59
  137. package/src/layouts/workspace/PageBar.vue +0 -87
  138. package/src/layouts/workspace/viewer/NodeListMenuTitle.vue +0 -68
  139. package/src/theme/dep-list.scss +0 -59
  140. package/types/layouts/sidebar/layer/use-filter.d.ts +0 -7
  141. package/types/layouts/workspace/PageBar.vue.d.ts +0 -15
  142. package/types/layouts/workspace/PageBarScrollContainer.vue.d.ts +0 -9
@@ -25,7 +25,14 @@ export class WebStorage extends BaseService {
25
25
  private namespace = 'tmagic';
26
26
 
27
27
  constructor() {
28
- super(['getStorage', 'getNamespace', 'clear', 'getItem', 'removeItem', 'setItem']);
28
+ super([
29
+ { name: 'getStorage', isAsync: false },
30
+ { name: 'getNamespace', isAsync: false },
31
+ { name: 'clear', isAsync: false },
32
+ { name: 'getItem', isAsync: false },
33
+ { name: 'removeItem', isAsync: false },
34
+ { name: 'setItem', isAsync: false },
35
+ ]);
29
36
  }
30
37
 
31
38
  /**
@@ -38,26 +45,27 @@ export class WebStorage extends BaseService {
38
45
  * },
39
46
  * });
40
47
  */
41
- public async getStorage(): Promise<Storage> {
48
+ public getStorage(): Storage {
42
49
  return this.storage;
43
50
  }
44
51
 
45
- public async getNamespace(): Promise<string> {
52
+ public getNamespace(): string {
46
53
  return this.namespace;
47
54
  }
48
55
 
49
56
  /**
50
57
  * 清理,支持storageService.usePlugin
51
58
  */
52
- public async clear(): Promise<void> {
53
- const storage = await this.getStorage();
59
+ public clear(): void {
60
+ const storage = this.getStorage();
54
61
  storage.clear();
55
62
  }
56
63
  /**
57
64
  * 获取存储项,支持storageService.usePlugin
58
65
  */
59
- public async getItem(key: string, options: Options = {}): Promise<any> {
60
- const [storage, namespace] = await Promise.all([this.getStorage(), this.getNamespace()]);
66
+ public getItem(key: string, options: Options = {}): any {
67
+ const storage = this.getStorage();
68
+ const namespace = this.getNamespace();
61
69
  const { protocol = options.protocol, item } = this.getValueAndProtocol(
62
70
  storage.getItem(`${options.namespace || namespace}:${key}`),
63
71
  );
@@ -80,24 +88,26 @@ export class WebStorage extends BaseService {
80
88
  /**
81
89
  * 获取指定索引位置的key
82
90
  */
83
- public async key(index: number): Promise<string | null> {
84
- const storage = await this.getStorage();
91
+ public key(index: number): string | null {
92
+ const storage = this.getStorage();
85
93
  return storage.key(index);
86
94
  }
87
95
 
88
96
  /**
89
97
  * 移除存储项,支持storageService.usePlugin
90
98
  */
91
- public async removeItem(key: string, options: Options = {}): Promise<void> {
92
- const [storage, namespace] = await Promise.all([this.getStorage(), this.getNamespace()]);
99
+ public removeItem(key: string, options: Options = {}): void {
100
+ const storage = this.getStorage();
101
+ const namespace = this.getNamespace();
93
102
  storage.removeItem(`${options.namespace || namespace}:${key}`);
94
103
  }
95
104
 
96
105
  /**
97
106
  * 设置存储项,支持storageService.usePlugin
98
107
  */
99
- public async setItem(key: string, value: any, options: Options = {}): Promise<void> {
100
- const [storage, namespace] = await Promise.all([this.getStorage(), this.getNamespace()]);
108
+ public setItem(key: string, value: any, options: Options = {}): void {
109
+ const storage = this.getStorage();
110
+ const namespace = this.getNamespace();
101
111
  let item = value;
102
112
  const protocol = options.protocol ? `${options.protocol}:` : '';
103
113
  if (typeof value === Protocol.STRING || typeof value === Protocol.NUMBER) {
@@ -52,7 +52,10 @@ const state = reactive<UiState>({
52
52
 
53
53
  class Ui extends BaseService {
54
54
  constructor() {
55
- super(['zoom', 'calcZoom']);
55
+ super([
56
+ { name: 'zoom', isAsync: true },
57
+ { name: 'calcZoom', isAsync: true },
58
+ ]);
56
59
  }
57
60
 
58
61
  public set<K extends keyof UiState, T extends UiState[K]>(name: K, value: T) {
@@ -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 {
@@ -0,0 +1,30 @@
1
+ .m-editor-float-box {
2
+ position: absolute;
3
+ background-color: #fff;
4
+ z-index: 100;
5
+ border: 1px solid $--border-color;
6
+ display: flex;
7
+ flex-direction: column;
8
+
9
+ .m-editor-float-box-title {
10
+ text-align: center;
11
+ font-size: 14px;
12
+ font-weight: 600;
13
+ padding: 5px;
14
+ cursor: move;
15
+ display: flex;
16
+ justify-content: space-between;
17
+ align-items: center;
18
+ border-bottom: 1px solid $--border-color;
19
+ }
20
+
21
+ .m-editor-float-box-body {
22
+ padding: 5px;
23
+ flex: 1;
24
+ overflow: auto;
25
+ }
26
+ }
27
+
28
+ .m-editor-floating-box-moveable {
29
+ opacity: 0;
30
+ }
@@ -4,4 +4,23 @@
4
4
  .m-editor-tree {
5
5
  padding-top: 48px;
6
6
  }
7
+
8
+ .search-wrapper {
9
+ display: flex;
10
+ align-items: center;
11
+ justify-content: center;
12
+ position: absolute;
13
+ top: 0;
14
+ width: 100%;
15
+ z-index: 1;
16
+
17
+ .search-input {
18
+ flex: 1;
19
+ position: relative;
20
+ }
21
+
22
+ .tmagic-design-button {
23
+ margin-right: 10px;
24
+ }
25
+ }
7
26
  }
@@ -1,7 +1,24 @@
1
- .m-editor-page-bar {
1
+ .m-editor-page-bar-tabs {
2
2
  position: fixed;
3
3
  bottom: 0;
4
4
  left: 0;
5
+ width: 100%;
6
+
7
+ .tmagic-design-button.m-editor-page-bar-switch-type-button {
8
+ margin-left: 7px;
9
+ position: relative;
10
+ top: 1px;
11
+ border-radius: 3px 3px 0 0;
12
+ border: 1px solid $--border-color;
13
+ border-bottom: 1px solid transparent;
14
+
15
+ &.active {
16
+ background-color: #f3f3f3;
17
+ }
18
+ }
19
+ }
20
+
21
+ .m-editor-page-bar {
5
22
  display: flex;
6
23
  width: 100%;
7
24
  height: $--page-bar-height;
@@ -25,3 +25,27 @@
25
25
  width: 0 !important;
26
26
  }
27
27
  }
28
+
29
+ .m-editor-stage-float-button {
30
+ cursor: pointer;
31
+ transform: translateY(-50%);
32
+ width: 12px;
33
+ font-size: 12px;
34
+ line-height: 1.2;
35
+ position: absolute;
36
+ left: 100%;
37
+ top: 50%;
38
+ padding: 5px;
39
+ background-color: #ffffff;
40
+ transition: background-color 0.2s;
41
+ color: rgba(0, 0, 0, 0.88);
42
+ box-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08),
43
+ 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
44
+ }
45
+
46
+ .m-editor-node-list-menu {
47
+ height: 100%;
48
+ width: 100%;
49
+ min-width: 300px;
50
+ max-height: 500px;
51
+ }
@@ -16,7 +16,6 @@
16
16
  @import "./event.scss";
17
17
  @import "./layout.scss";
18
18
  @import "./breadcrumb.scss";
19
- @import "./dep-list.scss";
20
19
  @import "./data-source.scss";
21
20
  @import "./data-source-fields.scss";
22
21
  @import "./data-source-methods.scss";
@@ -24,3 +23,4 @@
24
23
  @import "./key-value.scss";
25
24
  @import "./floatbox.scss";
26
25
  @import "./tree.scss";
26
+ @import "./floating-box.scss";
@@ -59,13 +59,24 @@
59
59
  width: 100px;
60
60
  overflow: hidden;
61
61
  text-overflow: ellipsis;
62
+
63
+ .disabled {
64
+ cursor: default;
65
+ }
66
+
67
+ .hook {
68
+ color: #999;
69
+ }
62
70
  }
63
71
  }
64
72
 
65
73
  .tree-node-tool {
66
- margin-right: 15px;
67
74
  display: flex;
68
75
  align-items: center;
76
+
77
+ .tmagic-design-icon {
78
+ margin-right: 10px;
79
+ }
69
80
  }
70
81
  }
71
82
  }
package/src/type.ts CHANGED
@@ -19,12 +19,14 @@
19
19
  import type { Component } from 'vue';
20
20
 
21
21
  import type { ColumnConfig, FilterFunction, FormConfig, FormItem } from '@tmagic/form';
22
- import type { CodeBlockContent, CodeBlockDSL, Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
22
+ import type { CodeBlockContent, CodeBlockDSL, Id, MApp, MContainer, MNode, MPage, MPageFragment } from '@tmagic/schema';
23
23
  import type StageCore from '@tmagic/stage';
24
24
  import type {
25
25
  ContainerHighlightType,
26
26
  CustomizeMoveableOptionsCallbackConfig,
27
+ GuidesOptions,
27
28
  MoveableOptions,
29
+ RenderType,
28
30
  UpdateDragEl,
29
31
  } from '@tmagic/stage';
30
32
 
@@ -52,13 +54,13 @@ export interface FrameworkSlots {
52
54
  workspace(props: {}): any;
53
55
  'props-panel'(props: {}): any;
54
56
  'footer'(props: {}): any;
57
+ 'page-bar-title'(props: { page: MPage | MPageFragment }): any;
58
+ 'page-bar-popover'(props: { page: MPage | MPageFragment }): any;
55
59
  }
56
60
 
57
61
  export interface WorkspaceSlots {
58
62
  stage(props: {}): any;
59
63
  'workspace-content'(props: {}): any;
60
- 'page-bar-title'(props: { page: MPage }): any;
61
- 'page-bar-popover'(props: { page: MPage }): any;
62
64
  }
63
65
 
64
66
  export interface ComponentListPanelSlots {
@@ -72,7 +74,7 @@ export interface CodeBlockListPanelSlots extends CodeBlockListSlots {
72
74
  }
73
75
 
74
76
  export interface CodeBlockListSlots {
75
- 'code-block-panel-tool'(props: { id: Id; data: CodeBlockContent }): any;
77
+ 'code-block-panel-tool'(props: { id: Id; data: any }): any;
76
78
  }
77
79
 
78
80
  export interface DataSourceListSlots {
@@ -81,12 +83,12 @@ export interface DataSourceListSlots {
81
83
 
82
84
  export interface LayerNodeSlots {
83
85
  'layer-node-content'(props: { data: MNode }): any;
86
+ 'layer-node-tool'(props: { data: MNode }): any;
87
+ 'layer-node-label'(props: { data: MNode }): any;
84
88
  }
85
89
 
86
90
  export interface LayerPanelSlots extends LayerNodeSlots {
87
91
  'layer-panel-header'(props: {}): any;
88
- 'layer-node-tool'(props: { data: MNode }): any;
89
- 'layer-node-content'(props: { data: MNode }): any;
90
92
  }
91
93
 
92
94
  export interface PropsPanelSlots {
@@ -129,18 +131,24 @@ export interface StageOptions {
129
131
  canSelect: (el: HTMLElement) => boolean | Promise<boolean>;
130
132
  isContainer: (el: HTMLElement) => boolean | Promise<boolean>;
131
133
  updateDragEl: UpdateDragEl;
134
+ renderType: RenderType;
135
+ guidesOptions: Partial<GuidesOptions>;
136
+ disabledMultiSelect?: boolean;
132
137
  }
133
138
 
134
139
  export interface StoreState {
135
140
  root: MApp | null;
136
- page: MPage | null;
141
+ page: MPage | MPageFragment | null;
137
142
  parent: MContainer | null;
138
143
  node: MNode | null;
139
144
  highlightNode: MNode | null;
140
145
  nodes: MNode[];
141
146
  stage: StageCore | null;
147
+ stageLoading: boolean;
142
148
  modifiedNodeIds: Map<Id, Id>;
143
149
  pageLength: number;
150
+ pageFragmentLength: number;
151
+ disabledMultiSelect: boolean;
144
152
  }
145
153
 
146
154
  export type StoreStateKey = keyof StoreState;
@@ -148,6 +156,7 @@ export type StoreStateKey = keyof StoreState;
148
156
  export interface PropsState {
149
157
  propsConfigMap: Record<string, FormConfig>;
150
158
  propsValueMap: Record<string, Partial<MNode>>;
159
+ relateIdMap: Record<Id, Id>;
151
160
  }
152
161
 
153
162
  export interface ComponentGroupState {
@@ -220,7 +229,7 @@ export interface UiState {
220
229
  export interface EditorNodeInfo {
221
230
  node: MNode | null;
222
231
  parent: MContainer | null;
223
- page: MPage | null;
232
+ page: MPage | MPageFragment | null;
224
233
  }
225
234
 
226
235
  export interface AddMNode {
@@ -485,7 +494,7 @@ export interface CodeParamStatement {
485
494
  }
486
495
 
487
496
  export interface StepValue {
488
- data: MPage;
497
+ data: MPage | MPageFragment;
489
498
  modifiedNodeIds: Map<Id, Id>;
490
499
  nodeId: Id;
491
500
  }
@@ -568,7 +577,7 @@ export interface KeyBindingCacheItem {
568
577
  command: KeyBindingCommand | string;
569
578
  keybinding?: string | string[];
570
579
  eventType: 'keyup' | 'keydown';
571
- binded: boolean;
580
+ bound: boolean;
572
581
  }
573
582
 
574
583
  export interface CodeSelectColConfig {
@@ -580,6 +589,15 @@ export interface CodeSelectColConfig {
580
589
  display?: boolean | FilterFunction;
581
590
  }
582
591
 
592
+ export interface PageFragmentSelectConfig {
593
+ type: 'page-fragment-select';
594
+ name: string;
595
+ text: string;
596
+ labelWidth?: number | string;
597
+ disabled?: boolean | FilterFunction;
598
+ display?: boolean | FilterFunction;
599
+ }
600
+
583
601
  export interface DataSourceMethodSelectConfig {
584
602
  type: 'data-source-method-select';
585
603
  name: string;
@@ -2,7 +2,7 @@
2
2
  * @param {Array} middleware
3
3
  * @return {Function}
4
4
  */
5
- export const compose = (middleware: Function[]) => {
5
+ export const compose = (middleware: Function[], isAsync: boolean) => {
6
6
  if (!Array.isArray(middleware)) throw new TypeError('Middleware 必须是一个数组!');
7
7
  for (const fn of middleware) {
8
8
  if (typeof fn !== 'function') throw new TypeError('Middleware 必须由函数组成!');
@@ -17,16 +17,35 @@ export const compose = (middleware: Function[]) => {
17
17
  // last called middleware #
18
18
  let index = -1;
19
19
  return dispatch(0);
20
- function dispatch(i: number): Promise<void> {
21
- if (i <= index) return Promise.reject(new Error('next() 被多次调用'));
20
+ function dispatch(i: number): Promise<void> | void {
21
+ if (i <= index) {
22
+ const error = new Error('next() 被多次调用');
23
+ if (isAsync) {
24
+ return Promise.reject(error);
25
+ }
26
+ throw error;
27
+ }
22
28
  index = i;
23
29
  let fn = middleware[i];
24
30
  if (i === middleware.length && next) fn = next;
25
- if (!fn) return Promise.resolve();
31
+ if (!fn) {
32
+ if (isAsync) {
33
+ return Promise.resolve();
34
+ }
35
+ return;
36
+ }
37
+
38
+ if (isAsync) {
39
+ try {
40
+ return Promise.resolve(fn(...args, dispatch.bind(null, i + 1)));
41
+ } catch (err) {
42
+ return Promise.reject(err);
43
+ }
44
+ }
26
45
  try {
27
- return Promise.resolve(fn(...args, dispatch.bind(null, i + 1)));
46
+ return fn(...args, dispatch.bind(null, i + 1));
28
47
  } catch (err) {
29
- return Promise.reject(err);
48
+ throw err;
30
49
  }
31
50
  }
32
51
  };
@@ -1,19 +1,21 @@
1
- import { computed, markRaw, Ref, ref } from 'vue';
1
+ import { computed, markRaw, Ref } from 'vue';
2
2
  import { CopyDocument, Delete, DocumentCopy } from '@element-plus/icons-vue';
3
3
 
4
4
  import { Id, MContainer, NodeType } from '@tmagic/schema';
5
- import { isPage } from '@tmagic/utils';
5
+ import { isPage, isPageFragment } from '@tmagic/utils';
6
6
 
7
7
  import ContentMenu from '@editor/components/ContentMenu.vue';
8
8
  import type { MenuButton, Services } from '@editor/type';
9
9
 
10
+ import { COPY_STORAGE_KEY } from './editor';
11
+
10
12
  export const useDeleteMenu = (): MenuButton => ({
11
13
  type: 'button',
12
14
  text: '删除',
13
15
  icon: Delete,
14
16
  display: (services) => {
15
17
  const node = services?.editorService?.get('node');
16
- return node?.type !== NodeType.ROOT && !isPage(node);
18
+ return node?.type !== NodeType.ROOT && !isPage(node) && !isPageFragment(node);
17
19
  },
18
20
  handler: (services) => {
19
21
  const nodes = services?.editorService?.get('nodes');
@@ -21,8 +23,6 @@ export const useDeleteMenu = (): MenuButton => ({
21
23
  },
22
24
  });
23
25
 
24
- const canPaste = ref(false);
25
-
26
26
  export const useCopyMenu = (): MenuButton => ({
27
27
  type: 'button',
28
28
  text: '复制',
@@ -30,7 +30,6 @@ export const useCopyMenu = (): MenuButton => ({
30
30
  handler: (services) => {
31
31
  const nodes = services?.editorService?.get('nodes');
32
32
  nodes && services?.editorService?.copy(nodes);
33
- canPaste.value = true;
34
33
  },
35
34
  });
36
35
 
@@ -38,7 +37,7 @@ export const usePasteMenu = (menu?: Ref<InstanceType<typeof ContentMenu> | undef
38
37
  type: 'button',
39
38
  text: '粘贴',
40
39
  icon: markRaw(DocumentCopy),
41
- display: () => canPaste.value,
40
+ display: (services) => !!services?.storageService?.getItem(COPY_STORAGE_KEY),
42
41
  handler: (services) => {
43
42
  const nodes = services?.editorService?.get('nodes');
44
43
  if (!nodes || nodes.length === 0) return;
@@ -18,24 +18,29 @@
18
18
 
19
19
  import serialize from 'serialize-javascript';
20
20
 
21
- import type { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
21
+ import type { Id, MApp, MContainer, MNode, MPage, MPageFragment } from '@tmagic/schema';
22
22
  import { NodeType } from '@tmagic/schema';
23
23
  import type StageCore from '@tmagic/stage';
24
- import { getNodePath, isNumber, isPage, isPop } from '@tmagic/utils';
24
+ import { getNodePath, isNumber, isPage, isPageFragment, isPop } from '@tmagic/utils';
25
25
 
26
26
  import { Layout } from '@editor/type';
27
27
  export const COPY_STORAGE_KEY = '$MagicEditorCopyData';
28
28
 
29
29
  /**
30
30
  * 获取所有页面配置
31
- * @param app DSL跟节点
31
+ * @param root DSL跟节点
32
32
  * @returns 所有页面配置
33
33
  */
34
- export const getPageList = (app: MApp): MPage[] => {
35
- if (app.items && Array.isArray(app.items)) {
36
- return app.items.filter((item: MPage) => item.type === NodeType.PAGE);
37
- }
38
- return [];
34
+ export const getPageList = (root?: MApp | null): MPage[] => {
35
+ if (!root) return [];
36
+ if (!Array.isArray(root.items)) return [];
37
+ return root.items.filter((item) => isPage(item)) as MPage[];
38
+ };
39
+
40
+ export const getPageFragmentList = (root?: MApp | null): MPageFragment[] => {
41
+ if (!root) return [];
42
+ if (!Array.isArray(root.items)) return [];
43
+ return root.items.filter((item) => isPageFragment(item)) as MPageFragment[];
39
44
  };
40
45
 
41
46
  /**
@@ -43,22 +48,23 @@ export const getPageList = (app: MApp): MPage[] => {
43
48
  * @param pages 所有页面配置
44
49
  * @returns 所有页面名称
45
50
  */
46
- export const getPageNameList = (pages: MPage[]): string[] => pages.map((page: MPage) => page.name || 'index');
51
+ export const getPageNameList = (pages: (MPage | MPageFragment)[]): string[] =>
52
+ pages.map((page) => page.name || 'index');
47
53
 
48
54
  /**
49
55
  * 新增页面时,生成页面名称
50
56
  * @param {Object} pageNameList 所有页面名称
51
57
  * @returns {string}
52
58
  */
53
- export const generatePageName = (pageNameList: string[]): string => {
59
+ export const generatePageName = (pageNameList: string[], type: NodeType.PAGE | NodeType.PAGE_FRAGMENT): string => {
54
60
  let pageLength = pageNameList.length;
55
61
 
56
- if (!pageLength) return 'index';
62
+ if (!pageLength) return `${type}_index`;
57
63
 
58
- let pageName = `page_${pageLength}`;
64
+ let pageName = `${type}_${pageLength}`;
59
65
  while (pageNameList.includes(pageName)) {
60
66
  pageLength += 1;
61
- pageName = `page_${pageLength}`;
67
+ pageName = `${type}_${pageLength}`;
62
68
  }
63
69
 
64
70
  return pageName;
@@ -69,7 +75,8 @@ export const generatePageName = (pageNameList: string[]): string => {
69
75
  * @param {Object} app 所有页面配置
70
76
  * @returns {string}
71
77
  */
72
- export const generatePageNameByApp = (app: MApp): string => generatePageName(getPageNameList(getPageList(app)));
78
+ export const generatePageNameByApp = (app: MApp, type: NodeType.PAGE | NodeType.PAGE_FRAGMENT): string =>
79
+ generatePageName(getPageNameList(type === 'page' ? getPageList(app) : getPageFragmentList(app)), type);
73
80
 
74
81
  /**
75
82
  * @param {Object} node
@@ -129,7 +136,7 @@ export const getInitPositionStyle = (style: Record<string, any> = {}, layout: La
129
136
  return style;
130
137
  };
131
138
 
132
- export const setChilrenLayout = (node: MContainer, layout: Layout) => {
139
+ export const setChildrenLayout = (node: MContainer, layout: Layout) => {
133
140
  node.items?.forEach((child: MNode) => {
134
141
  setLayout(child, layout);
135
142
  });
@@ -257,13 +264,22 @@ export const serializeConfig = (config: any) =>
257
264
  unsafe: true,
258
265
  }).replace(/"(\w+)":\s/g, '$1: ');
259
266
 
260
- export const traverseNode = (node: MNode, cb: (node: MNode, parents: MNode[]) => void, parents: MNode[] = []) => {
267
+ export interface NodeItem {
268
+ items?: NodeItem[];
269
+ [key: string]: any;
270
+ }
271
+
272
+ export const traverseNode = <T extends NodeItem = NodeItem>(
273
+ node: T,
274
+ cb: (node: T, parents: T[]) => void,
275
+ parents: T[] = [],
276
+ ) => {
261
277
  cb(node, parents);
262
278
 
263
279
  if (node.items?.length) {
264
280
  parents.push(node);
265
- node.items.forEach((item: MNode) => {
266
- traverseNode(item, cb, parents);
281
+ node.items.forEach((item) => {
282
+ traverseNode(item as T, cb, [...parents]);
267
283
  });
268
284
  }
269
285
  };
@@ -1,8 +1,8 @@
1
1
  import { toRaw } from 'vue';
2
2
  import { isEmpty } from 'lodash-es';
3
3
 
4
- import { Id, MContainer, MNode } from '@tmagic/schema';
5
- import { isPage } from '@tmagic/utils';
4
+ import { Id, MContainer, MNode, NodeType } from '@tmagic/schema';
5
+ import { isPage, isPageFragment } from '@tmagic/utils';
6
6
 
7
7
  import editorService from '@editor/services/editor';
8
8
  import propsService from '@editor/services/props';
@@ -40,8 +40,7 @@ export const beforePaste = async (position: PastePosition, config: MNode[]): Pro
40
40
  if (pastePosition.top && configItem.style?.top) {
41
41
  pastePosition.top = configItem.style?.top - referenceTop + pastePosition.top;
42
42
  }
43
-
44
- const pasteConfig = await propsService.setNewItemId(configItem);
43
+ const pasteConfig = await propsService.setNewItemId(configItem, false);
45
44
 
46
45
  if (pasteConfig.style) {
47
46
  const { left, top } = pasteConfig.style;
@@ -59,8 +58,8 @@ export const beforePaste = async (position: PastePosition, config: MNode[]): Pro
59
58
  };
60
59
  }
61
60
  const root = editorService.get('root');
62
- if (isPage(pasteConfig) && root) {
63
- pasteConfig.name = generatePageNameByApp(root);
61
+ if ((isPage(pasteConfig) || isPageFragment(pasteConfig)) && root) {
62
+ pasteConfig.name = generatePageNameByApp(root, isPage(pasteConfig) ? NodeType.PAGE : NodeType.PAGE_FRAGMENT);
64
63
  }
65
64
  return pasteConfig as MNode;
66
65
  }),
@@ -9,13 +9,17 @@ declare const _default: import("vue").DefineComponent<__VLS_TypePropsToRuntimePr
9
9
  }>, {
10
10
  show(): void;
11
11
  hide(): void;
12
- }, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
12
+ }, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
13
+ submit: (values: CodeBlockContent) => void;
14
+ }, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
13
15
  content: CodeBlockContent;
14
16
  disabled?: boolean | undefined;
15
17
  isDataSource?: boolean | undefined;
16
18
  dataSourceType?: string | undefined;
17
19
  slideType?: SlideType | undefined;
18
- }>>>, {}, {}>;
20
+ }>>> & {
21
+ onSubmit?: ((values: CodeBlockContent) => any) | undefined;
22
+ }, {}, {}>;
19
23
  export default _default;
20
24
  type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
21
25
  type __VLS_TypePropsToRuntimeProps<T> = {
@@ -5,7 +5,9 @@ declare const _default: import("vue").DefineComponent<__VLS_TypePropsToRuntimePr
5
5
  disabled?: boolean | undefined;
6
6
  name: string;
7
7
  paramsConfig: CodeParamStatement[];
8
- }>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "change"[], "change", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
8
+ }>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
9
+ change: (...args: any[]) => void;
10
+ }, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
9
11
  model: any;
10
12
  size?: "default" | "small" | "large" | undefined;
11
13
  disabled?: boolean | undefined;