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

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 (133) hide show
  1. package/bin/index.ts +14 -22
  2. package/bin/materials.ts +41 -90
  3. package/bin/project.ts +4 -0
  4. package/bin/utils/import.ts +127 -0
  5. package/bin/utils/traverse-file.ts +60 -0
  6. package/dist/esm/index.js +2073 -1601
  7. package/dist/esm/index.js.map +1 -1
  8. package/dist/index.d.mts +392 -131
  9. package/dist/index.d.ts +392 -131
  10. package/dist/index.js +2175 -1710
  11. package/dist/index.js.map +1 -1
  12. package/package.json +5 -4
  13. package/src/components/assign-row/components/blur-input.tsx +27 -0
  14. package/src/components/assign-row/index.tsx +84 -0
  15. package/src/components/assign-row/types.ts +25 -0
  16. package/src/components/assign-rows/index.tsx +59 -0
  17. package/src/components/batch-outputs/index.tsx +7 -14
  18. package/src/components/batch-outputs/types.ts +1 -1
  19. package/src/components/batch-variable-selector/index.tsx +2 -2
  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/index.tsx +31 -0
  24. package/src/components/condition-row/constants.ts +8 -10
  25. package/src/components/condition-row/hooks/useOp.tsx +15 -9
  26. package/src/components/condition-row/hooks/useRule.ts +9 -5
  27. package/src/components/condition-row/index.tsx +28 -10
  28. package/src/components/condition-row/types.ts +5 -5
  29. package/src/components/constant-input/index.tsx +20 -61
  30. package/src/components/constant-input/types.ts +6 -9
  31. package/src/components/display-flow-value/index.tsx +59 -0
  32. package/src/components/display-inputs-values/index.tsx +28 -0
  33. package/src/components/display-inputs-values/styles.ts +12 -0
  34. package/src/components/display-outputs/index.tsx +65 -0
  35. package/src/components/display-outputs/styles.ts +12 -0
  36. package/src/components/display-schema-tag/index.tsx +45 -0
  37. package/src/components/display-schema-tag/styles.ts +28 -0
  38. package/src/components/display-schema-tree/index.tsx +75 -0
  39. package/src/components/display-schema-tree/styles.tsx +90 -0
  40. package/src/components/dynamic-value-input/hooks.ts +53 -0
  41. package/src/components/dynamic-value-input/index.tsx +74 -19
  42. package/src/components/dynamic-value-input/styles.tsx +28 -2
  43. package/src/components/index.ts +9 -0
  44. package/src/components/inputs-values/components/blur-input.tsx +27 -0
  45. package/src/components/inputs-values/index.tsx +75 -0
  46. package/src/components/inputs-values/styles.tsx +19 -0
  47. package/src/components/inputs-values/types.ts +22 -0
  48. package/src/components/json-editor-with-variables/extensions/variable-tree.tsx +1 -1
  49. package/src/components/json-editor-with-variables/index.tsx +2 -1
  50. package/src/components/json-schema-editor/default-value.tsx +12 -106
  51. package/src/components/json-schema-editor/hooks.tsx +53 -94
  52. package/src/components/json-schema-editor/index.tsx +32 -13
  53. package/src/components/json-schema-editor/styles.tsx +0 -29
  54. package/src/components/json-schema-editor/types.ts +1 -1
  55. package/src/components/prompt-editor/types.tsx +1 -1
  56. package/src/components/prompt-editor-with-inputs/extensions/inputs-tree.tsx +2 -1
  57. package/src/components/prompt-editor-with-inputs/index.tsx +3 -2
  58. package/src/components/prompt-editor-with-inputs/inputs-picker.tsx +2 -2
  59. package/src/components/prompt-editor-with-variables/extensions/variable-tag.tsx +6 -3
  60. package/src/components/prompt-editor-with-variables/extensions/variable-tree.tsx +1 -1
  61. package/src/components/prompt-editor-with-variables/index.tsx +2 -1
  62. package/src/components/type-selector/index.tsx +58 -13
  63. package/src/components/variable-selector/index.tsx +42 -17
  64. package/src/components/variable-selector/styles.tsx +18 -8
  65. package/src/components/variable-selector/use-variable-tree.tsx +19 -22
  66. package/src/effects/auto-rename-ref/index.ts +1 -1
  67. package/src/effects/index.ts +3 -1
  68. package/src/effects/listen-ref-schema-change/index.ts +56 -0
  69. package/src/effects/listen-ref-value-change/index.ts +53 -0
  70. package/src/effects/provide-batch-input/index.ts +1 -1
  71. package/src/effects/provide-json-schema-outputs/index.ts +1 -3
  72. package/src/effects/sync-variable-title/index.ts +1 -0
  73. package/src/effects/validate-when-variable-sync/index.ts +35 -0
  74. package/src/form-plugins/batch-outputs-plugin/index.ts +1 -1
  75. package/src/form-plugins/index.ts +3 -1
  76. package/src/form-plugins/infer-assign-plugin/index.ts +90 -0
  77. package/src/form-plugins/infer-inputs-plugin/index.ts +108 -0
  78. package/src/hooks/index.tsx +6 -0
  79. package/src/hooks/use-object-list/index.tsx +136 -0
  80. package/src/index.ts +3 -1
  81. package/src/{utils/format-legacy-refs → plugins/disable-declaration-plugin}/config.json +1 -1
  82. package/src/plugins/disable-declaration-plugin/create-disable-declaration-plugin.ts +31 -0
  83. package/src/plugins/disable-declaration-plugin/index.tsx +6 -0
  84. package/src/plugins/index.ts +7 -0
  85. package/src/plugins/json-schema-preset/config.json +9 -0
  86. package/src/plugins/json-schema-preset/create-type-preset-plugin.tsx +28 -0
  87. package/src/plugins/json-schema-preset/index.tsx +41 -0
  88. package/src/plugins/json-schema-preset/manager.ts +18 -0
  89. package/src/plugins/json-schema-preset/type-definition/array.tsx +26 -0
  90. package/src/plugins/json-schema-preset/type-definition/boolean.tsx +33 -0
  91. package/src/plugins/json-schema-preset/type-definition/index.tsx +24 -0
  92. package/src/plugins/json-schema-preset/type-definition/integer.tsx +25 -0
  93. package/src/plugins/json-schema-preset/type-definition/number.tsx +25 -0
  94. package/src/plugins/json-schema-preset/type-definition/object.tsx +26 -0
  95. package/src/plugins/json-schema-preset/type-definition/string.tsx +24 -0
  96. package/src/{utils → shared}/index.ts +1 -1
  97. package/src/shared/inject-material/README.md +170 -0
  98. package/src/shared/inject-material/README.zh.md +174 -0
  99. package/src/shared/inject-material/index.tsx +87 -0
  100. package/src/typings/flow-value/index.ts +11 -0
  101. package/src/typings/index.ts +0 -1
  102. package/src/validate/index.tsx +6 -0
  103. package/src/validate/validate-flow-value/index.tsx +73 -0
  104. package/src/components/batch-outputs/config.json +0 -12
  105. package/src/components/batch-outputs/use-list.ts +0 -86
  106. package/src/components/batch-variable-selector/config.json +0 -5
  107. package/src/components/code-editor/config.json +0 -10
  108. package/src/components/condition-row/config.json +0 -5
  109. package/src/components/constant-input/config.json +0 -6
  110. package/src/components/dynamic-value-input/config.json +0 -5
  111. package/src/components/json-editor-with-variables/config.json +0 -13
  112. package/src/components/json-schema-editor/config.json +0 -13
  113. package/src/components/json-schema-editor/utils.ts +0 -29
  114. package/src/components/prompt-editor/config.json +0 -9
  115. package/src/components/prompt-editor-with-inputs/config.json +0 -13
  116. package/src/components/prompt-editor-with-variables/config.json +0 -13
  117. package/src/components/type-selector/config.json +0 -5
  118. package/src/components/type-selector/constants.tsx +0 -364
  119. package/src/components/variable-selector/config.json +0 -5
  120. package/src/effects/auto-rename-ref/config.json +0 -5
  121. package/src/effects/provide-batch-input/config.json +0 -5
  122. package/src/effects/provide-batch-outputs/config.json +0 -5
  123. package/src/effects/provide-batch-outputs/index.ts +0 -38
  124. package/src/effects/provide-json-schema-outputs/config.json +0 -8
  125. package/src/effects/sync-variable-title/config.json +0 -5
  126. package/src/form-plugins/batch-outputs-plugin/config.json +0 -7
  127. package/src/typings/flow-value/config.json +0 -5
  128. package/src/typings/json-schema/config.json +0 -5
  129. package/src/typings/json-schema/index.ts +0 -36
  130. package/src/utils/json-schema/config.json +0 -5
  131. package/src/utils/json-schema/index.ts +0 -180
  132. /package/src/{utils → shared}/format-legacy-refs/index.ts +0 -0
  133. /package/src/{utils → shared}/format-legacy-refs/readme.md +0 -0
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { useEffect, useState } from 'react';
7
+
8
+ import { nanoid } from 'nanoid';
9
+ import { difference, get, isObject, set } from 'lodash';
10
+
11
+ function genId() {
12
+ return nanoid();
13
+ }
14
+
15
+ interface ListItem<ValueType> {
16
+ id: string;
17
+ key?: string;
18
+ value?: ValueType;
19
+ }
20
+
21
+ type ObjectType<ValueType> = Record<string, ValueType | undefined>;
22
+
23
+ export function useObjectList<ValueType>({
24
+ value,
25
+ onChange,
26
+ sortIndexKey,
27
+ }: {
28
+ value?: ObjectType<ValueType>;
29
+ onChange: (value?: ObjectType<ValueType>) => void;
30
+ sortIndexKey?: string;
31
+ }) {
32
+ const [list, setList] = useState<ListItem<ValueType>[]>([]);
33
+
34
+ useEffect(() => {
35
+ setList((_prevList) => {
36
+ const newKeys = Object.entries(value || {})
37
+ .sort((a, b) => get(a[1], sortIndexKey || 0) - get(b[1], sortIndexKey || 0))
38
+ .map(([key]) => key);
39
+
40
+ const oldKeys = _prevList.map((item) => item.key).filter(Boolean) as string[];
41
+ const addKeys = difference(newKeys, oldKeys);
42
+
43
+ return _prevList
44
+ .filter((item) => !item.key || newKeys.includes(item.key))
45
+ .map((item) => ({
46
+ id: item.id,
47
+ key: item.key,
48
+ value: item.key ? value?.[item.key!] : item.value,
49
+ }))
50
+ .concat(
51
+ addKeys.map((_key) => ({
52
+ id: genId(),
53
+ key: _key,
54
+ value: value?.[_key],
55
+ }))
56
+ );
57
+ });
58
+ }, [value]);
59
+
60
+ const add = () => {
61
+ setList((prevList) => [
62
+ ...prevList,
63
+ {
64
+ id: genId(),
65
+ },
66
+ ]);
67
+ };
68
+
69
+ const updateValue = (itemId: string, value: ValueType) => {
70
+ setList((prevList) => {
71
+ const nextList = prevList.map((_item) => {
72
+ if (_item.id === itemId) {
73
+ return {
74
+ ..._item,
75
+ value,
76
+ };
77
+ }
78
+ return _item;
79
+ });
80
+
81
+ onChange(
82
+ Object.fromEntries(
83
+ nextList
84
+ .filter((item) => item.key)
85
+ .map((item) => [item.key!, item.value])
86
+ .map((_res, idx) => {
87
+ if (isObject(_res[1]) && sortIndexKey) {
88
+ set(_res[1], sortIndexKey, idx);
89
+ }
90
+ return _res;
91
+ })
92
+ )
93
+ );
94
+
95
+ return nextList;
96
+ });
97
+ };
98
+
99
+ const updateKey = (itemId: string, key: string) => {
100
+ setList((prevList) => {
101
+ const nextList = prevList.map((_item) => {
102
+ if (_item.id === itemId) {
103
+ return {
104
+ ..._item,
105
+ key,
106
+ };
107
+ }
108
+ return _item;
109
+ });
110
+
111
+ onChange(
112
+ Object.fromEntries(
113
+ nextList.filter((item) => item.key).map((item) => [item.key!, item.value])
114
+ )
115
+ );
116
+
117
+ return nextList;
118
+ });
119
+ };
120
+
121
+ const remove = (itemId: string) => {
122
+ setList((prevList) => {
123
+ const nextList = prevList.filter((_item) => _item.id !== itemId);
124
+
125
+ onChange(
126
+ Object.fromEntries(
127
+ nextList.filter((item) => item.key).map((item) => [item.key!, item.value])
128
+ )
129
+ );
130
+
131
+ return nextList;
132
+ });
133
+ };
134
+
135
+ return { list, add, updateKey, updateValue, remove };
136
+ }
package/src/index.ts CHANGED
@@ -5,6 +5,8 @@
5
5
 
