@skopon-cool/form-sdk 0.1.3 → 0.1.5
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/README.md +2 -0
- package/dist/adapter/a2uiAdapter.d.ts +0 -1
- package/dist/adapter/a2uiAdapter.d.ts.map +1 -1
- package/dist/adapter/formSchema.d.ts.map +1 -1
- package/dist/blocks/case_multiselect/adapter.d.ts +10 -0
- package/dist/blocks/case_multiselect/adapter.d.ts.map +1 -0
- package/dist/blocks/case_multiselect/index.d.ts +3 -0
- package/dist/blocks/case_multiselect/index.d.ts.map +1 -0
- package/dist/blocks/case_singleselect/catalog.d.ts +2 -0
- package/dist/blocks/case_singleselect/catalog.d.ts.map +1 -0
- package/dist/blocks/registry.d.ts +8 -0
- package/dist/blocks/registry.d.ts.map +1 -0
- package/dist/blocks/resume_multiselect/adapter.d.ts +10 -0
- package/dist/blocks/resume_multiselect/adapter.d.ts.map +1 -0
- package/dist/blocks/resume_multiselect/catalog.d.ts +2 -0
- package/dist/blocks/resume_multiselect/catalog.d.ts.map +1 -0
- package/dist/blocks/resume_multiselect/index.d.ts +3 -0
- package/dist/blocks/resume_multiselect/index.d.ts.map +1 -0
- package/dist/blocks/types.d.ts +27 -0
- package/dist/blocks/types.d.ts.map +1 -0
- package/dist/catalog/a2uiCustomCatalog.d.ts.map +1 -1
- package/dist/catalog/caseSearchContext.d.ts +28 -0
- package/dist/catalog/caseSearchContext.d.ts.map +1 -0
- package/dist/catalog/resumeSearchContext.d.ts +39 -0
- package/dist/catalog/resumeSearchContext.d.ts.map +1 -0
- package/dist/catalog/skoponCaseSelect.d.ts +2 -0
- package/dist/catalog/skoponCaseSelect.d.ts.map +1 -0
- package/dist/catalog/skoponResumeSelect.d.ts +2 -0
- package/dist/catalog/skoponResumeSelect.d.ts.map +1 -0
- package/dist/components/AskUserFormCard.d.ts +7 -1
- package/dist/components/AskUserFormCard.d.ts.map +1 -1
- package/dist/components/SkoponA2uiStreamRenderer.d.ts +7 -1
- package/dist/components/SkoponA2uiStreamRenderer.d.ts.map +1 -1
- package/dist/components/SkoponFormRenderer.d.ts +6 -0
- package/dist/components/SkoponFormRenderer.d.ts.map +1 -1
- package/dist/form-sdk.css +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1374 -889
- package/dist/submit/buildCurlStatement.d.ts +1 -1
- package/dist/submit/buildCurlStatement.d.ts.map +1 -1
- package/dist/submit/intersectPayloadBlocksWithForm.d.ts.map +1 -1
- package/dist/types/index.d.ts +33 -2
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/adapter/a2uiAdapter.test.ts +71 -0
- package/src/adapter/a2uiAdapter.ts +41 -4
- package/src/adapter/formSchema.ts +102 -19
- package/src/blocks/case_multiselect/adapter.ts +90 -0
- package/src/blocks/case_multiselect/index.ts +14 -0
- package/src/blocks/case_singleselect/catalog.ts +1 -0
- package/src/blocks/registry.ts +34 -0
- package/src/blocks/resume_multiselect/adapter.ts +57 -0
- package/src/blocks/resume_multiselect/catalog.ts +1 -0
- package/src/blocks/resume_multiselect/index.ts +14 -0
- package/src/blocks/types.ts +34 -0
- package/src/catalog/a2uiCustomCatalog.tsx +6 -0
- package/src/catalog/caseSearchContext.tsx +46 -0
- package/src/catalog/resumeSearchContext.tsx +58 -0
- package/src/catalog/skoponCaseSelect.tsx +240 -0
- package/src/catalog/skoponResumeSelect.tsx +293 -0
- package/src/components/AskUserFormCard.tsx +13 -1
- package/src/components/SkoponA2uiStreamRenderer.test.ts +18 -2
- package/src/components/SkoponA2uiStreamRenderer.test.tsx +26 -2
- package/src/components/SkoponA2uiStreamRenderer.tsx +71 -27
- package/src/components/SkoponFormRenderer.tsx +32 -10
- package/src/index.ts +23 -0
- package/src/styles/a2ui-preview.css +4 -4
- package/src/styles/index.css +191 -0
- package/src/submit/buildCurlStatement.ts +2 -23
- package/src/submit/intersectPayloadBlocksWithForm.ts +14 -2
- package/src/submit/submit.test.ts +34 -3
- package/src/types/index.ts +37 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare function buildCurlStatement(payload: unknown, callbackUrl?: string | null): string;
|
|
2
|
-
/**
|
|
2
|
+
/** 构建合法 JSON body(card + extra 合并,便于 curl 直接执行) */
|
|
3
3
|
export declare function buildAskUserCurlBodyJson(cardValues: Record<string, unknown>, extraValues: Record<string, unknown>): string;
|
|
4
4
|
export interface BuildAskUserCurlStatementOptions {
|
|
5
5
|
cardValues: Record<string, unknown>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildCurlStatement.d.ts","sourceRoot":"","sources":["../../src/submit/buildCurlStatement.ts"],"names":[],"mappings":"AAIA,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAQxF;
|
|
1
|
+
{"version":3,"file":"buildCurlStatement.d.ts","sourceRoot":"","sources":["../../src/submit/buildCurlStatement.ts"],"names":[],"mappings":"AAIA,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAQxF;AAED,mDAAmD;AACnD,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,MAAM,CAER;AAED,MAAM,WAAW,gCAAgC;IAC/C,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACrC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED,wBAAgB,yBAAyB,CAAC,EACxC,UAAU,EACV,WAAgB,EAChB,WAAW,GACZ,EAAE,gCAAgC,GAAG,MAAM,CAQ3C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intersectPayloadBlocksWithForm.d.ts","sourceRoot":"","sources":["../../src/submit/intersectPayloadBlocksWithForm.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAG3D,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,GAAG,aAAa,GAAG,QAAQ,CAAC,CAAA;AAE1F,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,SAAS,EAAE,CAAA;IAC1B,WAAW,EAAE,SAAS,EAAE,CAAA;IACxB,0DAA0D;IAC1D,YAAY,EAAE,SAAS,EAAE,CAAA;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;CACpB;AAqDD,uEAAuE;AACvE,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,uBAAuB,GAAG,IAAI,CAUvF;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,UAAU,EAAE,uBAAuB,EACnC,cAAc,EAAE,UAAU,GAAG,SAAS,GACrC,yBAAyB,CAqC3B;
|
|
1
|
+
{"version":3,"file":"intersectPayloadBlocksWithForm.d.ts","sourceRoot":"","sources":["../../src/submit/intersectPayloadBlocksWithForm.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAG3D,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,GAAG,aAAa,GAAG,QAAQ,CAAC,CAAA;AAE1F,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,SAAS,EAAE,CAAA;IAC1B,WAAW,EAAE,SAAS,EAAE,CAAA;IACxB,0DAA0D;IAC1D,YAAY,EAAE,SAAS,EAAE,CAAA;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;CACpB;AAqDD,uEAAuE;AACvE,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,uBAAuB,GAAG,IAAI,CAUvF;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,UAAU,EAAE,uBAAuB,EACnC,cAAc,EAAE,UAAU,GAAG,SAAS,GACrC,yBAAyB,CAqC3B;AA+BD,2CAA2C;AAC3C,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASzF;AAED,sDAAsD;AACtD,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,uBAAuB,GAAG,OAAO,CAIlF;AAED,0DAA0D;AAC1D,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,uBAAuB,GAAG,SAAS,EAAE,CAK3F;AAED,mDAAmD;AACnD,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,uBAAuB,GAAG,MAAM,EAAE,CAIvF"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
export type A2uiBinding<T> = T | {
|
|
5
5
|
path: string;
|
|
6
6
|
};
|
|
7
|
-
export type A2uiComponentName = 'Column' | 'Row' | 'Text' | 'Image' | 'Video' | 'AudioPlayer' | 'TextField' | 'CheckBox' | 'ChoicePicker' | 'DateTimeInput' | 'FileUpload' | 'SkoponMedia' | 'SkoponSelect';
|
|
7
|
+
export type A2uiComponentName = 'Column' | 'Row' | 'Text' | 'Image' | 'Video' | 'AudioPlayer' | 'TextField' | 'CheckBox' | 'ChoicePicker' | 'DateTimeInput' | 'FileUpload' | 'SkoponMedia' | 'SkoponSelect' | 'SkoponResumeSelect' | 'SkoponCaseSelect';
|
|
8
8
|
export interface A2uiComponentNode {
|
|
9
9
|
id: string;
|
|
10
10
|
component: A2uiComponentName | string;
|
|
@@ -21,7 +21,9 @@ export interface A2uiSurfaceDoc {
|
|
|
21
21
|
}
|
|
22
22
|
export declare const A2UI_PROTOCOL_VERSION: "v0.9";
|
|
23
23
|
export type FormJsonSchema = Record<string, unknown>;
|
|
24
|
-
export type FormBlockType = 'heading' | 'paragraph' | 'text' | 'textarea' | 'email' | 'number' | 'select' | 'multiselect' | 'radio' | 'checkbox' | 'toggle' | 'tel' | 'url' | 'datetime' | 'time' | 'file' | '
|
|
24
|
+
export type FormBlockType = 'heading' | 'paragraph' | 'text' | 'textarea' | 'email' | 'number' | 'select' | 'multiselect' | 'radio' | 'checkbox' | 'toggle' | 'tel' | 'url' | 'datetime' | 'time' | 'file' | 'resume_multiselect' | 'case_multiselect'
|
|
25
|
+
/** @deprecated 加载时自动迁移为 case_multiselect */
|
|
26
|
+
| 'case_singleselect' | 'image' | 'video' | 'audio';
|
|
25
27
|
export type FormMediaSize = 'huge' | 'large' | 'medium' | 'small' | 'icon';
|
|
26
28
|
export type FormFilePlaceholderIcon = 'video' | 'audio' | 'image' | 'file' | 'spreadsheet' | 'document';
|
|
27
29
|
export declare const FORM_MEDIA_SIZES: FormMediaSize[];
|
|
@@ -29,6 +31,27 @@ export interface FormBlockOption {
|
|
|
29
31
|
value: string;
|
|
30
32
|
label: string;
|
|
31
33
|
}
|
|
34
|
+
/** 简历多选组件:渲染时用于 /univ/resume/search 的筛选条件 */
|
|
35
|
+
export interface FormResumeFilter {
|
|
36
|
+
names?: string[];
|
|
37
|
+
agentUniqueIds?: string[];
|
|
38
|
+
resumeUniqueIds?: string[];
|
|
39
|
+
pageSize?: number;
|
|
40
|
+
}
|
|
41
|
+
/** 案例多选组件:渲染时用于 /univ/case/list 的筛选条件 */
|
|
42
|
+
export interface FormCaseFilter {
|
|
43
|
+
/** Agent 类型(编辑器辅助,运行时不用) */
|
|
44
|
+
agentKind?: string;
|
|
45
|
+
/** Agent unique_id(运行时用于限定所属 Agent) */
|
|
46
|
+
agentUniqueId?: string;
|
|
47
|
+
/** 流类型 unique_id */
|
|
48
|
+
flowType?: string;
|
|
49
|
+
/** 流类别 unique_id */
|
|
50
|
+
category?: string;
|
|
51
|
+
/** 流程编号(flow_unique_id)多选 */
|
|
52
|
+
flowUniqueIds?: string[];
|
|
53
|
+
pageSize?: number;
|
|
54
|
+
}
|
|
32
55
|
export interface FormBlock {
|
|
33
56
|
id: string;
|
|
34
57
|
type: FormBlockType;
|
|
@@ -47,6 +70,14 @@ export interface FormBlock {
|
|
|
47
70
|
fileMinCount?: number;
|
|
48
71
|
fileMaxCount?: number;
|
|
49
72
|
defaultValue?: string | string[] | boolean;
|
|
73
|
+
/** 简历多选:是否显示「换一批」 */
|
|
74
|
+
resumeEnableRefresh?: boolean;
|
|
75
|
+
/** 简历多选:列表筛选条件(持久化进 block json) */
|
|
76
|
+
resumeFilter?: FormResumeFilter;
|
|
77
|
+
/** 案例单选:是否显示「换一批」 */
|
|
78
|
+
caseEnableRefresh?: boolean;
|
|
79
|
+
/** 案例单选:列表筛选条件(持久化进 block json) */
|
|
80
|
+
caseFilter?: FormCaseFilter;
|
|
50
81
|
}
|
|
51
82
|
export interface FormSchema {
|
|
52
83
|
title?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEjD,MAAM,MAAM,iBAAiB,GACzB,QAAQ,GACR,KAAK,GACL,MAAM,GACN,OAAO,GACP,OAAO,GACP,aAAa,GACb,WAAW,GACX,UAAU,GACV,cAAc,GACd,eAAe,GACf,YAAY,GACZ,aAAa,GACb,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { describe, it, expect } from 'vitest'
|
|
5
5
|
import type { FormSchema } from '../types/index'
|
|
6
6
|
import { a2uiToBlocks, blocksToA2ui, isA2uiSurfaceEmpty, surfaceDocToMessages } from './a2uiAdapter'
|
|
7
|
+
import { normalizeFormDefinition } from './formSchema'
|
|
7
8
|
|
|
8
9
|
function makeDefinition(): Pick<FormSchema, 'title' | 'description' | 'blocks'> {
|
|
9
10
|
return {
|
|
@@ -238,4 +239,74 @@ describe('a2uiAdapter blocks <-> surface', () => {
|
|
|
238
239
|
const withHeader = blocksToA2ui(makeDefinition())
|
|
239
240
|
expect((withHeader.components.find((c) => c.id === 'root')?.children as string[]).length).toBe(12)
|
|
240
241
|
})
|
|
242
|
+
|
|
243
|
+
it('round-trips case_multiselect through blocksToA2ui and a2uiToBlocks', () => {
|
|
244
|
+
const doc = blocksToA2ui(
|
|
245
|
+
{
|
|
246
|
+
title: '',
|
|
247
|
+
description: '',
|
|
248
|
+
blocks: [
|
|
249
|
+
{
|
|
250
|
+
id: 'b-case',
|
|
251
|
+
type: 'case_multiselect',
|
|
252
|
+
name: 'selected_cases',
|
|
253
|
+
label: '选择案例',
|
|
254
|
+
placeholder: '暂无案例',
|
|
255
|
+
help: '请选择一个或多个案例',
|
|
256
|
+
caseEnableRefresh: true,
|
|
257
|
+
caseFilter: {
|
|
258
|
+
agentKind: 'public-user',
|
|
259
|
+
agentUniqueId: 'agent-1',
|
|
260
|
+
flowType: 'content',
|
|
261
|
+
category: 'short-video',
|
|
262
|
+
flowUniqueIds: ['flow-rec-a', 'flow-rec-b'],
|
|
263
|
+
pageSize: 10,
|
|
264
|
+
},
|
|
265
|
+
defaultValue: ['case-abc', 'case-def'],
|
|
266
|
+
},
|
|
267
|
+
],
|
|
268
|
+
},
|
|
269
|
+
{ includeHeader: false },
|
|
270
|
+
)
|
|
271
|
+
const node = doc.components.find((c) => c.id === 'b-case')
|
|
272
|
+
expect(node?.component).toBe('SkoponCaseSelect')
|
|
273
|
+
expect(node?.enableRefresh).toBe(true)
|
|
274
|
+
expect(node?.caseFilter).toEqual({
|
|
275
|
+
agentKind: 'public-user',
|
|
276
|
+
agentUniqueId: 'agent-1',
|
|
277
|
+
flowType: 'content',
|
|
278
|
+
category: 'short-video',
|
|
279
|
+
flowUniqueIds: ['flow-rec-a', 'flow-rec-b'],
|
|
280
|
+
pageSize: 10,
|
|
281
|
+
})
|
|
282
|
+
expect(doc.dataModel?.selected_cases).toEqual(['case-abc', 'case-def'])
|
|
283
|
+
|
|
284
|
+
const back = a2uiToBlocks(doc)
|
|
285
|
+
const block = back.blocks.find((b) => b.name === 'selected_cases')
|
|
286
|
+
expect(block?.type).toBe('case_multiselect')
|
|
287
|
+
expect(block?.caseEnableRefresh).toBe(true)
|
|
288
|
+
expect(block?.caseFilter?.flowType).toBe('content')
|
|
289
|
+
expect(block?.caseFilter?.category).toBe('short-video')
|
|
290
|
+
expect(block?.caseFilter?.flowUniqueIds).toEqual(['flow-rec-a', 'flow-rec-b'])
|
|
291
|
+
expect(block?.caseFilter?.pageSize).toBe(10)
|
|
292
|
+
expect(block?.defaultValue).toEqual(['case-abc', 'case-def'])
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
it('migrates legacy case_singleselect to case_multiselect on normalize', () => {
|
|
296
|
+
const normalized = normalizeFormDefinition({
|
|
297
|
+
title: '',
|
|
298
|
+
description: '',
|
|
299
|
+
blocks: [
|
|
300
|
+
{
|
|
301
|
+
id: 'legacy',
|
|
302
|
+
type: 'case_singleselect',
|
|
303
|
+
name: 'old_case',
|
|
304
|
+
defaultValue: 'case-old',
|
|
305
|
+
},
|
|
306
|
+
],
|
|
307
|
+
jsonSchema: {},
|
|
308
|
+
})
|
|
309
|
+
expect(normalized.blocks[0]?.type).toBe('case_multiselect')
|
|
310
|
+
expect(normalized.blocks[0]?.defaultValue).toEqual(['case-old'])
|
|
311
|
+
})
|
|
241
312
|
})
|
|
@@ -11,6 +11,7 @@ import { generateId } from './id'
|
|
|
11
11
|
import { coerceToggleValue } from './formSchema'
|
|
12
12
|
import { getMediaUrls, normalizeMediaSize } from './formMedia'
|
|
13
13
|
import { syncFormDefinition } from './formSchema'
|
|
14
|
+
import { getBlockTypeAdapter, getComponentAdapter } from '../blocks/registry'
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* A2UI surface <-> FormBlock 双向适配器。
|
|
@@ -99,14 +100,17 @@ function defaultValueForBlock(block: FormBlock): unknown {
|
|
|
99
100
|
return coerceToggleValue(block.defaultValue)
|
|
100
101
|
case 'multiselect':
|
|
101
102
|
case 'checkbox':
|
|
103
|
+
case 'resume_multiselect':
|
|
104
|
+
case 'case_multiselect':
|
|
102
105
|
if (Array.isArray(block.defaultValue)) return block.defaultValue
|
|
103
106
|
if (typeof block.defaultValue === 'string' && block.defaultValue) return [block.defaultValue]
|
|
104
107
|
return []
|
|
105
108
|
case 'select':
|
|
106
109
|
case 'radio':
|
|
107
|
-
|
|
108
|
-
if (typeof block.defaultValue === '
|
|
109
|
-
|
|
110
|
+
case 'number':
|
|
111
|
+
if (typeof block.defaultValue === 'number') return block.defaultValue
|
|
112
|
+
if (typeof block.defaultValue === 'string' && block.defaultValue) return block.defaultValue
|
|
113
|
+
return null
|
|
110
114
|
default:
|
|
111
115
|
if (typeof block.defaultValue === 'string') return block.defaultValue
|
|
112
116
|
return ''
|
|
@@ -131,6 +135,12 @@ function blockToComponent(block: FormBlock): {
|
|
|
131
135
|
dataValue?: unknown
|
|
132
136
|
} => (name ? { node, dataKey: name, dataValue: defaultValueForBlock(block) } : { node })
|
|
133
137
|
|
|
138
|
+
const adapterCtx = { id, label, name, path, withData }
|
|
139
|
+
const typeAdapter = getBlockTypeAdapter(block.type)
|
|
140
|
+
if (typeAdapter) {
|
|
141
|
+
return typeAdapter.toComponent(block, adapterCtx)
|
|
142
|
+
}
|
|
143
|
+
|
|
134
144
|
switch (block.type) {
|
|
135
145
|
case 'heading':
|
|
136
146
|
return { node: { id, component: 'Text', text: label, variant: 'h3' } }
|
|
@@ -351,6 +361,11 @@ function componentToBlock(node: A2uiComponentNode): FormBlock | null {
|
|
|
351
361
|
|
|
352
362
|
const base = (type: FormBlockType): FormBlock => ({ id, type, label })
|
|
353
363
|
|
|
364
|
+
const componentAdapter = getComponentAdapter(component)
|
|
365
|
+
if (componentAdapter) {
|
|
366
|
+
return componentAdapter.fromComponent(node, base, { asLiteral, nameFromValue })
|
|
367
|
+
}
|
|
368
|
+
|
|
354
369
|
switch (component) {
|
|
355
370
|
case 'Text': {
|
|
356
371
|
const variant = String(node.variant ?? 'body')
|
|
@@ -465,6 +480,23 @@ function collectOrder(
|
|
|
465
480
|
}
|
|
466
481
|
|
|
467
482
|
/** A2UI surface 文档 -> FormSchema(已 sync 出 jsonSchema) */
|
|
483
|
+
function applyDataModelDefaults(
|
|
484
|
+
blocks: FormBlock[],
|
|
485
|
+
dataModel: Record<string, unknown> | undefined,
|
|
486
|
+
): FormBlock[] {
|
|
487
|
+
if (!dataModel) return blocks
|
|
488
|
+
return blocks.map((block) => {
|
|
489
|
+
const name = block.name?.trim()
|
|
490
|
+
if (!name || !(name in dataModel)) return block
|
|
491
|
+
const raw = dataModel[name]
|
|
492
|
+
if (raw === undefined) return block
|
|
493
|
+
if (block.type === 'toggle') {
|
|
494
|
+
return { ...block, defaultValue: raw === true || raw === 'true' }
|
|
495
|
+
}
|
|
496
|
+
return { ...block, defaultValue: raw as FormBlock['defaultValue'] }
|
|
497
|
+
})
|
|
498
|
+
}
|
|
499
|
+
|
|
468
500
|
export function a2uiToBlocks(doc: A2uiSurfaceDoc | null | undefined): FormSchema {
|
|
469
501
|
if (!doc || !Array.isArray(doc.components)) {
|
|
470
502
|
return syncFormDefinition({ title: '', description: '', blocks: [], jsonSchema: {} })
|
|
@@ -490,7 +522,12 @@ export function a2uiToBlocks(doc: A2uiSurfaceDoc | null | undefined): FormSchema
|
|
|
490
522
|
if (block) blocks.push(block)
|
|
491
523
|
}
|
|
492
524
|
|
|
493
|
-
return syncFormDefinition({
|
|
525
|
+
return syncFormDefinition({
|
|
526
|
+
title,
|
|
527
|
+
description,
|
|
528
|
+
blocks: applyDataModelDefaults(blocks, doc.dataModel),
|
|
529
|
+
jsonSchema: {},
|
|
530
|
+
})
|
|
494
531
|
}
|
|
495
532
|
|
|
496
533
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FormBlock, FormBlockType, FormSchema } from '../types/index'
|
|
1
|
+
import type { FormBlock, FormBlockType, FormCaseFilter, FormResumeFilter, FormSchema } from '../types/index'
|
|
2
2
|
import { isInputBlockType, isMediaBlockType } from '../types/index'
|
|
3
3
|
import { generateId } from './id'
|
|
4
4
|
import {
|
|
@@ -29,7 +29,7 @@ function normalizeDefaultValue(
|
|
|
29
29
|
): FormBlock['defaultValue'] {
|
|
30
30
|
if (raw === undefined) return undefined
|
|
31
31
|
if (type === 'toggle') return coerceToggleValue(raw)
|
|
32
|
-
if (type === 'multiselect' || type === 'checkbox') {
|
|
32
|
+
if (type === 'multiselect' || type === 'checkbox' || type === 'resume_multiselect' || type === 'case_multiselect') {
|
|
33
33
|
if (Array.isArray(raw)) return raw.map(String)
|
|
34
34
|
if (typeof raw === 'string' && raw) return [raw]
|
|
35
35
|
return []
|
|
@@ -39,36 +39,102 @@ function normalizeDefaultValue(
|
|
|
39
39
|
return String(raw)
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
function normalizeCaseFilter(raw: FormCaseFilter | undefined): FormCaseFilter {
|
|
43
|
+
const pageSizeRaw = typeof raw?.pageSize === 'number' ? raw.pageSize : Number(raw?.pageSize)
|
|
44
|
+
const pageSize =
|
|
45
|
+
Number.isFinite(pageSizeRaw) && pageSizeRaw >= 1 && pageSizeRaw <= 100
|
|
46
|
+
? Math.floor(pageSizeRaw)
|
|
47
|
+
: 20
|
|
48
|
+
const agentKind =
|
|
49
|
+
typeof raw?.agentKind === 'string' && raw.agentKind.trim()
|
|
50
|
+
? raw.agentKind.trim()
|
|
51
|
+
: undefined
|
|
52
|
+
const agentUniqueId =
|
|
53
|
+
typeof raw?.agentUniqueId === 'string' && raw.agentUniqueId.trim()
|
|
54
|
+
? raw.agentUniqueId.trim()
|
|
55
|
+
: undefined
|
|
56
|
+
const flowType =
|
|
57
|
+
typeof raw?.flowType === 'string' && raw.flowType.trim()
|
|
58
|
+
? raw.flowType.trim()
|
|
59
|
+
: undefined
|
|
60
|
+
const category =
|
|
61
|
+
typeof raw?.category === 'string' && raw.category.trim()
|
|
62
|
+
? raw.category.trim()
|
|
63
|
+
: undefined
|
|
64
|
+
const flowUniqueIds = Array.isArray(raw?.flowUniqueIds)
|
|
65
|
+
? raw.flowUniqueIds.map(String).filter(Boolean)
|
|
66
|
+
: []
|
|
67
|
+
return { agentKind, agentUniqueId, flowType, category, flowUniqueIds, pageSize }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function normalizeResumeFilter(raw: FormResumeFilter | undefined): FormResumeFilter {
|
|
71
|
+
const pageSizeRaw = typeof raw?.pageSize === 'number' ? raw.pageSize : Number(raw?.pageSize)
|
|
72
|
+
const pageSize =
|
|
73
|
+
Number.isFinite(pageSizeRaw) && pageSizeRaw >= 1 && pageSizeRaw <= 100
|
|
74
|
+
? Math.floor(pageSizeRaw)
|
|
75
|
+
: 20
|
|
76
|
+
return {
|
|
77
|
+
names: Array.isArray(raw?.names) ? raw!.names.map(String).filter(Boolean) : [],
|
|
78
|
+
agentUniqueIds: Array.isArray(raw?.agentUniqueIds)
|
|
79
|
+
? raw!.agentUniqueIds.map(String).filter(Boolean)
|
|
80
|
+
: [],
|
|
81
|
+
resumeUniqueIds: Array.isArray(raw?.resumeUniqueIds)
|
|
82
|
+
? raw!.resumeUniqueIds.map(String).filter(Boolean)
|
|
83
|
+
: [],
|
|
84
|
+
pageSize,
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function migrateLegacyBlock(raw: FormBlock): FormBlock {
|
|
89
|
+
if (raw.type !== 'case_singleselect') return raw
|
|
90
|
+
const defaultValue =
|
|
91
|
+
typeof raw.defaultValue === 'string' && raw.defaultValue.trim()
|
|
92
|
+
? [raw.defaultValue.trim()]
|
|
93
|
+
: Array.isArray(raw.defaultValue)
|
|
94
|
+
? raw.defaultValue.map(String).filter(Boolean)
|
|
95
|
+
: []
|
|
96
|
+
return { ...raw, type: 'case_multiselect', defaultValue }
|
|
97
|
+
}
|
|
98
|
+
|
|
42
99
|
function normalizeBlock(raw: FormBlock): FormBlock {
|
|
43
|
-
const
|
|
44
|
-
const
|
|
100
|
+
const migrated = migrateLegacyBlock(raw)
|
|
101
|
+
const fileAcceptTypes = normalizeFileAcceptTypes(migrated.fileAcceptTypes)
|
|
102
|
+
const type = migrated.type
|
|
45
103
|
return {
|
|
46
|
-
id:
|
|
104
|
+
id: migrated.id?.trim() || generateId('block-'),
|
|
47
105
|
type,
|
|
48
|
-
name:
|
|
49
|
-
label:
|
|
50
|
-
placeholder:
|
|
51
|
-
help:
|
|
52
|
-
required:
|
|
106
|
+
name: migrated.name?.trim() || undefined,
|
|
107
|
+
label: migrated.label ?? '',
|
|
108
|
+
placeholder: migrated.placeholder ?? '',
|
|
109
|
+
help: migrated.help ?? '',
|
|
110
|
+
required: migrated.required === true,
|
|
53
111
|
mediaUrls: isMediaBlockType(type)
|
|
54
|
-
? normalizeMediaUrls(
|
|
112
|
+
? normalizeMediaUrls(migrated, DEFAULT_MEDIA_URL_MAX)
|
|
55
113
|
: undefined,
|
|
56
|
-
mediaSize: isMediaBlockType(type) ? normalizeMediaSize(
|
|
114
|
+
mediaSize: isMediaBlockType(type) ? normalizeMediaSize(migrated.mediaSize) : undefined,
|
|
57
115
|
fileAcceptTypes,
|
|
58
116
|
fileAcceptExtensions: filterFileAcceptExtensionsForTypes(
|
|
59
117
|
fileAcceptTypes,
|
|
60
|
-
|
|
118
|
+
migrated.fileAcceptExtensions,
|
|
61
119
|
),
|
|
62
|
-
filePlaceholderIcon: normalizeFilePlaceholderIcon(
|
|
63
|
-
fileMinCount: type === 'file' ? normalizeFileUploadCount(
|
|
64
|
-
fileMaxCount: type === 'file' ? normalizeFileUploadCount(
|
|
65
|
-
defaultValue: normalizeDefaultValue(type,
|
|
66
|
-
options: Array.isArray(
|
|
67
|
-
?
|
|
120
|
+
filePlaceholderIcon: normalizeFilePlaceholderIcon(migrated.filePlaceholderIcon),
|
|
121
|
+
fileMinCount: type === 'file' ? normalizeFileUploadCount(migrated.fileMinCount, 1) : undefined,
|
|
122
|
+
fileMaxCount: type === 'file' ? normalizeFileUploadCount(migrated.fileMaxCount, 1) : undefined,
|
|
123
|
+
defaultValue: normalizeDefaultValue(type, migrated.defaultValue),
|
|
124
|
+
options: Array.isArray(migrated.options)
|
|
125
|
+
? migrated.options.map((opt, index) => ({
|
|
68
126
|
value: opt.value?.trim() || `option_${index + 1}`,
|
|
69
127
|
label: opt.label?.trim() || `选项 ${index + 1}`,
|
|
70
128
|
}))
|
|
71
129
|
: undefined,
|
|
130
|
+
resumeEnableRefresh:
|
|
131
|
+
type === 'resume_multiselect' ? migrated.resumeEnableRefresh !== false : undefined,
|
|
132
|
+
resumeFilter:
|
|
133
|
+
type === 'resume_multiselect' ? normalizeResumeFilter(migrated.resumeFilter) : undefined,
|
|
134
|
+
caseEnableRefresh:
|
|
135
|
+
type === 'case_multiselect' ? migrated.caseEnableRefresh !== false : undefined,
|
|
136
|
+
caseFilter:
|
|
137
|
+
type === 'case_multiselect' ? normalizeCaseFilter(migrated.caseFilter) : undefined,
|
|
72
138
|
}
|
|
73
139
|
}
|
|
74
140
|
|
|
@@ -135,6 +201,23 @@ export function createEmptyBlock(type: FormBlockType): FormBlock {
|
|
|
135
201
|
block.fileMaxCount = 1
|
|
136
202
|
}
|
|
137
203
|
|
|
204
|
+
if (type === 'resume_multiselect') {
|
|
205
|
+
block.resumeEnableRefresh = true
|
|
206
|
+
block.resumeFilter = {
|
|
207
|
+
names: [],
|
|
208
|
+
agentUniqueIds: [],
|
|
209
|
+
resumeUniqueIds: [],
|
|
210
|
+
pageSize: 20,
|
|
211
|
+
}
|
|
212
|
+
block.defaultValue = []
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (type === 'case_multiselect') {
|
|
216
|
+
block.caseEnableRefresh = true
|
|
217
|
+
block.caseFilter = { flowUniqueIds: [], pageSize: 20 }
|
|
218
|
+
block.defaultValue = []
|
|
219
|
+
}
|
|
220
|
+
|
|
138
221
|
return block
|
|
139
222
|
}
|
|
140
223
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { A2uiComponentNode, FormBlock } from '../../types/index'
|
|
2
|
+
import type { BlockAdapterContext, BlockToComponentResult } from '../types'
|
|
3
|
+
|
|
4
|
+
function asLiteral(value: unknown): string | undefined {
|
|
5
|
+
return typeof value === 'string' ? value : undefined
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function readCaseFilterFromNode(cf: Record<string, unknown>) {
|
|
9
|
+
const pageSizeRaw = typeof cf.pageSize === 'number' ? cf.pageSize : Number(cf.pageSize)
|
|
10
|
+
const agentKind =
|
|
11
|
+
typeof cf.agentKind === 'string' && cf.agentKind.trim()
|
|
12
|
+
? cf.agentKind.trim()
|
|
13
|
+
: undefined
|
|
14
|
+
const agentUniqueId =
|
|
15
|
+
typeof cf.agentUniqueId === 'string' && cf.agentUniqueId.trim()
|
|
16
|
+
? cf.agentUniqueId.trim()
|
|
17
|
+
: undefined
|
|
18
|
+
const flowType =
|
|
19
|
+
typeof cf.flowType === 'string' && cf.flowType.trim()
|
|
20
|
+
? cf.flowType.trim()
|
|
21
|
+
: undefined
|
|
22
|
+
const category =
|
|
23
|
+
typeof cf.category === 'string' && cf.category.trim()
|
|
24
|
+
? cf.category.trim()
|
|
25
|
+
: undefined
|
|
26
|
+
const flowUniqueIds = Array.isArray(cf.flowUniqueIds)
|
|
27
|
+
? cf.flowUniqueIds.map(String).filter(Boolean)
|
|
28
|
+
: []
|
|
29
|
+
return {
|
|
30
|
+
agentKind,
|
|
31
|
+
agentUniqueId,
|
|
32
|
+
flowType,
|
|
33
|
+
category,
|
|
34
|
+
flowUniqueIds,
|
|
35
|
+
pageSize:
|
|
36
|
+
Number.isFinite(pageSizeRaw) && pageSizeRaw >= 1 && pageSizeRaw <= 100
|
|
37
|
+
? Math.floor(pageSizeRaw)
|
|
38
|
+
: 20,
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function caseMultiselectToComponent(
|
|
43
|
+
block: FormBlock,
|
|
44
|
+
ctx: BlockAdapterContext,
|
|
45
|
+
): BlockToComponentResult {
|
|
46
|
+
const { id, label, path, withData } = ctx
|
|
47
|
+
return withData({
|
|
48
|
+
id,
|
|
49
|
+
component: 'SkoponCaseSelect',
|
|
50
|
+
label,
|
|
51
|
+
placeholder: block.placeholder ?? '',
|
|
52
|
+
help: block.help ?? '',
|
|
53
|
+
enableRefresh: block.caseEnableRefresh !== false,
|
|
54
|
+
caseFilter: {
|
|
55
|
+
agentKind: block.caseFilter?.agentKind,
|
|
56
|
+
agentUniqueId: block.caseFilter?.agentUniqueId,
|
|
57
|
+
flowType: block.caseFilter?.flowType,
|
|
58
|
+
category: block.caseFilter?.category,
|
|
59
|
+
flowUniqueIds: block.caseFilter?.flowUniqueIds ?? [],
|
|
60
|
+
pageSize: block.caseFilter?.pageSize ?? 20,
|
|
61
|
+
},
|
|
62
|
+
value: { path },
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function caseMultiselectFromComponent(
|
|
67
|
+
node: A2uiComponentNode,
|
|
68
|
+
base: (type: 'case_multiselect') => FormBlock,
|
|
69
|
+
helpers: {
|
|
70
|
+
asLiteral: (value: unknown) => string | undefined
|
|
71
|
+
nameFromValue: (value: unknown) => string
|
|
72
|
+
},
|
|
73
|
+
): FormBlock {
|
|
74
|
+
const name = helpers.nameFromValue(node.value)
|
|
75
|
+
const block: FormBlock = {
|
|
76
|
+
...base('case_multiselect'),
|
|
77
|
+
name,
|
|
78
|
+
caseEnableRefresh: node.enableRefresh !== false,
|
|
79
|
+
}
|
|
80
|
+
const placeholder = helpers.asLiteral(node.placeholder)
|
|
81
|
+
if (placeholder) block.placeholder = placeholder
|
|
82
|
+
const help = helpers.asLiteral(node.help)
|
|
83
|
+
if (help) block.help = help
|
|
84
|
+
if (node.caseFilter && typeof node.caseFilter === 'object') {
|
|
85
|
+
block.caseFilter = readCaseFilterFromNode(node.caseFilter as Record<string, unknown>)
|
|
86
|
+
}
|
|
87
|
+
return block
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export { asLiteral }
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { BlockAdapterPlugin } from '../types'
|
|
2
|
+
import {
|
|
3
|
+
caseMultiselectFromComponent,
|
|
4
|
+
caseMultiselectToComponent,
|
|
5
|
+
} from './adapter'
|
|
6
|
+
import { SkoponCaseSelectImpl } from '../../catalog/skoponCaseSelect'
|
|
7
|
+
|
|
8
|
+
export const caseMultiselectAdapter: BlockAdapterPlugin = {
|
|
9
|
+
type: 'case_multiselect',
|
|
10
|
+
componentName: 'SkoponCaseSelect',
|
|
11
|
+
toComponent: caseMultiselectToComponent,
|
|
12
|
+
fromComponent: caseMultiselectFromComponent,
|
|
13
|
+
catalogComponents: [SkoponCaseSelectImpl],
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SkoponCaseSelectImpl } from '../../catalog/skoponCaseSelect'
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { FormBlockType } from '../types/index'
|
|
2
|
+
import type { BlockAdapterPlugin } from './types'
|
|
3
|
+
import { caseMultiselectAdapter } from './case_multiselect'
|
|
4
|
+
import { resumeMultiselectAdapter } from './resume_multiselect'
|
|
5
|
+
|
|
6
|
+
const adapters: BlockAdapterPlugin[] = [resumeMultiselectAdapter, caseMultiselectAdapter]
|
|
7
|
+
|
|
8
|
+
const adapterByType = new Map<FormBlockType, BlockAdapterPlugin>(
|
|
9
|
+
adapters.map((adapter) => [adapter.type, adapter]),
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
const adapterByComponent = new Map<string, BlockAdapterPlugin>(
|
|
13
|
+
adapters.map((adapter) => [adapter.componentName, adapter]),
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
export function getBlockTypeAdapter(type: FormBlockType): BlockAdapterPlugin | undefined {
|
|
17
|
+
return adapterByType.get(type)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function getComponentAdapter(componentName: string): BlockAdapterPlugin | undefined {
|
|
21
|
+
return adapterByComponent.get(componentName)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function getAllBlockAdapters(): BlockAdapterPlugin[] {
|
|
25
|
+
return adapters
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function getRegisteredCatalogComponents() {
|
|
29
|
+
return adapters.flatMap((adapter) => adapter.catalogComponents)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function getRegisteredCatalogComponentNames(): string[] {
|
|
33
|
+
return adapters.map((adapter) => adapter.componentName)
|
|
34
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { A2uiComponentNode, FormBlock } from '../../types/index'
|
|
2
|
+
import type { BlockAdapterContext, BlockToComponentResult } from '../types'
|
|
3
|
+
|
|
4
|
+
function asLiteral(value: unknown): string | undefined {
|
|
5
|
+
return typeof value === 'string' ? value : undefined
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function resumeMultiselectToComponent(
|
|
9
|
+
block: FormBlock,
|
|
10
|
+
ctx: BlockAdapterContext,
|
|
11
|
+
): BlockToComponentResult {
|
|
12
|
+
const { id, label, path, withData } = ctx
|
|
13
|
+
return withData({
|
|
14
|
+
id,
|
|
15
|
+
component: 'SkoponResumeSelect',
|
|
16
|
+
label,
|
|
17
|
+
placeholder: block.placeholder ?? '',
|
|
18
|
+
help: block.help ?? '',
|
|
19
|
+
enableRefresh: block.resumeEnableRefresh !== false,
|
|
20
|
+
resumeFilter: {
|
|
21
|
+
names: block.resumeFilter?.names ?? [],
|
|
22
|
+
agentUniqueIds: block.resumeFilter?.agentUniqueIds ?? [],
|
|
23
|
+
resumeUniqueIds: block.resumeFilter?.resumeUniqueIds ?? [],
|
|
24
|
+
pageSize: block.resumeFilter?.pageSize ?? 20,
|
|
25
|
+
},
|
|
26
|
+
value: { path },
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function resumeMultiselectFromComponent(
|
|
31
|
+
node: A2uiComponentNode,
|
|
32
|
+
base: (type: 'resume_multiselect') => FormBlock,
|
|
33
|
+
helpers: { asLiteral: (value: unknown) => string | undefined; nameFromValue: (value: unknown) => string },
|
|
34
|
+
): FormBlock {
|
|
35
|
+
const name = helpers.nameFromValue(node.value)
|
|
36
|
+
const block: FormBlock = {
|
|
37
|
+
...base('resume_multiselect'),
|
|
38
|
+
name,
|
|
39
|
+
resumeEnableRefresh: node.enableRefresh !== false,
|
|
40
|
+
}
|
|
41
|
+
const placeholder = helpers.asLiteral(node.placeholder)
|
|
42
|
+
if (placeholder) block.placeholder = placeholder
|
|
43
|
+
const help = helpers.asLiteral(node.help)
|
|
44
|
+
if (help) block.help = help
|
|
45
|
+
if (node.resumeFilter && typeof node.resumeFilter === 'object') {
|
|
46
|
+
const rf = node.resumeFilter as Record<string, unknown>
|
|
47
|
+
block.resumeFilter = {
|
|
48
|
+
names: Array.isArray(rf.names) ? rf.names.map(String) : [],
|
|
49
|
+
agentUniqueIds: Array.isArray(rf.agentUniqueIds) ? rf.agentUniqueIds.map(String) : [],
|
|
50
|
+
resumeUniqueIds: Array.isArray(rf.resumeUniqueIds) ? rf.resumeUniqueIds.map(String) : [],
|
|
51
|
+
pageSize: typeof rf.pageSize === 'number' ? rf.pageSize : 20,
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return block
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export { asLiteral }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SkoponResumeSelectImpl } from '../../catalog/skoponResumeSelect'
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { BlockAdapterPlugin } from '../types'
|
|
2
|
+
import {
|
|
3
|
+
resumeMultiselectFromComponent,
|
|
4
|
+
resumeMultiselectToComponent,
|
|
5
|
+
} from './adapter'
|
|
6
|
+
import { SkoponResumeSelectImpl } from './catalog'
|
|
7
|
+
|
|
8
|
+
export const resumeMultiselectAdapter: BlockAdapterPlugin = {
|
|
9
|
+
type: 'resume_multiselect',
|
|
10
|
+
componentName: 'SkoponResumeSelect',
|
|
11
|
+
toComponent: resumeMultiselectToComponent,
|
|
12
|
+
fromComponent: resumeMultiselectFromComponent,
|
|
13
|
+
catalogComponents: [SkoponResumeSelectImpl],
|
|
14
|
+
}
|