@flowgram.ai/form-materials 0.1.0-alpha.11 → 0.1.0-alpha.12

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 (121) hide show
  1. package/bin/index.ts +11 -5
  2. package/bin/materials.ts +10 -1
  3. package/dist/esm/index.js +1917 -1371
  4. package/dist/esm/index.js.map +1 -1
  5. package/dist/index.d.mts +320 -113
  6. package/dist/index.d.ts +320 -113
  7. package/dist/index.js +2023 -1484
  8. package/dist/index.js.map +1 -1
  9. package/package.json +5 -4
  10. package/src/components/assign-row/components/blur-input.tsx +27 -0
  11. package/src/components/assign-row/config.json +11 -0
  12. package/src/components/assign-row/index.tsx +84 -0
  13. package/src/components/assign-row/types.ts +25 -0
  14. package/src/components/assign-rows/config.json +11 -0
  15. package/src/components/assign-rows/index.tsx +59 -0
  16. package/src/components/batch-outputs/config.json +2 -1
  17. package/src/components/batch-outputs/index.tsx +4 -12
  18. package/src/components/batch-variable-selector/config.json +6 -2
  19. package/src/components/batch-variable-selector/index.tsx +1 -1
  20. package/src/components/code-editor/index.tsx +7 -0
  21. package/src/components/code-editor/language-features.ts +22 -1
  22. package/src/components/code-editor/theme/light.ts +1 -1
  23. package/src/components/code-editor-mini/config.json +7 -0
  24. package/src/components/code-editor-mini/index.tsx +31 -0
  25. package/src/components/condition-row/config.json +10 -2
  26. package/src/components/condition-row/constants.ts +6 -8
  27. package/src/components/condition-row/hooks/useOp.tsx +3 -1
  28. package/src/components/condition-row/hooks/useRule.ts +2 -2
  29. package/src/components/condition-row/index.tsx +2 -1
  30. package/src/components/condition-row/types.ts +3 -1
  31. package/src/components/constant-input/config.json +6 -3
  32. package/src/components/constant-input/index.tsx +18 -62
  33. package/src/components/constant-input/types.ts +6 -9
  34. package/src/components/display-flow-value/config.json +8 -0
  35. package/src/components/display-flow-value/index.tsx +59 -0
  36. package/src/components/display-inputs-values/config.json +9 -0
  37. package/src/components/display-inputs-values/index.tsx +27 -0
  38. package/src/components/display-inputs-values/styles.ts +12 -0
  39. package/src/components/display-outputs/config.json +10 -0
  40. package/src/components/display-outputs/index.tsx +64 -0
  41. package/src/components/display-outputs/styles.ts +12 -0
  42. package/src/components/display-schema-tag/config.json +10 -0
  43. package/src/components/display-schema-tag/index.tsx +44 -0
  44. package/src/components/display-schema-tag/styles.ts +28 -0
  45. package/src/components/display-schema-tree/config.json +11 -0
  46. package/src/components/display-schema-tree/index.tsx +74 -0
  47. package/src/components/display-schema-tree/styles.tsx +90 -0
  48. package/src/components/dynamic-value-input/config.json +11 -2
  49. package/src/components/dynamic-value-input/hooks.ts +53 -0
  50. package/src/components/dynamic-value-input/index.tsx +64 -13
  51. package/src/components/dynamic-value-input/styles.tsx +28 -2
  52. package/src/components/index.ts +9 -0
  53. package/src/components/inputs-values/components/blur-input.tsx +27 -0
  54. package/src/components/inputs-values/config.json +13 -0
  55. package/src/components/inputs-values/index.tsx +73 -0
  56. package/src/components/inputs-values/styles.tsx +19 -0
  57. package/src/components/inputs-values/types.ts +22 -0
  58. package/src/components/json-schema-editor/config.json +2 -2
  59. package/src/components/json-schema-editor/default-value.tsx +1 -1
  60. package/src/components/json-schema-editor/hooks.tsx +1 -1
  61. package/src/components/json-schema-editor/index.tsx +15 -2
  62. package/src/components/json-schema-editor/types.ts +1 -1
  63. package/src/components/prompt-editor-with-inputs/inputs-picker.tsx +1 -1
  64. package/src/components/prompt-editor-with-variables/extensions/variable-tag.tsx +6 -3
  65. package/src/components/type-selector/config.json +6 -2
  66. package/src/components/type-selector/index.tsx +55 -12
  67. package/src/components/variable-selector/config.json +6 -2
  68. package/src/components/variable-selector/index.tsx +34 -13
  69. package/src/components/variable-selector/styles.tsx +18 -8
  70. package/src/components/variable-selector/use-variable-tree.tsx +19 -22
  71. package/src/effects/index.ts +3 -1
  72. package/src/effects/listen-ref-schema-change/config.json +10 -0
  73. package/src/effects/listen-ref-schema-change/index.ts +56 -0
  74. package/src/effects/listen-ref-value-change/config.json +9 -0
  75. package/src/effects/listen-ref-value-change/index.ts +53 -0
  76. package/src/effects/provide-json-schema-outputs/config.json +4 -5
  77. package/src/effects/provide-json-schema-outputs/index.ts +1 -3
  78. package/src/effects/sync-variable-title/index.ts +1 -0
  79. package/src/effects/validate-when-variable-sync/config.json +5 -0
  80. package/src/effects/validate-when-variable-sync/index.ts +35 -0
  81. package/src/form-plugins/index.ts +3 -1
  82. package/src/form-plugins/infer-assign-plugin/config.json +7 -0
  83. package/src/form-plugins/infer-assign-plugin/index.ts +90 -0
  84. package/src/form-plugins/infer-inputs-plugin/config.json +9 -0
  85. package/src/form-plugins/infer-inputs-plugin/index.ts +108 -0
  86. package/src/hooks/index.tsx +6 -0
  87. package/src/hooks/use-object-list/config.json +8 -0
  88. package/src/hooks/use-object-list/index.tsx +136 -0
  89. package/src/index.ts +3 -1
  90. package/src/{typings/json-schema → plugins/disable-declaration-plugin}/config.json +1 -1
  91. package/src/plugins/disable-declaration-plugin/create-disable-declaration-plugin.ts +31 -0
  92. package/src/plugins/disable-declaration-plugin/index.tsx +6 -0
  93. package/src/plugins/index.ts +7 -0
  94. package/src/plugins/json-schema-preset/config.json +9 -0
  95. package/src/plugins/json-schema-preset/create-type-preset-plugin.tsx +28 -0
  96. package/src/plugins/json-schema-preset/index.tsx +41 -0
  97. package/src/plugins/json-schema-preset/manager.ts +18 -0
  98. package/src/plugins/json-schema-preset/type-definition/array.tsx +24 -0
  99. package/src/plugins/json-schema-preset/type-definition/boolean.tsx +32 -0
  100. package/src/plugins/json-schema-preset/type-definition/index.tsx +24 -0
  101. package/src/plugins/json-schema-preset/type-definition/integer.tsx +24 -0
  102. package/src/plugins/json-schema-preset/type-definition/number.tsx +24 -0
  103. package/src/plugins/json-schema-preset/type-definition/object.tsx +24 -0
  104. package/src/plugins/json-schema-preset/type-definition/string.tsx +18 -0
  105. package/src/{utils → shared}/index.ts +0 -1
  106. package/src/typings/flow-value/config.json +3 -1
  107. package/src/typings/flow-value/index.ts +11 -0
  108. package/src/typings/index.ts +0 -1
  109. package/src/validate/index.tsx +6 -0
  110. package/src/validate/validate-flow-value/config.json +7 -0
  111. package/src/validate/validate-flow-value/index.tsx +73 -0
  112. package/src/components/batch-outputs/use-list.ts +0 -86
  113. package/src/components/type-selector/constants.tsx +0 -364
  114. package/src/effects/provide-batch-outputs/config.json +0 -5
  115. package/src/effects/provide-batch-outputs/index.ts +0 -38
  116. package/src/typings/json-schema/index.ts +0 -36
  117. package/src/utils/json-schema/config.json +0 -5
  118. package/src/utils/json-schema/index.ts +0 -180
  119. /package/src/{utils → shared}/format-legacy-refs/config.json +0 -0
  120. /package/src/{utils → shared}/format-legacy-refs/index.ts +0 -0
  121. /package/src/{utils → shared}/format-legacy-refs/readme.md +0 -0
