@flowgram-vue/type-editor 0.2.0
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.
- package/LICENSE +22 -0
- package/dist/index.cjs +0 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +0 -0
- package/dist/index.js.map +1 -0
- package/package.json +63 -0
- package/src/components/index.ts +8 -0
- package/src/components/type-editor/columns/index.ts +404 -0
- package/src/components/type-editor/common.ts +44 -0
- package/src/components/type-editor/formatter/index.ts +44 -0
- package/src/components/type-editor/hooks/active-pos.ts +20 -0
- package/src/components/type-editor/hooks/disabled.ts +22 -0
- package/src/components/type-editor/hooks/formatter-value.ts +53 -0
- package/src/components/type-editor/hooks/index.ts +8 -0
- package/src/components/type-editor/index.ts +9 -0
- package/src/components/type-editor/mode/declare-assign.ts +102 -0
- package/src/components/type-editor/mode/index.ts +15 -0
- package/src/components/type-editor/mode/type-definition.ts +46 -0
- package/src/components/type-editor/table.vue +293 -0
- package/src/components/type-editor/type-editor.vue +107 -0
- package/src/components/type-editor/type.ts +142 -0
- package/src/components/type-editor/utils.ts +173 -0
- package/src/components/type-selector/index.ts +51 -0
- package/src/components/type-selector/type-selector.vue +100 -0
- package/src/contexts/index.ts +106 -0
- package/src/env.d.ts +10 -0
- package/src/index.ts +15 -0
- package/src/json-schema-exports.ts +18 -0
- package/src/preset/index.ts +6 -0
- package/src/preset/object-type-editor.vue +91 -0
- package/src/services/clipboard-service.ts +93 -0
- package/src/services/index.ts +11 -0
- package/src/services/shortcut-service.ts +9 -0
- package/src/services/type-editor-service.ts +396 -0
- package/src/services/type-operation-service.ts +99 -0
- package/src/services/type-registry-manager.ts +14 -0
- package/src/services/utils.ts +28 -0
- package/src/styles.css +235 -0
- package/src/type-registry/array.ts +18 -0
- package/src/type-registry/boolean.ts +30 -0
- package/src/type-registry/index.ts +22 -0
- package/src/type-registry/integer.ts +24 -0
- package/src/type-registry/number.ts +23 -0
- package/src/type-registry/object.ts +13 -0
- package/src/type-registry/string.ts +21 -0
- package/src/types/index.ts +7 -0
- package/src/types/registry.ts +52 -0
- package/src/types/type-editor.ts +150 -0
- package/src/utils/index.ts +6 -0
- package/src/utils/monitor-data/index.ts +7 -0
- package/src/utils/monitor-data/monitor-data.ts +43 -0
- package/src/utils/monitor-data/use-monitor-data.ts +29 -0
- package/src/utils/registry-adapter.ts +83 -0
- package/src/utils/toast.ts +16 -0
package/src/styles.css
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
.fg-type-editor {
|
|
2
|
+
position: relative;
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
gap: 4px;
|
|
6
|
+
outline: none;
|
|
7
|
+
width: 100%;
|
|
8
|
+
font-size: 13px;
|
|
9
|
+
color: #1c1f23;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.fg-type-editor table {
|
|
13
|
+
table-layout: fixed;
|
|
14
|
+
width: 100%;
|
|
15
|
+
border-collapse: collapse;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.fg-type-editor th,
|
|
19
|
+
.fg-type-editor td {
|
|
20
|
+
border: 1px solid #e5e6eb;
|
|
21
|
+
height: 36px;
|
|
22
|
+
padding: 0 8px;
|
|
23
|
+
background: #fff;
|
|
24
|
+
vertical-align: middle;
|
|
25
|
+
position: relative;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.fg-type-editor th {
|
|
29
|
+
background: #f7f8fa;
|
|
30
|
+
text-align: left;
|
|
31
|
+
font-weight: 600;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.fg-type-toolbar {
|
|
35
|
+
display: flex;
|
|
36
|
+
justify-content: flex-end;
|
|
37
|
+
gap: 8px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.fg-type-btn {
|
|
41
|
+
border: 1px solid #d9d9d9;
|
|
42
|
+
background: #fff;
|
|
43
|
+
border-radius: 4px;
|
|
44
|
+
height: 24px;
|
|
45
|
+
padding: 0 8px;
|
|
46
|
+
cursor: pointer;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.fg-type-btn:disabled {
|
|
50
|
+
opacity: 0.45;
|
|
51
|
+
cursor: not-allowed;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.fg-type-input,
|
|
55
|
+
.fg-type-select,
|
|
56
|
+
.fg-type-textarea {
|
|
57
|
+
width: 100%;
|
|
58
|
+
height: 100%;
|
|
59
|
+
border: none;
|
|
60
|
+
outline: none;
|
|
61
|
+
background: transparent;
|
|
62
|
+
font: inherit;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.fg-type-label {
|
|
66
|
+
display: inline-flex;
|
|
67
|
+
align-items: center;
|
|
68
|
+
gap: 6px;
|
|
69
|
+
width: 100%;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.fg-type-label-text {
|
|
73
|
+
overflow: hidden;
|
|
74
|
+
text-overflow: ellipsis;
|
|
75
|
+
white-space: nowrap;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.fg-type-key {
|
|
79
|
+
display: flex;
|
|
80
|
+
align-items: center;
|
|
81
|
+
gap: 4px;
|
|
82
|
+
width: 100%;
|
|
83
|
+
min-height: 36px;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.fg-type-key-text {
|
|
87
|
+
flex: 1;
|
|
88
|
+
overflow: hidden;
|
|
89
|
+
text-overflow: ellipsis;
|
|
90
|
+
white-space: nowrap;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.fg-type-icon-btn {
|
|
94
|
+
border: none;
|
|
95
|
+
background: transparent;
|
|
96
|
+
cursor: pointer;
|
|
97
|
+
padding: 0 2px;
|
|
98
|
+
color: #86909c;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.fg-type-icon-btn:disabled {
|
|
102
|
+
opacity: 0.4;
|
|
103
|
+
cursor: not-allowed;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.fg-type-center {
|
|
107
|
+
display: flex;
|
|
108
|
+
align-items: center;
|
|
109
|
+
justify-content: center;
|
|
110
|
+
height: 100%;
|
|
111
|
+
gap: 6px;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.fg-type-empty {
|
|
115
|
+
padding: 40px 0;
|
|
116
|
+
text-align: center;
|
|
117
|
+
color: #86909c;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.fg-type-feedback {
|
|
121
|
+
position: absolute;
|
|
122
|
+
left: 0;
|
|
123
|
+
right: 0;
|
|
124
|
+
bottom: -18px;
|
|
125
|
+
font-size: 11px;
|
|
126
|
+
color: #f53f3f;
|
|
127
|
+
z-index: 2;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.fg-type-feedback.is-warning {
|
|
131
|
+
color: #ff7d00;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.fg-type-error-border {
|
|
135
|
+
position: absolute;
|
|
136
|
+
inset: 0;
|
|
137
|
+
pointer-events: none;
|
|
138
|
+
box-shadow: inset 0 0 0 1px #f53f3f;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.fg-type-drop-tip {
|
|
142
|
+
position: absolute;
|
|
143
|
+
height: 1px;
|
|
144
|
+
background: #3370ff;
|
|
145
|
+
right: 0;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.fg-type-row.is-dragging {
|
|
149
|
+
opacity: 0.4;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.fg-type-selector {
|
|
153
|
+
position: relative;
|
|
154
|
+
width: 100%;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.fg-type-selector-panel {
|
|
158
|
+
position: absolute;
|
|
159
|
+
z-index: 20;
|
|
160
|
+
left: 0;
|
|
161
|
+
top: 100%;
|
|
162
|
+
min-width: 180px;
|
|
163
|
+
max-height: 240px;
|
|
164
|
+
overflow: auto;
|
|
165
|
+
background: #fff;
|
|
166
|
+
border: 1px solid #e5e6eb;
|
|
167
|
+
border-radius: 6px;
|
|
168
|
+
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.fg-type-selector-item {
|
|
172
|
+
display: flex;
|
|
173
|
+
align-items: center;
|
|
174
|
+
gap: 8px;
|
|
175
|
+
padding: 6px 10px;
|
|
176
|
+
cursor: pointer;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.fg-type-selector-item:hover,
|
|
180
|
+
.fg-type-selector-item.is-active {
|
|
181
|
+
background: #f2f3f5;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.fg-type-selector-item.is-disabled {
|
|
185
|
+
opacity: 0.45;
|
|
186
|
+
cursor: not-allowed;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.fg-type-modal {
|
|
190
|
+
position: fixed;
|
|
191
|
+
inset: 0;
|
|
192
|
+
background: rgba(0, 0, 0, 0.35);
|
|
193
|
+
display: flex;
|
|
194
|
+
align-items: center;
|
|
195
|
+
justify-content: center;
|
|
196
|
+
z-index: 50;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.fg-type-modal-card {
|
|
200
|
+
width: 720px;
|
|
201
|
+
max-width: 90vw;
|
|
202
|
+
background: #fff;
|
|
203
|
+
border-radius: 8px;
|
|
204
|
+
padding: 16px;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.fg-type-toast {
|
|
208
|
+
position: fixed;
|
|
209
|
+
top: 16px;
|
|
210
|
+
left: 50%;
|
|
211
|
+
transform: translateX(-50%);
|
|
212
|
+
background: #1c1f23;
|
|
213
|
+
color: #fff;
|
|
214
|
+
padding: 8px 12px;
|
|
215
|
+
border-radius: 6px;
|
|
216
|
+
z-index: 100;
|
|
217
|
+
font-size: 13px;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.fg-type-toast--success {
|
|
221
|
+
background: #00b42a;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.fg-type-toast--warning {
|
|
225
|
+
background: #ff7d00;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.fg-type-toast--error {
|
|
229
|
+
background: #f53f3f;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.fg-type-indent {
|
|
233
|
+
flex-shrink: 0;
|
|
234
|
+
height: 100%;
|
|
235
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { h } from 'vue';
|
|
7
|
+
import { IJsonSchema, JsonSchemaTypeRegistryCreator } from '@flowgram-vue/json-schema';
|
|
8
|
+
|
|
9
|
+
export const arrayRegistryCreator: JsonSchemaTypeRegistryCreator = ({ typeManager }) => ({
|
|
10
|
+
type: 'array',
|
|
11
|
+
getDisplayLabel: (type: IJsonSchema) => {
|
|
12
|
+
const config = typeManager.getTypeBySchema(type);
|
|
13
|
+
return h('span', { class: 'fg-type-label' }, [
|
|
14
|
+
config?.getDisplayIcon(type) || config?.icon,
|
|
15
|
+
h('span', { class: 'fg-type-label-text' }, typeManager.getComplexText(type)),
|
|
16
|
+
]);
|
|
17
|
+
},
|
|
18
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { h } from 'vue';
|
|
7
|
+
import { IJsonSchema, JsonSchemaTypeRegistryCreator } from '@flowgram-vue/json-schema';
|
|
8
|
+
|
|
9
|
+
import { TypeInputContext } from '../types';
|
|
10
|
+
|
|
11
|
+
export const booleanRegistryCreator: JsonSchemaTypeRegistryCreator = () => ({
|
|
12
|
+
type: 'boolean',
|
|
13
|
+
getInputNode({ value, onChange, onSubmit }: TypeInputContext<IJsonSchema>) {
|
|
14
|
+
return h(
|
|
15
|
+
'select',
|
|
16
|
+
{
|
|
17
|
+
class: 'fg-type-select',
|
|
18
|
+
value: Number(value),
|
|
19
|
+
onChange: (e: Event) => {
|
|
20
|
+
onChange(Boolean(Number((e.target as HTMLSelectElement).value)));
|
|
21
|
+
onSubmit();
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
[
|
|
25
|
+
h('option', { value: 1 }, 'True'),
|
|
26
|
+
h('option', { value: 0 }, 'False'),
|
|
27
|
+
]
|
|
28
|
+
);
|
|
29
|
+
},
|
|
30
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { JsonSchemaTypeRegistryCreator } from '@flowgram-vue/json-schema';
|
|
7
|
+
|
|
8
|
+
import { stringRegistryCreator } from './string';
|
|
9
|
+
import { objectRegistryCreator } from './object';
|
|
10
|
+
import { numberRegistryCreator } from './number';
|
|
11
|
+
import { integerRegistryCreator } from './integer';
|
|
12
|
+
import { booleanRegistryCreator } from './boolean';
|
|
13
|
+
import { arrayRegistryCreator } from './array';
|
|
14
|
+
|
|
15
|
+
export const defaultTypeRegistryCreators: JsonSchemaTypeRegistryCreator[] = [
|
|
16
|
+
stringRegistryCreator,
|
|
17
|
+
numberRegistryCreator,
|
|
18
|
+
integerRegistryCreator,
|
|
19
|
+
booleanRegistryCreator,
|
|
20
|
+
objectRegistryCreator,
|
|
21
|
+
arrayRegistryCreator,
|
|
22
|
+
];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { h } from 'vue';
|
|
7
|
+
import { IJsonSchema, JsonSchemaTypeRegistryCreator } from '@flowgram-vue/json-schema';
|
|
8
|
+
|
|
9
|
+
import { TypeInputContext } from '../types';
|
|
10
|
+
|
|
11
|
+
export const integerRegistryCreator: JsonSchemaTypeRegistryCreator = () => ({
|
|
12
|
+
type: 'integer',
|
|
13
|
+
getInputNode({ value, onChange, onSubmit }: TypeInputContext<IJsonSchema>) {
|
|
14
|
+
return h('input', {
|
|
15
|
+
class: 'fg-type-input',
|
|
16
|
+
type: 'number',
|
|
17
|
+
step: 1,
|
|
18
|
+
autofocus: true,
|
|
19
|
+
value: value as number,
|
|
20
|
+
onInput: (e: Event) => onChange(parseInt((e.target as HTMLInputElement).value, 10)),
|
|
21
|
+
onBlur: onSubmit,
|
|
22
|
+
});
|
|
23
|
+
},
|
|
24
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { h } from 'vue';
|
|
7
|
+
import { IJsonSchema, JsonSchemaTypeRegistryCreator } from '@flowgram-vue/json-schema';
|
|
8
|
+
|
|
9
|
+
import { TypeInputContext } from '../types';
|
|
10
|
+
|
|
11
|
+
export const numberRegistryCreator: JsonSchemaTypeRegistryCreator = () => ({
|
|
12
|
+
type: 'number',
|
|
13
|
+
getInputNode({ value, onChange, onSubmit }: TypeInputContext<IJsonSchema>) {
|
|
14
|
+
return h('input', {
|
|
15
|
+
class: 'fg-type-input',
|
|
16
|
+
type: 'number',
|
|
17
|
+
autofocus: true,
|
|
18
|
+
value: value as number,
|
|
19
|
+
onInput: (e: Event) => onChange(Number((e.target as HTMLInputElement).value)),
|
|
20
|
+
onBlur: onSubmit,
|
|
21
|
+
});
|
|
22
|
+
},
|
|
23
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { h } from 'vue';
|
|
7
|
+
import { JsonSchemaTypeRegistryCreator } from '@flowgram-vue/json-schema';
|
|
8
|
+
|
|
9
|
+
export const objectRegistryCreator: JsonSchemaTypeRegistryCreator = () => ({
|
|
10
|
+
type: 'object',
|
|
11
|
+
getInputNode: () =>
|
|
12
|
+
h('div', { class: 'fg-type-unsupported' }, 'Not Supported'),
|
|
13
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { h } from 'vue';
|
|
7
|
+
import { IJsonSchema, JsonSchemaTypeRegistryCreator } from '@flowgram-vue/json-schema';
|
|
8
|
+
|
|
9
|
+
import { TypeInputContext } from '../types';
|
|
10
|
+
|
|
11
|
+
export const stringRegistryCreator: JsonSchemaTypeRegistryCreator = () => ({
|
|
12
|
+
type: 'string',
|
|
13
|
+
getInputNode: ({ value, onChange, onSubmit }: TypeInputContext<IJsonSchema>) =>
|
|
14
|
+
h('input', {
|
|
15
|
+
class: 'fg-type-input',
|
|
16
|
+
autofocus: true,
|
|
17
|
+
value: value as string,
|
|
18
|
+
onInput: (e: Event) => onChange((e.target as HTMLInputElement).value),
|
|
19
|
+
onBlur: onSubmit,
|
|
20
|
+
}),
|
|
21
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { VNode } from 'vue';
|
|
7
|
+
import { IJsonSchema, JsonSchemaTypeRegistry } from '@flowgram-vue/json-schema';
|
|
8
|
+
|
|
9
|
+
export interface TypeInputConfig<TypeSchema extends Partial<IJsonSchema>> {
|
|
10
|
+
canEnter?: boolean;
|
|
11
|
+
getProps?: (typeSchema: TypeSchema) => Record<string, unknown>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface FlowSchemaInitCtx {
|
|
15
|
+
enum?: string[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface TypeInputContext<TypeSchema extends Partial<IJsonSchema>> {
|
|
19
|
+
value?: unknown;
|
|
20
|
+
onChange: (newVal: unknown) => void;
|
|
21
|
+
type: TypeSchema;
|
|
22
|
+
onSubmit: () => void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface TypeCascaderConfig<TypeSchema extends Partial<IJsonSchema>> {
|
|
26
|
+
customCascaderPanel?: (ctx: {
|
|
27
|
+
typeSchema: TypeSchema;
|
|
28
|
+
onChange: (typeSchema: TypeSchema) => void;
|
|
29
|
+
onFocus?: () => void;
|
|
30
|
+
onBlur?: () => void;
|
|
31
|
+
}) => VNode;
|
|
32
|
+
unClosePanelAfterSelect?: boolean;
|
|
33
|
+
generateInitCtx?: (typeSchema: TypeSchema) => FlowSchemaInitCtx;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface TypeEditorRegistry<TypeSchema extends Partial<IJsonSchema>>
|
|
37
|
+
extends JsonSchemaTypeRegistry<TypeSchema> {
|
|
38
|
+
defaultEditable?: true | string;
|
|
39
|
+
customDisabled?: (ctx: { level: number; parentType: string; parentTypes: string[] }) => string;
|
|
40
|
+
typeInputConfig?: TypeInputConfig<TypeSchema>;
|
|
41
|
+
typeCascaderConfig?: TypeCascaderConfig<TypeSchema>;
|
|
42
|
+
formatDefault?: (val: unknown, type: IJsonSchema) => IJsonSchema;
|
|
43
|
+
deFormatDefault?: (val: unknown) => unknown;
|
|
44
|
+
childrenDefaultEditable?: (type: TypeSchema) => true | string;
|
|
45
|
+
childrenValueEditable?: (type: TypeSchema) => true | string;
|
|
46
|
+
getInputNode?: (ctx: TypeInputContext<TypeSchema>) => VNode;
|
|
47
|
+
customChildOptionValue?: () => string[];
|
|
48
|
+
getItemTypes?: (ctx: {
|
|
49
|
+
level: number;
|
|
50
|
+
parentTypes?: string[];
|
|
51
|
+
}) => Array<{ type: string; disabled?: string }>;
|
|
52
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { Component, VNode } from 'vue';
|
|
7
|
+
import { IJsonSchema } from '@flowgram-vue/json-schema';
|
|
8
|
+
|
|
9
|
+
import { TypeEditorRegistryManager } from '../services/type-registry-manager';
|
|
10
|
+
import { type TypeEditorService } from '../services';
|
|
11
|
+
|
|
12
|
+
export interface TypeEditorPos {
|
|
13
|
+
x: number;
|
|
14
|
+
y: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface TypeEditorDropInfo {
|
|
18
|
+
rowDataId: string;
|
|
19
|
+
indent: number;
|
|
20
|
+
index: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface TypeChangeContext {
|
|
24
|
+
type: TypeEditorColumnType;
|
|
25
|
+
oldValue: unknown;
|
|
26
|
+
newValue: unknown;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface RenderProps<TypeSchema extends Partial<IJsonSchema>> {
|
|
30
|
+
rowData: TypeEditorRowData<TypeSchema>;
|
|
31
|
+
readonly?: boolean;
|
|
32
|
+
onViewMode: () => void;
|
|
33
|
+
typeEditor: TypeEditorService<TypeSchema>;
|
|
34
|
+
onChildrenVisibleChange: (rowDataKey: string, newVal: boolean) => void;
|
|
35
|
+
onChange: () => void;
|
|
36
|
+
onPaste?: (typeSchema?: TypeSchema) => TypeSchema | undefined;
|
|
37
|
+
onFieldChange?: (ctx: TypeChangeContext) => void;
|
|
38
|
+
onEditMode: () => void;
|
|
39
|
+
dragSource?: HTMLElement | null;
|
|
40
|
+
error: boolean;
|
|
41
|
+
onError?: (msg: string[]) => void;
|
|
42
|
+
unOpenKeys: Record<string, boolean>;
|
|
43
|
+
config: Omit<TypeEditorColumnViewConfig, 'type' | 'visible'>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ShortcutContext<TypeSchema extends Partial<IJsonSchema>> {
|
|
47
|
+
value: unknown;
|
|
48
|
+
rowData: TypeEditorRowData<TypeSchema>;
|
|
49
|
+
onChange: () => void;
|
|
50
|
+
onRemoveEmptyLine: (id: string) => void;
|
|
51
|
+
typeEditor: TypeEditorService<TypeSchema>;
|
|
52
|
+
onError?: (msg?: string) => void;
|
|
53
|
+
typeDefinitionService: TypeEditorRegistryManager<TypeSchema>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface TypeEditorColumnConfig<TypeSchema extends Partial<IJsonSchema>> {
|
|
57
|
+
type: TypeEditorColumnType;
|
|
58
|
+
label: string;
|
|
59
|
+
width?: number;
|
|
60
|
+
focusable?: boolean;
|
|
61
|
+
info?: () => string;
|
|
62
|
+
viewRender?: Component;
|
|
63
|
+
editRender?: Component;
|
|
64
|
+
customDrop?: boolean;
|
|
65
|
+
validateCell?: (
|
|
66
|
+
rowData: TypeEditorRowData<TypeSchema>,
|
|
67
|
+
extra: TypeEditorSpecialConfig<TypeSchema>
|
|
68
|
+
) =>
|
|
69
|
+
| {
|
|
70
|
+
level: 'error' | 'warning';
|
|
71
|
+
msg?: string;
|
|
72
|
+
}
|
|
73
|
+
| undefined;
|
|
74
|
+
shortcuts?: {
|
|
75
|
+
onEnter?: (ctx: ShortcutContext<TypeSchema>) => void;
|
|
76
|
+
onTab?: (ctx: ShortcutContext<TypeSchema>) => void;
|
|
77
|
+
onUp?: (ctx: ShortcutContext<TypeSchema>) => void;
|
|
78
|
+
onDown?: (ctx: ShortcutContext<TypeSchema>) => void;
|
|
79
|
+
onLeft?: (ctx: ShortcutContext<TypeSchema>) => void;
|
|
80
|
+
onRight?: (ctx: ShortcutContext<TypeSchema>) => void;
|
|
81
|
+
onCopy?: (ctx: ShortcutContext<TypeSchema>) => void;
|
|
82
|
+
onPaste?: (ctx: ShortcutContext<TypeSchema>) => void;
|
|
83
|
+
onDelete?: (ctx: ShortcutContext<TypeSchema>) => void;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface TypeEditorColumnViewConfig {
|
|
88
|
+
type: TypeEditorColumnType;
|
|
89
|
+
visible: boolean;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface DisableTypeInfo {
|
|
93
|
+
type: string;
|
|
94
|
+
reason: string;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export enum TypeEditorColumnType {
|
|
98
|
+
Key = 'key',
|
|
99
|
+
Type = 'type',
|
|
100
|
+
Required = 'required',
|
|
101
|
+
Description = 'description',
|
|
102
|
+
Default = 'default',
|
|
103
|
+
Operate = 'operate',
|
|
104
|
+
Value = 'value',
|
|
105
|
+
Private = 'private',
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface TypeEditorExtraInfo {
|
|
109
|
+
value?: unknown;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export type TypeEditorSchema<TypeSchema extends Partial<IJsonSchema>> = TypeSchema & {
|
|
113
|
+
extra?: TypeEditorExtraInfo;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export interface TypeEditorSpecialConfig<TypeSchema extends Partial<IJsonSchema>> {
|
|
117
|
+
defaultMode?: 'default' | 'server';
|
|
118
|
+
customValidateName?: (name: string) => string;
|
|
119
|
+
disableFixIndex?: boolean;
|
|
120
|
+
editorVisible?: boolean | string;
|
|
121
|
+
hiddenDrag?: boolean;
|
|
122
|
+
useExtra?: boolean;
|
|
123
|
+
customDisabledTypes?: Array<DisableTypeInfo>;
|
|
124
|
+
disabledAdd?: (rowData: TypeEditorRowData<TypeSchema>) => string;
|
|
125
|
+
customDefaultView?: (ctx: {
|
|
126
|
+
rowData: TypeEditorRowData<TypeSchema>;
|
|
127
|
+
value: unknown;
|
|
128
|
+
disabled?: string;
|
|
129
|
+
onChange: (value: unknown) => void;
|
|
130
|
+
onSubmit: (value: unknown) => void;
|
|
131
|
+
}) => VNode;
|
|
132
|
+
customDefaultEditable?: (rowData: TypeEditorRowData<TypeSchema>) => true | string;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export type TypeEditorRowData<TypeSchema extends Partial<IJsonSchema>> = TypeSchema & {
|
|
136
|
+
id: string;
|
|
137
|
+
key: string;
|
|
138
|
+
isRequired: boolean;
|
|
139
|
+
level: number;
|
|
140
|
+
self: TypeEditorSchema<TypeSchema>;
|
|
141
|
+
parent?: TypeEditorSchema<TypeSchema>;
|
|
142
|
+
childrenCount: number;
|
|
143
|
+
deepChildrenCount: number;
|
|
144
|
+
disableEditColumn?: Array<{ column: TypeEditorColumnType; reason: string }>;
|
|
145
|
+
cannotDrag?: boolean;
|
|
146
|
+
index: number;
|
|
147
|
+
extraConfig: TypeEditorSpecialConfig<TypeSchema>;
|
|
148
|
+
parentId?: string;
|
|
149
|
+
path: string[];
|
|
150
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Emitter, type Event } from '@flowgram-vue/utils';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 定义用于在 service 的一些需要被监听 onChange 的 data
|
|
10
|
+
* 搭配 useMonitorData 使用
|
|
11
|
+
*/
|
|
12
|
+
export class MonitorData<Type> {
|
|
13
|
+
private _data: Type;
|
|
14
|
+
|
|
15
|
+
protected readonly onDataChangeEmitter = new Emitter<{
|
|
16
|
+
prev: Type;
|
|
17
|
+
next: Type;
|
|
18
|
+
}>();
|
|
19
|
+
|
|
20
|
+
readonly onDataChange: Event<{
|
|
21
|
+
prev: Type;
|
|
22
|
+
next: Type;
|
|
23
|
+
}> = this.onDataChangeEmitter.event;
|
|
24
|
+
|
|
25
|
+
public get data(): Type {
|
|
26
|
+
return this._data;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public constructor(initialValue?: Type) {
|
|
30
|
+
if (initialValue !== undefined) {
|
|
31
|
+
this._data = initialValue;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public update(data: Type) {
|
|
36
|
+
const prev = this._data;
|
|
37
|
+
this._data = data;
|
|
38
|
+
this.onDataChangeEmitter.fire({
|
|
39
|
+
prev,
|
|
40
|
+
next: data,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { onBeforeUnmount, ref } from 'vue';
|
|
7
|
+
|
|
8
|
+
import { type MonitorData } from './monitor-data';
|
|
9
|
+
|
|
10
|
+
export const useMonitorData = <Type>(
|
|
11
|
+
monitorData: MonitorData<Type> | undefined
|
|
12
|
+
): { data: Type | undefined } => {
|
|
13
|
+
const data = ref(monitorData?.data) as { value: Type | undefined };
|
|
14
|
+
|
|
15
|
+
if (monitorData) {
|
|
16
|
+
const dispose = monitorData.onDataChange(({ next }) => {
|
|
17
|
+
data.value = next;
|
|
18
|
+
});
|
|
19
|
+
onBeforeUnmount(() => {
|
|
20
|
+
dispose.dispose();
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
get data() {
|
|
26
|
+
return data.value;
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
};
|