@tmagic/editor 1.3.0-beta.2 → 1.3.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 (78) hide show
  1. package/dist/style.css +52 -60
  2. package/dist/tmagic-editor.js +1634 -1065
  3. package/dist/tmagic-editor.js.map +1 -1
  4. package/dist/tmagic-editor.umd.cjs +1659 -1087
  5. package/dist/tmagic-editor.umd.cjs.map +1 -1
  6. package/package.json +10 -10
  7. package/src/Editor.vue +70 -65
  8. package/src/components/ContentMenu.vue +5 -1
  9. package/src/components/SearchInput.vue +5 -1
  10. package/src/editorProps.ts +51 -129
  11. package/src/fields/Code.vue +9 -3
  12. package/src/fields/DataSourceFieldSelect.vue +28 -16
  13. package/src/fields/DataSourceFields.vue +95 -7
  14. package/src/fields/DataSourceMethodSelect.vue +23 -14
  15. package/src/fields/DataSourceMocks.vue +237 -0
  16. package/src/fields/EventSelect.vue +18 -11
  17. package/src/index.ts +4 -1
  18. package/src/initService.ts +50 -20
  19. package/src/layouts/CodeEditor.vue +20 -4
  20. package/src/layouts/Framework.vue +3 -1
  21. package/src/layouts/PropsPanel.vue +3 -1
  22. package/src/layouts/sidebar/ComponentListPanel.vue +18 -8
  23. package/src/layouts/sidebar/Sidebar.vue +7 -10
  24. package/src/layouts/sidebar/code-block/CodeBlockList.vue +3 -1
  25. package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +3 -1
  26. package/src/layouts/sidebar/layer/LayerNode.vue +206 -0
  27. package/src/layouts/sidebar/layer/LayerNodeTool.vue +32 -0
  28. package/src/layouts/sidebar/layer/LayerPanel.vue +85 -0
  29. package/src/layouts/sidebar/layer/use-drag.ts +157 -0
  30. package/src/layouts/sidebar/layer/use-filter.ts +70 -0
  31. package/src/layouts/sidebar/layer/use-keybinding.ts +47 -0
  32. package/src/layouts/sidebar/layer/use-node-status.ts +103 -0
  33. package/src/layouts/workspace/Workspace.vue +3 -1
  34. package/src/layouts/workspace/viewer/NodeListMenu.vue +1 -1
  35. package/src/layouts/workspace/viewer/Stage.vue +19 -17
  36. package/src/services/dataSource.ts +10 -0
  37. package/src/services/editor.ts +45 -5
  38. package/src/theme/common/var.scss +2 -2
  39. package/src/theme/framework.scss +2 -0
  40. package/src/theme/layer-panel.scss +63 -63
  41. package/src/theme/props-panel.scss +8 -0
  42. package/src/theme/sidebar.scss +1 -5
  43. package/src/type.ts +60 -0
  44. package/src/utils/data-source/index.ts +11 -0
  45. package/src/utils/dep.ts +26 -11
  46. package/src/utils/editor.ts +14 -3
  47. package/src/utils/props.ts +3 -0
  48. package/types/editorProps.d.ts +61 -107
  49. package/types/fields/Code.vue.d.ts +10 -6
  50. package/types/fields/DataSourceMocks.vue.d.ts +32 -0
  51. package/types/index.d.ts +2 -1
  52. package/types/initService.d.ts +5 -4
  53. package/types/layouts/CodeEditor.vue.d.ts +5 -0
  54. package/types/layouts/Framework.vue.d.ts +2 -12
  55. package/types/layouts/PropsPanel.vue.d.ts +2 -3
  56. package/types/layouts/sidebar/ComponentListPanel.vue.d.ts +2 -7
  57. package/types/layouts/sidebar/Sidebar.vue.d.ts +2 -17
  58. package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +2 -7
  59. package/types/layouts/sidebar/code-block/CodeBlockListPanel.vue.d.ts +2 -9
  60. package/types/layouts/sidebar/{LayerMenu.vue.d.ts → layer/LayerMenu.vue.d.ts} +1 -1
  61. package/types/layouts/sidebar/layer/LayerNode.vue.d.ts +50 -0
  62. package/types/layouts/sidebar/{LayerNode.vue.d.ts → layer/LayerNodeTool.vue.d.ts} +1 -1
  63. package/types/layouts/sidebar/{LayerPanel.vue.d.ts → layer/LayerPanel.vue.d.ts} +2 -8
  64. package/types/layouts/sidebar/layer/use-drag.d.ts +14 -0
  65. package/types/layouts/sidebar/layer/use-filter.d.ts +8 -0
  66. package/types/layouts/sidebar/layer/use-keybinding.d.ts +4 -0
  67. package/types/layouts/sidebar/layer/use-node-status.d.ts +7 -0
  68. package/types/layouts/workspace/Workspace.vue.d.ts +2 -11
  69. package/types/layouts/workspace/viewer/Stage.vue.d.ts +1 -1
  70. package/types/services/dataSource.d.ts +3 -0
  71. package/types/services/editor.d.ts +1 -0
  72. package/types/type.d.ts +60 -0
  73. package/types/utils/dep.d.ts +1 -1
  74. package/types/utils/editor.d.ts +3 -2
  75. package/src/layouts/sidebar/LayerNode.vue +0 -40
  76. package/src/layouts/sidebar/LayerPanel.vue +0 -369
  77. package/types/Editor.vue.d.ts +0 -233
  78. /package/src/layouts/sidebar/{LayerMenu.vue → layer/LayerMenu.vue} +0 -0
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.3.0-beta.2",
2
+ "version": "1.3.0-beta.4",
3
3
  "name": "@tmagic/editor",
