@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
@@ -0,0 +1,106 @@
1
+ import { type ComputedRef, nextTick, type Ref } from 'vue';
2
+ import { Id } from '@tmagic/schema';
3
+ import { LayerNodeStatus, Services, TreeNodeData } from '../../../type';
4
+ export declare const useClick: (services: Services | undefined, isCtrlKeyDown: Ref<boolean>, nodeStatusMap: ComputedRef<Map<Id, LayerNodeStatus> | undefined>) => {
5
+ menu: Ref<({
6
+ $: import("vue").ComponentInternalInstance;
7
+ $data: {};
8
+ $props: {
9
+ key?: string | number | symbol | undefined;
10
+ ref?: import("vue").VNodeRef | undefined;
11
+ ref_for?: boolean | undefined;
12
+ ref_key?: string | undefined;
13
+ onVnodeBeforeMount?: ((vnode: import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
14
+ [key: string]: any;
15
+ }>) => void) | ((vnode: import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
16
+ [key: string]: any;
17
+ }>) => void)[] | undefined;
18
+ onVnodeMounted?: ((vnode: import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
19
+ [key: string]: any;
20
+ }>) => void) | ((vnode: import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
21
+ [key: string]: any;
22
+ }>) => void)[] | undefined;
23
+ onVnodeBeforeUpdate?: ((vnode: import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
24
+ [key: string]: any;
25
+ }>, oldVNode: import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
26
+ [key: string]: any;
27
+ }>) => void) | ((vnode: import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
28
+ [key: string]: any;
29
+ }>, oldVNode: import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
30
+ [key: string]: any;
31
+ }>) => void)[] | undefined;
32
+ onVnodeUpdated?: ((vnode: import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
33
+ [key: string]: any;
34
+ }>, oldVNode: import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
35
+ [key: string]: any;
36
+ }>) => void) | ((vnode: import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
37
+ [key: string]: any;
38
+ }>, oldVNode: import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
39
+ [key: string]: any;
40
+ }>) => void)[] | undefined;
41
+ onVnodeBeforeUnmount?: ((vnode: import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
42
+ [key: string]: any;
43
+ }>) => void) | ((vnode: import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
44
+ [key: string]: any;
45
+ }>) => void)[] | undefined;
46
+ onVnodeUnmounted?: ((vnode: import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
47
+ [key: string]: any;
48
+ }>) => void) | ((vnode: import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
49
+ [key: string]: any;
50
+ }>) => void)[] | undefined;
51
+ class?: unknown;
52
+ style?: unknown;
53
+ readonly layerContentMenu: (import("../../../type").MenuButton | import("../../../type").MenuComponent)[];
54
+ };
55
+ $attrs: {
56
+ [x: string]: unknown;
57
+ };
58
+ $refs: {
59
+ [x: string]: unknown;
60
+ };
61
+ $slots: Readonly<{
62
+ [name: string]: import("vue").Slot<any> | undefined;
63
+ }>;
64
+ $root: import("vue").ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, import("vue").ComponentOptionsBase<any, any, any, any, any, any, any, any, any, {}, {}, string, {}>, {}, {}> | null;
65
+ $parent: import("vue").ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, import("vue").ComponentOptionsBase<any, any, any, any, any, any, any, any, any, {}, {}, string, {}>, {}, {}> | null;
66
+ $emit: (event: string, ...args: any[]) => void;
67
+ $el: any;
68
+ $options: import("vue").ComponentOptionsBase<Readonly<import("vue").ExtractPropTypes<{
69
+ layerContentMenu: {
70
+ type: import("vue").PropType<(import("../../../type").MenuButton | import("../../../type").MenuComponent)[]>;
71
+ required: true;
72
+ };
73
+ }>>, {
74
+ show: (e: MouseEvent) => void;
75
+ }, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, {}, {}, string, {}> & {
76
+ beforeCreate?: ((() => void) | (() => void)[]) | undefined;
77
+ created?: ((() => void) | (() => void)[]) | undefined;
78
+ beforeMount?: ((() => void) | (() => void)[]) | undefined;
79
+ mounted?: ((() => void) | (() => void)[]) | undefined;
80
+ beforeUpdate?: ((() => void) | (() => void)[]) | undefined;
81
+ updated?: ((() => void) | (() => void)[]) | undefined;
82
+ activated?: ((() => void) | (() => void)[]) | undefined;
83
+ deactivated?: ((() => void) | (() => void)[]) | undefined;
84
+ beforeDestroy?: ((() => void) | (() => void)[]) | undefined;
85
+ beforeUnmount?: ((() => void) | (() => void)[]) | undefined;
86
+ destroyed?: ((() => void) | (() => void)[]) | undefined;
87
+ unmounted?: ((() => void) | (() => void)[]) | undefined;
88
+ renderTracked?: (((e: import("vue").DebuggerEvent) => void) | ((e: import("vue").DebuggerEvent) => void)[]) | undefined;
89
+ renderTriggered?: (((e: import("vue").DebuggerEvent) => void) | ((e: import("vue").DebuggerEvent) => void)[]) | undefined;
90
+ errorCaptured?: (((err: unknown, instance: import("vue").ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, import("vue").ComponentOptionsBase<any, any, any, any, any, any, any, any, any, {}, {}, string, {}>, {}, {}> | null, info: string) => boolean | void) | ((err: unknown, instance: import("vue").ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, import("vue").ComponentOptionsBase<any, any, any, any, any, any, any, any, any, {}, {}, string, {}>, {}, {}> | null, info: string) => boolean | void)[]) | undefined;
91
+ };
92
+ $forceUpdate: () => void;
93
+ $nextTick: typeof nextTick;
94
+ $watch<T extends string | ((...args: any) => any)>(source: T, cb: T extends (...args: any) => infer R ? (args_0: R, args_1: R) => any : (...args: any) => any, options?: import("vue").WatchOptions<boolean> | undefined): import("vue").WatchStopHandle;
95
+ } & Readonly<import("vue").ExtractPropTypes<{
96
+ layerContentMenu: {
97
+ type: import("vue").PropType<(import("../../../type").MenuButton | import("../../../type").MenuComponent)[]>;
98
+ required: true;
99
+ };
100
+ }>> & import("vue").ShallowUnwrapRef<{
101
+ show: (e: MouseEvent) => void;
102
+ }> & {} & import("vue").ComponentCustomProperties & {}) | undefined>;
103
+ nodeClickHandler: (event: MouseEvent, data: TreeNodeData) => void;
104
+ nodeContentmenuHandler(event: MouseEvent, data: TreeNodeData): void;
105
+ highlightHandler: import("lodash-es").DebouncedFunc<(event: MouseEvent, data: TreeNodeData) => void>;
106
+ };
@@ -1,7 +1,6 @@
1
1
  import { type ComputedRef } from 'vue';
