@flowgram.ai/form-materials 0.4.4 → 0.4.6

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 (47) hide show
  1. package/dist/esm/chunk-6OZSB6PD.js +10 -0
  2. package/dist/esm/chunk-6OZSB6PD.js.map +1 -0
  3. package/dist/esm/chunk-G4HQ7OSI.js +440 -0
  4. package/dist/esm/chunk-G4HQ7OSI.js.map +1 -0
  5. package/dist/esm/chunk-QIJ4QVB2.js +271 -0
  6. package/dist/esm/chunk-QIJ4QVB2.js.map +1 -0
  7. package/dist/esm/editor-6UMULJYB.js +180 -0
  8. package/dist/esm/editor-6UMULJYB.js.map +1 -0
  9. package/dist/esm/editor-E2BQTPCD.js +388 -0
  10. package/dist/esm/editor-E2BQTPCD.js.map +1 -0
  11. package/dist/esm/editor-H2R7JJLO.js +282 -0
  12. package/dist/esm/editor-H2R7JJLO.js.map +1 -0
  13. package/dist/esm/editor-JX42GFAZ.js +249 -0
  14. package/dist/esm/editor-JX42GFAZ.js.map +1 -0
  15. package/dist/esm/editor-YMNCDGUR.js +167 -0
  16. package/dist/esm/editor-YMNCDGUR.js.map +1 -0
  17. package/dist/esm/index.js +1388 -3029
  18. package/dist/esm/index.js.map +1 -1
  19. package/dist/index.d.mts +144 -51
  20. package/dist/index.d.ts +144 -51
  21. package/dist/index.js +3511 -2759
  22. package/dist/index.js.map +1 -1
  23. package/package.json +6 -6
  24. package/src/components/code-editor/editor.tsx +96 -0
  25. package/src/components/code-editor/index.tsx +5 -89
  26. package/src/components/code-editor/theme/dark.ts +49 -30
  27. package/src/components/code-editor/theme/light.ts +56 -32
  28. package/src/components/code-editor-mini/index.tsx +2 -2
  29. package/src/components/condition-row/index.tsx +4 -0
  30. package/src/components/db-condition-row/hooks/use-left.tsx +66 -0
  31. package/src/components/db-condition-row/hooks/use-op.tsx +59 -0
  32. package/src/components/db-condition-row/index.tsx +93 -0
  33. package/src/components/db-condition-row/styles.tsx +43 -0
  34. package/src/components/db-condition-row/types.ts +34 -0
  35. package/src/components/index.ts +1 -0
  36. package/src/components/json-editor-with-variables/editor.tsx +69 -0
  37. package/src/components/json-editor-with-variables/extensions/variable-tag.tsx +4 -3
  38. package/src/components/json-editor-with-variables/index.tsx +5 -60
  39. package/src/components/prompt-editor/editor.tsx +81 -0
  40. package/src/components/prompt-editor/index.tsx +5 -69
  41. package/src/components/prompt-editor-with-inputs/editor.tsx +25 -0
  42. package/src/components/prompt-editor-with-inputs/index.tsx +5 -15
  43. package/src/components/prompt-editor-with-variables/editor.tsx +22 -0
  44. package/src/components/prompt-editor-with-variables/extensions/variable-tag.tsx +10 -18
  45. package/src/components/prompt-editor-with-variables/index.tsx +5 -13
  46. package/src/shared/index.ts +1 -0
  47. package/src/shared/polyfill-create-root/index.tsx +33 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowgram.ai/form-materials",
3
- "version": "0.4.4",
3
+ "version": "0.4.6",
4
4
  "homepage": "https://flowgram.ai/",
5
5
  "repository": "https://github.com/bytedance/flowgram.ai",
6
6
  "license": "MIT",
@@ -30,13 +30,13 @@
30
30
  "chalk": "^5.3.0",
31
31
  "inquirer": "^9.2.7",
32
32
  "immer": "~10.1.1",
33
- "@coze-editor/editor": "0.1.0-alpha.879fbb",
33
+ "@coze-editor/editor": "0.1.0-alpha.5a549c",
34
34
  "@codemirror/view": "~6.38.0",
35
35
  "@codemirror/state": "~6.5.2",
36
36
  "typescript": "^5.8.3",
37
37
  "zod": "^3.24.4",
38
- "@flowgram.ai/editor": "0.4.4",
39
- "@flowgram.ai/json-schema": "0.4.4"
38
+ "@flowgram.ai/editor": "0.4.6",
39
+ "@flowgram.ai/json-schema": "0.4.6"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/lodash": "^4.14.137",
@@ -52,8 +52,8 @@
52
52
  "tsup": "^8.0.1",
