@flowgram.ai/form-antd-materials 0.1.8

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 (61) hide show
  1. package/dist/esm/index.js +1949 -0
  2. package/dist/esm/index.js.map +1 -0
  3. package/dist/index.d.mts +293 -0
  4. package/dist/index.d.ts +293 -0
  5. package/dist/index.js +1990 -0
  6. package/dist/index.js.map +1 -0
  7. package/package.json +62 -0
  8. package/src/components/batch-variable-selector/config.json +5 -0
  9. package/src/components/batch-variable-selector/index.tsx +19 -0
  10. package/src/components/condition-row/config.json +5 -0
  11. package/src/components/condition-row/constants.ts +123 -0
  12. package/src/components/condition-row/hooks/styles.tsx +21 -0
  13. package/src/components/condition-row/hooks/useOp.tsx +52 -0
  14. package/src/components/condition-row/hooks/useRule.ts +30 -0
  15. package/src/components/condition-row/index.tsx +73 -0
  16. package/src/components/condition-row/styles.tsx +25 -0
  17. package/src/components/condition-row/types.ts +37 -0
  18. package/src/components/constant-input/config.json +6 -0
  19. package/src/components/constant-input/index.tsx +83 -0
  20. package/src/components/constant-input/styles.tsx +25 -0
  21. package/src/components/constant-input/types.ts +18 -0
  22. package/src/components/dynamic-value-input/config.json +5 -0
  23. package/src/components/dynamic-value-input/index.tsx +88 -0
  24. package/src/components/dynamic-value-input/styles.tsx +29 -0
  25. package/src/components/index.ts +7 -0
  26. package/src/components/json-schema-editor/components/blur-input.tsx +21 -0
  27. package/src/components/json-schema-editor/config.json +5 -0
  28. package/src/components/json-schema-editor/default-value.tsx +133 -0
  29. package/src/components/json-schema-editor/hooks.tsx +166 -0
  30. package/src/components/json-schema-editor/index.tsx +256 -0
  31. package/src/components/json-schema-editor/styles.tsx +223 -0
  32. package/src/components/json-schema-editor/types.ts +21 -0
  33. package/src/components/json-schema-editor/utils.ts +24 -0
  34. package/src/components/type-selector/config.json +5 -0
  35. package/src/components/type-selector/constants.tsx +372 -0
  36. package/src/components/type-selector/index.tsx +58 -0
  37. package/src/components/variable-selector/config.json +5 -0
  38. package/src/components/variable-selector/index.tsx +77 -0
  39. package/src/components/variable-selector/styles.tsx +40 -0
  40. package/src/components/variable-selector/types.ts +15 -0
  41. package/src/components/variable-selector/use-variable-tree.tsx +102 -0
  42. package/src/effects/auto-rename-ref/config.json +5 -0
  43. package/src/effects/auto-rename-ref/index.ts +104 -0
  44. package/src/effects/index.ts +3 -0
  45. package/src/effects/provide-batch-input/config.json +5 -0
  46. package/src/effects/provide-batch-input/index.ts +38 -0
  47. package/src/effects/provide-batch-outputs/config.json +5 -0
  48. package/src/effects/provide-batch-outputs/index.ts +34 -0
  49. package/src/index.ts +4 -0
  50. package/src/typings/flow-value/config.json +5 -0
  51. package/src/typings/flow-value/index.ts +27 -0
  52. package/src/typings/index.ts +2 -0
  53. package/src/typings/json-schema/config.json +5 -0
  54. package/src/typings/json-schema/index.ts +31 -0
  55. package/src/utils/format-legacy-refs/config.json +5 -0
  56. package/src/utils/format-legacy-refs/index.ts +153 -0
  57. package/src/utils/format-legacy-refs/readme.md +38 -0
  58. package/src/utils/index.ts +3 -0
  59. package/src/utils/json-schema/config.json +5 -0
  60. package/src/utils/json-schema/index.ts +161 -0
  61. package/src/utils/svg-icon/index.tsx +8 -0