@@ -5,13 +5,14 @@
5
5
 
6
6
  import React, { useMemo } from 'react';
7
7
 
8
+ import { IJsonSchema } from '@flowgram.ai/json-schema';
8
9
  import { TriggerRenderProps } from '@douyinfe/semi-ui/lib/es/treeSelect';
9
10
  import { TreeNodeData } from '@douyinfe/semi-ui/lib/es/tree';
11
+ import { Popover } from '@douyinfe/semi-ui';
10
12
  import { IconChevronDownStroked, IconIssueStroked } from '@douyinfe/semi-icons';
11
13
 
12
- import { IJsonSchema } from '../../typings/json-schema';
13
14
  import { useVariableTree } from './use-variable-tree';
14
- import { UIRootTitle, UITag, UITreeSelect, UIVarName } from './styles';
15
+ import { UIPopoverContent, UIRootTitle, UITag, UITreeSelect, UIVarName } from './styles';
15
16
 
16
17
  interface PropTypes {
17
18
  value?: string[];
@@ -93,23 +94,43 @@ export const VariableSelector = ({
93
94
  );
94
95
  }
95
96
 
97
+ const rootIcon = renderIcon(_option.rootMeta?.icon || _option?.icon);
98
+
99
+ const rootTitle = (
100
+ <UIRootTitle>
101
+ {_option.rootMeta?.title
102
+ ? `${_option.rootMeta?.title} ${_option.isRoot ? '' : '-'} `
103
+ : null}
104
+ </UIRootTitle>
105
+ );
106
+
96
107
  return (
97
- <UITag
98
- prefixIcon={renderIcon(_option.rootMeta?.icon || _option?.icon)}
99
- closable={!readonly}
100
- onClose={() => onChange(undefined)}
101
- >
102
- <UIRootTitle>
103
- {_option.rootMeta?.title ? `${_option.rootMeta?.title} -` : null}
104
- </UIRootTitle>
105
- <UIVarName>{_option.label}</UIVarName>
106
- </UITag>
108
+ <div>
109
+ <Popover
110
+ content={
111
+ <UIPopoverContent>
112
+ {rootIcon}
113
+ {rootTitle}
114
+ <UIVarName>{_option.keyPath.slice(1).join('.')}</UIVarName>
115
+ </UIPopoverContent>
116
+ }
117
+ >
118
+ <UITag
119
+ prefixIcon={rootIcon}
120
+ closable={!readonly}
121
+ onClose={() => onChange(undefined)}
122
+ >
123
+ {rootTitle}
124
+ {!_option.isRoot && <UIVarName $inSelector>{_option.label}</UIVarName>}
125
+ </UITag>
126
+ </Popover>
127
+ </div>
107
128
  );
108
129
  }}
