@tmagic/editor 1.8.0-beta.3 → 1.8.0-beta.4

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 (66) hide show
  1. package/dist/es/components/CompareForm.vue_vue_type_script_setup_true_lang.js +15 -1
  2. package/dist/es/hooks/use-code-block-edit.js +6 -3
  3. package/dist/es/hooks/use-data-source-edit.js +5 -2
  4. package/dist/es/hooks/use-stage.js +6 -3
  5. package/dist/es/layouts/NavMenu.vue_vue_type_script_setup_true_lang.js +1 -1
  6. package/dist/es/layouts/history-list/Bucket.vue_vue_type_script_setup_true_lang.js +6 -2
  7. package/dist/es/layouts/history-list/BucketTab.vue_vue_type_script_setup_true_lang.js +3 -0
  8. package/dist/es/layouts/history-list/GroupRow.vue_vue_type_script_setup_true_lang.js +42 -29
  9. package/dist/es/layouts/history-list/HistoryDiffDialog.vue_vue_type_script_setup_true_lang.js +4 -2
  10. package/dist/es/layouts/history-list/HistoryListPanel.vue_vue_type_script_setup_true_lang.js +5 -1
  11. package/dist/es/layouts/history-list/PageTab.vue_vue_type_script_setup_true_lang.js +5 -2
  12. package/dist/es/layouts/history-list/composables.js +53 -1
  13. package/dist/es/layouts/props-panel/PropsPanel.vue_vue_type_script_setup_true_lang.js +5 -1
  14. package/dist/es/layouts/sidebar/ComponentListPanel.vue_vue_type_script_setup_true_lang.js +1 -1
  15. package/dist/es/layouts/sidebar/code-block/CodeBlockList.vue_vue_type_script_setup_true_lang.js +3 -3
  16. package/dist/es/layouts/sidebar/code-block/CodeBlockListPanel.vue_vue_type_script_setup_true_lang.js +1 -1
  17. package/dist/es/layouts/sidebar/code-block/useContentMenu.js +1 -1
  18. package/dist/es/layouts/sidebar/data-source/DataSourceListPanel.vue_vue_type_script_setup_true_lang.js +1 -1
  19. package/dist/es/layouts/sidebar/data-source/useContentMenu.js +1 -1
  20. package/dist/es/layouts/sidebar/layer/LayerMenu.vue_vue_type_script_setup_true_lang.js +5 -5
  21. package/dist/es/layouts/sidebar/layer/LayerNodeTool.vue_vue_type_script_setup_true_lang.js +1 -1
  22. package/dist/es/layouts/workspace/viewer/Stage.vue_vue_type_script_setup_true_lang.js +1 -1
  23. package/dist/es/layouts/workspace/viewer/ViewerMenu.vue_vue_type_script_setup_true_lang.js +8 -8
  24. package/dist/es/services/codeBlock.js +25 -10
  25. package/dist/es/services/dataSource.js +24 -10
  26. package/dist/es/services/editor.js +98 -46
  27. package/dist/es/services/history.js +2 -0
  28. package/dist/es/services/keybinding.js +3 -3
  29. package/dist/es/style.css +16 -4
  30. package/dist/es/utils/content-menu.js +17 -9
  31. package/dist/style.css +16 -4
  32. package/dist/tmagic-editor.umd.cjs +343 -144
  33. package/package.json +7 -7
  34. package/src/components/CompareForm.vue +19 -1
  35. package/src/hooks/use-code-block-edit.ts +4 -3
  36. package/src/hooks/use-data-source-edit.ts +2 -2
  37. package/src/hooks/use-stage.ts +3 -3
  38. package/src/layouts/NavMenu.vue +1 -1
  39. package/src/layouts/history-list/Bucket.vue +6 -2
  40. package/src/layouts/history-list/BucketTab.vue +3 -0
  41. package/src/layouts/history-list/GroupRow.vue +20 -3
  42. package/src/layouts/history-list/HistoryDiffDialog.vue +2 -1
  43. package/src/layouts/history-list/HistoryListPanel.vue +4 -0
  44. package/src/layouts/history-list/PageTab.vue +5 -1
  45. package/src/layouts/history-list/composables.ts +60 -0
  46. package/src/layouts/props-panel/PropsPanel.vue +5 -1
  47. package/src/layouts/sidebar/ComponentListPanel.vue +9 -5
  48. package/src/layouts/sidebar/code-block/CodeBlockList.vue +5 -5
  49. package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +1 -1
  50. package/src/layouts/sidebar/code-block/useContentMenu.ts +1 -1
  51. package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +1 -1
  52. package/src/layouts/sidebar/data-source/useContentMenu.ts +1 -1
  53. package/src/layouts/sidebar/layer/LayerMenu.vue +19 -11
  54. package/src/layouts/sidebar/layer/LayerNodeTool.vue +7 -4
  55. package/src/layouts/workspace/viewer/Stage.vue +1 -1
  56. package/src/layouts/workspace/viewer/ViewerMenu.vue +8 -8
  57. package/src/services/codeBlock.ts +33 -9
  58. package/src/services/dataSource.ts +30 -8
  59. package/src/services/editor.ts +111 -34
  60. package/src/services/history.ts +7 -0
  61. package/src/services/keybinding.ts +3 -3
  62. package/src/theme/history-list-panel.scss +15 -1
  63. package/src/theme/props-panel.scss +3 -3
  64. package/src/type.ts +58 -2
  65. package/src/utils/content-menu.ts +18 -9
  66. package/types/index.d.ts +96 -25