@@ -0,0 +1,73 @@
1
+ 'use client';
2
+
3
+ import React, { useMemo } from 'react';
4
+
5
+ import { VariableSelector } from '../variable-selector';
6
+ import { DynamicValueInput } from '../dynamic-value-input';
7
+ import { UIInput } from '../constant-input/styles';
8
+ import { JsonSchemaBasicType } from '../../typings';
9
+ import { ConditionRowValueType, Op } from './types';
10
+ import { UIContainer, UILeft, UIOperator, UIRight, UIValues } from './styles';
11
+ import { useRule } from './hooks/useRule';
12
+ import { useOp } from './hooks/useOp';
13
+
14
+ interface PropTypes {
15
+ value?: ConditionRowValueType;
16
+ onChange: (value?: ConditionRowValueType) => void;
17
+ style?: React.CSSProperties;
18
+ readonly?: boolean;
19
+ }
20
+
21
+ export function ConditionRow({ style, value, onChange, readonly }: PropTypes) {
22
+ const { left, operator, right } = value || {};
23
+ const { rule } = useRule(left);
24
+ const { renderOpSelect, opConfig } = useOp({
25
+ rule,
26
+ op: operator,
27
+ onChange: (v) => onChange({ ...value, operator: v }),
28
+ });
29
+
30
+ const targetSchema = useMemo(() => {
31
+ const targetType: JsonSchemaBasicType | null = rule?.[operator as Op] || null;
32
+ return targetType ? { type: targetType, extra: { weak: true } } : null;
33
+ }, [rule, opConfig]);
34
+
35
+ return (
36
+ <UIContainer style={style}>
37
+ <UIOperator>{renderOpSelect()}</UIOperator>
38
+ <UIValues>
39
+ <UILeft>
40
+ <VariableSelector
41
+ readonly={readonly}
42
+ style={{ width: '100%' }}
43
+ value={left?.content}
44
+ onChange={(v) =>
45
+ onChange({
46
+ ...value,
47
+ left: {
48
+ type: 'ref',
49
+ content: v,
50
+ },
51
+ })
52
+ }
53
+ allowClear={true}
54
+ />
55
+ </UILeft>
56
+ <UIRight>
57
+ {targetSchema ? (
58
+ <DynamicValueInput
59
+ readonly={readonly || !rule}
60
+ value={right}
61
+ schema={targetSchema}
62
+ onChange={(v) => onChange({ ...value, right: v })}
63
+ />
64
+ ) : (
65
+ <UIInput size="small" disabled value={opConfig?.rightDisplay || 'Empty'} />
66
+ )}
67
+ </UIRight>
68
+ </UIValues>
69
+ </UIContainer>
70
+ );
71
+ }
72
+
73
+ export type { ConditionRowValueType, Op, VariableSelector };
@@ -0,0 +1,25 @@
1
+ import styled from 'styled-components';
2
+
3
+ export const UIContainer = styled.div`
4
+ display: flex;
5
+ align-items: center;
6
+ gap: 4px;
7
+ `;
8
+
9
+ export const UIOperator = styled.div``;
10
+
11
+ export const UILeft = styled.div`
12
+ width: 100%;
13
+ `;
14
+
15
+ export const UIRight = styled.div`
16
+ width: 100%;
17
+ `;
18
+
19
+ export const UIValues = styled.div`
20
+ flex-grow: 1;
21
+ display: flex;
22
+ flex-direction: column;
23
+ align-items: center;
24
+ gap: 4px;
25
+ `;
@@ -0,0 +1,37 @@
1
+ import { IFlowConstantRefValue, IFlowRefValue, JsonSchemaBasicType } from '../../typings';
2
+
3
+ export enum Op {
4
+ EQ = 'eq',
5
+ NEQ = 'neq',
6
+ GT = 'gt',
7
+ GTE = 'gte',
8
+ LT = 'lt',
9
+ LTE = 'lte',
10
+ IN = 'in',
11
+ NIN = 'nin',
12
+ CONTAINS = 'contains',
13
+ NOT_CONTAINS = 'not_contains',
14
+ IS_EMPTY = 'is_empty',
15
+ IS_NOT_EMPTY = 'is_not_empty',
16
+ IS_TRUE = 'is_true',
17
+ IS_FALSE = 'is_false',
18
+ }
19
+
20
+ export interface OpConfig {
21
+ label: string;
22
+ abbreviation: string;
23
+ // When right is not a value, display this text
24
+ rightDisplay?: string;
25
+ }
26
+
27
+ export type OpConfigs = Record<Op, OpConfig>;
28
+
29
+ export type IRule = Partial<Record<Op, JsonSchemaBasicType | null>>;
30
+
31
+ export type IRules = Record<JsonSchemaBasicType, IRule>;
32
+
33
+ export interface ConditionRowValueType {
34
+ left?: IFlowRefValue;
35
+ operator?: Op;
36
+ right?: IFlowConstantRefValue;
37
+ }
@@ -0,0 +1,6 @@
1
+
2
+ {
3
+ "name": "constant-input",
4
+ "depMaterials": ["typings/json-schema"],
5
+ "depPackages": []
6
+ }
@@ -0,0 +1,83 @@
1
+ /* eslint-disable react/prop-types */
2
+ import React, { useMemo } from 'react';
3
+
4
+ import { PropsType, Strategy } from './types';
5
+ import { UIInput, UIInputNumber, UISelect } from './styles';
6
+
7
+ const defaultStrategies: Strategy[] = [
8
+ {
9
+ hit: (schema) => schema?.type === 'string',
10
+ Renderer: (props) => (
11
+ <UIInput
12
+ placeholder="Please Input String"
13
+ size="small"
14
+ disabled={props.readonly}
15
+ {...props}
16
+ />
17
+ ),
18
+ },
19
+ {
20
+ hit: (schema) => schema?.type === 'number',
21
+ Renderer: (props) => (
22
+ <UIInputNumber
23
+ placeholder="Please Input Number"
24
+ size="small"
25
+ disabled={props.readonly}
26
+ {...props}
27
+ />
28
+ ),
29
+ },
30
+ {
31
+ hit: (schema) => schema?.type === 'integer',
32
+ Renderer: (props) => (
33
+ <UIInputNumber
34
+ placeholder="Please Input Integer"
35
+ size="small"
36
+ disabled={props.readonly}
37
+ precision={0}
38
+ {...props}
39
+ />
40
+ ),
41
+ },
42
+ {
43
+ hit: (schema) => schema?.type === 'boolean',
44
+ Renderer: (props) => {
45
+ const { value, onChange, ...rest } = props;
46
+ return (
47
+ <UISelect
48
+ placeholder="Please Select Boolean"
49
+ size="small"
50
+ disabled={props.readonly}
51
+ options={[
52
+ { label: 'True', value: 1 },
53
+ { label: 'False', value: 0 },
54
+ ]}
55
+ value={value ? 1 : 0}
56
+ onChange={(value) => onChange?.(!!value)}
57
+ {...rest}
58
+ />
59
+ );
60
+ },
61
+ },
62
+ ];
63
+
64
+ export function ConstantInput(props: PropsType) {
65
+ const { value, onChange, schema, strategies: extraStrategies, readonly, ...rest } = props;
66
+
67
+ const strategies = useMemo(
68
+ () => [...defaultStrategies, ...(extraStrategies || [])],
69
+ [extraStrategies]
70
+ );
71
+
72
+ const Renderer = useMemo(() => {
73
+ const strategy = strategies.find((_strategy) => _strategy.hit(schema));
74
+
75
+ return strategy?.Renderer;
76
+ }, [strategies, schema]);
77
+
78
+ if (!Renderer) {
79
+ return <UIInput size="small" disabled placeholder="Unsupported type" />;
80
+ }
81
+
82
+ return <Renderer value={value} onChange={onChange} readonly={readonly} {...rest} />;
83
+ }
@@ -0,0 +1,25 @@
1
+ import styled from 'styled-components';
2
+ import type { SelectProps } from 'antd/es/select';
3
+ import type { InputNumberProps } from 'antd/es/input-number';
4
+ import { Input, InputNumber, Select } from 'antd';
5
+
6
+ const commonStyle = `
7
+ width: 100%;
8
+ height: 22px;
9
+ border-radius: 6px;
10
+ padding: 4px 11px;
11
+ display: flex;
12
+ justify-content: center;
13
+ align-items: center;
14
+ `;
15
+
16
+ export const UIInput = styled(Input)`
17
+ ${commonStyle}
18
+ `;
19
+ export const UIInputNumber: React.ComponentType<InputNumberProps> = styled(InputNumber)`
20
+ ${commonStyle}
21
+ padding: 4px 4px;
22
+ `;
23
+ export const UISelect: React.ComponentType<SelectProps> = styled(Select)`
24
+ ${commonStyle}
25
+ `;
@@ -0,0 +1,18 @@
1
+ import { IJsonSchema } from '../../typings';
2
+
3
+ export interface Strategy<Value = any> {
4
+ hit: (schema: IJsonSchema) => boolean;
5
+ Renderer: React.FC<RendererProps<Value>>;
6
+ }
7
+
8
+ export interface RendererProps<Value = any> {
9
+ value?: Value;
10
+ onChange?: (value: Value) => void;
11
+ readonly?: boolean;
12
+ }
13
+
14
+ export interface PropsType extends RendererProps {
15
+ schema: IJsonSchema;
16
+ strategies?: Strategy[];
17
+ [key: string]: any;
18
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "dynamic-value-input",
3
+ "depMaterials": ["flow-value", "constant-input", "variable-selector"],
4
+ "depPackages": ["styled-components"]
5
+ }
@@ -0,0 +1,88 @@
1
+ import React, { useMemo } from 'react';
2
+
3
+ import { theme } from 'antd';
4
+ import { SettingFilled } from '@ant-design/icons';
5
+
6
+ import { VariableSelector } from '../variable-selector';
7
+ import { Strategy } from '../constant-input/types';
8
+ import { ConstantInput } from '../constant-input';
9
+ import { IFlowConstantRefValue } from '../../typings/flow-value';
10
+ import { IJsonSchema } from '../../typings';
11
+ import { UIContainer, UIMain, UITrigger } from './styles';
12
+
13
+ const { useToken } = theme;
14
+
15
+ interface PropsType {
16
+ value?: IFlowConstantRefValue;
17
+ onChange: (value?: IFlowConstantRefValue) => void;
18
+ readonly?: boolean;
19
+ hasError?: boolean;
20
+ style?: React.CSSProperties;
21
+ schema?: IJsonSchema;
22
+ constantProps?: {
23
+ strategies?: Strategy[];
24
+ [key: string]: any;
25
+ };
26
+ }
27
+
28
+ export function DynamicValueInput({
29
+ value,
30
+ onChange,
31
+ readonly,
32
+ style,
33
+ schema,
34
+ constantProps,
35
+ }: PropsType) {
36
+ const { token } = useToken();
37
+
38
+ // When is number type, include integer as well
39
+ const includeSchema = useMemo(() => {
40
+ if (schema?.type === 'number') {
41
+ return [schema, { type: 'integer' }];
42
+ }
43
+ return schema;
44
+ }, [schema]);
45
+
46
+ const renderMain = () => {
47
+ if (value?.type === 'ref') {
48
+ // Display Variable Or Delete
49
+ return (
50
+ <VariableSelector
51
+ style={{ width: '100%' }}
52
+ value={value?.content}
53
+ onChange={(_v) => onChange(_v ? { type: 'ref', content: _v } : undefined)}
54
+ includeSchema={includeSchema}
55
+ readonly={readonly}
56
+ />
57
+ );
58
+ }
59
+
60
+ return (
61
+ <ConstantInput
62
+ value={value?.content}
63
+ onChange={(_v) => onChange({ type: 'constant', content: _v })}
64
+ schema={schema || { type: 'string' }}
65
+ readonly={readonly}
66
+ {...constantProps}
67
+ />
68
+ );
69
+ };
70
+
71
+ const renderTrigger = () => (
72
+ <VariableSelector
73
+ style={{ width: '100%' }}
74
+ value={value?.type === 'ref' ? value?.content : undefined}
75
+ onChange={(_v) => onChange({ type: 'ref', content: _v })}
76
+ includeSchema={includeSchema}
77
+ readonly={readonly}
78
+ triggerRender={() => <SettingFilled style={{ color: token.colorPrimary }} />}
79
+ />
80
+ );
81
+
82
+ return (
83
+ <UIContainer style={style}>
84
+ <UIMain>{renderMain()}</UIMain>
85
+ <UITrigger>{renderTrigger()}</UITrigger>
86
+ </UIContainer>
87
+ );
88
+ }
@@ -0,0 +1,29 @@
1
+ import styled from 'styled-components';
2
+
3
+ export const UIContainer = styled.div`
4
+ display: flex;
5
+ align-items: center;
6
+ gap: 5px;
7
+ `;
8
+
9
+ export const UIMain = styled.div`
10
+ flex-grow: 1;
11
+ `;
12
+
13
+ export const UITrigger = styled.div`
14
+ outline: none;
15
+ height: 22px;
16
+ min-height: 22px;
17
+ line-height: 22px;
18
+
19
+ & .ant-select-selection-wrap {
20
+ display: none;
21
+ }
22
+
23
+ & .ant-select-arrow {
24
+ right: 6px;
25
+ & > .anticon {
26
+ pointer-events: none !important;
27
+ }
28
+ }
29
+ `;
@@ -0,0 +1,7 @@
1
+ export * from './variable-selector';
2
+ export * from './type-selector';
3
+ export * from './json-schema-editor';
4
+ export * from './batch-variable-selector';
5
+ export * from './constant-input';
6
+ export * from './dynamic-value-input';
7
+ export * from './condition-row';
@@ -0,0 +1,21 @@
1
+ import React, { useEffect, useState } from 'react';
2
+
3
+ import { Input, InputProps } from 'antd';
4
+
5
+ export function BlurInput(props: InputProps) {
6
+ const [value, setValue] = useState('');
7
+
8
+ useEffect(() => {
9
+ setValue(props.value as string);
10
+ }, [props.value]);
11
+
12
+ return (
13
+ <Input
14
+ {...props}
15
+ value={value}
16
+ onChange={(value) => {
17
+ setValue((value as any).target?.value || '');
18
+ }}
19
+ />
20
+ );
21
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "json-schema-editor",
3
+ "depMaterials": ["type-selector", "typings/json-schema"],
4
+ "depPackages": ["styled-components"]
5
+ }
@@ -0,0 +1,133 @@
1
+ import React, { useCallback, useRef, useState } from 'react';
2
+
3
+ import { Button, Tooltip, theme } from 'antd';
4
+ import { CodeOutlined } from '@ant-design/icons';
5
+
6
+ import { ConstantInput } from '../constant-input';
7
+ import { IJsonSchema } from '../../typings';
8
+ import { getValueType } from './utils';
9
+ import {
10
+ ConstantInputWrapper,
11
+ JSONHeader,
12
+ JSONHeaderLeft,
13
+ JSONHeaderRight,
14
+ JSONViewerWrapper,
15
+ } from './styles';
16
+
17
+ const { useToken } = theme;
18
+
19
+ /**
20
+ * 根据不同的数据类型渲染对应的默认值输入组件。
21
+ * @param props - 组件属性,包括 value, type, placeholder, onChange。
22
+ * @returns 返回对应类型的输入组件或 null。
23
+ */
24
+ export function DefaultValue(props: {
25
+ value: any;
26
+ schema?: IJsonSchema;
27
+ name?: string;
28
+ type?: string;
29
+ placeholder?: string;
30
+ jsonFormatText?: string;
31
+ onChange: (value: any) => void;
32
+ }) {
33
+ const { token } = useToken();
34
+ const { value, schema, type, onChange, placeholder, jsonFormatText } = props;
35
+
36
+ const wrapperRef = useRef<HTMLDivElement>(null);
37
+
38
+ // TODO add JsonViewer
39
+ // const JsonViewerRef = useRef<JsonViewer>(null);
40
+
41
+ // 为 JsonViewer 添加状态管理
42
+ const [internalJsonValue, setInternalJsonValue] = useState<string>(
43
+ getValueType(value) === 'string' ? value : ''
44
+ );
45
+
46
+ // 使用 useCallback 创建稳定的回调函数
47
+ // const handleJsonChange = useCallback((val: string) => {
48
+ // // 只在值真正改变时才更新状态
49
+ // if (val !== internalJsonValue) {
50
+ // setInternalJsonValue(val);
51
+ // }
52
+ // }, []);
53
+
54
+ // 处理编辑完成事件
55
+ const handleEditComplete = useCallback(() => {
56
+ // 只有当存在key,编辑完成时才触发父组件的 onChange
57
+ onChange(internalJsonValue);
58
+ // 确保在更新后移除焦点
59
+ requestAnimationFrame(() => {
60
+ // JsonViewerRef.current?.format();
61
+ wrapperRef.current?.blur();
62
+ });
63
+ // setJsonReadOnly(true);
64
+ }, [internalJsonValue, onChange]);
65
+
66
+ // const [jsonReadOnly, setJsonReadOnly] = useState<boolean>(true);
67
+
68
+ const handleFormatJson = useCallback(() => {
69
+ try {
70
+ const parsed = JSON.parse(internalJsonValue);
71
+ const formatted = JSON.stringify(parsed, null, 4);
72
+ setInternalJsonValue(formatted);
73
+ onChange(formatted);
74
+ } catch (error) {
75
+ console.error('Invalid JSON:', error);
76
+ }
77
+ }, [internalJsonValue, onChange]);
78
+
79
+ return type === 'object' ? (
80
+ <>
81
+ <JSONHeader>
82
+ <JSONHeaderLeft>json</JSONHeaderLeft>
83
+ <JSONHeaderRight>
84
+ <Tooltip title={jsonFormatText ?? 'Format'}>
85
+ <Button
86
+ icon={<CodeOutlined style={{ color: token.colorPrimary }} />}
87
+ size="small"
88
+ onClick={handleFormatJson}
89
+ />
90
+ </Tooltip>
91
+ </JSONHeaderRight>
92
+ </JSONHeader>
93
+
94
+ <JSONViewerWrapper
95
+ ref={wrapperRef}
96
+ tabIndex={-1}
97
+ onBlur={(e) => {
98
+ if (wrapperRef.current && !wrapperRef.current?.contains(e.relatedTarget as Node)) {
99
+ handleEditComplete();
100
+ }
101
+ }}
102
+ onClick={(e: React.MouseEvent) => {
103
+ // setJsonReadOnly(false);
104
+ }}
105
+ >
106
+ {/* <JsonViewer
107
+ ref={JsonViewerRef}
108
+ value={getValueType(value) === 'string' ? value : ''}
109
+ height={120}
110
+ width="100%"
111
+ showSearch={false}
112
+ options={{
113
+ readOnly: jsonReadOnly,
114
+ formatOptions: { tabSize: 4, insertSpaces: true, eol: '\n' },
115
+ }}
116
+ style={{
117
+ padding: 0,
118
+ }}
119
+ onChange={handleJsonChange}
120
+ /> */}
121
+ </JSONViewerWrapper>
122
+ </>
123
+ ) : (
124
+ <ConstantInputWrapper>
125
+ <ConstantInput
126
+ value={value}
127
+ onChange={(_v) => onChange(_v)}
128
+ schema={schema || { type: 'string' }}
129
+ placeholder={placeholder ?? 'Default value if parameter is not provided'}
130
+ />
131
+ </ConstantInputWrapper>
132
+ );
133
+ }