109
130
  showClear={false}
110
131
  arrowIcon={<IconChevronDownStroked size="small" />}
111
132
  triggerRender={triggerRender}
112
- placeholder={config?.placeholder ?? 'Select Variable...'}
133
+ placeholder={config?.placeholder ?? 'Select Variable'}
113
134
  />
114
135
  </>
115
136
  );
@@ -3,7 +3,7 @@
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
5
 
6
- import styled from 'styled-components';
6
+ import styled, { css } from 'styled-components';
7
7
  import { Tag, TreeSelect } from '@douyinfe/semi-ui';
8
8
 
9
9
  export const UIRootTitle = styled.div`
@@ -15,11 +15,16 @@ export const UIRootTitle = styled.div`
15
15
  color: var(--semi-color-text-2);
16
16
  `;
17
17
 
18
- export const UIVarName = styled.div`
18
+ export const UIVarName = styled.div<{ $inSelector?: boolean }>`
19
19
  overflow: hidden;
20
20
  text-overflow: ellipsis;
21
21
  white-space: nowrap;
22
- min-width: 50%;
22
+
23
+ ${({ $inSelector }) =>
24
+ $inSelector &&
25
+ css`
26
+ min-width: 50%;
27
+ `}
23
28
  `;
24
29
 
25
30
  export const UITag = styled(Tag)`
@@ -34,18 +39,15 @@ export const UITag = styled(Tag)`
34
39
 