6
6
  export * from './components';
7
7
  export * from './effects';
8
- export * from './utils';
8
+ export * from './shared';
9
9
  export * from './typings';
10
10
  export * from './form-plugins';
11
+ export * from './plugins';
12
+ export * from './validate';
@@ -1,5 +1,5 @@
1
1
  {
2
- "name": "format-legacy-ref",
2
+ "name": "disable-declaration-plugin",
3
3
  "depMaterials": [],
4
4
  "depPackages": []
5
5
  }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import {
7
+ ASTMatch,
8
+ definePluginCreator,
9
+ type GlobalEventActionType,
10
+ VariableEngine,
11
+ } from '@flowgram.ai/editor';
12
+
13
+ export const createDisableDeclarationPlugin = definePluginCreator<void>({
14
+ onInit(ctx) {
15
+ const variableEngine = ctx.get(VariableEngine);
16
+
17
+ const handleEvent = (action: GlobalEventActionType) => {
18
+ if (ASTMatch.isVariableDeclaration(action.ast)) {
19
+ if (!action.ast.meta?.disabled) {
20
+ action.ast.updateMeta({
21
+ ...(action.ast.meta || {}),
22
+ disabled: true,
23
+ });
24
+ }
25
+ }
26
+ };
27
+
28
+ variableEngine.onGlobalEvent('NewAST', handleEvent);
29
+ variableEngine.onGlobalEvent('UpdateAST', handleEvent);
30
+ },
31
+ });
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ export { createDisableDeclarationPlugin } from './create-disable-declaration-plugin';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ export * from './json-schema-preset';
7
+ export * from './disable-declaration-plugin';
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "json-schema-preset",
3
+ "depMaterials": [
4
+ "components/code-editor-mini"
5
+ ],
6
+ "depPackages": [
7
+ "@flowgram.ai/json-schema"
8
+ ]
9
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import {
7
+ BaseTypeManager,
8
+ jsonSchemaContainerModule,
9
+ JsonSchemaTypeManager,
10
+ } from '@flowgram.ai/json-schema';
11
+ import { definePluginCreator } from '@flowgram.ai/editor';
12
+
13
+ import { jsonSchemaTypePreset } from './type-definition';
14
+ import { JsonSchemaTypeRegistry } from './manager';
15
+
16
+ export const createTypePresetPlugin = definePluginCreator<{
17
+ types?: Partial<JsonSchemaTypeRegistry> & Pick<JsonSchemaTypeRegistry, 'type'>[];
18
+ unregisterTypes?: string[];
19
+ }>({
20
+ onInit(ctx, opts) {
21
+ const typeManager = ctx.get(BaseTypeManager) as JsonSchemaTypeManager;
22
+ jsonSchemaTypePreset.forEach((_type) => typeManager.register(_type));
23
+
24
+ opts.types?.forEach((_type) => typeManager.register(_type));
25
+ opts.unregisterTypes?.forEach((_type) => typeManager.unregister(_type));
26
+ },
27
+ containerModules: [jsonSchemaContainerModule],
28
+ });
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+ import React from 'react';
6
+
7
+ import {
8
+ type IJsonSchema,
9
+ JsonSchemaUtils,
10
+ useTypeManager as useOriginTypeManager,
11
+ TypePresetProvider as OriginTypePresetProvider,
12
+ JsonSchemaTypeManager,
13
+ type JsonSchemaBasicType,
14
+ } from '@flowgram.ai/json-schema';
15
+
16
+ import { jsonSchemaTypePreset } from './type-definition';
17
+ import { type JsonSchemaTypeRegistry, type ConstantRendererProps } from './manager';
18
+ import { createTypePresetPlugin } from './create-type-preset-plugin';
19
+
20
+ const useTypeManager = () =>
21
+ useOriginTypeManager() as JsonSchemaTypeManager<IJsonSchema, JsonSchemaTypeRegistry>;
22
+
23
+ const JsonSchemaTypePresetProvider = ({
24
+ types = [],
25
+ children,
26
+ }: React.PropsWithChildren<{ types: JsonSchemaTypeRegistry[] }>) => (
27
+ <OriginTypePresetProvider types={[...jsonSchemaTypePreset, ...types]}>
28
+ {children}
29
+ </OriginTypePresetProvider>
30
+ );
31
+
32
+ export {
33
+ createTypePresetPlugin,
34
+ useTypeManager,
35
+ JsonSchemaTypePresetProvider,
36
+ IJsonSchema,
37
+ JsonSchemaUtils,
38
+ JsonSchemaTypeRegistry,
39
+ ConstantRendererProps,
40
+ JsonSchemaBasicType,
41
+ };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { JsonSchemaTypeRegistry as OriginJsonSchemaTypeRegistry } from '@flowgram.ai/json-schema';
7
+
8
+ export interface ConstantRendererProps<Value = any> {
9
+ value?: Value;
10
+ onChange?: (value: Value) => void;
11
+ readonly?: boolean;
12
+ }
13
+ export interface JsonSchemaTypeRegistry<Value = any> extends OriginJsonSchemaTypeRegistry {
14
+ /**
15
+ * Render Constant Input
16
+ */
17
+ ConstantRenderer: React.FC<ConstantRendererProps<Value>>;
18
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ /* eslint-disable react/prop-types */
7
+ import React from 'react';
8
+
9
+ import { I18n } from '@flowgram.ai/editor';
10
+
11
+ import { CodeEditorMini } from '@/components/code-editor-mini';
12
+
13
+ import { type JsonSchemaTypeRegistry } from '../manager';
14
+
15
+ export const arrayRegistry: Partial<JsonSchemaTypeRegistry> = {
16
+ type: 'array',
17
+ ConstantRenderer: (props) => (
18
+ <CodeEditorMini
19
+ value={props.value}
20
+ languageId="json"
21
+ onChange={(v) => props.onChange?.(v)}
22
+ placeholder={I18n.t('Please Input Array')}
23
+ readonly={props.readonly}
24
+ />
25
+ ),
26
+ };
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ /* eslint-disable react/prop-types */
7
+ import React from 'react';
8
+
9
+ import { I18n } from '@flowgram.ai/editor';
10
+ import { Select } from '@douyinfe/semi-ui';
11
+
12
+ import { type JsonSchemaTypeRegistry } from '../manager';
13
+
14
+ export const booleanRegistry: Partial<JsonSchemaTypeRegistry> = {
15
+ type: 'boolean',
16
+ ConstantRenderer: (props) => {
17
+ const { value, onChange, ...rest } = props;
18
+ return (
19
+ <Select
20
+ placeholder={I18n.t('Please Select Boolean')}
21
+ size="small"
22
+ disabled={props.readonly}
23
+ optionList={[
24
+ { label: I18n.t('True'), value: 1 },
25
+ { label: I18n.t('False'), value: 0 },
26
+ ]}
27
+ value={value ? 1 : 0}
28
+ onChange={(value) => onChange?.(!!value)}
29
+ {...rest}
30
+ />
31
+ );
32
+ },
33
+ };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { jsonSchemaTypeManager } from '@flowgram.ai/json-schema';
7
+
8
+ import { stringRegistry } from './string';
9
+ import { objectRegistry } from './object';
10
+ import { numberRegistry } from './number';
11
+ import { integerRegistry } from './integer';
12
+ import { booleanRegistry } from './boolean';
13
+ import { arrayRegistry } from './array';
14
+
15
+ export const jsonSchemaTypePreset = [
16
+ stringRegistry,
17
+ objectRegistry,
18
+ numberRegistry,
19
+ integerRegistry,
20
+ booleanRegistry,
21
+ arrayRegistry,
22
+ ];
23
+
24
+ jsonSchemaTypePreset.forEach((_type) => jsonSchemaTypeManager.register(_type));
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ /* eslint-disable react/prop-types */
7
+ import React from 'react';
8
+
9
+ import { I18n } from '@flowgram.ai/editor';
10
+ import { InputNumber } from '@douyinfe/semi-ui';
11
+
12
+ import { type JsonSchemaTypeRegistry } from '../manager';
13
+
14
+ export const integerRegistry: Partial<JsonSchemaTypeRegistry> = {
15
+ type: 'integer',
16
+ ConstantRenderer: (props) => (
17
+ <InputNumber
18
+ placeholder={I18n.t('Please Input Integer')}
19
+ size="small"
20
+ disabled={props.readonly}
21
+ precision={0}
22
+ {...props}
23
+ />
24
+ ),
25
+ };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ /* eslint-disable react/prop-types */
7
+ import React from 'react';
8
+
9
+ import { I18n } from '@flowgram.ai/editor';
10
+ import { InputNumber } from '@douyinfe/semi-ui';
11
+
12
+ import { type JsonSchemaTypeRegistry } from '../manager';
13
+
14
+ export const numberRegistry: Partial<JsonSchemaTypeRegistry> = {
15
+ type: 'number',
16
+ ConstantRenderer: (props) => (
17
+ <InputNumber
18
+ placeholder={I18n.t('Please Input Number')}
19
+ size="small"
20
+ disabled={props.readonly}
21
+ hideButtons
22
+ {...props}
23
+ />
24
+ ),
25
+ };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ /* eslint-disable react/prop-types */
7
+ import React from 'react';
8
+
9
+ import { I18n } from '@flowgram.ai/editor';
10
+
11
+ import { CodeEditorMini } from '@/components/code-editor-mini';
12
+
13
+ import { type JsonSchemaTypeRegistry } from '../manager';
14
+
15
+ export const objectRegistry: Partial<JsonSchemaTypeRegistry> = {
16
+ type: 'object',
17
+ ConstantRenderer: (props) => (
18
+ <CodeEditorMini
19
+ value={props.value}
20
+ onChange={(v) => props.onChange?.(v)}
21
+ languageId="json"
22
+ placeholder={I18n.t('Please Input Object')}
23
+ readonly={props.readonly}
24
+ />
25
+ ),
26
+ };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ /* eslint-disable react/prop-types */
7
+ import React from 'react';
8
+
9
+ import { I18n } from '@flowgram.ai/editor';
10
+ import { Input } from '@douyinfe/semi-ui';
11
+
12
+ import { type JsonSchemaTypeRegistry } from '../manager';
13
+
14
+ export const stringRegistry: Partial<JsonSchemaTypeRegistry> = {
15
+ type: 'string',
16
+ ConstantRenderer: (props) => (
17
+ <Input
18
+ placeholder={I18n.t('Please Input String')}
19
+ size="small"
20
+ disabled={props.readonly}
21
+ {...props}
22
+ />
23
+ ),
24
+ };
@@ -4,4 +4,4 @@
4
4
  */
5
5
 
6
6
  export * from './format-legacy-refs';
7
- export * from './json-schema';
7
+ export * from './inject-material';
@@ -0,0 +1,170 @@
1
+ # InjectMaterial Component
2
+
3
+ A material component wrapper with dependency injection support for implementing dynamic component replacement mechanisms.
4
+
5
+ ## Why Dependency Injection Matters
6
+
7
+ ### ❌ Tight Coupling: Traditional Dependency Issues
8
+
9
+ ```mermaid
10
+ graph TD
11
+ A[Material A] --> B[Material B]
12
+ B --> D[Material D]
13
+ C[Material C] --> D
14
+
15
+ style D fill:#ff4757
16
+ style A fill:#ffa502
17
+ style B fill:#ffa502
18
+ style C fill:#ffa502
19
+
20
+ note["💥 Problem: D changes require modifications to A, B, C"]
21
+ ```
22
+
23
+ **Issues:** Chain reactions, high maintenance costs
24
+
25
+ ### ✅ Decoupling: Dependency Injection Solution
26
+
27
+ ```mermaid
28
+ graph TD
29
+ A[Material A] --> RenderKey[Material D RenderKey]
30
+ B[Material B] --> RenderKey
31
+ C[Material C] --> RenderKey
32
+
33
+ RenderKey -.-> BaseD[Origin D]
34
+ CustomD[Custom D] -.-> RenderKey
35
+
36
+ style RenderKey fill:#5f27cd
37
+ style BaseD fill:#2ed573
38
+ style CustomD fill:#26d0ce
39
+ style A fill:#a55eea
40
+ style B fill:#a55eea
41
+ style C fill:#a55eea
42
+
43
+ note2["✅ A, B, C depend on abstract interface, decoupled from D"]
44
+ ```
45
+
46
+ **Benefits:** Hot-swapping, parallel development, version compatibility
47
+
48
+ ## Features
49
+
50
+ - 🔧 **Dependency Injection**: Support dynamic component replacement via FlowRendererRegistry
51
+ - 🔄 **Smart Fallback**: Automatically use default component when no custom component is registered
52
+ - 🎯 **Type Safety**: Full TypeScript type inference support
53
+ - 📦 **Zero Configuration**: Works out of the box without additional setup
54
+
55
+ ## Usage
56
+
57
+ ### 1. Create Injectable Material Component
58
+
59
+ ```tsx
60
+ import { createInjectMaterial } from '@flowgram.ai/form-materials';
61
+ import { VariableSelector } from './VariableSelector';
62
+
63
+ // Create injectable material wrapper component
64
+ const InjectVariableSelector = createInjectMaterial(VariableSelector);
65
+
66
+ // Now you can use it like a regular component
67
+ function MyComponent() {
68
+ return <InjectVariableSelector value={value} onChange={handleChange} />;
69
+ }
70
+ ```
71
+
72
+ ### 2. Register Custom Components
73
+
74
+ Configure custom renderer in `use-editor-props.tsx`:
75
+
76
+ ```tsx
77
+ import { useEditorProps } from '@flowgram.ai/editor';
78
+ import { YourCustomVariableSelector } from './YourCustomVariableSelector';
79
+ import { VariableSelector } from '@flowgram.ai/form-materials';
80
+
81
+ function useCustomEditorProps() {
82
+ const editorProps = useEditorProps({
83
+ materials: {
84
+ components: {
85
+ // Use component's renderKey or component name as key
86
+ [VariableSelector.renderKey]: YourCustomVariableSelector,
87
+ [TypeSelector.renderKey]: YourCustomTypeSelector,
88
+ }
89
+ }
90
+ });
91
+
92
+ return editorProps;
93
+ }
94
+ ```
95
+
96
+ ### 3. Use Custom renderKey
97
+
98
+ If your component requires a specific renderKey:
99
+
100
+ ```tsx
101
+ const InjectCustomComponent = createInjectMaterial(MyComponent, {
102
+ renderKey: 'my-custom-key'
103
+ });
104
+
105
+ // When registering
106
+ {
107
+ materials: {
108
+ components: {
109
+ 'my-custom-key': MyCustomRenderer
110
+ }
111
+ }
112
+ }
113
+ ```
114
+
115
+ ## Sequence Diagram
116
+
117
+ Complete component registration and rendering sequence diagram:
118
+
119
+ ```mermaid
120
+ sequenceDiagram
121
+ participant App as Application
122
+ participant Editor as use-editor-props
123
+ participant Registry as FlowRendererRegistry
124
+ participant Inject as InjectMaterial
125
+ participant Default as Default Component
126
+ participant Custom as Custom Component
127
+
128
+ Note over App,Custom: Component Registration Phase
129
+ App->>Editor: Call use-editor-props()
130
+ Editor->>Editor: Configure materials.components
131
+ Editor->>Registry: Register component to FlowRendererRegistry
132
+ Registry->>Registry: Store mapping relationship
133
+ Registry-->>App: Registration complete
134
+
135
+ Note over App,Custom: Component Rendering Phase
136
+ App->>Inject: Render InjectMaterial component
137
+ Inject->>Registry: Query renderer (getRendererComponent)
138
+
139
+ alt Custom renderer exists
140
+ Registry-->>Inject: Return custom React component
141
+ Inject->>Custom: Render with custom component
142
+ Custom-->>App: Render custom UI
143
+ else No custom renderer
144
+ Registry-->>Inject: Return null or type mismatch
145
+ Inject->>Default: Render with default component
146
+ Default-->>App: Render default UI
147
+ end
148
+ ```
149
+
150
+ ## Render Key Priority
151
+
152
+ Component render key determination follows this priority order:
153
+
154
+ 1. `params.renderKey` (second parameter of createInjectMaterial)
155
+ 2. `Component.renderKey` (component's own renderKey property)
156
+ 3. `Component.name` (component's display name)
157
+ 4. Empty string (final fallback)
158
+
159
+ ## Type Definition
160
+
161
+ ```typescript
162
+ interface CreateInjectMaterialOptions {
163
+ renderKey?: string;
164
+ }
165
+
166
+ function createInjectMaterial<Props>(
167
+ Component: React.FC<Props> & { renderKey?: string },
168
+ params?: CreateInjectMaterialOptions
169
+ ): React.FC<Props>
170
+ ```