@tmagic/editor 1.3.0-beta.6 → 1.3.0-beta.8

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 (42) hide show
  1. package/dist/style.css +57 -56
  2. package/dist/tmagic-editor.js +549 -436
  3. package/dist/tmagic-editor.js.map +1 -1
  4. package/dist/tmagic-editor.umd.cjs +567 -454
  5. package/dist/tmagic-editor.umd.cjs.map +1 -1
  6. package/package.json +10 -10
  7. package/src/Editor.vue +8 -0
  8. package/src/components/ContentMenu.vue +2 -6
  9. package/src/components/SplitView.vue +22 -6
  10. package/src/components/Tree.vue +66 -0
  11. package/src/components/TreeNode.vue +142 -0
  12. package/src/layouts/Framework.vue +11 -21
  13. package/src/layouts/sidebar/Sidebar.vue +13 -0
  14. package/src/layouts/sidebar/data-source/DataSourceList.vue +28 -17
  15. package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +8 -2
  16. package/src/layouts/sidebar/layer/LayerPanel.vue +40 -31
  17. package/src/layouts/sidebar/layer/use-click.ts +105 -0
  18. package/src/layouts/sidebar/layer/use-drag.ts +1 -1
  19. package/src/layouts/sidebar/layer/use-filter.ts +1 -12
  20. package/src/layouts/sidebar/layer/use-keybinding.ts +6 -2
  21. package/src/layouts/sidebar/layer/use-node-status.ts +4 -2
  22. package/src/layouts/workspace/viewer/NodeListMenu.vue +11 -2
  23. package/src/services/dep.ts +1 -1
  24. package/src/theme/layer-panel.scss +2 -74
  25. package/src/theme/theme.scss +1 -0
  26. package/src/theme/tree.scss +72 -0
  27. package/src/type.ts +16 -1
  28. package/src/utils/dep.ts +7 -2
  29. package/src/utils/tree.ts +15 -0
  30. package/types/components/ContentMenu.vue.d.ts +4 -1
  31. package/types/components/SplitView.vue.d.ts +3 -1
  32. package/types/{layouts/sidebar/layer/LayerNode.vue.d.ts → components/Tree.vue.d.ts} +19 -17
  33. package/types/components/TreeNode.vue.d.ts +47 -0
  34. package/types/layouts/sidebar/data-source/DataSourceList.vue.d.ts +2 -6
  35. package/types/layouts/sidebar/data-source/DataSourceListPanel.vue.d.ts +7 -1
  36. package/types/layouts/sidebar/layer/LayerPanel.vue.d.ts +1 -1
  37. package/types/layouts/sidebar/layer/use-click.d.ts +106 -0
  38. package/types/layouts/sidebar/layer/use-filter.d.ts +0 -1
  39. package/types/layouts/sidebar/layer/use-keybinding.d.ts +2 -1
  40. package/types/type.d.ts +20 -1
  41. package/types/utils/tree.d.ts +3 -0
  42. package/src/layouts/sidebar/layer/LayerNode.vue +0 -208
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.3.0-beta.6",
2
+ "version": "1.3.0-beta.8",
3
3
  "name": "@tmagic/editor",
4
4
  "type": "module",
