@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowgram.ai/form-materials",
3
- "version": "0.1.0-alpha.11",
3
+ "version": "0.1.0-alpha.13",
4
4
  "homepage": "https://flowgram.ai/",
5
5
  "repository": "https://github.com/bytedance/flowgram.ai",
6
6
  "license": "MIT",
@@ -34,7 +34,8 @@
34
34
  "@codemirror/view": "~6.38.0",
35
35
  "@codemirror/state": "~6.5.2",
36
36
  "typescript": "^5.8.3",
37
- "@flowgram.ai/editor": "0.1.0-alpha.11"
37
+ "@flowgram.ai/editor": "0.1.0-alpha.13",
38
+ "@flowgram.ai/json-schema": "0.1.0-alpha.13"
38
39
  },
39
40
  "devDependencies": {
40
41
  "@types/lodash": "^4.14.137",
@@ -50,8 +51,8 @@
50
51
  "tsup": "^8.0.1",
51
52
  "typescript": "^5.8.3",
52
53
  "vitest": "^0.34.6",
53
- "@flowgram.ai/ts-config": "0.1.0-alpha.11",
54
- "@flowgram.ai/eslint-config": "0.1.0-alpha.11"
54
+ "@flowgram.ai/eslint-config": "0.1.0-alpha.13",
55
+ "@flowgram.ai/ts-config": "0.1.0-alpha.13"
55
56
  },