35
40
  &.semi-tag {
36
41
  margin: 0;
42
+ height: 22px;
37
43
  }
38
44
  `;
39
45
 
40
46
  export const UITreeSelect = styled(TreeSelect)<{ $error?: boolean }>`
41
47
  outline: ${({ $error }) => ($error ? '1px solid red' : 'none')};
42
48
 
43
- height: 22px;
44
- min-height: 22px;
45
- line-height: 22px;
46
-
47
49
  & .semi-tree-select-selection {
48
- padding: 0 2px;
50
+ padding: 0px;
49
51
  height: 22px;
50
52
  }
51
53
 
@@ -57,3 +59,11 @@ export const UITreeSelect = styled(TreeSelect)<{ $error?: boolean }>`
57
59
  padding-left: 10px;
58
60
  }
59
61
  `;
62
+
63
+ export const UIPopoverContent = styled.div`
64
+ padding: 10px;
65
+ display: inline-flex;
66
+ align-items: center;
67
+ justify-content: flex-start;
68
+ white-space: nowrap;
69
+ `;
@@ -5,22 +5,27 @@
5
5
 
6
6
  import React, { useCallback } from 'react';
7
7
 
8
+ import { IJsonSchema, JsonSchemaUtils } from '@flowgram.ai/json-schema';
8
9
  import { ASTMatch, BaseVariableField, useAvailableVariables } from '@flowgram.ai/editor';
9
10
  import { TreeNodeData } from '@douyinfe/semi-ui/lib/es/tree';
10
11
  import { Icon } from '@douyinfe/semi-ui';
11
12
 
12
- import { ArrayIcons, VariableTypeIcons } from '../type-selector/constants';
13
- import { JsonSchemaUtils } from '../../utils/json-schema';
14
- import { IJsonSchema } from '../../typings/json-schema';
13
+ import { useTypeManager } from '../../plugins';
15
14
 
16
- type VariableField = BaseVariableField<{ icon?: string | JSX.Element; title?: string }>;
15
+ type VariableField = BaseVariableField<{
16
+ icon?: string | JSX.Element;
17
+ title?: string;
18
+ disabled?: boolean;
19
+ }>;
17
20
 