5
5
  "sideEffects": [
@@ -47,13 +47,13 @@
47
47
  "dependencies": {
48
48
  "@babel/core": "^7.18.0",
49
49
  "@element-plus/icons-vue": "^2.0.9",
50
- "@tmagic/core": "1.3.0-beta.6",
51
- "@tmagic/design": "1.3.0-beta.6",
52
- "@tmagic/form": "1.3.0-beta.6",
53
- "@tmagic/schema": "1.3.0-beta.6",
54
- "@tmagic/stage": "1.3.0-beta.6",
55
- "@tmagic/table": "1.3.0-beta.6",
56
- "@tmagic/utils": "1.3.0-beta.6",
50
+ "@tmagic/core": "1.3.0-beta.8",
51
+ "@tmagic/design": "1.3.0-beta.8",
52
+ "@tmagic/form": "1.3.0-beta.8",
53
+ "@tmagic/schema": "1.3.0-beta.8",
54
+ "@tmagic/stage": "1.3.0-beta.8",
55
+ "@tmagic/table": "1.3.0-beta.8",
56
+ "@tmagic/utils": "1.3.0-beta.8",
57
57
  "buffer": "^6.0.3",
58
58
  "color": "^3.1.3",
59
59
  "events": "^3.3.0",
@@ -65,8 +65,8 @@
65
65
  "vue": "^3.3.4"
66
66
  },
67
67
  "peerDependencies": {
68
- "@tmagic/design": "1.3.0-beta.6",
69
- "@tmagic/form": "1.3.0-beta.6",
68
+ "@tmagic/design": "1.3.0-beta.8",
69
+ "@tmagic/form": "1.3.0-beta.8",
70
70
  "monaco-editor": "^0.41.0",
71
71
  "vue": "^3.3.4"
72
72
  },
package/src/Editor.vue CHANGED
@@ -25,6 +25,10 @@
25
25
  <slot name="layer-node-content" :data="data"></slot>
26
26
  </template>
27
27
 
28
+ <template #layer-node-tool="{ data }">
29
+ <slot name="layer-node-tool" :data="data"></slot>
30
+ </template>
31
+
28
32
  <template #component-list-panel-header>
29
33
  <slot name="component-list-panel-header"></slot>
30
34
  </template>
@@ -40,6 +44,10 @@
40
44
  <template #code-block-panel-tool="{ id, data }">
41
45
  <slot name="code-block-panel-tool" :id="id" :data="data"></slot>
42
46
  </template>
47
+
48
+ <template #data-source-panel-tool="{ data }">
49
+ <slot name="data-source-panel-tool" :data="data"></slot>
50
+ </template>
43
51
  </Sidebar>
44
52
  </slot>
45
53
  </template>
@@ -126,17 +126,13 @@ const setPosition = (e: { clientY: number; clientX: number }) => {
126
126
  };
127
127
  };
128
128
 
