@tmagic/editor 1.7.14-beta.1 → 1.7.14-beta.3

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.
@@ -65,6 +65,25 @@ import type { HistoryOpContext } from '@editor/utils/editor-history';
65
65
  import { applyHistoryAddOp, applyHistoryRemoveOp, applyHistoryUpdateOp } from '@editor/utils/editor-history';
66
66
  import { beforePaste, getAddParent } from '@editor/utils/operator';
67
67
 
68
+ /**
69
+ * 经过 BaseService 的插件 / 中间件包装后,源方法的最后一个形参可能被注入为 dispatch 函数
70
+ * 当 options 形参位置被注入为函数(或为 null)时,将其归一为空对象,避免后续逻辑误读
71
+ */
72
+ const safeOptions = <T extends object>(options: unknown): T => {
73
+ const empty = {};
74
+ if (!options || typeof options === 'function') return empty as T;
75
+ return options as T;
76
+ };
77
+
78
+ /**
79
+ * 经过 BaseService 的插件 / 中间件包装后,源方法的形参可能被注入为 dispatch 函数
80
+ * 当 parent 形参位置被注入为函数(或为空值)时,归一为 null,由调用方继续走默认 parent 逻辑
81
+ */
82
+ const safeParent = (parent: unknown): MContainer | null => {
83
+ if (!parent || typeof parent === 'function') return null;
84
+ return parent as MContainer;
85
+ };
86
+
68
87
  class Editor extends BaseService {
69
88
  public state: StoreState = reactive({
70
89
  root: null,
@@ -349,9 +368,18 @@ class Editor extends BaseService {
349
368
  * 向指点容器添加组件节点
350
369
  * @param addConfig 将要添加的组件节点配置
351
370
  * @param parent 要添加到的容器组件节点配置,如果不设置,默认为当前选中的组件的父节点
371
+ * @param options 可选配置
372
+ * @param options.doNotSelect 添加后是否不更新当前选中节点(默认 false,添加后会选中新增的节点)
352
373
  * @returns 添加后的节点
353
374
  */
354
- public async add(addNode: AddMNode | MNode[], parent?: MContainer | null): Promise<MNode | MNode[]> {
375
+ public async add(
376
+ addNode: AddMNode | MNode[],
377
+ parent?: MContainer | null,
378
+ options?: { doNotSelect?: boolean },
379
+ ): Promise<MNode | MNode[]> {
380
+ const safeParentNode = safeParent(parent);
381
+ const { doNotSelect = false } = safeOptions<{ doNotSelect?: boolean }>(options);
382
+
355
383
  this.captureSelectionBeforeOp();
356
384
 
357
385
  const stage = this.get('stage');
@@ -374,25 +402,29 @@ class Editor extends BaseService {
374
402
  if ((isPage(node) || isPageFragment(node)) && root) {
375
403
  return this.doAdd(node, root);
376
404
  }
377
- const parentNode = parent && typeof parent !== 'function' ? parent : getAddParent(node);
405
+ const parentNode = safeParentNode ?? getAddParent(node);
378
406
  if (!parentNode) throw new Error('未找到父元素');
379
407
  return this.doAdd(node, parentNode);
380
408
  }),
381
409
  );
382
410
 
383
411
  if (newNodes.length > 1) {
384
- const newNodeIds = newNodes.map((node) => node.id);
385
- // 触发选中样式
386
- stage?.multiSelect(newNodeIds);
387
- await this.multiSelect(newNodeIds);
412
+ if (!doNotSelect) {
413
+ const newNodeIds = newNodes.map((node) => node.id);
414
+ // 触发选中样式
415
+ stage?.multiSelect(newNodeIds);
416
+ await this.multiSelect(newNodeIds);
417
+ }
388
418
  } else {
389
- await this.select(newNodes[0]);
419
+ if (!doNotSelect) {
420
+ await this.select(newNodes[0]);
421
+ }
390
422
 
391
423
  if (isPage(newNodes[0])) {
392
424
  this.state.pageLength += 1;
393
425
  } else if (isPageFragment(newNodes[0])) {
394
426
  this.state.pageFragmentLength += 1;
395
- } else {
427
+ } else if (!doNotSelect) {
396
428
  // 新增页面,这个时候页面还有渲染出来,此时select会出错,在runtime-ready的时候回去select
397
429
  stage?.select(newNodes[0].id);
398
430
  }
@@ -421,7 +453,9 @@ class Editor extends BaseService {
421
453
  return Array.isArray(addNode) ? newNodes : newNodes[0];
422
454
  }
423
455
 
424
- public async doRemove(node: MNode): Promise<void> {
456
+ public async doRemove(node: MNode, options?: { doNotSelect?: boolean }): Promise<void> {
457
+ const { doNotSelect = false } = safeOptions<{ doNotSelect?: boolean }>(options);
458
+
425
459
  const root = this.get('root');
426
460
  if (!root) throw new Error('root不能为空');
427
461
 
@@ -437,6 +471,24 @@ class Editor extends BaseService {
437
471
  const stage = this.get('stage');
438
472
  stage?.remove({ id: node.id, parentId: parent.id, root: cloneDeep(root) });
439
473
 
474
+ if (doNotSelect) {
475
+ // 当被删除节点正好在当前选中列表中时,必须从 state 中移除引用,避免 state 持有已删除节点(与 doNotSelect 无关)
476
+ const selectedNodes = this.get('nodes');
477
+ const removedSelectedIndex = selectedNodes.findIndex((n: MNode) => `${n.id}` === `${node.id}`);
478
+ if (removedSelectedIndex !== -1) {
479
+ const nextSelected = [...selectedNodes];
480
+ nextSelected.splice(removedSelectedIndex, 1);
481
+ this.set('nodes', nextSelected);
482
+ }
483
+ // 同理,如果被删除的是当前 page,也清空 state.page,避免持有已删除页面
484
+ if (isPage(node) || isPageFragment(node)) {
485
+ const currentPage = this.get('page');
486
+ if (currentPage && `${currentPage.id}` === `${node.id}`) {
487
+ this.set('page', null);
488
+ }
489
+ }
490
+ }
491
+
440
492
  const selectDefault = async (pages: MNode[]) => {
441
493
  if (pages[0]) {
442
494
  await this.select(pages[0]);
@@ -453,14 +505,20 @@ class Editor extends BaseService {
453
505
  if (isPage(node)) {
454
506
  this.state.pageLength -= 1;
455
507
 
456
- await selectDefault(rootItems);
508
+ if (!doNotSelect) {
509
+ await selectDefault(rootItems);
510
+ }
457
511
  } else if (isPageFragment(node)) {
458
512
  this.state.pageFragmentLength -= 1;
459
513
 
460
- await selectDefault(rootItems);
514
+ if (!doNotSelect) {
515
+ await selectDefault(rootItems);
516
+ }
461
517
  } else {
462
- await this.select(parent);
463
- stage?.select(parent.id);
518
+ if (!doNotSelect) {
519
+ await this.select(parent);
520
+ stage?.select(parent.id);
521
+ }
464
522
 
465
523
  this.addModifiedNodeId(parent.id);
466
524
  }
@@ -473,9 +531,13 @@ class Editor extends BaseService {
473
531
 
474
532
  /**
475
533
  * 删除组件
476
- * @param {Object} node
534
+ * @param {Object} node 要删除的节点或节点集合
535
+ * @param options 可选配置
536
+ * @param options.doNotSelect 删除后是否不更新当前选中节点(默认 false,删除后会选中父节点或首个页面)
477
537
  */
478
- public async remove(nodeOrNodeList: MNode | MNode[]): Promise<void> {
538
+ public async remove(nodeOrNodeList: MNode | MNode[], options?: { doNotSelect?: boolean }): Promise<void> {
539
+ const { doNotSelect = false } = safeOptions<{ doNotSelect?: boolean }>(options);
540
+
479
541
  this.captureSelectionBeforeOp();
480
542
 
481
543
  const nodes = Array.isArray(nodeOrNodeList) ? nodeOrNodeList : [nodeOrNodeList];
@@ -499,7 +561,7 @@ class Editor extends BaseService {
499
561
  }
500
562
  }
501
563
 
502
- await Promise.all(nodes.map((node) => this.doRemove(node)));
564
+ await Promise.all(nodes.map((node) => this.doRemove(node, { doNotSelect })));
503
565
 
504
566
  if (removedItems.length > 0 && pageForOp) {
505
567
  this.pushOpHistory('remove', { removedItems }, pageForOp);
@@ -510,10 +572,7 @@ class Editor extends BaseService {
510
572
 
511
573
  public async doUpdate(
512
574
  config: MNode,
513
- {
514
- changeRecords = [],
515
- selectedAfterUpdate = true,
516
- }: { changeRecords?: ChangeRecord[]; selectedAfterUpdate?: boolean } = {},
575
+ { changeRecords = [] }: { changeRecords?: ChangeRecord[] } = {},
517
576
  ): Promise<{ newNode: MNode; oldNode: MNode; changeRecords?: ChangeRecord[] }> {
518
577
  const root = this.get('root');
519
578
  if (!root) throw new Error('root为空');
@@ -557,12 +616,12 @@ class Editor extends BaseService {
557
616
 
558
617
  parentNodeItems[index] = newConfig;
559
618
 
560
- // 将update后的配置更新到nodes中
561
- if (selectedAfterUpdate) {
562
- const nodes = this.get('nodes');
563
- const targetIndex = nodes.findIndex((nodeItem: MNode) => `${nodeItem.id}` === `${newConfig.id}`);
564
- nodes.splice(targetIndex, 1, newConfig);
565
- this.set('nodes', [...nodes]);
619
+ // 当被更新节点正好在当前选中列表中时,必须同步引用,否则 state 会持有已被替换的旧节点
620
+ const selectedNodes = this.get('nodes');
621
+ const targetIndex = selectedNodes.findIndex((nodeItem: MNode) => `${nodeItem.id}` === `${newConfig.id}`);
622
+ if (targetIndex !== -1) {
623
+ selectedNodes.splice(targetIndex, 1, newConfig);
624
+ this.set('nodes', [...selectedNodes]);
566
625
  }
567
626
 
568
627
  if (isPage(newConfig) || isPageFragment(newConfig)) {
@@ -586,7 +645,7 @@ class Editor extends BaseService {
586
645
  */
587
646
  public async update(
588
647
  config: MNode | MNode[],
589
- data: { changeRecords?: ChangeRecord[]; selectedAfterUpdate?: boolean } = {},
648
+ data: { changeRecords?: ChangeRecord[] } = {},
590
649
  ): Promise<MNode | MNode[]> {
591
650
  this.captureSelectionBeforeOp();
592
651
 
@@ -620,9 +679,13 @@ class Editor extends BaseService {
620
679
  * 将id为id1的组件移动到id为id2的组件位置上,例如:[1,2,3,4] -> sort(1,3) -> [2,1,3,4]
621
680
  * @param id1 组件ID
622
681
  * @param id2 组件ID
682
+ * @param options 可选配置
683
+ * @param options.doNotSelect 排序后是否不更新当前选中节点(默认 false)
623
684
  * @returns void
624
685
  */
625
- public async sort(id1: Id, id2: Id): Promise<void> {
686
+ public async sort(id1: Id, id2: Id, options?: { doNotSelect?: boolean }): Promise<void> {
687
+ const { doNotSelect = false } = safeOptions<{ doNotSelect?: boolean }>(options);
688
+
626
689
  this.captureSelectionBeforeOp();
627
690
 
628
691
  const root = this.get('root');
@@ -642,7 +705,9 @@ class Editor extends BaseService {
642
705
  parent.items.splice(index2, 0, ...parent.items.splice(index1, 1));
643
706
 
644
707
  await this.update(parent);
645
- await this.select(node);
708
+ if (!doNotSelect) {
709
+ await this.select(node);
710
+ }
646
711
 
647
712
  this.get('stage')?.update({
648
713
  config: cloneDeep(node),
@@ -682,9 +747,18 @@ class Editor extends BaseService {
682
747
  /**
683
748
  * 从localStorage中获取节点,然后添加到当前容器中
684
749
  * @param position 粘贴的坐标
750
+ * @param collectorOptions 可选的依赖收集器配置
751
+ * @param options 可选配置
752
+ * @param options.doNotSelect 粘贴后是否不更新当前选中节点(默认 false)
685
753
  * @returns 添加后的组件节点配置
686
754
  */
687
- public async paste(position: PastePosition = {}, collectorOptions?: TargetOptions): Promise<MNode | MNode[] | void> {
755
+ public async paste(
756
+ position: PastePosition = {},
757
+ collectorOptions?: TargetOptions,
758
+ options?: { doNotSelect?: boolean },
759
+ ): Promise<MNode | MNode[] | void> {
760
+ const { doNotSelect = false } = safeOptions<{ doNotSelect?: boolean }>(options);
761
+
688
762
  const config: MNode[] = storageService.getItem(COPY_STORAGE_KEY);
689
763
  if (!Array.isArray(config)) return;
690
764
 
@@ -704,7 +778,7 @@ class Editor extends BaseService {
704
778
  propsService.replaceRelateId(config, pasteConfigs, collectorOptions);
705
779
  }
706
780
 
707
- return this.add(pasteConfigs, parent);
781
+ return this.add(pasteConfigs, parent, { doNotSelect });
708
782
  }
709
783
 
710
784
  public async doPaste(config: MNode[], position: PastePosition = {}): Promise<MNode[]> {
@@ -732,9 +806,13 @@ class Editor extends BaseService {
732
806
  /**
733
807
  * 将指点节点设置居中
734
808
  * @param config 组件节点配置
809
+ * @param options 可选配置
810
+ * @param options.doNotSelect 居中后是否不更新当前选中节点(默认 false)
735
811
  * @returns 当前组件节点配置
736
812
  */
737
- public async alignCenter(config: MNode | MNode[]): Promise<MNode | MNode[]> {
813
+ public async alignCenter(config: MNode | MNode[], options?: { doNotSelect?: boolean }): Promise<MNode | MNode[]> {
814
+ const { doNotSelect = false } = safeOptions<{ doNotSelect?: boolean }>(options);
815
+
738
816
  const nodes = Array.isArray(config) ? config : [config];
739
817
  const stage = this.get('stage');
740
818
 
@@ -742,10 +820,12 @@ class Editor extends BaseService {
742
820
 
743
821
  const newNode = await this.update(newNodes);
744
822
 
745
- if (newNodes.length > 1) {
746
- await stage?.multiSelect(newNodes.map((node) => node.id));
747
- } else {
748
- await stage?.select(newNodes[0].id);
823
+ if (!doNotSelect) {
824
+ if (newNodes.length > 1) {
825
+ await stage?.multiSelect(newNodes.map((node) => node.id));
826
+ } else {
827
+ await stage?.select(newNodes[0].id);
828
+ }
749
829
  }
750
830
 
751
831
  return newNode;
@@ -808,8 +888,16 @@ class Editor extends BaseService {
808
888
  * 移动到指定容器中
809
889
  * @param config 需要移动的节点
810
890
  * @param targetId 容器ID
891
+ * @param options 可选配置
892
+ * @param options.doNotSelect 移动后是否不更新当前选中节点(默认 false)
811
893
  */
812
- public async moveToContainer(config: MNode, targetId: Id): Promise<MNode | undefined> {
894
+ public async moveToContainer(
895
+ config: MNode,
896
+ targetId: Id,
897
+ options?: { doNotSelect?: boolean },
898
+ ): Promise<MNode | undefined> {
899
+ const { doNotSelect = false } = safeOptions<{ doNotSelect?: boolean }>(options);
900
+
813
901
  this.captureSelectionBeforeOp();
814
902
 
815
903
  const root = this.get('root');
@@ -837,7 +925,9 @@ class Editor extends BaseService {
837
925
 
838
926
  target.items.push(newConfig);
839
927
 
840
- await stage.select(targetId);
928
+ if (!doNotSelect) {
929
+ await stage.select(targetId);
930
+ }
841
931
 
842
932
  const targetParent = this.getParentById(target.id);
843
933
  await stage.update({
@@ -846,8 +936,10 @@ class Editor extends BaseService {
846
936
  root: cloneDeep(root),
847
937
  });
848
938
 
849
- await this.select(newConfig);
850
- stage.select(newConfig.id);
939
+ if (!doNotSelect) {
940
+ await this.select(newConfig);
941
+ stage.select(newConfig.id);
942
+ }
851
943
 
852
944
  this.addModifiedNodeId(target.id);
853
945
  this.addModifiedNodeId(parent.id);
@@ -22,6 +22,10 @@
22
22
  height: 100%;
23
23
  z-index: 1;
24
24
  align-items: center;
25
+ flex-wrap: nowrap;
26
+ overflow: hidden;
27
+ position: relative;
28
+ min-width: 0;
25
29
  }
26
30
 
27
31
  .menu-center {
@@ -32,8 +36,33 @@
32
36
  justify-content: flex-end;
33
37
  }
34
38
 
39
+ .m-editor-nav-menu-slot-hidden {
40
+ position: absolute;
41
+ left: -99999px;
42
+ top: 0;
43
+ visibility: hidden;
44
+ pointer-events: none;
45
+ }
46
+
47
+ .m-editor-nav-menu-more-wrapper {
48
+ flex: 0 0 auto;
49
+ display: flex;
50
+ align-items: center;
51
+ height: 100%;
52
+
53
+ &.m-editor-nav-menu-more-wrapper-hidden {
54
+ visibility: hidden;
55
+ pointer-events: none;
56
+ }
57
+ }
58
+
59
+ .m-editor-nav-menu-more {
60
+ flex: 0 0 auto;
61
+ }
62
+
35
63
  .menu-item {
36
64
  flex-direction: row;
65
+ flex: 0 0 auto;
37
66
  -webkit-box-align: center;
38
67
  align-items: center;
39
68
  vertical-align: middle;
@@ -47,6 +76,7 @@
47
76
  transition: all 0.3s ease 0s;
48
77
  border-bottom: 2px solid transparent;
49
78
  margin: 0;
79
+ white-space: nowrap;
50
80
 
51
81
  .is-disabled {
52
82
  opacity: 0.5;
@@ -70,6 +100,7 @@
70
100
 
71
101
  .menu-item-text {
72
102
  color: $nav-color;
103
+ white-space: nowrap;
73
104
  }
74
105
 
75
106
  &.rule {
@@ -84,3 +115,33 @@
84
115
  }
85
116
  }
86
117
  }
118
+
119
+ .m-editor-nav-menu-popover {
120
+ .m-editor-nav-menu-overflow-list {
121
+ display: flex;
122
+ flex-direction: column;
123
+ gap: 4px;
124
+ padding: 4px 0;
125
+
126
+ .menu-item {
127
+ display: flex;
128
+ align-items: center;
129
+ padding: 4px 8px;
130
+ cursor: pointer;
131
+ border-radius: 4px;
132
+
133
+ &:hover {
134
+ background-color: rgba(0, 0, 0, 0.05);
135
+ }
136
+
137
+ &.divider {
138
+ padding: 0;
139
+ cursor: default;
140
+
141
+ &:hover {
142
+ background-color: transparent;
143
+ }
144
+ }
145
+ }
146
+ }
147
+ }
package/src/type.ts CHANGED
@@ -143,6 +143,7 @@ export interface EditorInstallOptions {
143
143
  [key: string]: any;
144
144
  }
145
145
 
146
+ // #region Services
146
147
  export interface Services {
147
148
  editorService: EditorService;
148
149
  historyService: HistoryService;
@@ -157,6 +158,7 @@ export interface Services {
157
158
  keybindingService: KeybindingService;
158
159
  stageOverlayService: StageOverlayService;
159
160
  }
161
+ // #endregion Services
160
162
 
161
163
  export interface StageOptions {
162
164
  runtimeUrl?: string;
@@ -236,11 +238,13 @@ export interface ComponentGroupState {
236
238
  list: ComponentGroup[];
237
239
  }
238
240
 
241
+ // #region ColumnLayout
239
242
  export enum ColumnLayout {
240
243
  LEFT = 'left',
241
244
  CENTER = 'center',
242
245
  RIGHT = 'right',
243
246
  }
247
+ // #endregion ColumnLayout
244
248
 
245
249
  export interface SetColumnWidth {
246
250
  [ColumnLayout.LEFT]?: number;
@@ -309,11 +313,13 @@ export interface UiState {
309
313
  };
310
314
  }
311
315
 
316
+ // #region EditorNodeInfo
312
317
  export interface EditorNodeInfo {
313
318
  node: MNode | null;
314
319
  parent: MContainer | null;
315
320
  page: MPage | MPageFragment | null;
316
321
  }
322
+ // #endregion EditorNodeInfo
317
323
 
318
324
  export interface AddMNode {
319
325
  type: string;
@@ -322,6 +328,7 @@ export interface AddMNode {
322
328
  [key: string]: any;
323
329
  }
324
330
 
331
+ // #region PastePosition
325
332
  export interface PastePosition {
326
333
  left?: number;
327
334
  top?: number;
@@ -334,7 +341,9 @@ export interface PastePosition {
334
341
  */
335
342
  offsetY?: number;
336
343
  }
344
+ // #endregion PastePosition
337
345
 
346
+ // #region MenuButton
338
347
  /**
339
348
  * 菜单按钮
340
349
  */
@@ -367,7 +376,9 @@ export interface MenuButton {
367
376
  /** 唯一标识,用于高亮 */
368
377
  id?: string | number;
369
378
  }
379
+ // #endregion MenuButton
370
380
 
381
+ // #region MenuComponent
371
382
  export interface MenuComponent {
372
383
  type: 'component';
373
384
  /** Vue3组件 */
@@ -382,6 +393,7 @@ export interface MenuComponent {
382
393
  display?: boolean | ((data: Services) => Promise<boolean> | boolean);
383
394
  [key: string]: any;
384
395
  }
396
+ // #endregion MenuComponent
385
397
 
386
398
  /**
387
399
  * '/': 分隔符
@@ -396,6 +408,7 @@ export interface MenuComponent {
396
408
  * 'scale-to-original': 缩放到实际大小
397
409
  * 'scale-to-fit': 缩放以适应
398
410
  */
411
+ // #region MenuItem
399
412
  export type MenuItem =
400
413
  | '/'
401
414
  | 'delete'
@@ -411,7 +424,9 @@ export type MenuItem =
411
424
  | MenuButton
412
425
  | MenuComponent
413
426
  | string;
427
+ // #endregion MenuItem
414
428
 
429
+ // #region MenuBarData
415
430
  /** 工具栏 */
416
431
  export interface MenuBarData {
417
432
  /** 顶部工具栏左边项 */
@@ -421,7 +436,9 @@ export interface MenuBarData {
421
436
  /** 顶部工具栏右边项 */
422
437
  [ColumnLayout.RIGHT]?: MenuItem[];
423
438
  }
439
+ // #endregion MenuBarData
424
440
 
441
+ // #region SideComponent
425
442
  export interface SideComponent extends MenuComponent {
426
443
  /** 显示文案 */
427
444
  text: string;
@@ -444,21 +461,27 @@ export interface SideComponent extends MenuComponent {
444
461
  props?: Record<string, any>;
445
462
  };
446
463
  }
464
+ // #endregion SideComponent
447
465
 
466
+ // #region SideItemKey
448
467
  export enum SideItemKey {
449
468
  COMPONENT_LIST = 'component-list',
450
469
  LAYER = 'layer',
451
470
  CODE_BLOCK = 'code-block',
452
471
  DATA_SOURCE = 'data-source',
453
472
  }
473
+ // #endregion SideItemKey
454
474
 
475
+ // #region SideItem
455
476
  /**
456
477
  * component-list: 组件列表
457
478
  * layer: 已选组件树
458
479
  * code-block: 代码块
459
480
  */
460
481
  export type SideItem = `${SideItemKey}` | SideComponent;
482
+ // #endregion SideItem
461
483
 
484
+ // #region SideBarData
462
485
  /** 工具栏 */
463
486
  export interface SideBarData {
464
487
  /** 容器类型 */
@@ -468,7 +491,9 @@ export interface SideBarData {
468
491
  /** panel列表 */
469
492
  items: SideItem[];
470
493
  }
494
+ // #endregion SideBarData
471
495
 
496
+ // #region ComponentItem
472
497
  export interface ComponentItem {
473
498
  /** 显示文案 */
474
499
  text: string;
@@ -483,19 +508,23 @@ export interface ComponentItem {
483
508
  [key: string]: any;
484
509
  };
485
510
  }
511
+ // #endregion ComponentItem
486
512
 
513
+ // #region ComponentGroup
487
514
  export interface ComponentGroup {
488
515
  /** 显示文案 */
489
516
  title: string;
490
517
  /** 组内列表 */
491
518
  items: ComponentItem[];
492
519
  }
520
+ // #endregion ComponentGroup
493
521
 
494
522
  export enum LayerOffset {
495
523
  TOP = 'top',
496
524
  BOTTOM = 'bottom',
497
525
  }
498
526
 
527
+ // #region Layout
499
528
  /** 容器布局 */
500
529
  export enum Layout {
501
530
  FLEX = 'flex',
@@ -503,6 +532,7 @@ export enum Layout {
503
532
  RELATIVE = 'relative',
504
533
  ABSOLUTE = 'absolute',
505
534
  }
535
+ // #endregion Layout
506
536
 
507
537
  export enum Keys {
508
538
  ESCAPE = 'Space',
@@ -575,8 +605,11 @@ export interface CodeParamStatement {
575
605
  [key: string]: any;
576
606
  }
577
607
 
608
+ // #region HistoryOpType
578
609
  export type HistoryOpType = 'add' | 'remove' | 'update';
610
+ // #endregion HistoryOpType
579
611
 
612
+ // #region StepValue
580
613
  export interface StepValue {
581
614
  /** 页面信息 */
582
615
  data: { name: string; id: Id };
@@ -597,6 +630,7 @@ export interface StepValue {
597
630
  /** opType 'update': 变更前后的节点快照 */
598
631
  updatedItems?: { oldNode: MNode; newNode: MNode }[];
599
632
  }
633
+ // #endregion StepValue
600
634
 
601
635
  export interface HistoryState {
602
636
  pageId?: Id;
@@ -660,6 +694,7 @@ export interface KeyBindingCacheItem {
660
694
  bound: boolean;
661
695
  }
662
696
 
697
+ // #region DatasourceTypeOption
663
698
  /** 可新增的数据源类型选项 */
664
699
  export interface DatasourceTypeOption {
665
700
  /** 数据源类型 */
@@ -667,6 +702,7 @@ export interface DatasourceTypeOption {
667
702
  /** 数据源名称 */
668
703
  text: string;
669
704
  }
705
+ // #endregion DatasourceTypeOption
670
706
 
671
707
  /** 组件树节点状态 */
672
708
  export interface LayerNodeStatus {
@@ -688,12 +724,14 @@ export enum DragType {
688
724
  LAYER_TREE = 'layer-tree',
689
725
  }
690
726
 
727
+ // #region TreeNodeData
691
728
  export interface TreeNodeData {
692
729
  id: Id;
693
730
  name?: string;
694
731
  items?: TreeNodeData[];
695
732
  [key: string]: any;
696
733
  }
734
+ // #endregion TreeNodeData
697
735
 
698
736
  /** 判断组件树节点是否可展开(即是否要展示为拥有子节点的形态)的函数 */
699
737
  export type IsExpandableFunction = (_data: TreeNodeData, _nodeStatusMap: Map<Id, LayerNodeStatus>) => boolean;
@@ -775,9 +813,12 @@ export interface EventBus extends EventEmitter {
775
813
  emit<Name extends keyof EventBusEvent, Param extends EventBusEvent[Name]>(eventName: Name, ...args: Param): boolean;
776
814
  }
777
815
 
816
+ // #region PropsFormConfigFunction
778
817
  export type PropsFormConfigFunction = (data: { editorService: EditorService }) => FormConfig;
818
+ // #endregion PropsFormConfigFunction
779
819
  export type PropsFormValueFunction = (data: { editorService: EditorService }) => Partial<MNode>;
780
820
 
821
+ // #region PageBarSortOptions
781
822
  export type PartSortableOptions = Omit<Options, 'onStart' | 'onUpdate'>;
782
823
  export interface PageBarSortOptions extends PartSortableOptions {
783
824
  /** 在onUpdate之后调用 */
@@ -785,6 +826,7 @@ export interface PageBarSortOptions extends PartSortableOptions {
785
826
  /** 在onStart之前调用 */
786
827
  beforeStart?: (event: SortableEvent, sortable: Sortable) => void | Promise<void>;
787
828
  }
829
+ // #endregion PageBarSortOptions
788
830
 
789
831
  export type CustomContentMenuFunction = (
790
832
  menus: (MenuButton | MenuComponent)[],
@@ -18,6 +18,7 @@
18
18
 
19
19
  import { cloneDeep } from 'lodash-es';
20
20
 
21
+ // #region UndoRedo
21
22
  export class UndoRedo<T = any> {
22
23
  private elementList: T[];
23
24
  private listCursor: number;
@@ -75,3 +76,4 @@ export class UndoRedo<T = any> {
75
76
  return cloneDeep(this.elementList[this.listCursor - 1]);
76
77
  }
77
78
  }
79
+ // #endregion UndoRedo