18
21
  export function useVariableTree(params: {
19
22
  includeSchema?: IJsonSchema | IJsonSchema[];
20
23
  excludeSchema?: IJsonSchema | IJsonSchema[];
24
+ customSkip?: (variable: VariableField) => boolean;
21
25
  }): TreeNodeData[] {
22
- const { includeSchema, excludeSchema } = params;
26
+ const { includeSchema, excludeSchema, customSkip } = params;
23
27
 
28
+ const typeManager = useTypeManager();
24
29
  const variables = useAvailableVariables();
25
30
 
26
31
  const getVariableTypeIcon = useCallback((variable: VariableField) => {
@@ -32,22 +37,9 @@ export function useVariableTree(params: {
32
37
  return variable.meta.icon;
33
38
  }
34
39
 
35
- const _type = variable.type;
40
+ const schema = JsonSchemaUtils.astToSchema(variable.type, { drilldownObject: false });
36
41
 
37
- if (ASTMatch.isArray(_type)) {
38
- return (
39
- <Icon
40
- size="small"
41
- svg={ArrayIcons[_type.items?.kind.toLowerCase()] || VariableTypeIcons.array}
42
- />
43
- );
44
- }
45
-
46
- if (ASTMatch.isCustomType(_type)) {
47
- return <Icon size="small" svg={VariableTypeIcons[_type.typeName.toLowerCase()]} />;
48
- }
49
-
50
- return <Icon size="small" svg={VariableTypeIcons[variable.type?.kind.toLowerCase()]} />;
42
+ return <Icon size="small" svg={typeManager.getDisplayIcon(schema || {})} />;
51
43
  }, []);
52
44
 
53
45
  const renderVariable = (
@@ -77,8 +69,12 @@ export function useVariableTree(params: {
77
69
  const isSchemaExclude = excludeSchema
78
70
  ? JsonSchemaUtils.isASTMatchSchema(type, excludeSchema)
79
71
  : false;
72
+ const isCustomSkip = customSkip ? customSkip(variable) : false;
73
+
74
+ // disabled in meta when created
75
+ const isMetaDisabled = variable.meta?.disabled;
80
76
 
81
- const isSchemaMatch = isSchemaInclude && !isSchemaExclude;
77
+ const isSchemaMatch = isSchemaInclude && !isSchemaExclude && !isCustomSkip && !isMetaDisabled;
82
78
 
83
79
  // If not match, and no children, return null
84
80
  if (!isSchemaMatch && !children?.length) {
@@ -93,7 +89,8 @@ export function useVariableTree(params: {
93
89
  icon: getVariableTypeIcon(variable),
94
90
  children,
95
91
  disabled: !isSchemaMatch,
96
- rootMeta: parentFields[0]?.meta,
92
+ rootMeta: parentFields[0]?.meta || variable.meta,
93
+ isRoot: !parentFields?.length,
97
94
  };
98
95
  };
99
96
 
@@ -4,7 +4,9 @@
4
4
  */
5
5
 
6
6
  export * from './provide-batch-input';
7
- export * from './provide-batch-outputs';
8
7
  export * from './auto-rename-ref';
9
8
  export * from './provide-json-schema-outputs';
10
9
  export * from './sync-variable-title';
10
+ export * from './validate-when-variable-sync';
11
+ export * from './listen-ref-value-change';
12
+ export * from './listen-ref-schema-change';
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "listen-ref-schema-change",
3
+ "depMaterials": [
4
+ "flow-value"
5
+ ],
6
+ "depPackages": [
7
+ "lodash",
8
+ "@flowgram.ai/json-schema"
9
+ ]
10
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { IJsonSchema, JsonSchemaUtils } from '@flowgram.ai/json-schema';
7
+ import {
8
+ BaseType,
9
+ DataEvent,
10
+ Effect,
11
+ EffectFuncProps,
12
+ EffectOptions,
13
+ getNodeScope,
14
+ } from '@flowgram.ai/editor';
15
+
16
+ import { IFlowRefValue } from '../../typings';
17
+
18
+ /**
19
+ * Example:
20
+ * const formMeta = {
21
+ * effect: {
22
+ * 'inputsValues.*': listenRefSchemaChange(({ name, schema, form }) => {
23
+ * form.setValueIn(`${name}.schema`, schema);
24
+ * })
25
+ * }
26
+ * }
27
+ * @param cb
28
+ * @returns
29
+ */
30
+ export const listenRefSchemaChange = (
31
+ cb: (props: EffectFuncProps<IFlowRefValue> & { schema?: IJsonSchema }) => void
32
+ ): EffectOptions[] => [
33
+ {
34
+ event: DataEvent.onValueInitOrChange,
35
+ effect: ((params) => {
36
+ const { context, value } = params;
37
+
38
+ if (value?.type !== 'ref') {
39
+ return () => null;
40
+ }
41
+
42
+ const disposable = getNodeScope(context.node).available.trackByKeyPath<BaseType | undefined>(
43
+ value?.content || [],
44
+ (_type) => {
45
+ cb({ ...params, schema: JsonSchemaUtils.astToSchema(_type) });
46
+ },
47
+ {
48
+ selector: (_v) => _v?.type,
49
+ }
50
+ );
51
+ return () => {
52
+ disposable.dispose();
53
+ };
54
+ }) as Effect,
55
+ },
56
+ ];
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "listen-ref-value-change",
3
+ "depMaterials": [
4
+ "flow-value"
5
+ ],
6
+ "depPackages": [
7
+ "lodash"
8
+ ]
9
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import {
7
+ BaseVariableField,
8
+ DataEvent,
9
+ Effect,
10
+ EffectFuncProps,
11
+ EffectOptions,
12
+ getNodeScope,
13
+ } from '@flowgram.ai/editor';
14
+
15
+ import { IFlowRefValue } from '../../typings';
16
+
17
+ /**
18
+ * Example:
19
+ * const formMeta = {
20
+ * effect: {
21
+ * 'inputsValues.*': listenRefValueChange(({ name, variable, form }) => {
22
+ * const schema = JsonSchemaUtils.astToSchema(variable?.type);
23
+ * form.setValueIn(`${name}.schema`, schema);
24
+ * })
25
+ * }
26
+ * }
27
+ * @param cb
28
+ * @returns
29
+ */
30
+ export const listenRefValueChange = (
31
+ cb: (props: EffectFuncProps<IFlowRefValue> & { variable?: BaseVariableField }) => void
32
+ ): EffectOptions[] => [
33
+ {
34
+ event: DataEvent.onValueInitOrChange,
35
+ effect: ((params) => {
36
+ const { context, value } = params;
37
+
38
+ if (value?.type !== 'ref') {
39
+ return () => null;
40
+ }
41
+
42
+ const disposable = getNodeScope(context.node).available.trackByKeyPath(
43
+ value?.content || [],
44
+ (v) => {
45
+ cb({ ...params, variable: v });
46
+ }
47
+ );
48
+ return () => {
49
+ disposable.dispose();
50
+ };
51
+ }) as Effect,
52
+ },
53
+ ];
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "provide-json-schema-outputs",
3
- "depMaterials": [
4
- "typings/json-schema",
5
- "utils/json-schema"
6
- ],
7
- "depPackages": []
3
+ "depMaterials": [],
4
+ "depPackages": [
5
+ "@flowgram.ai/json-schema"
6
+ ]
8
7
  }
@@ -3,6 +3,7 @@
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
5
 
6
+ import { JsonSchemaUtils, IJsonSchema } from '@flowgram.ai/json-schema';
6
7
  import {
7
8
  ASTFactory,
8
9
  EffectOptions,
@@ -11,9 +12,6 @@ import {
11
12
  getNodeForm,
12
13
  } from '@flowgram.ai/editor';
13
14
 
14
- import { JsonSchemaUtils } from '../../utils';
15
- import { IJsonSchema } from '../../typings';
16
-
17
15
  export const provideJsonSchemaOutputs: EffectOptions[] = createEffectFromVariableProvider({
18
16
  parse: (value: IJsonSchema, ctx) => [
19
17
  ASTFactory.createVariableDeclaration({
@@ -18,6 +18,7 @@ export const syncVariableTitle: EffectOptions[] = [
18
18
  context.node.getData(FlowNodeVariableData).allScopes.forEach((_scope) => {
19
19
  _scope.output.variables.forEach((_var) => {
20
20
  _var.updateMeta({
21
+ ...(_var.meta || {}),
21
22
  title: value || context.node.id,
22
23
  icon: context.node.getNodeRegistry<FlowNodeRegistry>().info?.icon,
23
24
  });
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "validate-when-variable-sync",
3
+ "depMaterials": [],
4
+ "depPackages": []
5
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { isEmpty } from 'lodash';
7
+ import {
8
+ DataEvent,
9
+ Effect,
10
+ EffectOptions,
11
+ getNodeScope,
12
+ getNodePrivateScope,
13
+ } from '@flowgram.ai/editor';
14
+
15
+ export const validateWhenVariableSync = ({
16
+ scope,
17
+ }: {
18
+ scope?: 'private' | 'public';
19
+ } = {}): EffectOptions[] => [
20
+ {
21
+ event: DataEvent.onValueInit,
22
+ effect: (({ context, form }) => {
23
+ const nodeScope =
24
+ scope === 'private' ? getNodePrivateScope(context.node) : getNodeScope(context.node);
25
+
26
+ const disposable = nodeScope.available.onListOrAnyVarChange(() => {
27
+ if (!isEmpty(form.state.errors)) {
28
+ form.validate();
29
+ }
30
+ });
31
+
32
+ return () => disposable.dispose();
33
+ }) as Effect,
34
+ },
35
+ ];
@@ -3,4 +3,6 @@
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
5
 
6
- export { createBatchOutputsFormPlugin } from './batch-outputs-plugin';
6
+ export * from './batch-outputs-plugin';
7
+ export * from './infer-inputs-plugin';
8
+ export * from './infer-assign-plugin';
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "infer-assign-plugin",
3
+ "depMaterials": [
4
+ "flow-value"
5
+ ],
6
+ "depPackages": []
7
+ }
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { set, uniqBy } from 'lodash';
7
+ import { JsonSchemaUtils } from '@flowgram.ai/json-schema';
8
+ import {
9
+ ASTFactory,
10
+ createEffectFromVariableProvider,
11
+ defineFormPluginCreator,
12
+ FlowNodeRegistry,
13
+ getNodeForm,
14
+ getNodeScope,
15
+ } from '@flowgram.ai/editor';
16
+
17
+ import { IFlowRefValue, IFlowValue } from '../../typings';
18
+
19
+ type AssignValueType =
20
+ | {
21
+ operator: 'assign';
22
+ left?: IFlowRefValue;
23
+ right?: IFlowValue;
24
+ }
25
+ | {
26
+ operator: 'declare';
27
+ left?: string;
28
+ right?: IFlowValue;
29
+ };
30
+
31
+ interface InputConfig {
32
+ assignKey: string;
33
+ outputKey: string;
34
+ }
35
+
36
+ export const createInferAssignPlugin = defineFormPluginCreator<InputConfig>({
37
+ onSetupFormMeta({ addFormatOnSubmit, mergeEffect }, { assignKey, outputKey }) {
38
+ if (!assignKey || !outputKey) {
39
+ return;
40
+ }
41
+
42
+ mergeEffect({
43
+ [assignKey]: createEffectFromVariableProvider({
44
+ parse: (value: AssignValueType[], ctx) => {
45
+ const declareRows = uniqBy(
46
+ value.filter((_v) => _v.operator === 'declare' && _v.left && _v.right),
47
+ 'left'
48
+ );
49
+
50
+ return [
51
+ ASTFactory.createVariableDeclaration({
52
+ key: `${ctx.node.id}`,
53
+ meta: {
54
+ title: getNodeForm(ctx.node)?.getValueIn('title'),
55
+ icon: ctx.node.getNodeRegistry<FlowNodeRegistry>().info?.icon,
56
+ },
57
+ type: ASTFactory.createObject({
58
+ properties: declareRows.map((_v) =>
59
+ ASTFactory.createProperty({
60
+ key: _v.left as string,
61
+ type:
62
+ _v.right?.type === 'constant'
63
+ ? JsonSchemaUtils.schemaToAST(_v.right?.schema || {})
64
+ : undefined,
65
+ initializer:
66
+ _v.right?.type === 'ref'
67
+ ? ASTFactory.createKeyPathExpression({
68
+ keyPath: _v.right?.content || [],
69
+ })
70
+ : {},
71
+ })
72
+ ),
73
+ }),
74
+ }),
75
+ ];
76
+ },
77
+ }),
78
+ });
79
+
80
+ addFormatOnSubmit((formData, ctx) => {
81
+ set(
82
+ formData,
83
+ outputKey,
84
+ JsonSchemaUtils.astToSchema(getNodeScope(ctx.node).output.variables?.[0]?.type)
85
+ );
86
+
87
+ return formData;
88
+ });
89
+ },
90
+ });
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "infer-inputs-plugin",
3
+ "depMaterials": [
4
+ "flow-value"
5
+ ],
6
+ "depPackages": [
7
+ "@flowgram.ai/json-schema"
8
+ ]
9
+ }
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { get, set } from 'lodash';
7
+ import { JsonSchemaUtils, IJsonSchema } from '@flowgram.ai/json-schema';
8
+ import {
9
+ defineFormPluginCreator,
10
+ getNodePrivateScope,
11
+ getNodeScope,
12
+ Scope,
13
+ } from '@flowgram.ai/editor';
14
+
15
+ import { IFlowConstantValue, IFlowRefValue, IFlowTemplateValue } from '../../typings';
16
+
17
+ interface InputConfig {
18
+ sourceKey: string;
19
+ targetKey: string;
20
+ scope?: 'private' | 'public';
21
+ }
22
+
23
+ export const createInferInputsPlugin = defineFormPluginCreator<InputConfig>({
24
+ onSetupFormMeta({ addFormatOnSubmit }, { sourceKey, targetKey, scope }) {
25
+ if (!sourceKey || !targetKey) {
26
+ return;
27
+ }
28
+
29
+ addFormatOnSubmit((formData, ctx) => {
30
+ set(
31
+ formData,
32
+ targetKey,
33
+ infer(
34
+ get(formData, sourceKey),
35
+ scope === 'private' ? getNodePrivateScope(ctx.node) : getNodeScope(ctx.node)
36
+ )
37
+ );
38
+
39
+ return formData;
40
+ });
41
+ },
42
+ });
43
+
44
+ function isRef(value: any): value is IFlowRefValue {
45
+ return (
46
+ value?.type === 'ref' && Array.isArray(value?.content) && typeof value?.content[0] === 'string'
47
+ );
48
+ }
49
+
50
+ function isTemplate(value: any): value is IFlowTemplateValue {
51
+ return value?.type === 'template' && typeof value?.content === 'string';
52
+ }
53
+
54
+ function isConstant(value: any): value is IFlowConstantValue {
55
+ return value?.type === 'constant' && typeof value?.content !== 'undefined';
56
+ }
57
+
58
+ const infer = (values: any, scope: Scope): IJsonSchema | undefined => {
59
+ if (typeof values === 'object') {
60
+ if (isConstant(values)) {
61
+ if (values?.schema) {
62
+ return values.schema;
63
+ }
64
+
65
+ if (typeof values.content === 'string') {
66
+ return {
67
+ type: 'string',
68
+ };
69
+ }
70
+
71
+ if (typeof values.content === 'number') {
72
+ return {
73
+ type: 'number',
74
+ };
75
+ }
76
+
77
+ if (typeof values.content === 'boolean') {
78
+ return {
79
+ type: 'boolean',
80
+ };
81
+ }
82
+ }
83
+
84
+ if (isRef(values)) {
85
+ const variable = scope.available.getByKeyPath(values?.content);
86
+ const schema = variable?.type ? JsonSchemaUtils.astToSchema(variable?.type) : undefined;
87
+
88
+ return schema;
89
+ }
90
+
91
+ if (isTemplate(values)) {
92
+ return {
93
+ type: 'string',
94
+ };
95
+ }
96
+
97
+ return {
98
+ type: 'object',
99
+ properties: Object.keys(values).reduce((acc, key) => {
100
+ const schema = infer(values[key], scope);
101
+ if (schema) {
102
+ acc[key] = schema;
103
+ }
104
+ return acc;
105
+ }, {} as Record<string, IJsonSchema>),
106
+ };
107
+ }
108
+ };
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ export * from './use-object-list';
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "use-object-list",
3
+ "depMaterials": [],
4
+ "depPackages": [
5
+ "lodash",
6
+ "nanoid"
7
+ ]
8
+ }