@@ -36,11 +36,11 @@ var ViewerMenu_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ def
36
36
  display: () => canCenter.value,
37
37
  handler: () => {
38
38
  if (!nodes.value) return;
39
- editorService.alignCenter(nodes.value);
39
+ editorService.alignCenter(nodes.value, { historySource: "stage-contextmenu" });
40
40
  }
41
41
  },
42
42
  useCopyMenu(),
43
- usePasteMenu(menuRef),
43
+ usePasteMenu("stage-contextmenu", menuRef),
44
44
  {
45
45
  type: "divider",
46
46
  direction: "horizontal",
@@ -55,7 +55,7 @@ var ViewerMenu_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ def
55
55
  icon: markRaw(Top),
56
56
  display: () => !isPage(node.value) && !isPageFragment(node.value) && !props.isMultiSelect,
57
57
  handler: () => {
58
- editorService.moveLayer(1);
58
+ editorService.moveLayer(1, { historySource: "stage-contextmenu" });
59
59
  }
60
60
  },
61
61
  {
@@ -64,7 +64,7 @@ var ViewerMenu_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ def
64
64
  icon: markRaw(Bottom),
65
65
  display: () => !isPage(node.value) && !isPageFragment(node.value) && !props.isMultiSelect,
66
66
  handler: () => {
67
- editorService.moveLayer(-1);
67
+ editorService.moveLayer(-1, { historySource: "stage-contextmenu" });
68
68
  }
69
69
  },
70
70
  {
@@ -73,7 +73,7 @@ var ViewerMenu_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ def
73
73
  icon: markRaw(Top),
74
74
  display: () => !isPage(node.value) && !isPageFragment(node.value) && !props.isMultiSelect,
75
75
  handler: () => {
76
- editorService.moveLayer(LayerOffset.TOP);
76
+ editorService.moveLayer(LayerOffset.TOP, { historySource: "stage-contextmenu" });
77
77
  }
78
78
  },
79
79
  {
@@ -82,16 +82,16 @@ var ViewerMenu_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ def
82
82
  icon: markRaw(Bottom),
83
83
  display: () => !isPage(node.value) && !isPageFragment(node.value) && !props.isMultiSelect,
84
84
  handler: () => {
85
- editorService.moveLayer(LayerOffset.BOTTOM);
85
+ editorService.moveLayer(LayerOffset.BOTTOM, { historySource: "stage-contextmenu" });
86
86
  }
87
87
  },
88
- useMoveToMenu(services),
88
+ useMoveToMenu(services, "stage-contextmenu"),
89
89
  {
90
90
  type: "divider",
91
91
  direction: "horizontal",
92
92
  display: () => !isPage(node.value) && !isPageFragment(node.value) && !props.isMultiSelect
93
93
  },