4
4
  "type": "module",
5
5
  "sideEffects": [
@@ -46,13 +46,13 @@
46
46
  "dependencies": {
47
47
  "@babel/core": "^7.18.0",
48
48
  "@element-plus/icons-vue": "^2.0.9",
49
- "@tmagic/core": "1.3.0-beta.2",
50
- "@tmagic/design": "1.3.0-beta.2",
51
- "@tmagic/form": "1.3.0-beta.2",
52
- "@tmagic/schema": "1.3.0-beta.2",
53
- "@tmagic/stage": "1.3.0-beta.2",
54
- "@tmagic/table": "1.3.0-beta.2",
55
- "@tmagic/utils": "1.3.0-beta.2",
49
+ "@tmagic/core": "1.3.0-beta.4",
50
+ "@tmagic/design": "1.3.0-beta.4",
51
+ "@tmagic/form": "1.3.0-beta.4",
52
+ "@tmagic/schema": "1.3.0-beta.4",
53
+ "@tmagic/stage": "1.3.0-beta.4",
54
+ "@tmagic/table": "1.3.0-beta.4",
55
+ "@tmagic/utils": "1.3.0-beta.4",
56
56
  "buffer": "^6.0.3",
57
57
  "color": "^3.1.3",
58
58
  "events": "^3.3.0",
@@ -64,8 +64,8 @@
64
64
  "vue": "^3.3.4"
65
65
  },
66
66
  "peerDependencies": {
67
- "@tmagic/design": "1.3.0-beta.2",
68
- "@tmagic/form": "1.3.0-beta.2",
67
+ "@tmagic/design": "1.3.0-beta.4",
68
+ "@tmagic/form": "1.3.0-beta.4",
69
69
  "monaco-editor": "^0.41.0",
70
70
  "vue": "^3.3.4"
71
71
  },
package/src/Editor.vue CHANGED
@@ -21,8 +21,8 @@
21
21
  <slot name="layer-panel-header"></slot>
22
22
  </template>
23
23
 
24
- <template #layer-node-content="{ node, data }">
25
- <slot name="layer-node-content" :data="data" :node="node"></slot>
24
+ <template #layer-node-content="{ data }">
25
+ <slot name="layer-node-content" :data="data"></slot>
26
26
  </template>
27
27
 
28
28
  <template #component-list-panel-header>
@@ -80,11 +80,13 @@
80
80
  </Framework>
81
81
  </template>
82
82
 
83
- <script lang="ts">
84
- import { defineComponent, provide, reactive } from 'vue';
83
+ <script lang="ts" setup>
84
+ import { provide, reactive } from 'vue';
85
+
86
+ import type { MApp } from '@tmagic/schema';
85
87
 
86
88
  import Framework from './layouts/Framework.vue';
87
- import NavMenu from './layouts/NavMenu.vue';
89
+ import TMagicNavMenu from './layouts/NavMenu.vue';
88
90
  import PropsPanel from './layouts/PropsPanel.vue';
89
91
  import Sidebar from './layouts/sidebar/Sidebar.vue';
90
92
  import Workspace from './layouts/workspace/Workspace.vue';
@@ -92,7 +94,7 @@ import codeBlockService from './services/codeBlock';
92
94
  import componentListService from './services/componentList';
93
95
  import dataSourceService from './services/dataSource';
94
96
  import depService from './services/dep';
95
- import editorService from './services/editor';
97
+ import editorService, { type EditorService } from './services/editor';
96
98
  import eventsService from './services/events';
97
99
  import historyService from './services/history';
98
100
  import keybindingService from './services/keybinding';
@@ -100,66 +102,69 @@ import propsService from './services/props';
100
102
  import storageService from './services/storage';
101
103
  import uiService from './services/ui';
102
104
  import keybindingConfig from './utils/keybinding-config';
103
- import editorProps from './editorProps';
105
+ import { defaultEditorProps, EditorProps } from './editorProps';
104
106
  import { initServiceEvents, initServiceState } from './initService';
105
- import type { Services } from './type';
106
-
107
- export default defineComponent({
107
+ import type { FrameworkSlots, PropsPanelSlots, Services, SidebarSlots, WorkspaceSlots } from './type';
108
+
109
+ defineSlots<
110
+ FrameworkSlots &
111
+ WorkspaceSlots &
112
+ SidebarSlots &
113
+ PropsPanelSlots & {
114
+ workspace(props: { editorService: EditorService }): any;
115
+ 'workspace-content'(props: { editorService: EditorService }): any;
116
+ }
117
+ >();
118
+
119
+ defineOptions({
108
120
  name: 'MEditor',
109
-
110
- components: {
111
- TMagicNavMenu: NavMenu,
112
- Sidebar,
113
- Workspace,
114
- PropsPanel,
115
- Framework,
116
- },
117
-
118
- props: editorProps,
119
-
120
- emits: ['props-panel-mounted', 'update:modelValue'],
121
-
122
- setup(props, { emit }) {
123
- const services: Services = {
124
- componentListService,
125
- eventsService,
126
- historyService,
127
- propsService,
128
- editorService,
129
- uiService,
130
- storageService,
131
- codeBlockService,
132
- depService,
133
- dataSourceService,
134
- keybindingService,
135
- };
136
-
137
- initServiceEvents(props, emit, services);
138
- initServiceState(props, services);
139
- keybindingService.registe(keybindingConfig);
140
- keybindingService.registeEl('global');
141
-
142
- provide('services', services);
143
-
144
- provide('codeOptions', props.codeOptions);
145
- provide(
146
- 'stageOptions',
147
- reactive({
148
- runtimeUrl: props.runtimeUrl,
149
- autoScrollIntoView: props.autoScrollIntoView,
150
- render: props.render,
151
- moveableOptions: props.moveableOptions,
152
- canSelect: props.canSelect,
153
- updateDragEl: props.updateDragEl,
154
- isContainer: props.isContainer,
155
- containerHighlightClassName: props.containerHighlightClassName,
156
- containerHighlightDuration: props.containerHighlightDuration,
157
- containerHighlightType: props.containerHighlightType,
158
- disabledDragStart: props.disabledDragStart,
159
- }),
160
- );
161
-
162
- return services;
163
- },
164
121
  });
122
+
123
+ const emit = defineEmits<{
124
+ 'props-panel-mounted': [instance: InstanceType<typeof PropsPanel>];
125
+ 'update:modelValue': [value: MApp | null];
126
+ }>();
127
+
128
+ const props = withDefaults(defineProps<EditorProps>(), defaultEditorProps);
129
+
130
+ const services: Services = {
131
+ componentListService,
132
+ eventsService,
133
+ historyService,
134
+ propsService,
135
+ editorService,
136
+ uiService,
137
+ storageService,
138
+ codeBlockService,
139
+ depService,
140
+ dataSourceService,
141
+ keybindingService,
142
+ };
143
+
144
+ initServiceEvents(props, emit, services);
145
+ initServiceState(props, services);
146
+ keybindingService.registe(keybindingConfig);
147
+ keybindingService.registeEl('global');
148
+
149
+ provide('services', services);
150
+
151
+ provide('codeOptions', props.codeOptions);
152
+ provide(
153
+ 'stageOptions',
154
+ reactive({
155
+ runtimeUrl: props.runtimeUrl,
156
+ autoScrollIntoView: props.autoScrollIntoView,
157
+ render: props.render,
158
+ moveableOptions: props.moveableOptions,
159
+ canSelect: props.canSelect,
160
+ updateDragEl: props.updateDragEl,
161
+ isContainer: props.isContainer,
162
+ containerHighlightClassName: props.containerHighlightClassName,
163
+ containerHighlightDuration: props.containerHighlightDuration,
164
+ containerHighlightType: props.containerHighlightType,
165
+ disabledDragStart: props.disabledDragStart,
166
+ }),
167
+ );
168
+
169
+ defineExpose(services);
165
170
  </script>
@@ -145,12 +145,16 @@ const show = (e?: MouseEvent) => {
145
145
 
146
146
  const showSubMenu = (item: MenuButton | MenuComponent, index: number) => {
147
147
  const menuItem = item as MenuButton;
148
- if (typeof item !== 'object' || !menuItem.items?.length) {
148
+ if (typeof item !== 'object') {
149
149
  return;
150
150
  }
151
151
 
152
152
  subMenuData.value = menuItem.items || [];
153
153
  setTimeout(() => {
154
+ if (!visible.value) {
155
+ return;
156
+ }
157
+
154
158
  if (menu.value) {
155
159
  // 将子菜单放置在按钮右侧,与按钮齐平
156
160
  let y = menu.value.offsetTop;
@@ -27,7 +27,11 @@ const emit = defineEmits(['search']);
27
27
 
28
28
  const filterText = ref('');
29
29
 
30
+ let timer: NodeJS.Timeout | null = null;
30
31
  const filterTextChangeHandler = () => {
31
- emit('search', filterText.value);
32
+ timer && clearTimeout(timer);
33
+ timer = setTimeout(() => {
34
+ emit('search', filterText.value);
35
+ }, 300);
32
36
  };
33
37
  </script>
@@ -1,8 +1,6 @@
1
- import type { PropType } from 'vue';
2
-
3
1
  import type { EventOption } from '@tmagic/core';
4
2
  import type { FormConfig, FormState } from '@tmagic/form';
5
- import type { DataSourceSchema, MApp, MNode } from '@tmagic/schema';
3
+ import type { DataSourceSchema, Id, MApp, MNode } from '@tmagic/schema';
6
4
  import StageCore, {
7
5
  CONTAINER_HIGHLIGHT_CLASS_NAME,
8
6
  ContainerHighlightType,
@@ -21,145 +19,69 @@ import type {
21
19
  StageRect,
22
20
  } from './type';
23
21
 
24
- export default {
22
+ export interface EditorProps {
25
23
  /** 页面初始值 */
26
- modelValue: {
27
- type: Object as PropType<MApp>,
28
- default: () => ({}),
29
- require: true,
30
- },
31
-
32
- /** 左侧面板中的组件列表 */
33
- componentGroupList: {
34
- type: Array as PropType<ComponentGroup[]>,
35
- default: () => [],
36
- },
37
-
38
- /** 左侧面板中的组件列表 */
39
- datasourceList: {
40
- type: Array as PropType<DatasourceTypeOption[]>,
41
- default: () => [],
42
- },
43
-
24
+ modelValue?: MApp;
25
+ /** 左侧面板中的组件类型列表 */
26
+ componentGroupList?: ComponentGroup[];
27
+ /** 左侧面板中的数据源类型列表 */
28
+ datasourceList?: DatasourceTypeOption[];
44
29
  /** 左侧面板配置 */
45
- sidebar: {
46
- type: Object as PropType<SideBarData>,
47
- },
48
-
30
+ sidebar?: SideBarData;
49
31
  /** 顶部工具栏配置 */
50
- menu: {
51
- type: Object as PropType<MenuBarData>,
52
- default: () => ({ left: [], right: [] }),
53
- },
54
-
32
+ menu?: MenuBarData;
55
33
  /** 组件树右键菜单 */
56
- layerContentMenu: {
57
- type: Array as PropType<(MenuButton | MenuComponent)[]>,
58
- default: () => [],
59
- },
60
-
34
+ layerContentMenu?: (MenuButton | MenuComponent)[];
61
35
  /** 画布右键菜单 */
62
- stageContentMenu: {
63
- type: Array as PropType<(MenuButton | MenuComponent)[]>,
64
- default: () => [],
65
- },
66
-
36
+ stageContentMenu?: (MenuButton | MenuComponent)[];
67
37
  /** 中间工作区域中画布渲染的内容 */
68
- render: {
69
- type: Function as PropType<(stage: StageCore) => HTMLDivElement | Promise<HTMLDivElement>>,
70
- },
71
-
38
+ render?: (stage: StageCore) => HTMLDivElement | Promise<HTMLDivElement>;
72
39
  /** 中间工作区域中画布通过iframe渲染时的页面url */
73
- runtimeUrl: String,
74
-
40
+ runtimeUrl?: string;
75
41
  /** 选中时是否自动滚动到可视区域 */
76
- autoScrollIntoView: Boolean,
77
-
42
+ autoScrollIntoView?: boolean;
78
43
  /** 组件的属性配置表单的dsl */
79
- propsConfigs: {
80
- type: Object as PropType<Record<string, FormConfig>>,
81
- default: () => ({}),
82
- },
83
-
44
+ propsConfigs?: Record<string, FormConfig>;
84
45
  /** 添加组件时的默认值 */
85
- propsValues: {
86
- type: Object as PropType<Record<string, Partial<MNode>>>,
87
- default: () => ({}),
88
- },
89
-
46
+ propsValues?: Record<string, Partial<MNode>>;
90
47
  /** 组件联动事件选项列表 */
91
- eventMethodList: {
92
- type: Object as PropType<Record<string, { events: EventOption[]; methods: EventOption[] }>>,
93
- default: () => ({}),
94
- },
95
-
48
+ eventMethodList?: Record<string, { events: EventOption[]; methods: EventOption[] }>;
96
49
  /** 添加数据源时的默认值 */
97
- datasourceValues: {
98
- type: Object as PropType<Record<string, Partial<DataSourceSchema>>>,
99
- default: () => ({}),
100
- },
101
-
50
+ datasourceValues?: Record<string, Partial<DataSourceSchema>>;
102
51
  /** 数据源的属性配置表单的dsl */
103
- datasourceConfigs: {
104
- type: Object as PropType<Record<string, FormConfig>>,
105
- default: () => ({}),
106
- },
107
-
52
+ datasourceConfigs?: Record<string, FormConfig>;
53
+ datasourceEventMethodList?: Record<string, { events: EventOption[]; methods: EventOption[] }>;
108
54
  /** 画布中组件选中框的移动范围 */
109
- moveableOptions: {
110
- type: [Object, Function] as PropType<
111
- MoveableOptions | ((config?: CustomizeMoveableOptionsCallbackConfig) => MoveableOptions)
112
- >,
113
- },
114
-
55
+ moveableOptions?: MoveableOptions | ((config?: CustomizeMoveableOptionsCallbackConfig) => MoveableOptions);
115
56
  /** 编辑器初始化时默认选中的组件ID */
116
- defaultSelected: {
117
- type: [Number, String],
118
- },
119
-
120
- canSelect: {
121
- type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
122
- default: (el: HTMLElement) => Boolean(el.id),
123
- },
124
-
125
- isContainer: {
126
- type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
127
- default: (el: HTMLElement) => el.classList.contains('magic-ui-container'),
128
- },
129
-
130
- containerHighlightClassName: {
131
- type: String,
132
- default: CONTAINER_HIGHLIGHT_CLASS_NAME,
133
- },
134
-
135
- containerHighlightDuration: {
136
- type: Number,
137
- default: 800,
138
- },
139
-
140
- containerHighlightType: {
141
- type: String as PropType<ContainerHighlightType>,
142
- default: ContainerHighlightType.DEFAULT,
143
- },
144
-
145
- stageRect: {
146
- type: [String, Object] as PropType<StageRect>,
147
- },
148
-
149
- codeOptions: {
150
- type: Object,
151
- default: () => ({}),
152
- },
153
-
154
- updateDragEl: {
155
- type: Function as PropType<UpdateDragEl>,
156
- },
157
-
158
- disabledDragStart: {
159
- type: Boolean,
160
- },
161
-
162
- extendFormState: {
163
- type: Function as PropType<(state: FormState) => Record<string, any> | Promise<Record<string, any>>>,
164
- },
57
+ defaultSelected?: Id;
58
+ canSelect?: (el: HTMLElement) => boolean | Promise<boolean>;
59
+ isContainer?: (el: HTMLElement) => boolean | Promise<boolean>;
60
+ containerHighlightClassName?: string;
61
+ containerHighlightDuration?: number;
62
+ containerHighlightType?: ContainerHighlightType;
63
+ stageRect?: StageRect;
64
+ codeOptions?: { [key: string]: any };
65
+ updateDragEl?: UpdateDragEl;
66
+ disabledDragStart?: boolean;
67
+ extendFormState?: (state: FormState) => Record<string, any> | Promise<Record<string, any>>;
68
+ }
69
+
70
+ export const defaultEditorProps = {
71
+ componentGroupList: () => [],
72
+ datasourceList: () => [],
73
+ menu: () => ({ left: [], right: [] }),
74
+ layerContentMenu: () => [],
75
+ stageContentMenu: () => [],
76
+ propsConfigs: () => ({}),
77
+ propsValues: () => ({}),
78
+ eventMethodList: () => ({}),
79
+ datasourceValues: () => ({}),
80
+ datasourceConfigs: () => ({}),
81
+ canSelect: (el: HTMLElement) => Boolean(el.id),
82
+ isContainer: (el: HTMLElement) => el.classList.contains('magic-ui-container'),
83
+ containerHighlightClassName: CONTAINER_HIGHLIGHT_CLASS_NAME,
84
+ containerHighlightDuration: 800,
85
+ containerHighlightType: ContainerHighlightType.DEFAULT,
86
+ codeOptions: () => ({}),
165
87
  };
@@ -7,6 +7,7 @@
7
7
  ...config.options,
8
8
  readOnly: disabled,
9
9
  }"
10
+ :parse="config.parse"
10
11
  @save="save"
11
12
  ></MagicCodeEditor>
12
13
  </template>
@@ -20,14 +21,19 @@ defineOptions({
20
21
  name: 'MEditorCode',
21
22
  });
22
23
 
23
- const emit = defineEmits(['change']);
24
+ const emit = defineEmits<{
25
+ change: [value: string | any];
26
+ }>();
24
27
 
25
28
  const props = withDefaults(
26
29
  defineProps<
27
30
  FieldProps<{
28
31
  language?: string;
29
- options?: Object;
32
+ options?: {
33
+ [key: string]: any;
34
+ };
30
35
  height?: string;
36
+ parse?: boolean;
31
37
  }>
32
38
  >(),
33
39
  {
@@ -35,7 +41,7 @@ const props = withDefaults(
35
41
  },
36
42
  );
37
43
 
38
- const save = (v: string) => {
44
+ const save = (v: string | any) => {
39
45
  props.model[props.name] = v;
40
46
  emit('change', v);
41
47
  };
@@ -12,7 +12,9 @@
12
12
  <script setup lang="ts">
13
13
  import { computed, inject } from 'vue';
14
14
 
15
- import type { FieldProps } from '@tmagic/form';
15
+ import type { CascaderOption, FieldProps } from '@tmagic/form';
16
+ import type { DataSchema } from '@tmagic/schema';
17
+ import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX } from '@tmagic/utils';
16
18
 
17
19
  import type { DataSourceFieldSelectConfig, Services } from '@editor/type';
18
20
 
@@ -25,21 +27,31 @@ const props = withDefaults(defineProps<FieldProps<DataSourceFieldSelectConfig>>(
25
27
 
26
28
  const dataSources = computed(() => services?.dataSourceService.get('dataSources'));
27
29
 
28
- const cascaderConfig = {
29
- type: 'cascader',
30
- name: props.name,
31
- options: () =>
32
- dataSources.value
33
- ?.filter((ds) => ds.fields?.length)
34
- ?.map((ds) => ({
35
- label: ds.title || ds.id,
36
- value: ds.id,
37
- children: ds.fields?.map((field) => ({
38
- label: field.title,
39
- value: field.name,
40
- })),
41
- })) || [],
42
- };
30
+ const getOptionChildren = (fields: DataSchema[] = []): CascaderOption[] =>
31
+ fields.map((field) => ({
32
+ label: field.title || field.name,
33
+ value: field.name,
34
+ children: field.type === 'array' ? [] : getOptionChildren(field.fields),
35
+ }));
36
+
37
+ const cascaderConfig = computed(() => {
38
+ const valueIsKey = props.config.value === 'key';
39
+
40
+ return {
41
+ type: 'cascader',
42
+ name: props.name,
43
+ checkStrictly: !valueIsKey,
44
+ text: '',
45
+ options: () =>
46
+ dataSources.value
47
+ ?.filter((ds) => ds.fields?.length)
48
+ ?.map((ds) => ({
49
+ label: ds.title || ds.id,
50
+ value: valueIsKey ? ds.id : `${DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX}${ds.id}`,
51
+ children: getOptionChildren(ds.fields),
52
+ })) || [],
53
+ };
54
+ });
43
55
 
44
56
  const onChangeHandler = (value: any) => {
45
57
  emit('change', value);