129
- const show = (e?: MouseEvent) => {
129
+ const show = (e?: { clientY: number; clientX: number }) => {
130
130
  // 加settimeout是以为,如果菜单中的按钮监听的是mouseup,那么菜单显示出来时鼠标如果正好在菜单上就会马上触发按钮的mouseup
131
131
  setTimeout(() => {
132
132
  visible.value = true;
133
133
 
134
- if (!e) {
135
- return;
136
- }
137
-
138
134
  nextTick(() => {
139
- setPosition(e);
135
+ e && setPosition(e);
140
136
 
141
137
  emit('show');
142
138
  });
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div ref="el" class="m-editor-layout">
2
+ <div ref="el" class="m-editor-layout" :style="`min-width: ${props.minCenter + props.minLeft + props.minRight}px`">
3
3
  <template v-if="hasLeft && $slots.left">
4
4
  <div class="m-editor-layout-left" :class="leftClass" :style="`width: ${left}px`">
5
5
  <slot name="left"></slot>
@@ -55,14 +55,18 @@ const el = ref<HTMLElement>();
55
55
  const hasLeft = computed(() => typeof props.left !== 'undefined');
56
56
  const hasRight = computed(() => typeof props.right !== 'undefined');
57
57
 
58
- const getCenterWidth = (clientWidth: number, left: number, right: number) => {
58
+ const getCenterWidth = (clientWidth: number, l = 0, r = 0) => {
59
+ let right = r > 0 ? r : 0;
60
+ let left = l > 0 ? l : 0;
59
61
  let center = clientWidth - left - right;
62
+
60
63
  if (center < props.minCenter) {
61
64
  center = props.minCenter;
62
- if (left < right) {
63
- right = clientWidth - left - props.minCenter;
65
+ if (right > center + props.minRight) {
66
+ right = clientWidth - left - center;
64
67
  } else {
65
- left = clientWidth - right - props.minCenter;
68
+ right = props.minRight;
69
+ left = clientWidth - right - center;
66
70
  }
67
71
  }
68
72
  return {
@@ -141,7 +145,7 @@ const changeRight = ({ deltaX }: OnDrag) => {
141
145
  right = props.right;
142
146
  }
143
147
 
144
- const columnWidth = getCenterWidth(clientWidth, props.left || 0, right);
148
+ const columnWidth = getCenterWidth(clientWidth, props.left, right);
145
149
 
146
150
  center.value = columnWidth.center;
147
151
 
@@ -151,4 +155,16 @@ const changeRight = ({ deltaX }: OnDrag) => {
151
155
  right: columnWidth.right,
152
156
  });
153
157
  };
158
+
159
+ defineExpose({
160
+ updateWidth() {
161
+ const columnWidth = getCenterWidth(el.value?.clientWidth || clientWidth, props.left, props.right);
162
+
163
+ emit('change', {
164
+ left: columnWidth.left,
165
+ center: center.value,
166
+ right: columnWidth.right,
167
+ });
168
+ },
169
+ });
154
170
  </script>
@@ -0,0 +1,66 @@
1
+ <template>
2
+ <div class="m-editor-tree" @dragover="handleDragOver">
3
+ <template v-if="data?.length">
4
+ <TreeNode v-for="item in data" :key="item.id" :data="item" :indent="indent" :node-status-map="nodeStatusMap">
5
+ <template #tree-node-content="{ data: nodeData }">
6
+ <slot name="tree-node-content" :data="nodeData"> </slot>
7
+ </template>
8
+
9
+ <template #tree-node-tool="{ data: nodeData }">
10
+ <slot name="tree-node-tool" :data="nodeData"> </slot>
11
+ </template>
12
+ </TreeNode>
13
+ </template>
14
+ <div v-else>
15
+ <p>{{ emptyText }}</p>
16
+ </div>
17
+ </div>
18
+ </template>
19
+
20
+ <script setup lang="ts">
21
+ import { provide } from 'vue';
22
+
23
+ import type { Id } from '@tmagic/schema';
24
+
25
+ import type { LayerNodeStatus, TreeNodeData } from '@editor/type';
26
+
27
+ import TreeNode from './TreeNode.vue';
28
+
29
+ defineSlots<{
30
+ 'tree-node-content'(props: { data: TreeNodeData }): any;
31
+ 'tree-node-tool'(props: { data: TreeNodeData }): any;
32
+ }>();
33
+
34
+ defineOptions({
35
+ name: 'MEditorTree',
36
+ });
37
+
38
+ const emit = defineEmits<{
39
+ 'node-dragover': [event: DragEvent];
40
+ 'node-dragstart': [event: DragEvent, data: TreeNodeData];
41
+ 'node-dragleave': [event: DragEvent, data: TreeNodeData];
42
+ 'node-dragend': [event: DragEvent, data: TreeNodeData];
43
+ 'node-contextmenu': [event: MouseEvent, data: TreeNodeData];
44
+ 'node-mouseenter': [event: MouseEvent, data: TreeNodeData];
45
+ 'node-click': [event: MouseEvent, data: TreeNodeData];
46
+ }>();
47
+
48
+ provide('treeEmit', emit);
49
+
50
+ withDefaults(
51
+ defineProps<{
52
+ data: TreeNodeData[];
53
+ nodeStatusMap: Map<Id, LayerNodeStatus>;
54
+ indent?: number;
55
+ emptyText?: string;
56
+ }>(),
57
+ {
58
+ indent: 0,
59
+ emptyText: '暂无数据',
60
+ },
61
+ );
62
+
63
+ const handleDragOver = (event: DragEvent) => {
64
+ emit('node-dragover', event);
65
+ };
66
+ </script>
@@ -0,0 +1,142 @@
1
+ <template>
2
+ <div
3
+ v-show="visible"
4
+ class="m-editor-tree-node"
5
+ :draggable="draggable"
6
+ :data-node-id="data.id"
7
+ :data-is-container="Array.isArray(data.items)"
8
+ @dragstart="handleDragStart"
9
+ @dragleave="handleDragLeave"
10
+ @dragend="handleDragEnd"
11
+ >
12
+ <div
13
+ class="tree-node"
14
+ :class="{ selected, expanded }"
15
+ :style="`padding-left: ${indent}px`"
16
+ @contextmenu="nodeContentmenuHandler"
17
+ @mouseenter="mouseenterHandler"
18
+ >
19
+ <MIcon
20
+ class="expand-icon"
21
+ :style="hasChilren ? '' : 'color: transparent; cursor: default'"
22
+ :icon="expanded ? ArrowDown : ArrowRight"
23
+ @click="expandHandler"
24
+ ></MIcon>
25
+
26
+ <div class="tree-node-content" @click="nodeClickHandler">
27
+ <slot name="tree-node-content" :data="data">
28
+ <div class="tree-node-label">{{ `${data.name} (${data.id})` }}</div>
29
+ <div class="tree-node-tool">
30
+ <slot name="tree-node-tool" :data="data"></slot>
31
+ </div>
32
+ </slot>
33
+ </div>
34
+ </div>
35
+
36
+ <div v-if="hasChilren && expanded" class="m-editor-tree-node-children">
37
+ <TreeNode
38
+ v-for="item in data.items"
39
+ :key="item.id"
40
+ :data="item"
41
+ :node-status-map="nodeStatusMap"
42
+ :indent="indent + 11"
43
+ >
44
+ <template #tree-node-content="{ data: nodeData }">
45
+ <slot name="tree-node-content" :data="nodeData"> </slot>
46
+ </template>
47
+ <template #tree-node-tool="{ data: nodeData }">
48
+ <slot name="tree-node-tool" :data="nodeData"> </slot>
49
+ </template>
50
+ </TreeNode>
51
+ </div>
52
+ </div>
53
+ </template>
54
+
55
+ <script setup lang="ts">
56
+ import { computed, inject } from 'vue';
57
+ import { ArrowDown, ArrowRight } from '@element-plus/icons-vue';
58
+
59
+ import type { Id } from '@tmagic/schema';
60
+
61
+ import MIcon from '@editor/components/Icon.vue';
62
+ import type { LayerNodeStatus, TreeNodeData } from '@editor/type';
63
+ import { updateStatus } from '@editor/utils/tree';
64
+
65
+ defineSlots<{
66
+ 'tree-node-tool'(props: { data: TreeNodeData }): any;
67
+ 'tree-node-content'(props: { data: TreeNodeData }): any;
68
+ }>();
69
+
70
+ defineOptions({
71
+ name: 'MEditorTreeNode',
72
+ });
73
+
74
+ const emit = defineEmits<{
75
+ 'node-dragstart': [event: DragEvent, data: TreeNodeData];
76
+ 'node-dragleave': [event: DragEvent, data: TreeNodeData];
77
+ 'node-dragend': [event: DragEvent, data: TreeNodeData];
78
+ 'node-contextmenu': [event: MouseEvent, data: TreeNodeData];
79
+ 'node-mouseenter': [event: MouseEvent, data: TreeNodeData];
80
+ 'node-click': [event: MouseEvent, data: TreeNodeData];
81
+ }>();
82
+
83
+ const treeEmit = inject<typeof emit>('treeEmit');
84
+
85
+ const props = withDefaults(
86
+ defineProps<{
87
+ data: TreeNodeData;
88
+ nodeStatusMap: Map<Id, LayerNodeStatus>;
89
+ indent?: number;
90
+ }>(),
91
+ {
92
+ indent: 0,
93
+ },
94
+ );
95
+
96
+ const nodeStatus = computed(
97
+ () =>
98
+ props.nodeStatusMap?.get(props.data.id) || {
99
+ selected: false,
100
+ expand: false,
101
+ visible: false,
102
+ draggable: false,
103
+ },
104
+ );
105
+
106
+ const expanded = computed(() => nodeStatus.value.expand);
107
+ const selected = computed(() => nodeStatus.value.selected);
108
+ const visible = computed(() => nodeStatus.value.visible);
109
+ const draggable = computed(() => nodeStatus.value.draggable);
110
+
111
+ const hasChilren = computed(() => props.data.items && props.data.items.length > 0);
112
+
113
+ const handleDragStart = (event: DragEvent) => {
114
+ treeEmit?.('node-dragstart', event, props.data);
115
+ };
116
+
117
+ const handleDragLeave = (event: DragEvent) => {
118
+ treeEmit?.('node-dragleave', event, props.data);
119
+ };
120
+
121
+ const handleDragEnd = (event: DragEvent) => {
122
+ treeEmit?.('node-dragend', event, props.data);
123
+ };
124
+
125
+ const nodeContentmenuHandler = (event: MouseEvent) => {
126
+ treeEmit?.('node-contextmenu', event, props.data);
127
+ };
128
+
129
+ const mouseenterHandler = (event: MouseEvent) => {
130
+ treeEmit?.('node-mouseenter', event, props.data);
131
+ };
132
+
133
+ const expandHandler = () => {
134
+ updateStatus(props.nodeStatusMap, props.data.id, {
135
+ expand: !expanded.value,
136
+ });
137
+ };
138
+
139
+ const nodeClickHandler = (event: MouseEvent) => {
140
+ treeEmit?.('node-click', event, props.data);
141
+ };
142
+ </script>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="m-editor" ref="content">
2
+ <div class="m-editor" ref="content" style="min-width: 180px">
3
3
  <slot name="header"></slot>
4
4
 
5
5
  <slot name="nav"></slot>
@@ -12,6 +12,7 @@
12
12
 
13
13
  <SplitView
14
14
  v-else
15
+ ref="splitView"
15
16
  class="m-editor-content"
16
17
  left-class="m-editor-framework-left"
17
18
  center-class="m-editor-framework-center"
@@ -20,6 +21,7 @@
20
21
  v-model:right="columnWidth.right"
21
22
  :min-left="65"
22
23
  :min-right="20"
24
+ :min-center="100"
23
25
  @change="columnWidthChange"
24
26
  >
25
27
  <template #left>
@@ -70,6 +72,7 @@ const codeOptions = inject('codeOptions', {});
70
72
  const { editorService, uiService } = inject<Services>('services') || {};
71
73
 
72
74
  const content = ref<HTMLDivElement>();
75
+ const splitView = ref<InstanceType<typeof SplitView>>();
73
76
 
74
77
  const root = computed(() => editorService?.get('root'));
75
78
 
@@ -79,8 +82,10 @@ const showSrc = computed(() => uiService?.get('showSrc'));
79
82
  const LEFT_COLUMN_WIDTH_STORAGE_KEY = '$MagicEditorLeftColumnWidthData';
80
83
  const RIGHT_COLUMN_WIDTH_STORAGE_KEY = '$MagicEditorRightColumnWidthData';
81
84
 
82
- const leftColumnWidthCacheData = Number(globalThis.localStorage.getItem(LEFT_COLUMN_WIDTH_STORAGE_KEY));
83
- const RightColumnWidthCacheData = Number(globalThis.localStorage.getItem(RIGHT_COLUMN_WIDTH_STORAGE_KEY));
85
+ const leftColumnWidthCacheData =
86
+ Number(globalThis.localStorage.getItem(LEFT_COLUMN_WIDTH_STORAGE_KEY)) || DEFAULT_LEFT_COLUMN_WIDTH;
87
+ const RightColumnWidthCacheData =
88
+ Number(globalThis.localStorage.getItem(RIGHT_COLUMN_WIDTH_STORAGE_KEY)) || DEFAULT_RIGHT_COLUMN_WIDTH;
84
89
 
85
90
  const columnWidth = ref<Partial<GetColumnWidth>>({
86
91
  left: leftColumnWidthCacheData,
@@ -89,24 +94,9 @@ const columnWidth = ref<Partial<GetColumnWidth>>({
89
94
  });
90
95
 
91
96
  watch(
92
- pageLength,
93
- (length) => {
94
- const left = columnWidth.value.left || DEFAULT_LEFT_COLUMN_WIDTH;
95
-
96
- columnWidth.value.left = left;
97
-
98
- const container = content.value || document.body;
99
-
100
- if (length <= 0) {
101
- columnWidth.value.right = undefined;
102
- columnWidth.value.center = container.clientWidth - left;
103
- } else {
104
- const right = columnWidth.value.right || RightColumnWidthCacheData || DEFAULT_RIGHT_COLUMN_WIDTH;
105
- columnWidth.value.right = right;
106
- columnWidth.value.center = container.clientWidth - left - right;
107
- }
108
-
109
- uiService?.set('columnWidth', columnWidth.value as GetColumnWidth);
97
+ [pageLength, splitView],
98
+ () => {
99
+ splitView.value?.updateWidth();
110
100
  },
111
101
  {
112
102
  immediate: true,
@@ -64,6 +64,19 @@
64
64
  <slot v-if="config.$key === 'layer'" name="layer-node-content" :data="nodeData"></slot>
65
65
  <component v-else-if="config.slots?.layerNodeContent" :is="config.slots.layerNodeContent" :data="nodeData" />
66
66
  </template>
67
+
68
+ <template #layer-node-tool="{ data: nodeData }" v-if="config.$key === 'layer' || config.slots?.layerNodeTool">
69
+ <slot v-if="config.$key === 'layer'" name="layer-node-tool" :data="nodeData"></slot>
70
+ <component v-else-if="config.slots?.layerNodeTool" :is="config.slots.layerNodeTool" :data="nodeData" />
71
+ </template>
72
+
73
+ <template
74
+ #data-source-panel-tool="{ data }"
75
+ v-if="config.$key === 'data-source' || config.slots?.codeBlockPanelTool"
76
+ >
77
+ <slot v-if="config.$key === 'data-source'" name="data-source-panel-tool" :data="data"></slot>
78
+ <component v-else-if="config.slots?.DataSourcePanelTool" :is="config.slots.DataSourcePanelTool" />
79
+ </template>
67
80
  </component>
68
81
  </div>
69
82
  </div>
@@ -26,7 +26,7 @@
26
26
  <TMagicTooltip v-if="editable" effect="dark" content="删除" placement="bottom">
27
27
  <Icon :icon="Close" class="edit-icon" @click.stop="removeHandler(`${data.id}`)"></Icon>
28
28
  </TMagicTooltip>
29
- <slot name="data-source-panel-tool" :id="data.id" :data="data.codeBlockContent"></slot>
29
+ <slot name="data-source-panel-tool" :data="data"></slot>
30
30
  </div>
31
31
  </div>
32
32
  </div>
@@ -42,7 +42,9 @@ import { tMagicMessageBox, TMagicTooltip, TMagicTree } from '@tmagic/design';
42
42
  import { Dep, Id } from '@tmagic/schema';
43
43
 
44
44
  import Icon from '@editor/components/Icon.vue';
45
- import { DepTargetType, Services } from '@editor/type';
45
+ import { type DataSourceListSlots, DepTargetType, type Services } from '@editor/type';
46
+
47
+ defineSlots<DataSourceListSlots>();
46
48
 
47
49
  defineOptions({
48
50
  name: 'MEditorDataSourceList',
@@ -73,6 +75,26 @@ const getNodeTreeConfig = (id: string, dep: Dep[string], type?: string) => ({
73
75
  children: getKeyTreeConfig(dep, type),
74
76
  });
75
77
 
78
+ /**
79
+ * 生成tree中依赖节点的数据
80
+ * @param children 节点
81
+ * @param deps 依赖
82
+ * @param type 依赖类型
83
+ */
84
+ const mergeChildren = (children: any[], deps: Dep, type?: string) => {
85
+ Object.entries(deps).forEach(([id, dep]) => {
86
+ // 已经生成过的节点
87
+ const nodeItem = children.find((item) => item.id === id);
88
+ // 节点存在,则追加依赖的key
89
+ if (nodeItem) {
90
+ nodeItem.children = nodeItem.children.concat(getKeyTreeConfig(dep, type));
91
+ } else {
92
+ // 节点不存在,则生成
93
+ children.push(getNodeTreeConfig(id, dep, type));
94
+ }
95
+ });
96
+ };
97
+
76
98
  const list = computed(() =>
77
99
  dataSources.value.map((ds) => {
78
100
  const dsDeps = dsDep.value[ds.id].deps;
@@ -80,21 +102,10 @@ const list = computed(() =>
80
102
  const dsCondDeps = dsCondDep.value[ds.id].deps;
81
103
 
82
104
  const children: any[] = [];
83
-
84
- const mergeChildren = (deps: Dep, type?: string) => {
85
- Object.entries(deps).forEach(([id, dep]) => {
86
- const nodeItem = children.find((item) => item.id === id);
87
- if (nodeItem) {
88
- nodeItem.children = nodeItem.children.concat(getKeyTreeConfig(dep, type));
89
- } else {
90
- children.push(getNodeTreeConfig(id, dep, type));
91
- }
92
- });
93
- };
94
-
95
- mergeChildren(dsDeps);
96
- mergeChildren(dsMethodDeps, 'method');
97
- mergeChildren(dsCondDeps, 'cond');
105
+ // 数据源依赖分为三种类型:key/node、method、cond,是分开存储,这里将其合并展示
106
+ mergeChildren(children, dsDeps);
107
+ mergeChildren(children, dsMethodDeps, 'method');
108
+ mergeChildren(children, dsCondDeps, 'cond');
98
109
 
99
110
  return {
100
111
  id: ds.id,
@@ -23,7 +23,11 @@
23
23
  </div>
24
24
 
25
25
  <!-- 数据源列表 -->
26
- <DataSourceList @edit="editHandler" @remove="removeHandler"></DataSourceList>
26
+ <DataSourceList @edit="editHandler" @remove="removeHandler">
27
+ <template #data-source-panel-tool="{ data }">
28
+ <slot name="data-source-panel-tool" :data="data"></slot>
29
+ </template>
30
+ </DataSourceList>
27
31
 
28
32
  <DataSourceConfigPanel
29
33
  ref="editDialog"
@@ -44,11 +48,13 @@ import type { DataSourceSchema } from '@tmagic/schema';
44
48
 
45
49
  import SearchInput from '@editor/components/SearchInput.vue';
46
50
  import ToolButton from '@editor/components/ToolButton.vue';
47
- import type { Services } from '@editor/type';
51
+ import type { DataSourceListSlots, Services } from '@editor/type';
48
52
 
49
53
  import DataSourceConfigPanel from './DataSourceConfigPanel.vue';
50
54
  import DataSourceList from './DataSourceList.vue';
51
55
 
56
+ defineSlots<DataSourceListSlots>();
57
+
52
58
  defineOptions({
53
59
  name: 'MEditorDataSourceListPanel',
54
60
  });
@@ -1,22 +1,33 @@
1
1
  <template>
2
- <TMagicScrollbar class="magic-editor-layer-panel">
2
+ <TMagicScrollbar class="m-editor-layer-panel">
3
3
  <slot name="layer-panel-header"></slot>
4
4
 
5
5
  <SearchInput @search="filterTextChangeHandler"></SearchInput>
6
6
 
7
- <div class="magic-editor-layer-tree" ref="layerTreeContainer" tabindex="-1" @dragover="handleDragOver">
8
- <LayerNode
9
- v-if="page && root"
10
- :data="page"
11
- :filter-text="filterText"
12
- :is-ctrl-key-down="isCtrlKeyDown"
13
- @node-contextmenu="contextmenu"
14
- >
15
- <template #layer-node-content="{ data: nodeData }">
16
- <slot name="layer-node-content" :data="nodeData"> </slot>
17
- </template>
18
- </LayerNode>
19
- </div>
7
+ <Tree
8
+ v-if="page && nodeStatusMap"
9
+ tabindex="-1"
10
+ ref="tree"
11
+ :data="[page]"
12
+ :node-status-map="nodeStatusMap"
13
+ @node-dragover="handleDragOver"
14
+ @node-dragstart="handleDragStart"
15
+ @node-dragleave="handleDragLeave"
16
+ @node-dragend="handleDragEnd"
17
+ @node-contextmenu="nodeContentmenuHandler"
18
+ @node-mouseenter="mouseenterHandler"
19
+ @node-click="nodeClickHandler"
20
+ >
21
+ <template #tree-node-tool="{ data: nodeData }">
22
+ <slot name="layer-node-tool" :data="nodeData">
23
+ <LayerNodeTool :data="nodeData"></LayerNodeTool>
24
+ </slot>
25
+ </template>
26
+
27
+ <template #tree-node-content="{ data: nodeData }">
28
+ <slot name="layer-node-content" :data="nodeData"> </slot>
29
+ </template>
30
+ </Tree>
20
31
 
21
32
  <Teleport to="body">
22
33
  <LayerMenu ref="menu" :layer-content-menu="layerContentMenu" @collapse-all="collapseAllHandler"></LayerMenu>
@@ -25,15 +36,17 @@
25
36
  </template>
26
37
 
27
38
  <script setup lang="ts">
28
- import { computed, inject, provide, ref } from 'vue';
39
+ import { computed, inject, ref } from 'vue';
29
40
 
30
41
  import { TMagicScrollbar } from '@tmagic/design';
31
42
 
32
43
  import SearchInput from '@editor/components/SearchInput.vue';
33
- import type { LayerPanelSlots, MenuButton, MenuComponent, Services } from '@editor/type';
44
+ import Tree from '@editor/components/Tree.vue';
45
+ import { LayerPanelSlots, MenuButton, MenuComponent, Services } from '@editor/type';
34
46
 
35
47
  import LayerMenu from './LayerMenu.vue';
36
- import LayerNode from './LayerNode.vue';
48
+ import LayerNodeTool from './LayerNodeTool.vue';
49
+ import { useClick } from './use-click';
37
50
  import { useDrag } from './use-drag';
38
51
  import { useFilter } from './use-filter';
39
52
  import { useKeybinding } from './use-keybinding';
@@ -52,17 +65,14 @@ defineProps<{
52
65
  const services = inject<Services>('services');
53
66
  const editorService = services?.editorService;
54
67
 
55
- const layerTreeContainer = ref<HTMLDivElement>();
68
+ const tree = ref<InstanceType<typeof Tree>>();
56
69
 
57
70
  const page = computed(() => editorService?.get('page'));
58
- const root = computed(() => editorService?.get('root'));
59
71
 
60
72
  const { nodeStatusMap } = useNodeStatus(services, page);
61
- const { isCtrlKeyDown } = useKeybinding(services, layerTreeContainer);
73
+ const { isCtrlKeyDown } = useKeybinding(services, tree);
62
74
 
63
- provide('nodeStatusMap', nodeStatusMap);
64
-
65
- const { filterText, filterTextChangeHandler } = useFilter(nodeStatusMap, page);
75
+ const { filterTextChangeHandler } = useFilter(nodeStatusMap, page);
66
76
 
67
77
  const collapseAllHandler = () => {
68
78
  if (!page.value || !nodeStatusMap.value) return;
@@ -75,13 +85,12 @@ const collapseAllHandler = () => {
75
85
  }
76
86
  };
77
87
 
78
- // 右键菜单
79
- const menu = ref<InstanceType<typeof LayerMenu>>();
80
- const contextmenu = (event: MouseEvent): void => {
81
- event.preventDefault();
82
-
83
- menu.value?.show(event);
84
- };
88
+ const { handleDragStart, handleDragEnd, handleDragLeave, handleDragOver } = useDrag(services);
85
89
 
86
- const { handleDragOver } = useDrag(services);
90
+ const {
91
+ menu,
92
+ nodeClickHandler,
93
+ nodeContentmenuHandler,
94
+ highlightHandler: mouseenterHandler,
95
+ } = useClick(services, isCtrlKeyDown, nodeStatusMap);
87
96
  </script>