2
2
  import { Id, MPage } from '@tmagic/schema';
3
3
  import { LayerNodeStatus } from '../../../type';
4
- export declare const updateStatus: (nodeStatusMap: Map<Id, LayerNodeStatus>, id: Id, status: Partial<LayerNodeStatus>) => void;
5
4
  export declare const useFilter: (nodeStatusMap: ComputedRef<Map<Id, LayerNodeStatus> | undefined>, page: ComputedRef<MPage | null | undefined>) => {
6
5
  filterText: import("vue").Ref<string>;
7
6
  filterTextChangeHandler(text: string): void;
@@ -1,5 +1,6 @@
1
1
  import { type Ref } from 'vue';
2
+ import Tree from '../../../components/Tree.vue';
2
3
  import type { Services } from '../../../type';
3
- export declare const useKeybinding: (services: Services | undefined, contianer: Ref<HTMLDivElement | undefined>) => {
4
+ export declare const useKeybinding: (services: Services | undefined, contianer: Ref<InstanceType<typeof Tree> | undefined>) => {
4
5
  isCtrlKeyDown: Ref<boolean>;
5
6
  };
package/types/type.d.ts CHANGED
@@ -53,6 +53,11 @@ export interface CodeBlockListSlots {
53
53
  data: CodeBlockContent;
54
54
  }): any;
55
55
  }