94
- useDeleteMenu(),
94
+ useDeleteMenu("stage-contextmenu"),
95
95
  {
96
96
  type: "divider",
97
97
  direction: "horizontal"
@@ -86,10 +86,12 @@ var CodeBlock = class extends BaseService {
86
86
  * @param options.doNotPushHistory 是否不写入历史记录(默认 false)
87
87
  * @returns {void}
88
88
  */
89
- async setCodeDslById(id, codeConfig, { changeRecords, doNotPushHistory = false } = {}) {
89
+ async setCodeDslById(id, codeConfig, { changeRecords, doNotPushHistory = false, historyDescription, historySource } = {}) {
90
90
  this.setCodeDslByIdSync(id, codeConfig, true, {
91
91
  changeRecords,
92
- doNotPushHistory
92
+ doNotPushHistory,
93
+ historyDescription,
94
+ historySource
93
95
  });
94
96
  }
95
97
  /**
@@ -104,7 +106,7 @@ var CodeBlock = class extends BaseService {
104
106
  * @param options.historyDescription 入栈时附带的人类可读描述,用于历史面板展示
105
107
  * @returns {void}
106
108
  */
107
- setCodeDslByIdSync(id, codeConfig, force = true, { changeRecords, doNotPushHistory = false, historyDescription } = {}) {
109
+ setCodeDslByIdSync(id, codeConfig, force = true, { changeRecords, doNotPushHistory = false, historyDescription, historySource } = {}) {
108
110
  const codeDsl = this.getCodeDsl();
109
111
  if (!codeDsl) throw new Error("dsl中没有codeBlocks");
110
112
  if (codeDsl[id] && !force) return;
@@ -123,7 +125,8 @@ var CodeBlock = class extends BaseService {
123
125
  oldContent,
124
126
  newContent,
125
127
  changeRecords,
126
- historyDescription
128
+ historyDescription,
129
+ source: historySource
127
130
  });
128
131
  this.emit("addOrUpdate", id, codeDsl[id]);
129
132
  }
@@ -204,7 +207,7 @@ var CodeBlock = class extends BaseService {
204
207
  * @param options 可选配置
205
208
  * @param options.doNotPushHistory 是否不写入历史记录(默认 false)
206
209
  */
207
- async deleteCodeDslByIds(codeIds, { doNotPushHistory = false, historyDescription } = {}) {
210
+ async deleteCodeDslByIds(codeIds, { doNotPushHistory = false, historyDescription, historySource } = {}) {
208
211
  const currentDsl = await this.getCodeDsl();
209
212
  if (!currentDsl) return;
210
213
  codeIds.forEach((id) => {
@@ -213,7 +216,8 @@ var CodeBlock = class extends BaseService {
213
216
  if (oldContent && !doNotPushHistory) history_default.pushCodeBlock(id, {
214
217
  oldContent,
215
218
  newContent: null,
216
- historyDescription
219
+ historyDescription,
220
+ source: historySource
217
221
  });
218
222
  this.emit("remove", id);
219
223
  });
@@ -293,6 +297,7 @@ var CodeBlock = class extends BaseService {
293
297
  async revert(id, index) {
294
298
  const entry = history_default.getCodeBlockStepList(id)[index];
295
299
  if (!entry?.applied) return null;
300
+ if (entry.step.oldContent && entry.step.newContent && !entry.step.changeRecords?.length) return null;
296
301
  const description = `回滚 #${index + 1}: ${describeRevertCodeBlockStep(entry.step)}`;
297
302
  return await this.applyRevertStep(entry.step, description);
298
303
  }
@@ -363,11 +368,17 @@ var CodeBlock = class extends BaseService {
363
368
  async applyRevertStep(step, historyDescription) {
364
369
  const { id, oldContent, newContent, changeRecords } = step;
365
370
  if (oldContent === null && newContent) {
366
- await this.deleteCodeDslByIds([id], { historyDescription });
371
+ await this.deleteCodeDslByIds([id], {
372
+ historyDescription,
373
+ historySource: "rollback"
374
+ });
367
375
  return history_default.getCodeBlockStepList(id).slice(-1)[0]?.step ?? null;
368
376
  }
369
377
  if (oldContent && newContent === null) {
370
- this.setCodeDslByIdSync(id, cloneDeep$1(oldContent), true, { historyDescription });
378
+ this.setCodeDslByIdSync(id, cloneDeep$1(oldContent), true, {
379
+ historyDescription,
380
+ historySource: "rollback"
381
+ });
371
382
  return history_default.getCodeBlockStepList(id).slice(-1)[0]?.step ?? null;
372
383
  }
373
384
  if (!oldContent || !newContent) return null;
@@ -386,11 +397,15 @@ var CodeBlock = class extends BaseService {
386
397
  }
387
398
  this.setCodeDslByIdSync(id, fallbackToFullReplace ? cloneDeep$1(oldContent) : patched, true, {
388
399
  changeRecords,
389
- historyDescription
400
+ historyDescription,
401
+ historySource: "rollback"
390
402
  });
391
403
  return history_default.getCodeBlockStepList(id).slice(-1)[0]?.step ?? null;
392
404
  }
393
- this.setCodeDslByIdSync(id, cloneDeep$1(oldContent), true, { historyDescription });
405
+ this.setCodeDslByIdSync(id, cloneDeep$1(oldContent), true, {
406
+ historyDescription,
407
+ historySource: "rollback"
408
+ });
394
409
  return history_default.getCodeBlockStepList(id).slice(-1)[0]?.step ?? null;
395
410
  }
396
411
  /**
@@ -91,7 +91,7 @@ var DataSource = class extends BaseService {
91
91
  * @param options.doNotPushHistory 是否不写入历史记录(默认 false)
92
92
  * @param options.historyDescription 入栈时附带的人类可读描述,用于历史面板展示
93
93
  */
94
- add(config, { doNotPushHistory = false, historyDescription } = {}) {
94
+ add(config, { doNotPushHistory = false, historyDescription, historySource } = {}) {
95
95
  const newConfig = {
96
96
  ...config,
97
97
  id: config.id && !this.getDataSourceById(config.id) ? config.id : this.createId()
@@ -100,7 +100,8 @@ var DataSource = class extends BaseService {
100
100
  if (!doNotPushHistory) history_default.pushDataSource(newConfig.id, {
101
101
  oldSchema: null,
102
102
  newSchema: newConfig,
103
- historyDescription
103
+ historyDescription,
104
+ source: historySource
104
105
  });
105
106
  this.emit("add", newConfig);
106
107
  return newConfig;
@@ -113,7 +114,7 @@ var DataSource = class extends BaseService {
113
114
  * @param data.doNotPushHistory 是否不写入历史记录(默认 false)
114
115
  * @param data.historyDescription 入栈时附带的人类可读描述,用于历史面板展示
115
116
  */
116
- update(config, { changeRecords = [], doNotPushHistory = false, historyDescription } = {}) {
117
+ update(config, { changeRecords = [], doNotPushHistory = false, historyDescription, historySource } = {}) {
117
118
  const dataSources = this.get("dataSources");
118
119
  const index = dataSources.findIndex((ds) => ds.id === config.id);
119
120
  const oldConfig = dataSources[index];
@@ -123,7 +124,8 @@ var DataSource = class extends BaseService {
123
124
  oldSchema: oldConfig ? cloneDeep$1(oldConfig) : null,
124
125
  newSchema: newConfig,
125
126
  changeRecords,
126
- historyDescription
127
+ historyDescription,
128
+ source: historySource
127
129
  });
128
130
  this.emit("update", newConfig, {
129
131
  oldConfig,
@@ -138,7 +140,7 @@ var DataSource = class extends BaseService {
138
140
  * @param options.doNotPushHistory 是否不写入历史记录(默认 false)
139
141
  * @param options.historyDescription 入栈时附带的人类可读描述,用于历史面板展示
140
142
  */
141
- remove(id, { doNotPushHistory = false, historyDescription } = {}) {
143
+ remove(id, { doNotPushHistory = false, historyDescription, historySource } = {}) {
142
144
  const dataSources = this.get("dataSources");
143
145
  const index = dataSources.findIndex((ds) => ds.id === id);
144
146
  const oldConfig = index !== -1 ? dataSources[index] : null;
@@ -146,7 +148,8 @@ var DataSource = class extends BaseService {
146
148
  if (oldConfig && !doNotPushHistory) history_default.pushDataSource(id, {
147
149
  oldSchema: cloneDeep$1(oldConfig),
148
150
  newSchema: null,
149
- historyDescription
151
+ historyDescription,
152
+ source: historySource
150
153
  });
151
154
  this.emit("remove", id);
152
155
  }
@@ -218,6 +221,7 @@ var DataSource = class extends BaseService {
218
221
  revert(id, index) {
219
222
  const entry = history_default.getDataSourceStepList(id)[index];
220
223
  if (!entry?.applied) return null;
224
+ if (entry.step.oldSchema && entry.step.newSchema && !entry.step.changeRecords?.length) return null;
221
225
  const description = `回滚 #${index + 1}: ${describeRevertDataSourceStep(entry.step)}`;
222
226
  return this.applyRevertStep(entry.step, description);
223
227
  }
@@ -281,11 +285,17 @@ var DataSource = class extends BaseService {
281
285
  applyRevertStep(step, historyDescription) {
282
286
  const { id, oldSchema, newSchema, changeRecords } = step;
283
287
  if (oldSchema === null && newSchema) {
284
- this.remove(`${id}`, { historyDescription });
288
+ this.remove(`${id}`, {
289
+ historyDescription,
290
+ historySource: "rollback"
291
+ });
285
292
  return history_default.getDataSourceStepList(id).slice(-1)[0]?.step ?? null;
286
293
  }
287
294
  if (oldSchema && newSchema === null) {
288
- this.add(cloneDeep$1(oldSchema), { historyDescription });
295
+ this.add(cloneDeep$1(oldSchema), {
296
+ historyDescription,
297
+ historySource: "rollback"
298
+ });
289
299
  return history_default.getDataSourceStepList(id).slice(-1)[0]?.step ?? null;
290
300
  }
291
301
  if (!oldSchema || !newSchema) return null;
@@ -304,11 +314,15 @@ var DataSource = class extends BaseService {
304
314
  }
305
315
  this.update(fallbackToFullReplace ? cloneDeep$1(oldSchema) : patched, {
306
316
  changeRecords,
307
- historyDescription
317
+ historyDescription,
318
+ historySource: "rollback"
308
319
  });
309
320
  return history_default.getDataSourceStepList(id).slice(-1)[0]?.step ?? null;
310
321
  }
311
- this.update(cloneDeep$1(oldSchema), { historyDescription });
322
+ this.update(cloneDeep$1(oldSchema), {
323
+ historyDescription,
324
+ historySource: "rollback"
325
+ });
312
326
  return history_default.getDataSourceStepList(id).slice(-1)[0]?.step ?? null;
313
327
  }
314
328
  /**
@@ -269,7 +269,7 @@ var Editor = class extends BaseService {
269
269
  * @param options.doNotPushHistory 是否不写入历史记录(默认 false)
270
270
  * @returns 添加后的节点
271
271
  */
272
- async add(addNode, parent, { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false, historyDescription } = {}) {
272
+ async add(addNode, parent, { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false, historyDescription, historySource } = {}) {
273
273
  this.captureSelectionBeforeOp();
274
274
  const stage = this.get("stage");
275
275
  const addNodes = [];
@@ -303,16 +303,21 @@ var Editor = class extends BaseService {
303
303
  if (!(isPage(newNodes[0]) || isPageFragment(newNodes[0]))) {
304
304
  const pageForOp = this.getNodeInfo(newNodes[0].id, false).page;
305
305
  if (!doNotPushHistory) this.pushOpHistory("add", {
306
- nodes: newNodes.map((n) => cloneDeep$1(toRaw(n))),
307
- parentId: (this.getParentById(newNodes[0].id, false) ?? this.get("root")).id,
308
- indexMap: Object.fromEntries(newNodes.map((n) => {
309
- const p = this.getParentById(n.id, false);
310
- return [n.id, p ? getNodeIndex(n.id, p) : -1];
311
- }))
312
- }, {
313
- name: pageForOp?.name || "",
314
- id: pageForOp.id
315
- }, historyDescription);
306
+ extra: {
307
+ nodes: newNodes.map((n) => cloneDeep$1(toRaw(n))),
308
+ parentId: (this.getParentById(newNodes[0].id, false) ?? this.get("root")).id,
309
+ indexMap: Object.fromEntries(newNodes.map((n) => {
310
+ const p = this.getParentById(n.id, false);
311
+ return [n.id, p ? getNodeIndex(n.id, p) : -1];
312
+ }))
313
+ },
314
+ pageData: {
315
+ name: pageForOp?.name || "",
316
+ id: pageForOp.id
317
+ },
318
+ historyDescription,
319
+ source: historySource
320
+ });
316
321
  else this.selectionBeforeOp = null;
317
322
  }
318
323
  this.emit("add", newNodes);
@@ -379,7 +384,7 @@ var Editor = class extends BaseService {
379
384
  * @param options.doNotSwitchPage 删除后是否不切换当前页面(默认 false;删除页面 / 页面片段时为 true 会跳过自动切换到首个剩余页面)
380
385
  * @param options.doNotPushHistory 是否不写入历史记录(默认 false)
381
386
  */
382
- async remove(nodeOrNodeList, { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false, historyDescription } = {}) {
387
+ async remove(nodeOrNodeList, { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false, historyDescription, historySource } = {}) {
383
388
  this.captureSelectionBeforeOp();
384
389
  const nodes = Array.isArray(nodeOrNodeList) ? nodeOrNodeList : [nodeOrNodeList];
385
390
  const removedItems = [];
@@ -403,7 +408,12 @@ var Editor = class extends BaseService {
403
408
  doNotSelect,
404
409
  doNotSwitchPage
405
410
  })));
406
- if (removedItems.length > 0 && pageForOp) if (!doNotPushHistory) this.pushOpHistory("remove", { removedItems }, pageForOp, historyDescription);
411
+ if (removedItems.length > 0 && pageForOp) if (!doNotPushHistory) this.pushOpHistory("remove", {
412
+ extra: { removedItems },
413
+ pageData: pageForOp,
414
+ historyDescription,
415
+ source: historySource
416
+ });
407
417
  else this.selectionBeforeOp = null;
408
418
  this.emit("remove", nodes);
409
419
  }
@@ -464,7 +474,7 @@ var Editor = class extends BaseService {
464
474
  */
465
475
  async update(config, data = {}) {
466
476
  this.captureSelectionBeforeOp();
467
- const { doNotPushHistory = false, changeRecordList, changeRecords, historyDescription } = data;
477
+ const { doNotPushHistory = false, changeRecordList, changeRecords, historyDescription, historySource } = data;
468
478
  const nodes = Array.isArray(config) ? config : [config];
469
479
  const updateData = await Promise.all(nodes.map((node, index) => {
470
480
  const recordsForNode = changeRecordList ? changeRecordList[index] ?? [] : changeRecords ?? [];
@@ -473,14 +483,19 @@ var Editor = class extends BaseService {
473
483
  if (updateData[0].oldNode?.type !== NodeType.ROOT) {
474
484
  if (this.get("nodes").length) if (!doNotPushHistory) {
475
485
  const pageForOp = this.getNodeInfo(nodes[0].id, false).page;
476
- this.pushOpHistory("update", { updatedItems: updateData.map((d) => ({
477
- oldNode: cloneDeep$1(d.oldNode),
478
- newNode: cloneDeep$1(toRaw(d.newNode)),
479
- changeRecords: d.changeRecords?.length ? cloneDeep$1(d.changeRecords) : void 0
480
- })) }, {
481
- name: pageForOp?.name || "",
482
- id: pageForOp.id
483
- }, historyDescription);
486
+ this.pushOpHistory("update", {
487
+ extra: { updatedItems: updateData.map((d) => ({
488
+ oldNode: cloneDeep$1(d.oldNode),
489
+ newNode: cloneDeep$1(toRaw(d.newNode)),
490
+ changeRecords: d.changeRecords?.length ? cloneDeep$1(d.changeRecords) : void 0
491
+ })) },
492
+ pageData: {
493
+ name: pageForOp?.name || "",
494
+ id: pageForOp.id
495
+ },
496
+ historyDescription,
497
+ source: historySource
498
+ });
484
499
  } else this.selectionBeforeOp = null;
485
500
  }
486
501
  this.emit("update", updateData);
@@ -496,7 +511,7 @@ var Editor = class extends BaseService {
496
511
  * @param options.doNotPushHistory 是否不写入历史记录(默认 false)
497
512
  * @returns void
498
513
  */
499
- async sort(id1, id2, { doNotSelect = false, doNotPushHistory = false } = {}) {
514
+ async sort(id1, id2, { doNotSelect = false, doNotPushHistory = false, historySource } = {}) {
500
515
  this.captureSelectionBeforeOp();
501
516
  const root = this.get("root");
502
517
  if (!root) throw new Error("root为空");
@@ -508,7 +523,10 @@ var Editor = class extends BaseService {
508
523
  if (index2 < 0) return;
509
524
  const index1 = parent.items.findIndex((node) => `${node.id}` === `${id1}`);
510
525
  parent.items.splice(index2, 0, ...parent.items.splice(index1, 1));
511
- await this.update(parent, { doNotPushHistory });
526
+ await this.update(parent, {
527
+ doNotPushHistory,
528
+ historySource
529
+ });
512
530
  if (!doNotSelect) await this.select(node);
513
531
  this.get("stage")?.update({
514
532
  config: cloneDeep$1(node),
@@ -544,7 +562,7 @@ var Editor = class extends BaseService {
544
562
  * @param options.doNotPushHistory 是否不写入历史记录(默认 false)
545
563
  * @returns 添加后的组件节点配置
546
564
  */
547
- async paste(position = {}, collectorOptions, { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false } = {}) {
565
+ async paste(position = {}, collectorOptions, { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false, historyDescription, historySource } = {}) {
548
566
  const config = storage_default.getItem(COPY_STORAGE_KEY);
549
567
  if (!Array.isArray(config)) return;
550
568
  const node = this.get("node");
@@ -558,7 +576,9 @@ var Editor = class extends BaseService {
558
576
  return this.add(pasteConfigs, parent, {
559
577
  doNotSelect,
560
578
  doNotSwitchPage,
561
- doNotPushHistory
579
+ doNotPushHistory,
580
+ historyDescription,
581
+ historySource
562
582
  });
563
583
  }
564
584
  async doPaste(config, position = {}) {
@@ -586,11 +606,15 @@ var Editor = class extends BaseService {
586
606
  * @param options.doNotPushHistory 是否不写入历史记录(默认 false)
587
607
  * @returns 当前组件节点配置
588
608
  */
589
- async alignCenter(config, { doNotSelect = false, doNotPushHistory = false } = {}) {
609
+ async alignCenter(config, { doNotSelect = false, doNotPushHistory = false, historyDescription, historySource } = {}) {
590
610
  const nodes = Array.isArray(config) ? config : [config];
591
611
  const stage = this.get("stage");
592
612
  const newNodes = await Promise.all(nodes.map((node) => this.doAlignCenter(node)));
593
- const newNode = await this.update(newNodes, { doNotPushHistory });
613
+ const newNode = await this.update(newNodes, {
614
+ doNotPushHistory,
615
+ historyDescription,
616
+ historySource
617
+ });
594
618
  if (!doNotSelect) if (newNodes.length > 1) await stage?.multiSelect(newNodes.map((node) => node.id));
595
619
  else await stage?.select(newNodes[0].id);
596
620
  return newNode;
@@ -601,7 +625,7 @@ var Editor = class extends BaseService {
601
625
  * @param options 可选配置
602
626
  * @param options.doNotPushHistory 是否不写入历史记录(默认 false)
603
627
  */
604
- async moveLayer(offset, { doNotPushHistory = false } = {}) {
628
+ async moveLayer(offset, { doNotPushHistory = false, historyDescription, historySource } = {}) {
605
629
  this.captureSelectionBeforeOp();
606
630
  const root = this.get("root");
607
631
  if (!root) throw new Error("root为空");
@@ -626,12 +650,17 @@ var Editor = class extends BaseService {
626
650
  this.addModifiedNodeId(parent.id);
627
651
  if (!doNotPushHistory) {
628
652
  const pageForOp = this.getNodeInfo(node.id, false).page;
629
- this.pushOpHistory("update", { updatedItems: [{
630
- oldNode: oldParent,
631
- newNode: cloneDeep$1(toRaw(parent))
632
- }] }, {
633
- name: pageForOp?.name || "",
634
- id: pageForOp.id
653
+ this.pushOpHistory("update", {
654
+ extra: { updatedItems: [{
655
+ oldNode: oldParent,
656
+ newNode: cloneDeep$1(toRaw(parent))
657
+ }] },
658
+ pageData: {
659
+ name: pageForOp?.name || "",
660
+ id: pageForOp.id
661
+ },
662
+ historyDescription,
663
+ source: historySource
635
664
  });
636
665
  } else this.selectionBeforeOp = null;
637
666
  this.emit("move-layer", offset);
@@ -650,7 +679,7 @@ var Editor = class extends BaseService {
650
679
  * @param options.doNotSwitchPage 移动后是否不切换当前页面(默认 false;目标容器位于其它页面时为 true 会跳过自动选中以避免页面切换)
651
680
  * @param options.doNotPushHistory 是否不写入历史记录(默认 false)
652
681
  */
653
- async moveToContainer(config, targetId, { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false } = {}) {
682
+ async moveToContainer(config, targetId, { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false, historyDescription, historySource } = {}) {
654
683
  const isBatch = Array.isArray(config);
655
684
  const configs = (isBatch ? config : [config]).filter((item) => !(isPage(item) || isPageFragment(item)));
656
685
  if (configs.length === 0) throw new Error("没有可移动的节点");
@@ -698,11 +727,16 @@ var Editor = class extends BaseService {
698
727
  name: "",
699
728
  id: target.id
700
729
  };
701
- this.pushOpHistory("update", { updatedItems }, historyPage);
730
+ this.pushOpHistory("update", {
731
+ extra: { updatedItems },
732
+ pageData: historyPage,
733
+ historyDescription,
734
+ source: historySource
735
+ });
702
736
  } else this.selectionBeforeOp = null;
703
737
  return isBatch ? newConfigs : newConfigs[0];
704
738
  }
705
- async dragTo(config, targetParent, targetIndex, { doNotPushHistory = false } = {}) {
739
+ async dragTo(config, targetParent, targetIndex, { doNotPushHistory = false, historyDescription, historySource } = {}) {
706
740
  this.captureSelectionBeforeOp();
707
741
  if (!targetParent || !Array.isArray(targetParent.items)) return;
708
742
  const configs = Array.isArray(config) ? config : [config];
@@ -744,9 +778,14 @@ var Editor = class extends BaseService {
744
778
  }
745
779
  if (!doNotPushHistory) {
746
780
  const pageForOp = this.getNodeInfo(configs[0].id, false).page;
747
- this.pushOpHistory("update", { updatedItems }, {
748
- name: pageForOp?.name || "",
749
- id: pageForOp.id
781
+ this.pushOpHistory("update", {
782
+ extra: { updatedItems },
783
+ pageData: {
784
+ name: pageForOp?.name || "",
785
+ id: pageForOp.id
786
+ },
787
+ historyDescription,
788
+ source: historySource
750
789
  });
751
790
  } else this.selectionBeforeOp = null;
752
791
  this.emit("drag-to", {
@@ -794,6 +833,10 @@ var Editor = class extends BaseService {
794
833
  if (!entry?.applied) return null;
795
834
  const { step } = entry;
796
835
  if (!this.get("root")) return null;
836
+ if (step.opType === "update") {
837
+ const items = step.updatedItems ?? [];
838
+ if (!items.length || !items.every((item) => item.changeRecords?.length)) return null;
839
+ }
797
840
  let revertedStep = null;
798
841
  const captureRevert = (s) => {
799
842
  revertedStep = s;
@@ -803,7 +846,8 @@ var Editor = class extends BaseService {
803
846
  const opts = {
804
847
  doNotSelect: true,
805
848
  doNotSwitchPage: true,
806
- historyDescription
849
+ historyDescription,
850
+ historySource: "rollback"
807
851
  };
808
852
  try {
809
853
  switch (step.opType) {
@@ -839,7 +883,10 @@ var Editor = class extends BaseService {
839
883
  }
840
884
  return cloneDeep$1(oldNode);
841
885
  });
842
- if (configs.length) await this.update(configs, { historyDescription });
886
+ if (configs.length) await this.update(configs, {
887
+ historyDescription,
888
+ historySource: "rollback"
889
+ });
843
890
  break;
844
891
  }
845
892
  }
@@ -873,7 +920,7 @@ var Editor = class extends BaseService {
873
920
  }
874
921
  return cursor;
875
922
  }
876
- async move(left, top, { doNotPushHistory = false } = {}) {
923
+ async move(left, top, { doNotPushHistory = false, historyDescription, historySource } = {}) {
877
924
  const node = toRaw(this.get("node"));
878
925
  if (!node || isPage(node)) return;
879
926
  const newStyle = calcMoveStyle(node.style || {}, left, top);
@@ -882,7 +929,11 @@ var Editor = class extends BaseService {
882
929
  id: node.id,
883
930
  type: node.type,
884
931
  style: newStyle
885
- }, { doNotPushHistory });
932
+ }, {
933
+ doNotPushHistory,
934
+ historyDescription,
935
+ historySource
936
+ });
886
937
  }
887
938
  resetState() {
888
939
  this.set("root", null);
@@ -922,7 +973,7 @@ var Editor = class extends BaseService {
922
973
  if (this.selectionBeforeOp) return;
923
974
  this.selectionBeforeOp = this.get("nodes").map((n) => n.id);
924
975
  }
925
- pushOpHistory(opType, extra, pageData, historyDescription) {
976
+ pushOpHistory(opType, { extra, pageData, historyDescription, source }) {
926
977
  const step = {
927
978
  data: pageData,
928
979
  opType,
@@ -932,6 +983,7 @@ var Editor = class extends BaseService {
932
983
  ...extra
933
984
  };
934
985
  if (historyDescription) step.historyDescription = historyDescription;
986
+ if (source) step.source = source;
935
987
  history_default.push(step, pageData.id);
936
988
  this.selectionBeforeOp = null;
937
989
  }
@@ -236,6 +236,7 @@ var history_default = new class History extends BaseService {
236
236
  newContent: payload.newContent ? cloneDeep(payload.newContent) : null,
237
237
  changeRecords: payload.changeRecords?.length ? cloneDeep(payload.changeRecords) : void 0,
238
238
  historyDescription: payload.historyDescription,
239
+ source: payload.source,
239
240
  timestamp: Date.now()
240
241
  };
241
242
  this.getCodeBlockUndoRedo(codeBlockId).pushElement(step);
@@ -254,6 +255,7 @@ var history_default = new class History extends BaseService {
254
255
  newSchema: payload.newSchema ? cloneDeep(payload.newSchema) : null,
255
256
  changeRecords: payload.changeRecords?.length ? cloneDeep(payload.changeRecords) : void 0,
256
257
  historyDescription: payload.historyDescription,
258
+ source: payload.source,
257
259
  timestamp: Date.now()
258
260
  };
259
261
  this.getDataSourceUndoRedo(dataSourceId).pushElement(step);
@@ -13,7 +13,7 @@ var Keybinding = class extends BaseService {
13
13
  [KeyBindingCommand.DELETE_NODE]: () => {
14
14
  const nodes = editor_default.get("nodes");
15
15
  if (!nodes || isPage(nodes[0]) || isPageFragment(nodes[0])) return;
16
- editor_default.remove(nodes);
16
+ editor_default.remove(nodes, { historySource: "shortcut" });
17
17
  },
18
18
  [KeyBindingCommand.COPY_NODE]: () => {
19
19
  const nodes = editor_default.get("nodes");
@@ -23,13 +23,13 @@ var Keybinding = class extends BaseService {
23
23
  const nodes = editor_default.get("nodes");
24
24
  if (!nodes || isPage(nodes[0]) || isPageFragment(nodes[0])) return;
25
25
  editor_default.copy(nodes);
26
- editor_default.remove(nodes);
26
+ editor_default.remove(nodes, { historySource: "shortcut" });
27
27
  },
28
28
  [KeyBindingCommand.PASTE_NODE]: () => {
29
29
  editor_default.get("nodes") && editor_default.paste({
30
30
  offsetX: 10,
31
31
  offsetY: 10
32
- });
32
+ }, void 0, { historySource: "shortcut" });
33
33
  },
34
34
  [KeyBindingCommand.UNDO]: () => {
35
35
  editor_default.undo();
package/dist/es/style.css CHANGED
@@ -592,7 +592,7 @@ fieldset.m-fieldset .m-form-tip {
592
592
  position: absolute;
593
593
  top: 4px;
594
594
  right: 4px;
595
- z-index: 1;
595
+ z-index: 2;
596
596
  display: flex;
597
597
  align-items: center;
598
598
  height: 40px;
@@ -804,6 +804,18 @@ fieldset.m-fieldset .m-form-tip {
804
804
  text-overflow: ellipsis;
805
805
  white-space: nowrap;
806
806
  }
807
+ .m-editor-history-list-popover .m-editor-history-list-item-source {
808
+ flex: 0 0 auto;
809
+ padding: 0 6px;
810
+ border: 1px solid #dcdfe6;
811
+ border-radius: 8px;
812
+ font-size: 10px;
813
+ line-height: 14px;
814
+ color: #909399;
815
+ background-color: #f4f4f5;
816
+ white-space: nowrap;
817
+ font-weight: 400;
818
+ }
807
819
  .m-editor-history-list-popover .m-editor-history-list-item-merge {
808
820
  flex: 0 0 auto;
809
821
  padding: 0 8px;
@@ -1452,7 +1464,7 @@ fieldset.m-fieldset .m-form-tip {
1452
1464
  position: absolute;
1453
1465
  right: 15px;
1454
1466
  bottom: 15px;
1455
- z-index: 30;
1467
+ z-index: 32;
1456
1468
  opacity: 0.5;
1457
1469
  }
1458
1470
  .m-editor-props-panel .m-editor-props-panel-src-icon:hover {
@@ -1462,7 +1474,7 @@ fieldset.m-fieldset .m-form-tip {
1462
1474
  position: absolute;
1463
1475
  right: 15px;
1464
1476
  bottom: 60px;
1465
- z-index: 30;
1477
+ z-index: 31;
1466
1478
  opacity: 0.5;
1467
1479
  }
1468
1480
  .m-editor-props-panel .m-editor-props-panel-style-icon:hover {
@@ -1472,7 +1484,7 @@ fieldset.m-fieldset .m-form-tip {
1472
1484
  position: absolute;
1473
1485
  left: 0;
1474
1486
  top: 0;
1475
- z-index: 10;
1487
+ z-index: 31;
1476
1488
  }
1477
1489
  .m-editor-props-panel .m-editor-resizer {
1478
1490
  position: absolute;