@tmagic/editor 1.7.14-beta.0 → 1.7.14-beta.2

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.
@@ -1,6 +1,7 @@
1
1
  <template>
2
2
  <div
3
3
  v-if="display"
4
+ ref="rootEl"
4
5
  class="menu-item"
5
6
  :class="`${data.type} ${data.className || ''}`"
6
7
  @click="clickHandler(data, $event)"
@@ -56,7 +57,7 @@
56
57
  </template>
57
58
 
58
59
  <script lang="ts" setup>
59
- import { computed } from 'vue';
60
+ import { computed, useTemplateRef } from 'vue';
60
61
  import { ArrowDown } from '@element-plus/icons-vue';
61
62
 
62
63
  import {
@@ -93,6 +94,9 @@ const props = withDefaults(
93
94
  );
94
95
  const services = useServices();
95
96
 
97
+ const rootElRef = useTemplateRef<HTMLDivElement>('rootEl');
98
+ const getElRef = () => rootElRef;
99
+
96
100
  const disabled = computed(() => {
97
101
  if (typeof props.data === 'string') return false;
98
102
  if (props.data.type === 'component') return false;
@@ -145,4 +149,6 @@ const mouseupHandler = (item: MenuButton | MenuComponent, event: MouseEvent) =>
145
149
  buttonHandler(item, event);
146
150
  }
147
151
  };
152
+
153
+ defineExpose({ getElRef });
148
154
  </script>
@@ -74,7 +74,11 @@ const collapseValue = shallowRef(
74
74
 
75
75
  const change = (v: any, eventData: ContainerChangeEventData) => {
76
76
  eventData.changeRecords?.forEach((record) => {
77
- record.propPath = `${props.name}.${record.propPath}`;
77
+ if (props.prop) {
78
+ record.propPath = `${props.prop}.${record.propPath}`;
79
+ } else if (props.name) {
80
+ record.propPath = `${props.name}.${record.propPath}`;
81
+ }
78
82
  });
79
83
  emit('change', v, eventData);
80
84
  };
@@ -214,24 +214,32 @@ const setEditorValue = (v: string | any, m: string | any) => {
214
214
  if (props.type === 'diff') {
215
215
  const originalModel = monaco.editor.createModel(values.value, 'text/javascript');
216
216
  const modifiedModel = monaco.editor.createModel(toString(m, props.language), 'text/javascript');
217
- const position = vsDiffEditor?.getPosition();
217
+ // 保存视图状态(光标、选区、滚动、折叠等)
218
+ const viewState = vsDiffEditor?.saveViewState();
218
219
  const result = vsDiffEditor?.setModel({
219
220
  original: originalModel,
220
221
  modified: modifiedModel,
221
222
  });
222
- if (position) {
223
- vsDiffEditor?.setPosition(position);
224
- vsDiffEditor?.focus();
223
+ // setAutoHeight 内部会在 nextTick 中将 scrollTop 重置为 0,这里也放到 nextTick 中
224
+ // 利用 Vue nextTick 队列的 FIFO 特性,保证恢复在重置之后执行
225
+ if (viewState) {
226
+ nextTick(() => {
227
+ vsDiffEditor?.restoreViewState(viewState);
228
+ vsDiffEditor?.focus();
229
+ });
225
230
  }
226
231
  return result;
227
232
  }
228
- // 保存当前光标位置
229
- const position = vsEditor?.getPosition();
233
+ // 保存视图状态(光标、选区、滚动、折叠等)
234
+ const viewState = vsEditor?.saveViewState();
230
235
  const result = vsEditor?.setValue(values.value);
231
- // 恢复光标位置
232
- if (position) {
233
- vsEditor?.setPosition(position);
234
- vsEditor?.focus();
236
+ // setAutoHeight 内部会在 nextTick 中将 scrollTop 重置为 0,这里也放到 nextTick 中
237
+ // 利用 Vue nextTick 队列的 FIFO 特性,保证恢复在重置之后执行
238
+ if (viewState) {
239
+ nextTick(() => {
240
+ vsEditor?.restoreViewState(viewState);
241
+ vsEditor?.focus();
242
+ });
235
243
  }
236
244
  return result;
237
245
  };
@@ -1,8 +1,12 @@
1
1
  <template>
2
2
  <div class="m-editor-nav-menu" :style="{ height: `${height}px` }" ref="navMenu">
3
- <div v-for="key in keys" :class="`menu-${key}`" :key="key" :style="`width: ${columnWidth?.[key]}px`">
4
- <ToolButton :data="item" v-for="(item, index) in buttons[key]" :key="index"></ToolButton>
5
- </div>
3
+ <NavMenuColumn
4
+ v-for="key in keys"
5
+ :key="key"
6
+ :column-key="key"
7
+ :items="buttons[key]"
8
+ :width="columnWidth?.[key]"
9
+ ></NavMenuColumn>
6
10
  </div>
7
11
  </template>
8
12
 
@@ -12,10 +16,11 @@ import { Back, Delete, FullScreen, Grid, Memo, Right, ScaleToOriginal, ZoomIn, Z
12
16
 
13
17
  import { NodeType } from '@tmagic/core';
14
18
 
15
- import ToolButton from '@editor/components/ToolButton.vue';
16
19
  import { useServices } from '@editor/hooks/use-services';
17
20
  import { ColumnLayout, MenuBarData, MenuButton, MenuComponent, MenuItem } from '@editor/type';
18
21
 
22
+ import NavMenuColumn from './NavMenuColumn.vue';
23
+
19
24
  defineOptions({
20
25
  name: 'MEditorNavMenu',
21
26
  });
@@ -0,0 +1,252 @@
1
+ <template>
2
+ <div
3
+ :class="`menu-${columnKey} m-editor-nav-menu-column`"
4
+ :style="width != null ? `width: ${width}px` : ''"
5
+ ref="columnEl"
6
+ >
7
+ <ToolButton
8
+ v-for="(item, index) in items"
9
+ :data="item"
10
+ :key="`item-${index}`"
11
+ :class="{ 'm-editor-nav-menu-slot-hidden': hiddenIndexSet.has(index) }"
12
+ :ref="(comp: any) => setItemRef(comp, index)"
13
+ ></ToolButton>
14
+
15
+ <div
16
+ class="m-editor-nav-menu-more-wrapper"
17
+ :class="{ 'm-editor-nav-menu-more-wrapper-hidden': !hasOverflow }"
18
+ ref="moreWrapperEl"
19
+ >
20
+ <TMagicPopover
21
+ placement="bottom-end"
22
+ popper-class="m-editor-nav-menu-popover"
23
+ :width="popoverWidth"
24
+ :visible="popoverVisible"
25
+ >
26
+ <div class="m-editor-nav-menu-overflow-list">
27
+ <ToolButton v-for="(item, index) in overflowItems" :data="item" :key="`o-${index}`"></ToolButton>
28
+ </div>
29
+ <template #reference>
30
+ <div class="menu-item button m-editor-nav-menu-more" ref="referenceEl" @click="togglePopover">
31
+ <TMagicButton
32
+ size="small"
33
+ text
34
+ :icon="popoverVisible ? ArrowUp : ArrowDown"
35
+ :bg="popoverVisible"
36
+ :type="popoverVisible ? 'primary' : ''"
37
+ ></TMagicButton>
38
+ </div>
39
+ </template>
40
+ </TMagicPopover>
41
+ </div>
42
+ </div>
43
+ </template>
44
+
45
+ <script lang="ts" setup>
46
+ import { computed, onBeforeUnmount, onMounted, ref, useTemplateRef, watch } from 'vue';
47
+ import { ArrowDown, ArrowUp } from '@element-plus/icons-vue';
48
+
49
+ import { TMagicButton, TMagicPopover } from '@tmagic/design';
50
+
51
+ import ToolButton from '@editor/components/ToolButton.vue';
52
+ import { MenuButton, MenuComponent } from '@editor/type';
53
+
54
+ defineOptions({
55
+ name: 'MEditorNavMenuColumn',
56
+ });
57
+
58
+ const props = withDefaults(
59
+ defineProps<{
60
+ columnKey: string;
61
+ items: (MenuButton | MenuComponent)[];
62
+ width?: number;
63
+ /** 子元素之间的间距,需与 SCSS gap 保持一致 */
64
+ gap?: number;
65
+ /** Popover 内容宽度 */
66
+ popoverWidth?: number;
67
+ }>(),
68
+ {
69
+ items: () => [],
70
+ gap: 3,
71
+ popoverWidth: 180,
72
+ },
73
+ );
74
+
75
+ const columnEl = useTemplateRef<HTMLDivElement>('columnEl');
76
+ const moreWrapperEl = useTemplateRef<HTMLDivElement>('moreWrapperEl');
77
+
78
+ const popoverVisible = ref(false);
79
+ const togglePopover = () => {
80
+ popoverVisible.value = !popoverVisible.value;
81
+ };
82
+
83
+ const itemInstances = ref<(InstanceType<typeof ToolButton> | null)[]>([]);
84
+ let slotsRO: ResizeObserver | undefined;
85
+ const observedEls = new Set<HTMLElement>();
86
+
87
+ const setItemRef = (inst: InstanceType<typeof ToolButton> | null, index: number) => {
88
+ itemInstances.value[index] = inst ?? null;
89
+ };
90
+
91
+ const itemEls = computed<(HTMLElement | null)[]>(() =>
92
+ itemInstances.value.map((inst) => inst?.getElRef?.().value ?? null),
93
+ );
94
+
95
+ const reobserveSlots = () => {
96
+ if (!slotsRO) return;
97
+ for (const el of observedEls) slotsRO.unobserve(el);
98
+ observedEls.clear();
99
+ for (const el of itemEls.value) {
100
+ if (el) {
101
+ slotsRO.observe(el);
102
+ observedEls.add(el);
103
+ }
104
+ }
105
+ };
106
+
107
+ const cachedWidths = ref<Map<number, number>>(new Map());
108
+ const moreWidth = ref(0);
109
+ const containerWidth = ref(0);
110
+ const hiddenIndexSet = ref<Set<number>>(new Set());
111
+
112
+ const hasOverflow = computed(() => hiddenIndexSet.value.size > 0);
113
+ const overflowItems = computed(() => props.items.filter((_, index) => hiddenIndexSet.value.has(index)));
114
+
115
+ const measureAndCompute = () => {
116
+ if (!columnEl.value) return;
117
+
118
+ containerWidth.value = columnEl.value.clientWidth;
119
+
120
+ const els = itemEls.value;
121
+ for (let i = 0; i < props.items.length; i++) {
122
+ const el = els[i];
123
+ if (!el) {
124
+ cachedWidths.value.delete(i);
125
+ continue;
126
+ }
127
+ const w = el.getBoundingClientRect().width;
128
+ if (w > 0) {
129
+ cachedWidths.value.set(i, w);
130
+ } else {
131
+ cachedWidths.value.delete(i);
132
+ }
133
+ }
134
+
135
+ if (moreWrapperEl.value) {
136
+ const w = moreWrapperEl.value.getBoundingClientRect().width;
137
+ if (w > 0) moreWidth.value = w;
138
+ }
139
+
140
+ const total = props.items.length;
141
+ if (total === 0 || containerWidth.value <= 0) {
142
+ if (hiddenIndexSet.value.size > 0) hiddenIndexSet.value = new Set();
143
+ return;
144
+ }
145
+
146
+ let fullSum = 0;
147
+ let positive = 0;
148
+ for (let i = 0; i < total; i++) {
149
+ const w = cachedWidths.value.get(i) ?? 0;
150
+ if (w > 0) {
151
+ fullSum += w;
152
+ positive += 1;
153
+ }
154
+ }
155
+ fullSum += props.gap * Math.max(0, positive - 1);
156
+
157
+ // more 按钮位置始终保留,参与"是否放得下"的判断,避免出现时再次挤压
158
+ const effectiveMoreWidth = moreWidth.value > 0 ? moreWidth.value : 32;
159
+ const reservedMore = effectiveMoreWidth + (positive > 0 ? props.gap : 0);
160
+
161
+ let nextHidden: Set<number> | null = null;
162
+ if (fullSum + reservedMore <= containerWidth.value + 0.5) {
163
+ if (hiddenIndexSet.value.size > 0) nextHidden = new Set();
164
+ } else {
165
+ const newHidden = new Set<number>();
166
+ let used = effectiveMoreWidth;
167
+ let cutoff = -1;
168
+ for (let i = 0; i < total; i++) {
169
+ const w = cachedWidths.value.get(i) ?? 0;
170
+ if (w === 0) continue;
171
+ const need = props.gap + w;
172
+ if (used + need > containerWidth.value) {
173
+ cutoff = i;
174
+ break;
175
+ }
176
+ used += need;
177
+ }
178
+ if (cutoff >= 0) {
179
+ for (let j = cutoff; j < total; j++) newHidden.add(j);
180
+ }
181
+ nextHidden = newHidden;
182
+ }
183
+
184
+ if (nextHidden) {
185
+ const same =
186
+ nextHidden.size === hiddenIndexSet.value.size && [...nextHidden].every((v) => hiddenIndexSet.value.has(v));
187
+ if (!same) hiddenIndexSet.value = nextHidden;
188
+ }
189
+ };
190
+
191
+ let raf = 0;
192
+ const scheduleMeasure = () => {
193
+ if (raf) cancelAnimationFrame(raf);
194
+ raf = requestAnimationFrame(() => {
195
+ raf = 0;
196
+ measureAndCompute();
197
+ if (hasOverflow.value && moreWidth.value === 0) {
198
+ raf = requestAnimationFrame(() => {
199
+ raf = 0;
200
+ measureAndCompute();
201
+ });
202
+ }
203
+ });
204
+ };
205
+
206
+ watch(hasOverflow, (value) => {
207
+ if (!value) popoverVisible.value = false;
208
+ });
209
+
210
+ watch(
211
+ () => props.items,
212
+ () => {
213
+ cachedWidths.value = new Map();
214
+ hiddenIndexSet.value = new Set();
215
+ },
216
+ { deep: true },
217
+ );
218
+
219
+ watch(itemEls, () => {
220
+ cachedWidths.value = new Map();
221
+ reobserveSlots();
222
+ scheduleMeasure();
223
+ });
224
+
225
+ watch(
226
+ () => props.width,
227
+ () => scheduleMeasure(),
228
+ );
229
+
230
+ let ro: ResizeObserver | undefined;
231
+
232
+ onMounted(() => {
233
+ if (typeof ResizeObserver !== 'undefined') {
234
+ if (columnEl.value) {
235
+ ro = new ResizeObserver(() => scheduleMeasure());
236
+ ro.observe(columnEl.value);
237
+ }
238
+ slotsRO = new ResizeObserver(() => scheduleMeasure());
239
+ reobserveSlots();
240
+ }
241
+
242
+ scheduleMeasure();
243
+ });
244
+
245
+ onBeforeUnmount(() => {
246
+ if (raf) cancelAnimationFrame(raf);
247
+ ro?.disconnect();
248
+ slotsRO?.disconnect();
249
+ slotsRO = undefined;
250
+ observedEls.clear();
251
+ });
252
+ </script>
@@ -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)[],