56
+ export interface DataSourceListSlots {
57
+ 'data-source-panel-tool'(props: {
58
+ data: any;
59
+ }): any;
60
+ }
56
61
  export interface LayerNodeSlots {
57
62
  'layer-node-content'(props: {
58
63
  data: MNode;
@@ -60,11 +65,17 @@ export interface LayerNodeSlots {
60
65
  }
61
66
  export interface LayerPanelSlots extends LayerNodeSlots {
62
67
  'layer-panel-header'(props: {}): any;
68
+ 'layer-node-tool'(props: {
69
+ data: MNode;
70
+ }): any;
71
+ 'layer-node-content'(props: {
72
+ data: MNode;
73
+ }): any;
63
74
  }
64
75
  export interface PropsPanelSlots {
65
76
  'props-panel-header'(props: {}): any;
66
77
  }
67
- export type SidebarSlots = LayerPanelSlots & CodeBlockListPanelSlots & ComponentListPanelSlots;
78
+ export type SidebarSlots = LayerPanelSlots & CodeBlockListPanelSlots & ComponentListPanelSlots & DataSourceListSlots;
68
79
  export type BeforeAdd = (config: MNode, parent: MContainer) => Promise<MNode> | MNode;
69
80
  export type GetConfig = (config: FormConfig) => Promise<FormConfig> | FormConfig;
70
81
  export interface InstallOptions {
@@ -505,6 +516,8 @@ export interface LayerNodeStatus {
505
516
  expand: boolean;
506
517
  /** 选中 */
507
518
  selected: boolean;
519
+ /** 是否可拖拽 */
520
+ draggable: boolean;
508
521
  }
509
522
  /** 拖拽类型 */
510
523
  export declare enum DragType {
@@ -515,3 +528,9 @@ export declare enum DragType {
515
528
  }
516
529
  /** 当uiService.get('uiSelectMode')为true,点击组件(包括任何形式,组件树/画布)时触发的事件名 */
517
530
  export declare const UI_SELECT_MODE_EVENT_NAME = "ui-select";
531
+ export interface TreeNodeData {
532
+ id: Id;
533
+ name?: string;
534
+ items?: TreeNodeData[];
535
+ [key: string]: any;
536
+ }
@@ -0,0 +1,3 @@
1
+ import type { Id } from '@tmagic/schema';
2
+ import type { LayerNodeStatus } from '../type';
3
+ export declare const updateStatus: (nodeStatusMap: Map<Id, LayerNodeStatus>, id: Id, status: Partial<LayerNodeStatus>) => void;
@@ -1,208 +0,0 @@
1
- <template>
2
- <div
3
- v-show="visible"
4
- class="magic-editor-layer-node"
5
- ref="nodeEl"
6
- :draggable="!isPage(data)"
7
- :data-node-id="data.id"
8
- :data-is-container="Array.isArray(data.items)"
9
- @dragstart="handleDragStart"
10
- @dragleave="handleDragLeave"
11
- @dragend="handleDragEnd($event, data)"
12
- >
13
- <div
14
- class="layer-node"
15
- :class="{ selected, expanded }"
16
- :style="`padding-left: ${indent}px`"
17
- @contextmenu="contextmenuHandler"
18
- @mouseenter="highlightHandler()"
19
- >
20
- <MIcon
21
- class="expand-icon"
22
- :style="hasChilren ? '' : 'color: transparent; cursor: default'"
23
- :icon="expanded ? ArrowDown : ArrowRight"
24
- @click="expandHandler"
25
- ></MIcon>
26
-
27
- <div class="layer-node-content" @click="nodeClickHandler">
28
- <slot name="layer-node-content" :data="data">
29
- <div class="layer-node-label">{{ `${data.name} (${data.id})` }}</div>
30
- <div class="layer-node-tool">
31
- <LayerNodeTool :data="data"></LayerNodeTool>
32
- </div>
33
- </slot>
34
- </div>
35
- </div>
36
-
37
- <div v-if="hasChilren && expanded" class="magic-editor-layer-node-children">
38
- <LayerNode
39
- v-for="item in data.items"
40
- :data="item"
41
- :parent="(data as MContainer)"
42
- :key="item.id"
43
- :indent="indent + 11"
44
- :filter-text="filterText"
45
- :is-ctrl-key-down="isCtrlKeyDown"
46
- @node-contextmenu="nodeContentmenuHandler"
47
- >
48
- <template #layer-node-content="{ data: nodeData }">
49
- <slot name="layer-node-content" :data="nodeData"> </slot>
50
- </template>
51
- </LayerNode>
52
- </div>
53
- </div>
54
- </template>
55
-
56
- <script lang="ts" setup>
57
- import { computed, type ComputedRef, inject, nextTick, ref } from 'vue';
58
- import { ArrowDown, ArrowRight } from '@element-plus/icons-vue';
59
- import { throttle } from 'lodash-es';
60
-
61
- import type { Id, MContainer, MNode } from '@tmagic/schema';
62
- import { isPage } from '@tmagic/utils';
63
-
64
- import MIcon from '@editor/components/Icon.vue';
65
- import { LayerNodeSlots, LayerNodeStatus, Services, UI_SELECT_MODE_EVENT_NAME } from '@editor/type';
66
-
67
- import LayerNodeTool from './LayerNodeTool.vue';
68
- import { useDrag } from './use-drag';
69
- import { updateStatus } from './use-filter';
70
-
71
- defineSlots<LayerNodeSlots>();
72
-
73
- defineOptions({
74
- name: 'MEditorLayerNode',
75
- });
76
-
77
- const props = withDefaults(
78
- defineProps<{
79
- data: MNode;
80
- parent?: MContainer;
81
- indent?: number;
82
- filterText?: string;
83
- isCtrlKeyDown?: boolean;
84
- }>(),
85
- {
86
- indent: 0,
87
- filterText: '',
88
- isCtrlKeyDown: false,
89
- },
90
- );
91
-
92
- const emit = defineEmits<{
93
- 'node-contextmenu': [event: MouseEvent, node: MNode];
94
- }>();
95
-
96
- const services = inject<Services>('services');
97
- const nodeStatusMap = inject<ComputedRef<Map<Id, LayerNodeStatus>>>('nodeStatusMap');
98
- const editorService = services?.editorService;
99
- const uiService = services?.uiService;
100
-
101
- const nodeStatus = computed(
102
- () =>
103
- nodeStatusMap?.value?.get(props.data.id) || {
104
- selected: false,
105
- expand: false,
106
- visible: false,
107
- },
108
- );
109
-
110
- const expanded = computed(() => nodeStatus.value.expand);
111
- const selected = computed(() => nodeStatus.value.selected);
112
- const visible = computed(() => nodeStatus.value.visible);
113
-
114
- const hasChilren = computed(() => props.data.items?.length > 0);
115
-
116
- const nodeEl = ref<HTMLDivElement>();
117
- const { handleDragStart, handleDragEnd, handleDragLeave } = useDrag(services);
118
-
119
- const expandHandler = () => {
120
- if (!nodeStatusMap?.value) return;
121
-
122
- updateStatus(nodeStatusMap.value, props.data.id, {
123
- expand: !expanded.value,
124
- });
125
- };
126
-
127
- const nodeClickHandler = () => {
128
- if (!nodeStatusMap?.value) return;
129
-
130
- if (uiService?.get('uiSelectMode')) {
131
- document.dispatchEvent(new CustomEvent(UI_SELECT_MODE_EVENT_NAME, { detail: props.data }));
132
- return;
133
- }
134
-
135
- if (hasChilren.value && !props.isCtrlKeyDown) {
136
- updateStatus(nodeStatusMap.value, props.data.id, {
137
- expand: true,
138
- });
139
- }
140
-
141
- nextTick(() => {
142
- select(props.data);
143
- });
144
- };
145
-
146
- const contextmenuHandler = (event: MouseEvent) => {
147
- event.preventDefault();
148
- const nodes = editorService?.get('nodes') || [];
149
- if (nodes.length < 2 || !nodes.includes(props.data)) {
150
- nodeClickHandler();
151
- }
152
-
153
- emit('node-contextmenu', event, props.data);
154
- };
155
-
156
- const nodeContentmenuHandler = (event: MouseEvent, node: MNode) => {
157
- emit('node-contextmenu', event, node);
158
- };
159
-
160
- // 触发画布选中
161
- const select = async (data: MNode) => {
162
- if (!data.id) {
163
- throw new Error('没有id');
164
- }
165
-
166
- if (props.isCtrlKeyDown) {
167
- multiSelect(data);
168
- } else {
169
- await editorService?.select(data);
170
- editorService?.get('stage')?.select(data.id);
171
- }
172
- };
173
-
174
- const multiSelect = async (data: MNode) => {
175
- const nodes = editorService?.get('nodes') || [];
176
-
177
- const newNodes: Id[] = [];
178
- let isCancel = false;
179
- nodes.forEach((node) => {
180
- if (node.id === data.id) {
181
- isCancel = true;
182
- return;
183
- }
184
-
185
- newNodes.push(node.id);
186
- });
187
-
188
- // 只剩一个不能取消选中
189
- if (!isCancel || newNodes.length === 0) {
190
- newNodes.push(data.id);
191
- }
192
-
193
- await editorService?.multiSelect(newNodes);
194
- editorService?.get('stage')?.multiSelect(newNodes);
195
- };
196
-
197
- const throttleTime = 300;
198
- // 鼠标在组件树移动触发高亮
199
- const highlightHandler = throttle(() => {
200
- highlight();
201
- }, throttleTime);
202
-
203
- // 触发画布高亮
204
- const highlight = () => {
205
- editorService?.highlight(props.data);
206
- editorService?.get('stage')?.highlight(props.data.id);
207
- };
208
- </script>