56
57
  "peerDependencies": {
57
58
  "react": ">=16.8",
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import React, { useEffect, useState } from 'react';
7
+
8
+ import Input, { InputProps } from '@douyinfe/semi-ui/lib/es/input';
9
+
10
+ export function BlurInput(props: InputProps) {
11
+ const [value, setValue] = useState('');
12
+
13
+ useEffect(() => {
14
+ setValue(props.value as string);
15
+ }, [props.value]);
16
+
17
+ return (
18
+ <Input
19
+ {...props}
20
+ value={value}
21
+ onChange={(value) => {
22
+ setValue(value);
23
+ }}
24
+ onBlur={(e) => props.onChange?.(value, e)}
25
+ />
26
+ );
27
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import React from 'react';
7
+
8
+ import { IconButton } from '@douyinfe/semi-ui';
9
+ import { IconMinus } from '@douyinfe/semi-icons';
10
+
11
+ import { IFlowConstantRefValue } from '@/typings';
12
+ import { InjectVariableSelector } from '@/components/variable-selector';
13
+ import { InjectDynamicValueInput } from '@/components/dynamic-value-input';
14
+
15
+ import { AssignRowProps } from './types';
16
+ import { BlurInput } from './components/blur-input';
17
+
18
+ export function AssignRow(props: AssignRowProps) {
19
+ const {
20
+ value = {
21
+ operator: 'assign',
22
+ },
23
+ onChange,
24
+ onDelete,
25
+ readonly,
26
+ } = props;
27
+
28
+ return (
29
+ <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
30
+ <div style={{ width: 150, minWidth: 150, maxWidth: 150 }}>
31
+ {value?.operator === 'assign' ? (
32
+ <InjectVariableSelector
33
+ style={{ width: '100%', height: 26 }}
34
+ value={value?.left?.content}
35
+ config={{ placeholder: 'Select Left' }}
36
+ onChange={(v) =>
37
+ onChange?.({
38
+ ...value,
39
+ left: { type: 'ref', content: v },
40
+ })
41
+ }
42
+ />
43
+ ) : (
44
+ <BlurInput
45
+ style={{ height: 26 }}
46
+ size="small"
47
+ placeholder="Input Name"
48
+ value={value?.left}
49
+ onChange={(v) =>
50
+ onChange?.({
51
+ ...value,
52
+ left: v,
53
+ })
54
+ }
55
+ />
56
+ )}
57
+ </div>
58
+ <div style={{ flexGrow: 1 }}>
59
+ <InjectDynamicValueInput
60
+ readonly={readonly}
61
+ value={value?.right as IFlowConstantRefValue | undefined}
62
+ onChange={(v) =>
63
+ onChange?.({
64
+ ...value,
65
+ right: v,
66
+ })
67
+ }
68
+ />
69
+ </div>
70
+ {onDelete && (
71
+ <div>
72
+ <IconButton
73
+ size="small"
74
+ theme="borderless"
75
+ icon={<IconMinus />}
76
+ onClick={() => onDelete?.()}
77
+ />
78
+ </div>
79
+ )}
80
+ </div>
81
+ );
82
+ }
83
+
84
+ export { AssignValueType } from './types';
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { IFlowRefValue, IFlowValue } from '@/typings';
7
+
8
+ export type AssignValueType =
9
+ | {
10
+ operator: 'assign';
11
+ left?: IFlowRefValue;
12
+ right?: IFlowValue;
13
+ }
14
+ | {
15
+ operator: 'declare';
16
+ left?: string;
17
+ right?: IFlowValue;
18
+ };
19
+
20
+ export interface AssignRowProps {
21
+ value?: AssignValueType;
22
+ onChange?: (value?: AssignValueType) => void;
23
+ onDelete?: () => void;
24
+ readonly?: boolean;
25
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import React from 'react';
7
+
8
+ import { FieldArray, FieldArrayRenderProps } from '@flowgram.ai/editor';
9
+ import { Button } from '@douyinfe/semi-ui';
10
+ import { IconPlus } from '@douyinfe/semi-icons';
11
+
12
+ import { AssignRow, AssignValueType } from '@/components/assign-row';
13
+
14
+ interface AssignRowsProps {
15
+ name: string;
16
+ readonly?: boolean;
17
+ }
18
+
19
+ export function AssignRows(props: AssignRowsProps) {
20
+ const { name, readonly } = props;
21
+
22
+ return (
23
+ <FieldArray name={name}>
24
+ {({ field }: FieldArrayRenderProps<AssignValueType | undefined>) => (
25
+ <>
26
+ {field.map((childField, index) => (
27
+ <AssignRow
28
+ key={childField.key}
29
+ readonly={readonly}
30
+ value={childField.value}
31
+ onChange={(value) => {
32
+ childField.onChange(value);
33
+ }}
34
+ onDelete={() => field.remove(index)}
35
+ />
36
+ ))}
37
+ <div style={{ display: 'flex', gap: 5 }}>
38
+ <Button
39
+ size="small"
40
+ theme="borderless"
41
+ icon={<IconPlus />}
42
+ onClick={() => field.append({ operator: 'assign' })}
43
+ >
44
+ Assign
45
+ </Button>
46
+ <Button
47
+ size="small"
48
+ theme="borderless"
49
+ icon={<IconPlus />}
50
+ onClick={() => field.append({ operator: 'declare' })}
51
+ >
52
+ Declaration
53
+ </Button>
54
+ </div>
55
+ </>
56
+ )}
57
+ </FieldArray>
58
+ );
59
+ }
@@ -8,15 +8,16 @@ import React from 'react';
8
8
  import { Button, Input } from '@douyinfe/semi-ui';
9
9
  import { IconDelete, IconPlus } from '@douyinfe/semi-icons';
10
10
 
11
- import { useList } from './use-list';
11
+ import { useObjectList } from '@/hooks';
12
+ import { InjectVariableSelector } from '@/components/variable-selector';
13
+
12
14
  import { PropsType } from './types';
13
- import { VariableSelector } from '../variable-selector';
14
15
  import { UIRow, UIRows } from './styles';
15
16
 
16
17
  export function BatchOutputs(props: PropsType) {
17
18
  const { readonly, style } = props;
18
19
 
19
- const { list, add, update, remove } = useList(props);
20
+ const { list, add, updateKey, updateValue, remove } = useObjectList(props);
20
21
 
21
22
  return (
22
23
  <div>
@@ -28,21 +29,13 @@ export function BatchOutputs(props: PropsType) {
28
29
  disabled={readonly}
29
30
  size="small"
30
31
  value={item.key}
31
- onChange={(v) => update({ ...item, key: v })}
32
+ onChange={(v) => updateKey(item.id, v)}
32
33
  />
33
- <VariableSelector
34
+ <InjectVariableSelector
34
35
  style={{ flexGrow: 1 }}
35
36
  readonly={readonly}
36
37
  value={item.value?.content}
37
- onChange={(v) =>
38
- update({
39
- ...item,
40
- value: {
41
- type: 'ref',
42
- content: v,
43
- },
44
- })
45
- }
38
+ onChange={(v) => updateValue(item.id, { type: 'ref', content: v })}
46
39
  />
47
40
  <Button
48
41
  disabled={readonly}
@@ -3,7 +3,7 @@
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
5
 
6
- import { IFlowRefValue } from '../../typings';
6
+ import { IFlowRefValue } from '@/typings';
7
7
 
8
8
  export type ValueType = Record<string, IFlowRefValue | undefined>;
9
9
 
@@ -5,10 +5,10 @@
5
5
 
6
6
  import React from 'react';
7
7
 
8
+ import { IJsonSchema } from '@flowgram.ai/json-schema';
8
9
  import { PrivateScopeProvider } from '@flowgram.ai/editor';
9
10
 
10
- import { VariableSelector, VariableSelectorProps } from '../variable-selector';
11
- import { IJsonSchema } from '../../typings';
11
+ import { VariableSelector, VariableSelectorProps } from '@/components/variable-selector';
12
12
 
13
13
  const batchVariableSchema: IJsonSchema = {
14
14
  type: 'array',
@@ -15,6 +15,7 @@ import preset, { type EditorAPI } from '@coze-editor/editor/preset-code';
15
15
  import { EditorView } from '@codemirror/view';
16
16
 
17
17
  import { getSuffixByLanguageId } from './utils';
18
+ import { initTsWorker } from './language-features';
18
19
 
19
20
  import './theme';
20
21
  import './language-features';
@@ -54,6 +55,12 @@ export function CodeEditor({
54
55
  }: CodeEditorPropsType) {
55
56
  const editorRef = useRef<EditorAPI | null>(null);
56
57
 
58
+ useEffect(() => {
59
+ if (languageId === 'typescript') {
60
+ initTsWorker();
61
+ }
62
+ }, [languageId]);
63
+
57
64
  useEffect(() => {
58
65
  // listen to value change
59
66
  if (editorRef.current?.getValue() !== value) {
@@ -11,8 +11,8 @@ import { json } from '@coze-editor/editor/language-json';
11
11
  import { mixLanguages } from '@coze-editor/editor';
12
12
 
13
13
  languages.register('python', python);
14
- languages.register('typescript', typescript);
15
14
  languages.register('shell', shell);
15
+ languages.register('typescript', typescript);
16
16
 
17
17
  languages.register('json', {
18
18
  // mixLanguages is used to solve the problem that interpolation also uses parentheses, which causes incorrect highlighting
@@ -21,3 +21,24 @@ languages.register('json', {
21
21
  }),
22
22
  languageService: json.languageService,
23
23
  });
24
+
25
+ let tsWorkerInit = false;
26
+
27
+ export const initTsWorker = () => {
28
+ if (tsWorkerInit) {
29
+ return;
30
+ }
31
+ tsWorkerInit = true;
32
+
33
+ const tsWorker = new Worker(
34
+ new URL(`@coze-editor/editor/language-typescript/worker`, import.meta.url),
35
+ { type: 'module' }
36
+ );
37
+ typescript.languageService.initialize(tsWorker, {
38
+ compilerOptions: {
39
+ // eliminate Promise error
40
+ lib: ['es2015', 'dom'],
41
+ noImplicitAny: false,
42
+ },
43
+ });
44
+ };
@@ -29,7 +29,7 @@ export const lightTheme: Extension = createTheme({
29
29
  gutterForeground: '#666',
30
30
  gutterBorderColor: 'transparent',
31
31
  gutterBorderWidth: 0,
32
- lineHighlight: '#f0f0f0',
32
+ lineHighlight: '#e1e1e180',
33
33
  bracketColors: ['#FFD700', '#DD99FF', '#78B0FF'],
34
34
  tooltip: {
35
35
  backgroundColor: '#f0f0f0',
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import React from 'react';
7
+
8
+ import styled from 'styled-components';
9
+
10
+ import { CodeEditor, CodeEditorPropsType } from '@/components/code-editor';
11
+
12
+ const UIMini = styled.div`
13
+ .ͼ1 .cm-content {
14
+ padding: 0;
15
+ }
16
+ `;
17
+
18
+ export function CodeEditorMini(props: CodeEditorPropsType) {
19
+ return (
20
+ <UIMini>
21
+ <CodeEditor
22
+ {...props}
23
+ options={{
24
+ lineNumbersGutter: false,
25
+ foldGutter: false,
26
+ ...(props.options || {}),
27
+ }}
28
+ />
29
+ </UIMini>
30
+ );
31
+ }
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { IRules, Op, OpConfigs } from './types';
7
7
 
8
- export const rules: IRules = {
8
+ export const defaultRules: IRules = {
9
9
  string: {
10
10
  [Op.EQ]: 'string',
11
11
  [Op.NEQ]: 'string',
@@ -13,8 +13,8 @@ export const rules: IRules = {
13
13
  [Op.NOT_CONTAINS]: 'string',
14
14
  [Op.IN]: 'array',
15
15
  [Op.NIN]: 'array',
16
- [Op.IS_EMPTY]: 'string',
17
- [Op.IS_NOT_EMPTY]: 'string',
16
+ [Op.IS_EMPTY]: null,
17
+ [Op.IS_NOT_EMPTY]: null,
18
18
  },
19
19
  number: {
20
20
  [Op.EQ]: 'number',
@@ -25,8 +25,6 @@ export const rules: IRules = {
25
25
  [Op.LTE]: 'number',
26
26
  [Op.IN]: 'array',
27
27
  [Op.NIN]: 'array',
28
- [Op.IS_EMPTY]: null,
29
- [Op.IS_NOT_EMPTY]: null,
30
28
  },
31
29
  integer: {
32
30
  [Op.EQ]: 'number',
@@ -37,8 +35,6 @@ export const rules: IRules = {
37
35
  [Op.LTE]: 'number',
38
36
  [Op.IN]: 'array',
39
37
  [Op.NIN]: 'array',
40
- [Op.IS_EMPTY]: null,
41
- [Op.IS_NOT_EMPTY]: null,
42
38
  },
43
39
  boolean: {
44
40
  [Op.EQ]: 'boolean',
@@ -47,8 +43,6 @@ export const rules: IRules = {
47
43
  [Op.IS_FALSE]: null,
48
44
  [Op.IN]: 'array',
49
45
  [Op.NIN]: 'array',
50
- [Op.IS_EMPTY]: null,
51
- [Op.IS_NOT_EMPTY]: null,
52
46
  },
53
47
  object: {
54
48
  [Op.IS_EMPTY]: null,
@@ -57,6 +51,10 @@ export const rules: IRules = {
57
51
  array: {
58
52
  [Op.IS_EMPTY]: null,
59
53
  [Op.IS_NOT_EMPTY]: null,
54
+ [Op.CONTAINS]: 'array',
55
+ [Op.NOT_CONTAINS]: 'array',
56
+ [Op.EQ]: 'array',
57
+ [Op.NEQ]: 'array',
60
58
  },
61
59
  map: {
62
60
  [Op.IS_EMPTY]: null,
@@ -64,7 +62,7 @@ export const rules: IRules = {
64
62
  },
65
63
  };
66
64
 
67
- export const opConfigs: OpConfigs = {
65
+ export const defaultOpConfigs: OpConfigs = {
68
66
  [Op.EQ]: {
69
67
  label: 'Equal',
70
68
  abbreviation: '=',
@@ -5,38 +5,44 @@
5
5
 
6
6
  import React, { useMemo } from 'react';
7
7
 
8
+ import { I18n } from '@flowgram.ai/editor';
8
9
  import { Button, Select } from '@douyinfe/semi-ui';
9
10
  import { IconChevronDownStroked } from '@douyinfe/semi-icons';
10
11
 
11
- import { IRule, Op } from '../types';
12
- import { opConfigs } from '../constants';
12
+ import { IRule, OpConfigs } from '../types';
13
+ import { defaultOpConfigs } from '../constants';
13
14
 
14
15
  interface HookParams {
15
16
  rule?: IRule;
16
- op?: Op;
17
- onChange: (op: Op) => void;
17
+ op?: string;
18
+ onChange: (op: string) => void;
19
+ readonly?: boolean;
20
+ userOps?: OpConfigs;
18
21
  }
19
22
 
20
- export function useOp({ rule, op, onChange }: HookParams) {
23
+ export function useOp({ rule, op, onChange, readonly, userOps }: HookParams) {
21
24
  const options = useMemo(
22
25
  () =>
23
26
  Object.keys(rule || {}).map((_op) => ({
24
- ...(opConfigs[_op as Op] || {}),
27
+ ...(defaultOpConfigs[_op] || {}),
28
+ ...(userOps?.[_op] || {}),
25
29
  value: _op,
30
+ label: I18n.t(userOps?.[_op]?.label || defaultOpConfigs[_op]?.label),
26
31
  })),
27
- [rule]
32
+ [rule, userOps]
28
33
  );
29
34
 
30
- const opConfig = useMemo(() => opConfigs[op as Op], [op]);
35
+ const opConfig = useMemo(() => defaultOpConfigs[op as string], [op]);
31
36
 
32
37
  const renderOpSelect = () => (
33
38
  <Select
34
39
  style={{ height: 22 }}
40
+ disabled={readonly}
35
41
  size="small"
36
42
  value={op}
37
43
  optionList={options}
38
44
  onChange={(v) => {
39
- onChange(v as Op);
45
+ onChange(v as string);
40
46
  }}
41
47
  triggerRender={({ value }) => (
42
48
  <Button size="small" disabled={!rule}>
@@ -5,15 +5,19 @@
5
5
 
6
6
  import { useMemo } from 'react';
7
7
 
8
+ import { JsonSchemaUtils, JsonSchemaBasicType } from '@flowgram.ai/json-schema';
8
9
  import { useScopeAvailable } from '@flowgram.ai/editor';
9
10
 
10
- import { rules } from '../constants';
11
- import { JsonSchemaUtils } from '../../../utils';
12
- import { IFlowRefValue, JsonSchemaBasicType } from '../../../typings';
11
+ import { IFlowRefValue } from '@/typings';
13
12
 
14
- export function useRule(left?: IFlowRefValue) {
13
+ import { IRules } from '../types';
14
+ import { defaultRules } from '../constants';
15
+
16
+ export function useRule(left?: IFlowRefValue, userRules?: IRules) {
15
17
  const available = useScopeAvailable();
16
18
 
19
+ const rules = useMemo(() => ({ ...defaultRules, ...(userRules || {}) }), [userRules]);
20
+
17
21
  const variable = useMemo(() => {
18
22
  if (!left) return undefined;
19
23
  return available.getByKeyPath(left.content);
@@ -25,7 +29,7 @@ export function useRule(left?: IFlowRefValue) {
25
29
  const schema = JsonSchemaUtils.astToSchema(variable.type, { drilldown: false });
26
30
 
27
31
  return rules[schema?.type as JsonSchemaBasicType];
28
- }, [variable?.type]);
32
+ }, [variable?.type, rules]);
29
33
 
30
34
  return { rule };
31
35
  }
@@ -5,34 +5,52 @@
5
5
 
6
6
  import React, { useMemo } from 'react';
7
7
 
8
+ import { I18n } from '@flowgram.ai/editor';
8
9
  import { Input } from '@douyinfe/semi-ui';
9
10
 
10
- import { ConditionRowValueType, Op } from './types';
11
+ import { InjectVariableSelector } from '@/components/variable-selector';
12
+ import { InjectDynamicValueInput } from '@/components/dynamic-value-input';
13
+
14
+ import { ConditionRowValueType, IRules, OpConfigs } from './types';
11
15
  import { UIContainer, UILeft, UIOperator, UIRight, UIValues } from './styles';
12
16
  import { useRule } from './hooks/useRule';
13
17
  import { useOp } from './hooks/useOp';
14
- import { VariableSelector } from '../variable-selector';
15
- import { DynamicValueInput } from '../dynamic-value-input';
16
- import { JsonSchemaBasicType } from '../../typings';
17
18
 
18
19
  interface PropTypes {
19
20
  value?: ConditionRowValueType;
20
21
  onChange: (value?: ConditionRowValueType) => void;
21
22
  style?: React.CSSProperties;
22
23
  readonly?: boolean;
24
+ ruleConfig?: {
25
+ ops?: OpConfigs;
26
+ rules?: IRules;
27
+ };
23
28
  }
24
29
 
25
- export function ConditionRow({ style, value, onChange, readonly }: PropTypes) {
30
+ const defaultRuleConfig = {
31
+ ops: {},
32
+ rules: {},
33
+ };
34
+
35
+ export function ConditionRow({
36
+ style,
37
+ value,
38
+ onChange,
39
+ readonly,
40
+ ruleConfig = defaultRuleConfig,
41
+ }: PropTypes) {
26
42
  const { left, operator, right } = value || {};
27
- const { rule } = useRule(left);
43
+ const { rule } = useRule(left, ruleConfig.rules);
28
44
  const { renderOpSelect, opConfig } = useOp({
29
45
  rule,
30
46
  op: operator,
31
47
  onChange: (v) => onChange({ ...value, operator: v }),
48
+ readonly,
49
+ userOps: ruleConfig.ops,
32
50
  });
33
51
 
34
52
  const targetSchema = useMemo(() => {
35
- const targetType: JsonSchemaBasicType | null = rule?.[operator as Op] || null;
53
+ const targetType: string | null = rule?.[operator || ''] || null;
36
54
  return targetType ? { type: targetType, extra: { weak: true } } : null;
37
55
  }, [rule, opConfig]);
38
56
 
@@ -41,7 +59,7 @@ export function ConditionRow({ style, value, onChange, readonly }: PropTypes) {
41
59
  <UIOperator>{renderOpSelect()}</UIOperator>
42
60
  <UIValues>
43
61
  <UILeft>
44
- <VariableSelector
62
+ <InjectVariableSelector
45
63
  readonly={readonly}
46
64
  style={{ width: '100%' }}
47
65
  value={left?.content}
@@ -58,7 +76,7 @@ export function ConditionRow({ style, value, onChange, readonly }: PropTypes) {
58
76
  </UILeft>
59
77
  <UIRight>
60
78
  {targetSchema ? (
61
- <DynamicValueInput
79
+ <InjectDynamicValueInput
62
80
  readonly={readonly || !rule}
63
81
  value={right}
64
82
  schema={targetSchema}
@@ -69,7 +87,7 @@ export function ConditionRow({ style, value, onChange, readonly }: PropTypes) {
69
87
  size="small"
70
88
  disabled
71
89
  style={{ pointerEvents: 'none' }}
72
- value={opConfig?.rightDisplay || 'Empty'}
90
+ value={opConfig?.rightDisplay || I18n.t('Empty')}
73
91
  />
74
92
  )}
75
93
  </UIRight>
@@ -3,7 +3,7 @@
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
5
 
6
- import { IFlowConstantRefValue, IFlowRefValue, JsonSchemaBasicType } from '../../typings';
6
+ import { IFlowConstantRefValue, IFlowRefValue } from '@/typings';
7
7
 
8
8
  export enum Op {
9
9
  EQ = 'eq',
@@ -29,14 +29,14 @@ export interface OpConfig {
29
29
  rightDisplay?: string;
30
30
  }
31
31
 
32
- export type OpConfigs = Record<Op, OpConfig>;
32
+ export type OpConfigs = Record<string, OpConfig>;
33
33
 
34
- export type IRule = Partial<Record<Op, JsonSchemaBasicType | null>>;
34
+ export type IRule = Partial<Record<string, string | null>>;
35
35
 
36
- export type IRules = Record<JsonSchemaBasicType, IRule>;
36
+ export type IRules = Record<string, IRule>;
37
37
 
38
38
  export interface ConditionRowValueType {
39
39
  left?: IFlowRefValue;
40
- operator?: Op;
40
+ operator?: string;
41
41
  right?: IFlowConstantRefValue;
42
42
  }