53
53
  "typescript": "^5.8.3",
54
54
  "vitest": "^0.34.6",
55
- "@flowgram.ai/ts-config": "0.4.4",
56
- "@flowgram.ai/eslint-config": "0.4.4"
55
+ "@flowgram.ai/eslint-config": "0.4.6",
56
+ "@flowgram.ai/ts-config": "0.4.6"
57
57
  },
58
58
  "peerDependencies": {
59
59
  "react": ">=16.8",
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import React, { useEffect, useRef } from 'react';
7
+
8
+ import {
9
+ ActiveLinePlaceholder,
10
+ createRenderer,
11
+ EditorProvider,
12
+ InferValues,
13
+ } from '@coze-editor/editor/react';
14
+ import preset, { type EditorAPI } from '@coze-editor/editor/preset-code';
15
+ import { EditorView } from '@codemirror/view';
16
+
17
+ import { getSuffixByLanguageId } from './utils';
18
+ import { initTsWorker } from './language-features';
19
+
20
+ import './theme';
21
+ import './language-features';
22
+
23
+ const OriginCodeEditor = createRenderer(preset, [
24
+ EditorView.theme({
25
+ '&.cm-focused': {
26
+ outline: 'none',
27
+ },
28
+ }),
29
+ ]);
30
+
31
+ type Preset = typeof preset;
32
+ type Options = Partial<InferValues<Preset[number]>>;
33
+
34
+ export interface CodeEditorPropsType extends React.PropsWithChildren<{}> {
35
+ value?: string;
36
+ onChange?: (value: string) => void;
37
+ languageId: 'python' | 'typescript' | 'shell' | 'json';
38
+ theme?: 'dark' | 'light';
39
+ placeholder?: string;
40
+ activeLinePlaceholder?: string;
41
+ readonly?: boolean;
42
+ options?: Options;
43
+ }
44
+
45
+ export function CodeEditor({
46
+ value,
47
+ onChange,
48
+ languageId = 'python',
49
+ theme = 'light',
50
+ children,
51
+ placeholder,
52
+ activeLinePlaceholder,
53
+ options,
54
+ readonly,
55
+ }: CodeEditorPropsType) {
56
+ const editorRef = useRef<EditorAPI | null>(null);
57
+
58
+ useEffect(() => {
59
+ if (languageId === 'typescript') {
60
+ initTsWorker();
61
+ }
62
+ }, [languageId]);
63
+
64
+ useEffect(() => {
65
+ // listen to value change
66
+ if (editorRef.current?.getValue() !== value) {
67
+ editorRef.current?.setValue(String(value || ''));
68
+ }
69
+ }, [value]);
70
+
71
+ return (
72
+ <EditorProvider>
73
+ <OriginCodeEditor
74
+ defaultValue={String(value || '')}
75
+ options={{
76
+ uri: `file:///untitled${getSuffixByLanguageId(languageId)}`,
77
+ languageId,
78
+ theme,
79
+ placeholder,
80
+ readOnly: readonly,
81
+ editable: !readonly,
82
+ ...(options || {}),
83
+ }}
84
+ didMount={(editor: EditorAPI) => {
85
+ editorRef.current = editor;
86
+ }}
87
+ onChange={(e) => onChange?.(e.value)}
88
+ >
89
+ {activeLinePlaceholder && (
90
+ <ActiveLinePlaceholder>{activeLinePlaceholder}</ActiveLinePlaceholder>
91
+ )}
92
+ {children}
93
+ </OriginCodeEditor>
94
+ </EditorProvider>
95
+ );
96
+ }
@@ -3,94 +3,10 @@
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
5
 
6
- import React, { useEffect, useRef } from 'react';
6
+ import { lazy } from 'react';
7
7
 
8
- import {
9
- ActiveLinePlaceholder,
10
- createRenderer,
11
- EditorProvider,
12
- InferValues,
13
- } from '@coze-editor/editor/react';
14
- import preset, { type EditorAPI } from '@coze-editor/editor/preset-code';
15
- import { EditorView } from '@codemirror/view';
8
+ export const CodeEditor = lazy(() =>
9
+ import('./editor').then((module) => ({ default: module.CodeEditor }))
10
+ );
16
11
 
17
- import { getSuffixByLanguageId } from './utils';
18
- import { initTsWorker } from './language-features';
19
-
20
- import './theme';
21
- import './language-features';
22
-
23
- const OriginCodeEditor = createRenderer(preset, [
24
- EditorView.theme({
25
- '&.cm-focused': {
26
- outline: 'none',
27
- },
28
- }),
29
- ]);
30
-
31
- type Preset = typeof preset;
32
- type Options = Partial<InferValues<Preset[number]>>;
33
-
34
- export interface CodeEditorPropsType extends React.PropsWithChildren<{}> {
35
- value?: string;
36
- onChange?: (value: string) => void;
37
- languageId: 'python' | 'typescript' | 'shell' | 'json';
38
- theme?: 'dark' | 'light';
39
- placeholder?: string;
40
- activeLinePlaceholder?: string;
41
- readonly?: boolean;
42
- options?: Options;
43
- }
44
-
45
- export function CodeEditor({
46
- value,
47
- onChange,
48
- languageId = 'python',
49
- theme = 'light',
50
- children,
51
- placeholder,
52
- activeLinePlaceholder,
53
- options,
54
- readonly,
55
- }: CodeEditorPropsType) {
56
- const editorRef = useRef<EditorAPI | null>(null);
57
-
58
- useEffect(() => {
59
- if (languageId === 'typescript') {
60
- initTsWorker();
61
- }
62
- }, [languageId]);
63
-
64
- useEffect(() => {
65
- // listen to value change
66
- if (editorRef.current?.getValue() !== value) {
67
- editorRef.current?.setValue(String(value || ''));
68
- }
69
- }, [value]);
70
-
71
- return (
72
- <EditorProvider>
73
- <OriginCodeEditor
74
- defaultValue={value}
75
- options={{
76
- uri: `file:///untitled${getSuffixByLanguageId(languageId)}`,
77
- languageId,
78
- theme,
79
- placeholder,
80
- readOnly: readonly,
81
- editable: !readonly,
82
- ...(options || {}),
83
- }}
84
- didMount={(editor: EditorAPI) => {
85
- editorRef.current = editor;
86
- }}
87
- onChange={(e) => onChange?.(e.value)}
88
- >
89
- {activeLinePlaceholder && (
90
- <ActiveLinePlaceholder>{activeLinePlaceholder}</ActiveLinePlaceholder>
91
- )}
92
- {children}
93
- </OriginCodeEditor>
94
- </EditorProvider>
95
- );
96
- }
12
+ export type { CodeEditorPropsType } from './editor';
@@ -7,55 +7,56 @@ import { createTheme, tags as t } from '@coze-editor/editor/preset-code';
7
7
  import { type Extension } from '@codemirror/state';
8
8
 
9
9
  const colors = {
10
- background: '#151B27',
11
- // syntax
12
- comment: '#FFFFFF63',
13
- key: '#39E5D7',
14
- string: '#FF94D2',
15
- number: '#FF9933',
16
- boolean: '#78B0FF',
17
- null: '#78B0FF',
18
- separator: '#FFFFFFC9',
10
+ background: '#0D1117',
11
+ // syntax - 现代化暗色主题配色
12
+ comment: '#8B949E',
13
+ key: '#7DD3FC',
14
+ variable: '#F472B6',
15
+ string: '#34D399',
16
+ number: '#FBBF24',
17
+ boolean: '#A78BFA',
18
+ null: '#A78BFA',
19
+ separator: '#E6EDF3',
19
20
  };
20
21
 
21
22
  export const darkTheme: Extension = createTheme({
22
23
  variant: 'dark',
23
24
  settings: {
24
25
  background: colors.background,
25
- foreground: '#fff',
26
- caret: '#AEAFAD',
27
- selection: '#d9d9d942',
26
+ foreground: '#E6EDF3',
27
+ caret: '#7DD3FC',
28
+ selection: '#264F7833',
28
29
  gutterBackground: colors.background,
29
- gutterForeground: '#FFFFFF63',
30
+ gutterForeground: '#6E7681',
30
31
  gutterBorderColor: 'transparent',
31
32
  gutterBorderWidth: 0,
32
- lineHighlight: '#272e3d36',
33
- bracketColors: ['#FFEF61', '#DD99FF', '#78B0FF'],
33
+ lineHighlight: '#21262D',
34
+ bracketColors: ['#FBBF24', '#A78BFA', '#7DD3FC'],
34
35
  tooltip: {
35
- backgroundColor: '#363D4D',
36
- color: '#fff',
37
- border: 'none',
36
+ backgroundColor: '#21262D',
37
+ color: '#E6EDF3',
38
+ border: '1px solid #30363D',
38
39
  },
39
40
  link: {
40
- color: '#4daafc',
41
+ color: '#58A6FF',
41
42
  },
42
43
  completionItemHover: {
43
- backgroundColor: '#FFFFFF0F',
44
+ backgroundColor: '#21262D',
44
45
  },
45
46
  completionItemSelected: {
46
- backgroundColor: '#FFFFFF17',
47
+ backgroundColor: '#1F6EEB',
47
48
  },
48
49
  completionItemIcon: {
49
- color: '#FFFFFFC9',
50
+ color: '#8B949E',
50
51
  },
51
52
  completionItemLabel: {
52
- color: '#FFFFFFC9',
53
+ color: '#E6EDF3',
53
54
  },
54
55
  completionItemInfo: {
55
- color: '#FFFFFFC9',
56
+ color: '#8B949E',
56
57
  },
57
58
  completionItemDetail: {
58
- color: '#FFFFFF63',
59
+ color: '#6E7681',
59
60
  },
60
61
  },
61
62
  styles: [
@@ -89,31 +90,49 @@ export const darkTheme: Extension = createTheme({
89
90
  color: colors.separator,
90
91
  },
91
92
 
93
+ // js
94
+ {
95
+ tag: [t.definitionKeyword],
96
+ color: '#C084FC',
97
+ },
98
+ {
99
+ tag: [t.modifier],
100
+ color: '#C084FC',
101
+ },
102
+ {
103
+ tag: [t.controlKeyword],
104
+ color: '#C084FC',
105
+ },
106
+ {
107
+ tag: [t.operatorKeyword],
108
+ color: '#C084FC',
109
+ },
110
+
92
111
  // markdown
93
112
  {
94
113
  tag: [t.heading],
95
- color: '#6b6bff',
114
+ color: '#7DD3FC',
96
115
  },
97
116
  {
98
117
  tag: [t.processingInstruction],
99
- color: '#6b6bff',
118
+ color: '#7DD3FC',
100
119
  },
101
120
 
102
121
  // shell
103
122
  // curl
104
123
  {
105
124
  tag: [t.standard(t.variableName)],
106
- color: '#3BEB84',
125
+ color: '#34D399',
107
126
  },
108
127
  // -X
109
128
  {
110
129
  tag: [t.attributeName],
111
- color: '#FF9933',
130
+ color: '#FBBF24',
112
131
  },
113
132
  // url in string (includes quotes), e.g. "https://..."
114
133
  {
115
134
  tag: [t.special(t.string)],
116
- color: '#78B0FF',
135
+ color: '#7DD3FC',
117
136
  },
118
137
  ],
119
138
  });
@@ -7,55 +7,56 @@ import { createTheme, tags as t } from '@coze-editor/editor/preset-code';
7
7
  import { type Extension } from '@codemirror/state';
8
8
 
9
9
  const colors = {
10
- background: '#F7F7FC',
11
- // syntax
12
- comment: '#000A298A',
13
- key: '#00818C',
14
- string: '#D1009D',
15
- number: '#C74200',
16
- boolean: '#2B57D9',
17
- null: '#2B57D9',
18
- separator: '#0F1529D1',
10
+ background: '#FFFFFF',
11
+ comment: '#6B7280',
12
+ key: '#2563EB',
13
+ variable: '#DC2626',
14
+ string: '#059669',
15
+ number: '#EA580C',
16
+ boolean: '#7C3AED',
17
+ null: '#7C3AED',
18
+ separator: '#374151',
19
19
  };
20
20
 
21
21
  export const lightTheme: Extension = createTheme({
22
22
  variant: 'light',
23
23
  settings: {
24
- background: '#fff',
25
- foreground: '#000',
26
- caret: '#000',
27
- selection: '#d9d9d9',
28
- gutterBackground: '#f0f0f0',
29
- gutterForeground: '#666',
24
+ background: '#FFFFFF',
25
+ foreground: '#1F2937',
26
+ caret: '#2563EB',
27
+ selection: '#E5E7EB',
28
+ gutterBackground: '#F9FAFB',
29
+ gutterForeground: '#6B7280',
30
30
  gutterBorderColor: 'transparent',
31
31
  gutterBorderWidth: 0,
32
- lineHighlight: '#e1e1e180',
33
- bracketColors: ['#FFD700', '#DD99FF', '#78B0FF'],
32
+ lineHighlight: '#F3F4F680',
33
+ bracketColors: ['#F59E0B', '#8B5CF6', '#06B6D4'],
34
34
  tooltip: {
35
- backgroundColor: '#f0f0f0',
36
- color: '#000',
37
- border: '1px solid #ccc',
35
+ backgroundColor: '#FFFFFF',
36
+ color: '#1F2937',
37
+ border: '1px solid #E5E7EB',
38
+ boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
38
39
  },
39
40
  link: {
40
- color: '#007bff',
41
+ color: '#2563EB',
41
42
  },
42
43
  completionItemHover: {
43
- backgroundColor: '#f0f0f0',
44
+ backgroundColor: '#F3F4F6',
44
45
  },
45
46
  completionItemSelected: {
46
- backgroundColor: '#e0e0e0',
47
+ backgroundColor: '#E5E7EB',
47
48
  },
48
49
  completionItemIcon: {
49
- color: '#333',
50
+ color: '#4B5563',
50
51
  },
51
52
  completionItemLabel: {
52
- color: '#333',
53
+ color: '#1F2937',
53
54
  },
54
55
  completionItemInfo: {
55
- color: '#333',
56
+ color: '#4B5563',
56
57
  },
57
58
  completionItemDetail: {
58
- color: '#666',
59
+ color: '#6B7280',
59
60
  },
60
61
  },
61
62
  styles: [
@@ -68,6 +69,11 @@ export const lightTheme: Extension = createTheme({
68
69
  tag: [t.propertyName],
69
70
  color: colors.key,
70
71
  },
72
+ {
73
+ tag: [t.variableName],
74
+ color: colors.variable,
75
+ },
76
+
71
77
  {
72
78
  tag: [t.string],
73
79
  color: colors.string,
@@ -92,28 +98,46 @@ export const lightTheme: Extension = createTheme({
92
98
  // markdown
93
99
  {
94
100
  tag: [t.heading],
95
- color: '#3e76ef',
101
+ color: '#2563EB',
96
102
  },
97
103
  {
98
104
  tag: [t.processingInstruction],
99
- color: '#3e76ef',
105
+ color: '#2563EB',
106
+ },
107
+
108
+ // js
109
+ {
110
+ tag: [t.definitionKeyword],
111
+ color: '#9333EA',
112
+ },
113
+ {
114
+ tag: [t.modifier],
115
+ color: '#9333EA',
116
+ },
117
+ {
118
+ tag: [t.controlKeyword],
119
+ color: '#9333EA',
120
+ },
121
+ {
122
+ tag: [t.operatorKeyword],
123
+ color: '#9333EA',
100
124
  },
101
125
 
102
126
  // shell
103
127
  // curl
104
128
  {
105
129
  tag: [t.standard(t.variableName)],
106
- color: '#00804A',
130
+ color: '#059669',
107
131
  },
108
132
  // -X
109
133
  {
110
134
  tag: [t.attributeName],
111
- color: '#C74200',
135
+ color: '#EA580C',
112
136
  },
113
137
  // url in string (includes quotes), e.g. "https://..."
114
138
  {
115
139
  tag: [t.special(t.string)],
116
- color: '#2B57D9',
140
+ color: '#2563EB',
117
141
  },
118
142
  ],
119
143
  });
@@ -7,11 +7,10 @@ import React from 'react';
7
7
 
8
8
  import styled from 'styled-components';
9
9
 
10
- import { CodeEditor, CodeEditorPropsType } from '@/components/code-editor';
10
+ import { CodeEditor, type CodeEditorPropsType } from '@/components/code-editor';
11
11
 
12
12
  const UIMini = styled.div`
13
13
  .ͼ1 .cm-content {
14
- padding: 0;
15
14
  }
16
15
  `;
17
16
 
@@ -23,6 +22,7 @@ export function CodeEditorMini(props: CodeEditorPropsType) {
23
22
  options={{
24
23
  lineNumbersGutter: false,
25
24
  foldGutter: false,
25
+ minHeight: 24,
26
26
  ...(props.options || {}),
27
27
  }}
28
28
  />
@@ -15,6 +15,7 @@ import { ConditionRowValueType, IRules, OpConfigs } from './types';
15
15
  import { UIContainer, UILeft, UIOperator, UIRight, UIValues } from './styles';
16
16
  import { useRule } from './hooks/useRule';
17
17
  import { useOp } from './hooks/useOp';
18
+ import { defaultOpConfigs, defaultRules } from './constants';
18
19
 
19
20
  interface PropTypes {
20
21
  value?: ConditionRowValueType;
@@ -96,4 +97,7 @@ export function ConditionRow({
96
97
  );
97
98
  }
98
99
 
100
+ ConditionRow.defaultRules = defaultRules;
101
+ ConditionRow.defaultOpConfigs = defaultOpConfigs;
102
+
99
103
  export { type ConditionRowValueType };
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { useMemo } from 'react';
7
+ import React from 'react';
8
+
9
+ import { JsonSchemaTypeManager, useTypeManager } from '@flowgram.ai/json-schema';
10
+ import { Icon } from '@douyinfe/semi-ui';
11
+
12
+ import { ConditionRow } from '@/components';
13
+
14
+ import { DBConditionOptionType, IRules } from '../types';
15
+ import { UIOptionLabel, UISelect } from '../styles';
16
+
17
+ const defaultRules = ConditionRow.defaultRules;
18
+
19
+ interface HookParams {
20
+ left?: string;
21
+ options?: DBConditionOptionType[];
22
+ userRules?: IRules;
23
+ readonly?: boolean;
24
+ onChange: (leftKey: string) => void;
25
+ }
26
+
27
+ export function useLeft({ left, options, userRules, readonly, onChange }: HookParams) {
28
+ const rules = useMemo(() => ({ ...defaultRules, ...(userRules || {}) }), [userRules]);
29
+
30
+ const typeManager = useTypeManager() as JsonSchemaTypeManager;
31
+
32
+ const rule = useMemo(() => {
33
+ if (!left) return undefined;
34
+
35
+ const option = options?.find((item) => item.value === left);
36
+
37
+ if (!option?.schema?.type) {
38
+ return undefined;
39
+ }
40
+
41
+ return rules[option.schema.type];
42
+ }, [left, options, rules]);
43
+
44
+ const renderDBOptionSelect = () => (
45
+ <UISelect
46
+ disabled={readonly}
47
+ size="small"
48
+ style={{ width: '100%' }}
49
+ value={left}
50
+ onChange={(v) => onChange(v as string)}
51
+ optionList={
52
+ options?.map((item) => ({
53
+ label: (
54
+ <UIOptionLabel>
55
+ <Icon size="small" svg={typeManager.getDisplayIcon(item.schema)} />
56
+ {item.label}
57
+ </UIOptionLabel>
58
+ ),
59
+ value: item.value,
60
+ })) || []
61
+ }
62
+ />
63
+ );
64
+
65
+ return { rule, renderDBOptionSelect };
66
+ }
@@ -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, { useMemo } from 'react';
7
+
8
+ import { I18n } from '@flowgram.ai/editor';
9
+ import { Button, Select } from '@douyinfe/semi-ui';
10
+ import { IconChevronDownStroked } from '@douyinfe/semi-icons';
11
+
12
+ import { ConditionRow } from '@/components';
13
+
14
+ import { IRule, OpConfigs } from '../types';
15
+
16
+ const defaultOpConfigs = ConditionRow.defaultOpConfigs;
17
+
18
+ interface HookParams {
19
+ rule?: IRule;
20
+ op?: string;
21
+ onChange: (op: string) => void;
22
+ readonly?: boolean;
23
+ userOps?: OpConfigs;
24
+ }
25
+
26
+ export function useOp({ rule, op, onChange, readonly, userOps }: HookParams) {
27
+ const options = useMemo(
28
+ () =>
29
+ Object.keys(rule || {}).map((_op) => ({
30
+ ...(defaultOpConfigs[_op] || {}),
31
+ ...(userOps?.[_op] || {}),
32
+ value: _op,
33
+ label: I18n.t(userOps?.[_op]?.label || defaultOpConfigs[_op]?.label),
34
+ })),
35
+ [rule, userOps]
36
+ );
37
+
38
+ const opConfig = useMemo(() => defaultOpConfigs[op as string], [op]);
39
+
40
+ const renderOpSelect = () => (
41
+ <Select
42
+ style={{ height: 22 }}
43
+ disabled={readonly}
44
+ size="small"
45
+ value={op}
46
+ optionList={options}
47
+ onChange={(v) => {
48
+ onChange(v as string);
49
+ }}
50
+ triggerRender={({ value }) => (
51
+ <Button size="small" disabled={!rule}>
52
+ {opConfig?.abbreviation || <IconChevronDownStroked size="small" />}
53
+ </Button>
54
+ )}
55
+ />
56
+ );
57
+
58
+ return { renderOpSelect, opConfig };
59
+ }