Преглед изворни кода

refactor(condition): condition context (#821)

Yiwei Mao пре 4 месеци
родитељ
комит
42f05f25a8
27 измењених фајлова са 523 додато и 452 уклоњено
  1. 28 0
      packages/materials/form-materials/src/components/condition-context/context.tsx
  2. 99 0
      packages/materials/form-materials/src/components/condition-context/hooks/use-condition.tsx
  3. 14 0
      packages/materials/form-materials/src/components/condition-context/index.tsx
  4. 86 0
      packages/materials/form-materials/src/components/condition-context/op.ts
  5. 22 0
      packages/materials/form-materials/src/components/condition-context/types.ts
  6. 0 136
      packages/materials/form-materials/src/components/condition-row/constants.ts
  7. 0 56
      packages/materials/form-materials/src/components/condition-row/hooks/useOp.tsx
  8. 0 35
      packages/materials/form-materials/src/components/condition-row/hooks/useRule.ts
  9. 44 22
      packages/materials/form-materials/src/components/condition-row/index.tsx
  10. 0 30
      packages/materials/form-materials/src/components/condition-row/types.ts
  11. 0 66
      packages/materials/form-materials/src/components/db-condition-row/hooks/use-left.tsx
  12. 0 59
      packages/materials/form-materials/src/components/db-condition-row/hooks/use-op.tsx
  13. 76 24
      packages/materials/form-materials/src/components/db-condition-row/index.tsx
  14. 0 13
      packages/materials/form-materials/src/components/db-condition-row/types.ts
  15. 4 2
      packages/materials/form-materials/src/plugins/json-schema-preset/create-type-preset-plugin.tsx
  16. 1 1
      packages/materials/form-materials/src/plugins/json-schema-preset/index.tsx
  17. 1 1
      packages/materials/form-materials/src/plugins/json-schema-preset/react.tsx
  18. 10 1
      packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/array.tsx
  19. 17 1
      packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/boolean.tsx
  20. 13 1
      packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/date-time.tsx
  21. 7 0
      packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/index.tsx
  22. 19 1
      packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/integer.tsx
  23. 31 0
      packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/map.tsx
  24. 19 1
      packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/number.tsx
  25. 6 1
      packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/object.tsx
  26. 19 1
      packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/string.tsx
  27. 7 0
      packages/materials/form-materials/src/plugins/json-schema-preset/types.ts

+ 28 - 0
packages/materials/form-materials/src/components/condition-context/context.tsx

@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
+ * SPDX-License-Identifier: MIT
+ */
+
+import React, { createContext, useContext } from 'react';
+
+import { IConditionRule, ConditionOpConfigs } from './types';
+import { defaultConditionOpConfigs } from './op';
+
+interface ContextType {
+  rules?: Record<string, IConditionRule>;
+  ops?: ConditionOpConfigs;
+}
+
+export const ConditionContext = createContext<ContextType>({
+  rules: {},
+  ops: defaultConditionOpConfigs,
+});
+
+export const ConditionProvider = (props: React.PropsWithChildren<ContextType>) => {
+  const { rules, ops } = props;
+  return (
+    <ConditionContext.Provider value={{ rules, ops }}>{props.children}</ConditionContext.Provider>
+  );
+};
+
+export const useConditionContext = () => useContext(ConditionContext);

+ 99 - 0
packages/materials/form-materials/src/components/condition-context/hooks/use-condition.tsx

@@ -0,0 +1,99 @@
+/**
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
+ * SPDX-License-Identifier: MIT
+ */
+
+import { useMemo } from 'react';
+
+import { IJsonSchema } from '@flowgram.ai/json-schema';
+import { I18n } from '@flowgram.ai/editor';
+
+import { useTypeManager } from '@/plugins';
+
+import { IConditionRule, ConditionOpConfigs } from '../types';
+import { useConditionContext } from '../context';
+
+interface HooksParams {
+  leftSchema?: IJsonSchema;
+  operator?: string;
+
+  /**
+   * custom rule config
+   */
+  ruleConfig?: {
+    ops?: ConditionOpConfigs;
+    rules?: Record<string, IConditionRule>;
+  };
+}
+
+export function useCondition({ leftSchema, operator, ruleConfig }: HooksParams) {
+  const typeManager = useTypeManager();
+  const { rules: contextRules, ops: contextOps } = useConditionContext();
+
+  // 合并用户规则和上下文规则
+  const userRules = useMemo(
+    () => ruleConfig?.rules || contextRules || {},
+    [contextRules, ruleConfig?.rules]
+  );
+
+  // 合并用户操作符和上下文操作符
+  const allOps = useMemo(() => ruleConfig?.ops || contextOps || {}, [contextOps, ruleConfig?.ops]);
+
+  // 获取类型配置
+  const config = useMemo(
+    () => (leftSchema ? typeManager.getTypeBySchema(leftSchema) : undefined),
+    [leftSchema, typeManager]
+  );
+
+  // 计算规则
+  const rule = useMemo(() => {
+    if (!config) {
+      return undefined;
+    }
+    if (userRules[config.type]) {
+      return userRules[config.type];
+    }
+    if (typeof config.conditionRule === 'function') {
+      return config.conditionRule(leftSchema);
+    }
+    return config.conditionRule;
+  }, [userRules, leftSchema, config]);
+
+  // 计算操作符选项列表
+  const opOptionList = useMemo(
+    () =>
+      Object.keys(rule || {})
+        .filter((_op) => allOps[_op])
+        .map((_op) => ({
+          ...(allOps?.[_op] || {}),
+          value: _op,
+          label: I18n.t(allOps?.[_op]?.label || _op),
+        })),
+    [rule, allOps]
+  );
+
+  // get target schema
+  const targetSchema = useMemo(() => {
+    const targetType: string | IJsonSchema | null = rule?.[operator || ''] || null;
+
+    if (!targetType) {
+      return undefined;
+    }
+
+    if (typeof targetType === 'string') {
+      return { type: targetType, extra: { weak: true } };
+    }
+
+    return targetType;
+  }, [rule, operator]);
+
+  // get current operator config
+  const opConfig = useMemo(() => allOps[operator || ''], [operator, allOps]);
+
+  return {
+    rule,
+    opConfig,
+    opOptionList,
+    targetSchema,
+  };
+}

+ 14 - 0
packages/materials/form-materials/src/components/condition-context/index.tsx

@@ -0,0 +1,14 @@
+/**
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
+ * SPDX-License-Identifier: MIT
+ */
+
+export {
+  type IConditionRule,
+  type IConditionRuleFactory,
+  type ConditionOpConfigs,
+  type ConditionOpConfig,
+} from './types';
+export { ConditionPresetOp } from './op';
+export { ConditionProvider, useConditionContext } from './context';
+export { useCondition } from './hooks/use-condition';

+ 86 - 0
packages/materials/form-materials/src/components/condition-context/op.ts

@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
+ * SPDX-License-Identifier: MIT
+ */
+
+import { ConditionOpConfigs } from './types';
+
+export enum ConditionPresetOp {
+  EQ = 'eq',
+  NEQ = 'neq',
+  GT = 'gt',
+  GTE = 'gte',
+  LT = 'lt',
+  LTE = 'lte',
+  IN = 'in',
+  NIN = 'nin',
+  CONTAINS = 'contains',
+  NOT_CONTAINS = 'not_contains',
+  IS_EMPTY = 'is_empty',
+  IS_NOT_EMPTY = 'is_not_empty',
+  IS_TRUE = 'is_true',
+  IS_FALSE = 'is_false',
+}
+
+export const defaultConditionOpConfigs: ConditionOpConfigs = {
+  [ConditionPresetOp.EQ]: {
+    label: 'Equal',
+    abbreviation: '=',
+  },
+  [ConditionPresetOp.NEQ]: {
+    label: 'Not Equal',
+    abbreviation: '≠',
+  },
+  [ConditionPresetOp.GT]: {
+    label: 'Greater Than',
+    abbreviation: '>',
+  },
+  [ConditionPresetOp.GTE]: {
+    label: 'Greater Than or Equal',
+    abbreviation: '>=',
+  },
+  [ConditionPresetOp.LT]: {
+    label: 'Less Than',
+    abbreviation: '<',
+  },
+  [ConditionPresetOp.LTE]: {
+    label: 'Less Than or Equal',
+    abbreviation: '<=',
+  },
+  [ConditionPresetOp.IN]: {
+    label: 'In',
+    abbreviation: '∈',
+  },
+  [ConditionPresetOp.NIN]: {
+    label: 'Not In',
+    abbreviation: '∉',
+  },
+  [ConditionPresetOp.CONTAINS]: {
+    label: 'Contains',
+    abbreviation: '⊇',
+  },
+  [ConditionPresetOp.NOT_CONTAINS]: {
+    label: 'Not Contains',
+    abbreviation: '⊉',
+  },
+  [ConditionPresetOp.IS_EMPTY]: {
+    label: 'Is Empty',
+    abbreviation: '=',
+    rightDisplay: 'Empty',
+  },
+  [ConditionPresetOp.IS_NOT_EMPTY]: {
+    label: 'Is Not Empty',
+    abbreviation: '≠',
+    rightDisplay: 'Empty',
+  },
+  [ConditionPresetOp.IS_TRUE]: {
+    label: 'Is True',
+    abbreviation: '=',
+    rightDisplay: 'True',
+  },
+  [ConditionPresetOp.IS_FALSE]: {
+    label: 'Is False',
+    abbreviation: '=',
+    rightDisplay: 'False',
+  },
+};

+ 22 - 0
packages/materials/form-materials/src/components/condition-context/types.ts

@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
+ * SPDX-License-Identifier: MIT
+ */
+
+import { type IJsonSchema } from '@flowgram.ai/json-schema';
+
+export interface ConditionOpConfig {
+  label: string;
+  abbreviation: string;
+  // When right is not a value, display this text
+  rightDisplay?: string;
+}
+
+export type OpKey = string;
+
+export type ConditionOpConfigs = Record<OpKey, ConditionOpConfig>;
+
+export type IConditionRule = Record<OpKey, string | IJsonSchema | null>;
+export type IConditionRuleFactory = (
+  schema?: IJsonSchema
+) => Record<OpKey, string | IJsonSchema | null>;

+ 0 - 136
packages/materials/form-materials/src/components/condition-row/constants.ts

@@ -1,136 +0,0 @@
-/**
- * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
- * SPDX-License-Identifier: MIT
- */
-
-import { IRules, Op, OpConfigs } from './types';
-
-export const defaultRules: IRules = {
-  string: {
-    [Op.EQ]: 'string',
-    [Op.NEQ]: 'string',
-    [Op.CONTAINS]: 'string',
-    [Op.NOT_CONTAINS]: 'string',
-    [Op.IN]: 'array',
-    [Op.NIN]: 'array',
-    [Op.IS_EMPTY]: null,
-    [Op.IS_NOT_EMPTY]: null,
-  },
-  number: {
-    [Op.EQ]: 'number',
-    [Op.NEQ]: 'number',
-    [Op.GT]: 'number',
-    [Op.GTE]: 'number',
-    [Op.LT]: 'number',
-    [Op.LTE]: 'number',
-    [Op.IN]: 'array',
-    [Op.NIN]: 'array',
-  },
-  integer: {
-    [Op.EQ]: 'number',
-    [Op.NEQ]: 'number',
-    [Op.GT]: 'number',
-    [Op.GTE]: 'number',
-    [Op.LT]: 'number',
-    [Op.LTE]: 'number',
-    [Op.IN]: 'array',
-    [Op.NIN]: 'array',
-  },
-  boolean: {
-    [Op.EQ]: 'boolean',
-    [Op.NEQ]: 'boolean',
-    [Op.IS_TRUE]: null,
-    [Op.IS_FALSE]: null,
-    [Op.IN]: 'array',
-    [Op.NIN]: 'array',
-  },
-  object: {
-    [Op.IS_EMPTY]: null,
-    [Op.IS_NOT_EMPTY]: null,
-  },
-  array: {
-    [Op.IS_EMPTY]: null,
-    [Op.IS_NOT_EMPTY]: null,
-    [Op.CONTAINS]: 'array',
-    [Op.NOT_CONTAINS]: 'array',
-    [Op.EQ]: 'array',
-    [Op.NEQ]: 'array',
-  },
-  map: {
-    [Op.IS_EMPTY]: null,
-    [Op.IS_NOT_EMPTY]: null,
-  },
-  ['date-time']: {
-    [Op.EQ]: 'date-time',
-    [Op.NEQ]: 'date-time',
-    [Op.GT]: 'date-time',
-    [Op.GTE]: 'date-time',
-    [Op.LT]: 'date-time',
-    [Op.LTE]: 'date-time',
-    [Op.IS_EMPTY]: null,
-    [Op.IS_NOT_EMPTY]: null,
-  },
-};
-
-export const defaultOpConfigs: OpConfigs = {
-  [Op.EQ]: {
-    label: 'Equal',
-    abbreviation: '=',
-  },
-  [Op.NEQ]: {
-    label: 'Not Equal',
-    abbreviation: '≠',
-  },
-  [Op.GT]: {
-    label: 'Greater Than',
-    abbreviation: '>',
-  },
-  [Op.GTE]: {
-    label: 'Greater Than or Equal',
-    abbreviation: '>=',
-  },
-  [Op.LT]: {
-    label: 'Less Than',
-    abbreviation: '<',
-  },
-  [Op.LTE]: {
-    label: 'Less Than or Equal',
-    abbreviation: '<=',
-  },
-  [Op.IN]: {
-    label: 'In',
-    abbreviation: '∈',
-  },
-  [Op.NIN]: {
-    label: 'Not In',
-    abbreviation: '∉',
-  },
-  [Op.CONTAINS]: {
-    label: 'Contains',
-    abbreviation: '⊇',
-  },
-  [Op.NOT_CONTAINS]: {
-    label: 'Not Contains',
-    abbreviation: '⊉',
-  },
-  [Op.IS_EMPTY]: {
-    label: 'Is Empty',
-    abbreviation: '=',
-    rightDisplay: 'Empty',
-  },
-  [Op.IS_NOT_EMPTY]: {
-    label: 'Is Not Empty',
-    abbreviation: '≠',
-    rightDisplay: 'Empty',
-  },
-  [Op.IS_TRUE]: {
-    label: 'Is True',
-    abbreviation: '=',
-    rightDisplay: 'True',
-  },
-  [Op.IS_FALSE]: {
-    label: 'Is False',
-    abbreviation: '=',
-    rightDisplay: 'False',
-  },
-};

+ 0 - 56
packages/materials/form-materials/src/components/condition-row/hooks/useOp.tsx

@@ -1,56 +0,0 @@
-/**
- * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
- * SPDX-License-Identifier: MIT
- */
-
-import React, { useMemo } from 'react';
-
-import { I18n } from '@flowgram.ai/editor';
-import { Button, Select } from '@douyinfe/semi-ui';
-import { IconChevronDownStroked } from '@douyinfe/semi-icons';
-
-import { IRule, OpConfigs } from '../types';
-import { defaultOpConfigs } from '../constants';
-
-interface HookParams {
-  rule?: IRule;
-  op?: string;
-  onChange: (op: string) => void;
-  readonly?: boolean;
-  userOps?: OpConfigs;
-}
-
-export function useOp({ rule, op, onChange, readonly, userOps }: HookParams) {
-  const options = useMemo(
-    () =>
-      Object.keys(rule || {}).map((_op) => ({
-        ...(defaultOpConfigs[_op] || {}),
-        ...(userOps?.[_op] || {}),
-        value: _op,
-        label: I18n.t(userOps?.[_op]?.label || defaultOpConfigs[_op]?.label),
-      })),
-    [rule, userOps]
-  );
-
-  const opConfig = useMemo(() => defaultOpConfigs[op as string], [op]);
-
-  const renderOpSelect = () => (
-    <Select
-      style={{ height: 22 }}
-      disabled={readonly}
-      size="small"
-      value={op}
-      optionList={options}
-      onChange={(v) => {
-        onChange(v as string);
-      }}
-      triggerRender={({ value }) => (
-        <Button size="small" disabled={!rule}>
-          {opConfig?.abbreviation || <IconChevronDownStroked size="small" />}
-        </Button>
-      )}
-    />
-  );
-
-  return { renderOpSelect, opConfig };
-}

+ 0 - 35
packages/materials/form-materials/src/components/condition-row/hooks/useRule.ts

@@ -1,35 +0,0 @@
-/**
- * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
- * SPDX-License-Identifier: MIT
- */
-
-import { useMemo } from 'react';
-
-import { JsonSchemaUtils, JsonSchemaBasicType } from '@flowgram.ai/json-schema';
-import { useScopeAvailable } from '@flowgram.ai/editor';
-
-import { IFlowRefValue } from '@/shared';
-
-import { IRules } from '../types';
-import { defaultRules } from '../constants';
-
-export function useRule(left?: IFlowRefValue, userRules?: IRules) {
-  const available = useScopeAvailable();
-
-  const rules = useMemo(() => ({ ...defaultRules, ...(userRules || {}) }), [userRules]);
-
-  const variable = useMemo(() => {
-    if (!left) return undefined;
-    return available.getByKeyPath(left.content);
-  }, [available, left]);
-
-  const rule = useMemo(() => {
-    if (!variable) return undefined;
-
-    const schema = JsonSchemaUtils.astToSchema(variable.type, { drilldown: false });
-
-    return rules[schema?.type as JsonSchemaBasicType];
-  }, [variable?.type, rules]);
-
-  return { rule };
-}

+ 44 - 22
packages/materials/form-materials/src/components/condition-row/index.tsx

@@ -5,17 +5,17 @@
 
 
 import React, { useMemo } from 'react';
 import React, { useMemo } from 'react';
 
 
-import { I18n } from '@flowgram.ai/editor';
-import { Input } from '@douyinfe/semi-ui';
+import { JsonSchemaUtils } from '@flowgram.ai/json-schema';
+import { I18n, useScopeAvailable } from '@flowgram.ai/editor';
+import { Button, Input, Select } from '@douyinfe/semi-ui';
+import { IconChevronDownStroked } from '@douyinfe/semi-icons';
 
 
 import { InjectVariableSelector } from '@/components/variable-selector';
 import { InjectVariableSelector } from '@/components/variable-selector';
 import { InjectDynamicValueInput } from '@/components/dynamic-value-input';
 import { InjectDynamicValueInput } from '@/components/dynamic-value-input';
+import { IConditionRule, ConditionOpConfigs, useCondition } from '@/components/condition-context';
 
 
-import { ConditionRowValueType, IRules, OpConfigs } from './types';
+import { ConditionRowValueType } from './types';
 import { UIContainer, UILeft, UIOperator, UIRight, UIValues } from './styles';
 import { UIContainer, UILeft, UIOperator, UIRight, UIValues } from './styles';
-import { useRule } from './hooks/useRule';
-import { useOp } from './hooks/useOp';
-import { defaultOpConfigs, defaultRules } from './constants';
 
 
 interface PropTypes {
 interface PropTypes {
   value?: ConditionRowValueType;
   value?: ConditionRowValueType;
@@ -23,8 +23,8 @@ interface PropTypes {
   style?: React.CSSProperties;
   style?: React.CSSProperties;
   readonly?: boolean;
   readonly?: boolean;
   ruleConfig?: {
   ruleConfig?: {
-    ops?: OpConfigs;
-    rules?: IRules;
+    ops?: ConditionOpConfigs;
+    rules?: Record<string, IConditionRule>;
   };
   };
 }
 }
 
 
@@ -41,19 +41,44 @@ export function ConditionRow({
   ruleConfig = defaultRuleConfig,
   ruleConfig = defaultRuleConfig,
 }: PropTypes) {
 }: PropTypes) {
   const { left, operator, right } = value || {};
   const { left, operator, right } = value || {};
-  const { rule } = useRule(left, ruleConfig.rules);
-  const { renderOpSelect, opConfig } = useOp({
-    rule,
-    op: operator,
-    onChange: (v) => onChange({ ...value, operator: v }),
-    readonly,
-    userOps: ruleConfig.ops,
+
+  const available = useScopeAvailable();
+
+  const variable = useMemo(() => {
+    if (!left) return undefined;
+    return available.getByKeyPath(left.content);
+  }, [available, left]);
+
+  const leftSchema = useMemo(() => {
+    if (!variable) return undefined;
+    return JsonSchemaUtils.astToSchema(variable.type, { drilldown: false });
+  }, [variable?.type?.hash]);
+
+  const { rule, opConfig, opOptionList, targetSchema } = useCondition({
+    leftSchema,
+    operator,
   });
   });
 
 
-  const targetSchema = useMemo(() => {
-    const targetType: string | null = rule?.[operator || ''] || null;
-    return targetType ? { type: targetType, extra: { weak: true } } : null;
-  }, [rule, opConfig]);
+  const renderOpSelect = () => (
+    <Select
+      style={{ height: 22 }}
+      disabled={readonly}
+      size="small"
+      value={operator}
+      optionList={opOptionList}
+      onChange={(v) => {
+        onChange({
+          ...value,
+          operator: v as string,
+        });
+      }}
+      triggerRender={({ value }) => (
+        <Button size="small" disabled={!rule}>
+          {opConfig?.abbreviation || <IconChevronDownStroked size="small" />}
+        </Button>
+      )}
+    />
+  );
 
 
   return (
   return (
     <UIContainer style={style}>
     <UIContainer style={style}>
@@ -97,7 +122,4 @@ export function ConditionRow({
   );
   );
 }
 }
 
 
-ConditionRow.defaultRules = defaultRules;
-ConditionRow.defaultOpConfigs = defaultOpConfigs;
-
 export { type ConditionRowValueType };
 export { type ConditionRowValueType };

+ 0 - 30
packages/materials/form-materials/src/components/condition-row/types.ts

@@ -5,36 +5,6 @@
 
 
 import { IFlowConstantRefValue, IFlowRefValue } from '@/shared';
 import { IFlowConstantRefValue, IFlowRefValue } from '@/shared';
 
 
-export enum Op {
-  EQ = 'eq',
-  NEQ = 'neq',
-  GT = 'gt',
-  GTE = 'gte',
-  LT = 'lt',
-  LTE = 'lte',
-  IN = 'in',
-  NIN = 'nin',
-  CONTAINS = 'contains',
-  NOT_CONTAINS = 'not_contains',
-  IS_EMPTY = 'is_empty',
-  IS_NOT_EMPTY = 'is_not_empty',
-  IS_TRUE = 'is_true',
-  IS_FALSE = 'is_false',
-}
-
-export interface OpConfig {
-  label: string;
-  abbreviation: string;
-  // When right is not a value, display this text
-  rightDisplay?: string;
-}
-
-export type OpConfigs = Record<string, OpConfig>;
-
-export type IRule = Partial<Record<string, string | null>>;
-
-export type IRules = Record<string, IRule>;
-
 export interface ConditionRowValueType {
 export interface ConditionRowValueType {
   left?: IFlowRefValue;
   left?: IFlowRefValue;
   operator?: string;
   operator?: string;

+ 0 - 66
packages/materials/form-materials/src/components/db-condition-row/hooks/use-left.tsx

@@ -1,66 +0,0 @@
-/**
- * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
- * SPDX-License-Identifier: MIT
- */
-
-import { useMemo } from 'react';
-import React from 'react';
-
-import { JsonSchemaTypeManager, useTypeManager } from '@flowgram.ai/json-schema';
-import { Icon } from '@douyinfe/semi-ui';
-
-import { ConditionRow } from '@/components';
-
-import { DBConditionOptionType, IRules } from '../types';
-import { UIOptionLabel, UISelect } from '../styles';
-
-const defaultRules = ConditionRow.defaultRules;
-
-interface HookParams {
-  left?: string;
-  options?: DBConditionOptionType[];
-  userRules?: IRules;
-  readonly?: boolean;
-  onChange: (leftKey: string) => void;
-}
-
-export function useLeft({ left, options, userRules, readonly, onChange }: HookParams) {
-  const rules = useMemo(() => ({ ...defaultRules, ...(userRules || {}) }), [userRules]);
-
-  const typeManager = useTypeManager() as JsonSchemaTypeManager;
-
-  const rule = useMemo(() => {
-    if (!left) return undefined;
-
-    const option = options?.find((item) => item.value === left);
-
-    if (!option?.schema?.type) {
-      return undefined;
-    }
-
-    return rules[option.schema.type];
-  }, [left, options, rules]);
-
-  const renderDBOptionSelect = () => (
-    <UISelect
-      disabled={readonly}
-      size="small"
-      style={{ width: '100%' }}
-      value={left}
-      onChange={(v) => onChange(v as string)}
-      optionList={
-        options?.map((item) => ({
-          label: (
-            <UIOptionLabel>
-              <Icon size="small" svg={typeManager.getDisplayIcon(item.schema)} />
-              {item.label}
-            </UIOptionLabel>
-          ),
-          value: item.value,
-        })) || []
-      }
-    />
-  );
-
-  return { rule, renderDBOptionSelect };
-}

+ 0 - 59
packages/materials/form-materials/src/components/db-condition-row/hooks/use-op.tsx

@@ -1,59 +0,0 @@
-/**
- * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
- * SPDX-License-Identifier: MIT
- */
-
-import React, { useMemo } from 'react';
-
-import { I18n } from '@flowgram.ai/editor';
-import { Button, Select } from '@douyinfe/semi-ui';
-import { IconChevronDownStroked } from '@douyinfe/semi-icons';
-
-import { ConditionRow } from '@/components';
-
-import { IRule, OpConfigs } from '../types';
-
-const defaultOpConfigs = ConditionRow.defaultOpConfigs;
-
-interface HookParams {
-  rule?: IRule;
-  op?: string;
-  onChange: (op: string) => void;
-  readonly?: boolean;
-  userOps?: OpConfigs;
-}
-
-export function useOp({ rule, op, onChange, readonly, userOps }: HookParams) {
-  const options = useMemo(
-    () =>
-      Object.keys(rule || {}).map((_op) => ({
-        ...(defaultOpConfigs[_op] || {}),
-        ...(userOps?.[_op] || {}),
-        value: _op,
-        label: I18n.t(userOps?.[_op]?.label || defaultOpConfigs[_op]?.label),
-      })),
-    [rule, userOps]
-  );
-
-  const opConfig = useMemo(() => defaultOpConfigs[op as string], [op]);
-
-  const renderOpSelect = () => (
-    <Select
-      style={{ height: 22 }}
-      disabled={readonly}
-      size="small"
-      value={op}
-      optionList={options}
-      onChange={(v) => {
-        onChange(v as string);
-      }}
-      triggerRender={({ value }) => (
-        <Button size="small" disabled={!rule}>
-          {opConfig?.abbreviation || <IconChevronDownStroked size="small" />}
-        </Button>
-      )}
-    />
-  );
-
-  return { renderOpSelect, opConfig };
-}

+ 76 - 24
packages/materials/form-materials/src/components/db-condition-row/index.tsx

@@ -6,14 +6,27 @@
 import React, { useMemo } from 'react';
 import React, { useMemo } from 'react';
 
 
 import { I18n } from '@flowgram.ai/editor';
 import { I18n } from '@flowgram.ai/editor';
-import { Input } from '@douyinfe/semi-ui';
+import { Button, Icon, Input, Select } from '@douyinfe/semi-ui';
+import { IconChevronDownStroked } from '@douyinfe/semi-icons';
 
 
+import { useTypeManager } from '@/plugins';
 import { InjectDynamicValueInput } from '@/components/dynamic-value-input';
 import { InjectDynamicValueInput } from '@/components/dynamic-value-input';
+import {
+  useCondition,
+  type ConditionOpConfigs,
+  type IConditionRule,
+} from '@/components/condition-context';
 
 
-import { DBConditionOptionType, DBConditionRowValueType, IRules, OpConfigs } from './types';
-import { UIContainer, UILeft, UIOperator, UIRight, UIValues } from './styles';
-import { useOp } from './hooks/use-op';
-import { useLeft } from './hooks/use-left';
+import { DBConditionOptionType, DBConditionRowValueType } from './types';
+import {
+  UIContainer,
+  UILeft,
+  UIOperator,
+  UIOptionLabel,
+  UIRight,
+  UISelect,
+  UIValues,
+} from './styles';
 
 
 interface PropTypes {
 interface PropTypes {
   value?: DBConditionRowValueType;
   value?: DBConditionRowValueType;
@@ -22,8 +35,8 @@ interface PropTypes {
   options?: DBConditionOptionType[];
   options?: DBConditionOptionType[];
   readonly?: boolean;
   readonly?: boolean;
   ruleConfig?: {
   ruleConfig?: {
-    ops?: OpConfigs;
-    rules?: IRules;
+    ops?: ConditionOpConfigs;
+    rules?: Record<string, IConditionRule>;
   };
   };
 }
 }
 
 
@@ -42,26 +55,65 @@ export function DBConditionRow({
 }: PropTypes) {
 }: PropTypes) {
   const { left, operator, right } = value || {};
   const { left, operator, right } = value || {};
 
 
-  const { rule, renderDBOptionSelect } = useLeft({
-    left,
-    options,
-    onChange: (leftKey) => onChange({ ...value, left: leftKey }),
-    readonly,
-    userRules: ruleConfig.rules,
-  });
+  const typeManager = useTypeManager();
+
+  const leftSchema = useMemo(
+    () => options?.find((item) => item.value === left)?.schema,
+    [left, options]
+  );
 
 
-  const { renderOpSelect, opConfig } = useOp({
-    rule,
-    op: operator,
-    onChange: (v) => onChange({ ...value, operator: v }),
-    readonly,
-    userOps: ruleConfig.ops,
+  const { opConfig, rule, opOptionList, targetSchema } = useCondition({
+    leftSchema,
+    operator,
+    ruleConfig,
   });
   });
 
 
-  const targetSchema = useMemo(() => {
-    const targetType: string | null = rule?.[operator || ''] || null;
-    return targetType ? { type: targetType, extra: { weak: true } } : null;
-  }, [rule, opConfig]);
+  const renderDBOptionSelect = () => (
+    <UISelect
+      disabled={readonly}
+      size="small"
+      style={{ width: '100%' }}
+      value={left}
+      onChange={(v) =>
+        onChange({
+          ...value,
+          left: v as string,
+        })
+      }
+      optionList={
+        options?.map((item) => ({
+          label: (
+            <UIOptionLabel>
+              <Icon size="small" svg={typeManager.getDisplayIcon(item.schema)} />
+              {item.label}
+            </UIOptionLabel>
+          ),
+          value: item.value,
+        })) || []
+      }
+    />
+  );
+
+  const renderOpSelect = () => (
+    <Select
+      style={{ height: 22 }}
+      disabled={readonly}
+      size="small"
+      value={operator}
+      optionList={opOptionList}
+      onChange={(v) => {
+        onChange({
+          ...value,
+          operator: v as string,
+        });
+      }}
+      triggerRender={({ value }) => (
+        <Button size="small" disabled={!rule}>
+          {opConfig?.abbreviation || <IconChevronDownStroked size="small" />}
+        </Button>
+      )}
+    />
+  );
 
 
   return (
   return (
     <UIContainer style={style}>
     <UIContainer style={style}>

+ 0 - 13
packages/materials/form-materials/src/components/db-condition-row/types.ts

@@ -7,19 +7,6 @@ import { IJsonSchema } from '@flowgram.ai/json-schema';
 
 
 import { IFlowConstantRefValue } from '@/shared';
 import { IFlowConstantRefValue } from '@/shared';
 
 
-export interface OpConfig {
-  label: string;
-  abbreviation: string;
-  // When right is not a value, display this text
-  rightDisplay?: string;
-}
-
-export type OpConfigs = Record<string, OpConfig>;
-
-export type IRule = Partial<Record<string, string | null>>;
-
-export type IRules = Record<string, IRule>;
-
 export interface DBConditionRowValueType {
 export interface DBConditionRowValueType {
   left?: string;
   left?: string;
   schema?: IJsonSchema;
   schema?: IJsonSchema;

+ 4 - 2
packages/materials/form-materials/src/plugins/json-schema-preset/create-type-preset-plugin.tsx

@@ -10,8 +10,10 @@ import {
 } from '@flowgram.ai/json-schema';
 } from '@flowgram.ai/json-schema';
 import { definePluginCreator } from '@flowgram.ai/editor';
 import { definePluginCreator } from '@flowgram.ai/editor';
 
 
-import { jsonSchemaTypePreset } from './type-definition';
-import { JsonSchemaTypeRegistry } from './manager';
+import { JsonSchemaTypeRegistry } from './types';
+import { initRegistries, jsonSchemaTypePreset } from './type-definition';
+
+initRegistries();
 
 
 export const createTypePresetPlugin = definePluginCreator<{
 export const createTypePresetPlugin = definePluginCreator<{
   types?: Partial<JsonSchemaTypeRegistry> & Pick<JsonSchemaTypeRegistry, 'type'>[];
   types?: Partial<JsonSchemaTypeRegistry> & Pick<JsonSchemaTypeRegistry, 'type'>[];

+ 1 - 1
packages/materials/form-materials/src/plugins/json-schema-preset/index.tsx

@@ -9,8 +9,8 @@ import {
   type IJsonSchema,
   type IJsonSchema,
 } from '@flowgram.ai/json-schema';
 } from '@flowgram.ai/json-schema';
 
 
+import { type ConstantRendererProps, type JsonSchemaTypeRegistry } from './types';
 import { useTypeManager, JsonSchemaTypePresetProvider } from './react';
 import { useTypeManager, JsonSchemaTypePresetProvider } from './react';
-import { ConstantRendererProps, type JsonSchemaTypeRegistry } from './manager';
 import { createTypePresetPlugin } from './create-type-preset-plugin';
 import { createTypePresetPlugin } from './create-type-preset-plugin';
 
 
 export {
 export {

+ 1 - 1
packages/materials/form-materials/src/plugins/json-schema-preset/react.tsx

@@ -12,8 +12,8 @@ import {
   JsonSchemaTypeManager,
   JsonSchemaTypeManager,
 } from '@flowgram.ai/json-schema';
 } from '@flowgram.ai/json-schema';
 
 
+import { type JsonSchemaTypeRegistry } from './types';
 import { initRegistries, jsonSchemaTypePreset } from './type-definition';
 import { initRegistries, jsonSchemaTypePreset } from './type-definition';
-import { type JsonSchemaTypeRegistry } from './manager';
 
 
 // If you want to use new type Manager, init registries
 // If you want to use new type Manager, init registries
 initRegistries();
 initRegistries();

+ 10 - 1
packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/array.tsx

@@ -8,9 +8,10 @@ import React from 'react';
 
 
 import { I18n } from '@flowgram.ai/editor';
 import { I18n } from '@flowgram.ai/editor';
 
 
+import { ConditionPresetOp } from '@/components/condition-context/op';
 import { CodeEditorMini } from '@/components/code-editor-mini';
 import { CodeEditorMini } from '@/components/code-editor-mini';
 
 
-import { type JsonSchemaTypeRegistry } from '../manager';
+import { type JsonSchemaTypeRegistry } from '../types';
 
 
 export const arrayRegistry: Partial<JsonSchemaTypeRegistry> = {
 export const arrayRegistry: Partial<JsonSchemaTypeRegistry> = {
   type: 'array',
   type: 'array',
@@ -23,4 +24,12 @@ export const arrayRegistry: Partial<JsonSchemaTypeRegistry> = {
       readonly={props.readonly}
       readonly={props.readonly}
     />
     />
   ),
   ),
+  conditionRule: {
+    [ConditionPresetOp.IS_EMPTY]: null,
+    [ConditionPresetOp.IS_NOT_EMPTY]: null,
+    [ConditionPresetOp.CONTAINS]: { type: 'array', extra: { weak: true } },
+    [ConditionPresetOp.NOT_CONTAINS]: { type: 'array', extra: { weak: true } },
+    [ConditionPresetOp.EQ]: { type: 'array', extra: { weak: true } },
+    [ConditionPresetOp.NEQ]: { type: 'array', extra: { weak: true } },
+  },
 };
 };

+ 17 - 1
packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/boolean.tsx

@@ -9,7 +9,9 @@ import React from 'react';
 import { I18n } from '@flowgram.ai/editor';
 import { I18n } from '@flowgram.ai/editor';
 import { Select } from '@douyinfe/semi-ui';
 import { Select } from '@douyinfe/semi-ui';
 
 
-import { type JsonSchemaTypeRegistry } from '../manager';
+import { ConditionPresetOp } from '@/components/condition-context/op';
+
+import { type JsonSchemaTypeRegistry } from '../types';
 
 
 export const booleanRegistry: Partial<JsonSchemaTypeRegistry> = {
 export const booleanRegistry: Partial<JsonSchemaTypeRegistry> = {
   type: 'boolean',
   type: 'boolean',
@@ -30,4 +32,18 @@ export const booleanRegistry: Partial<JsonSchemaTypeRegistry> = {
       />
       />
     );
     );
   },
   },
+  conditionRule: {
+    [ConditionPresetOp.EQ]: { type: 'boolean' },
+    [ConditionPresetOp.NEQ]: { type: 'boolean' },
+    [ConditionPresetOp.IS_TRUE]: null,
+    [ConditionPresetOp.IS_FALSE]: null,
+    [ConditionPresetOp.IN]: {
+      type: 'array',
+      items: { type: 'boolean' },
+    },
+    [ConditionPresetOp.NIN]: {
+      type: 'array',
+      items: { type: 'boolean' },
+    },
+  },
 };
 };

+ 13 - 1
packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/date-time.tsx

@@ -10,7 +10,9 @@ import { format } from 'date-fns';
 import { type DatePickerProps } from '@douyinfe/semi-ui/lib/es/datePicker';
 import { type DatePickerProps } from '@douyinfe/semi-ui/lib/es/datePicker';
 import { DatePicker } from '@douyinfe/semi-ui';
 import { DatePicker } from '@douyinfe/semi-ui';
 
 
-import { type JsonSchemaTypeRegistry } from '../manager';
+import { ConditionPresetOp } from '@/components/condition-context/op';
+
+import { type JsonSchemaTypeRegistry } from '../types';
 
 
 export const dateTimeRegistry: Partial<JsonSchemaTypeRegistry> = {
 export const dateTimeRegistry: Partial<JsonSchemaTypeRegistry> = {
   type: 'date-time',
   type: 'date-time',
@@ -29,4 +31,14 @@ export const dateTimeRegistry: Partial<JsonSchemaTypeRegistry> = {
       value={props.value}
       value={props.value}
     />
     />
   ),
   ),
+  conditionRule: {
+    [ConditionPresetOp.EQ]: { type: 'date-time' },
+    [ConditionPresetOp.NEQ]: { type: 'date-time' },
+    [ConditionPresetOp.GT]: { type: 'date-time' },
+    [ConditionPresetOp.GTE]: { type: 'date-time' },
+    [ConditionPresetOp.LT]: { type: 'date-time' },
+    [ConditionPresetOp.LTE]: { type: 'date-time' },
+    [ConditionPresetOp.IS_EMPTY]: null,
+    [ConditionPresetOp.IS_NOT_EMPTY]: null,
+  },
 };
 };

+ 7 - 0
packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/index.tsx

@@ -8,10 +8,12 @@ import { jsonSchemaTypeManager } from '@flowgram.ai/json-schema';
 import { stringRegistry } from './string';
 import { stringRegistry } from './string';
 import { objectRegistry } from './object';
 import { objectRegistry } from './object';
 import { numberRegistry } from './number';
 import { numberRegistry } from './number';
+import { mapRegistry } from './map';
 import { integerRegistry } from './integer';
 import { integerRegistry } from './integer';
 import { dateTimeRegistry } from './date-time';
 import { dateTimeRegistry } from './date-time';
 import { booleanRegistry } from './boolean';
 import { booleanRegistry } from './boolean';
 import { arrayRegistry } from './array';
 import { arrayRegistry } from './array';
+import { type JsonSchemaTypeRegistry } from '../types';
 
 
 export const jsonSchemaTypePreset = [
 export const jsonSchemaTypePreset = [
   stringRegistry,
   stringRegistry,
@@ -20,9 +22,14 @@ export const jsonSchemaTypePreset = [
   integerRegistry,
   integerRegistry,
   booleanRegistry,
   booleanRegistry,
   arrayRegistry,
   arrayRegistry,
+  mapRegistry,
   dateTimeRegistry,
   dateTimeRegistry,
 ];
 ];
 
 
 export const initRegistries = () => {
 export const initRegistries = () => {
+  if ((jsonSchemaTypeManager.getTypeByName('string') as JsonSchemaTypeRegistry)?.ConstantRenderer) {
+    return;
+  }
+
   jsonSchemaTypePreset.forEach((_type) => jsonSchemaTypeManager.register(_type));
   jsonSchemaTypePreset.forEach((_type) => jsonSchemaTypeManager.register(_type));
 };
 };

+ 19 - 1
packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/integer.tsx

@@ -9,7 +9,9 @@ import React from 'react';
 import { I18n } from '@flowgram.ai/editor';
 import { I18n } from '@flowgram.ai/editor';
 import { InputNumber } from '@douyinfe/semi-ui';
 import { InputNumber } from '@douyinfe/semi-ui';
 
 
-import { type JsonSchemaTypeRegistry } from '../manager';
+import { ConditionPresetOp } from '@/components/condition-context/op';
+
+import { type JsonSchemaTypeRegistry } from '../types';
 
 
 export const integerRegistry: Partial<JsonSchemaTypeRegistry> = {
 export const integerRegistry: Partial<JsonSchemaTypeRegistry> = {
   type: 'integer',
   type: 'integer',
@@ -22,4 +24,20 @@ export const integerRegistry: Partial<JsonSchemaTypeRegistry> = {
       {...props}
       {...props}
     />
     />
   ),
   ),
+  conditionRule: {
+    [ConditionPresetOp.EQ]: { type: 'number' },
+    [ConditionPresetOp.NEQ]: { type: 'number' },
+    [ConditionPresetOp.GT]: { type: 'number' },
+    [ConditionPresetOp.GTE]: { type: 'number' },
+    [ConditionPresetOp.LT]: { type: 'number' },
+    [ConditionPresetOp.LTE]: { type: 'number' },
+    [ConditionPresetOp.IN]: {
+      type: 'array',
+      extra: { weak: true },
+    },
+    [ConditionPresetOp.NIN]: {
+      type: 'array',
+      extra: { weak: true },
+    },
+  },
 };
 };

+ 31 - 0
packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/map.tsx

@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
+ * SPDX-License-Identifier: MIT
+ */
+
+/* eslint-disable react/prop-types */
+import React from 'react';
+
+import { I18n } from '@flowgram.ai/editor';
+
+import { ConditionPresetOp } from '@/components/condition-context/op';
+import { CodeEditorMini } from '@/components/code-editor-mini';
+
+import { type JsonSchemaTypeRegistry } from '../types';
+
+export const mapRegistry: Partial<JsonSchemaTypeRegistry> = {
+  type: 'map',
+  ConstantRenderer: (props) => (
+    <CodeEditorMini
+      value={props.value}
+      onChange={(v) => props.onChange?.(v)}
+      languageId="json"
+      placeholder={I18n.t('Please Input Map')}
+      readonly={props.readonly}
+    />
+  ),
+  conditionRule: {
+    [ConditionPresetOp.IS_EMPTY]: null,
+    [ConditionPresetOp.IS_NOT_EMPTY]: null,
+  },
+};

+ 19 - 1
packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/number.tsx

@@ -9,7 +9,9 @@ import React from 'react';
 import { I18n } from '@flowgram.ai/editor';
 import { I18n } from '@flowgram.ai/editor';
 import { InputNumber } from '@douyinfe/semi-ui';
 import { InputNumber } from '@douyinfe/semi-ui';
 
 
-import { type JsonSchemaTypeRegistry } from '../manager';
+import { ConditionPresetOp } from '@/components/condition-context/op';
+
+import { type JsonSchemaTypeRegistry } from '../types';
 
 
 export const numberRegistry: Partial<JsonSchemaTypeRegistry> = {
 export const numberRegistry: Partial<JsonSchemaTypeRegistry> = {
   type: 'number',
   type: 'number',
@@ -22,4 +24,20 @@ export const numberRegistry: Partial<JsonSchemaTypeRegistry> = {
       {...props}
       {...props}
     />
     />
   ),
   ),
+  conditionRule: {
+    [ConditionPresetOp.EQ]: { type: 'number' },
+    [ConditionPresetOp.NEQ]: { type: 'number' },
+    [ConditionPresetOp.GT]: { type: 'number' },
+    [ConditionPresetOp.GTE]: { type: 'number' },
+    [ConditionPresetOp.LT]: { type: 'number' },
+    [ConditionPresetOp.LTE]: { type: 'number' },
+    [ConditionPresetOp.IN]: {
+      type: 'array',
+      extra: { weak: true },
+    },
+    [ConditionPresetOp.NIN]: {
+      type: 'array',
+      extra: { weak: true },
+    },
+  },
 };
 };

+ 6 - 1
packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/object.tsx

@@ -8,9 +8,10 @@ import React from 'react';
 
 
 import { I18n } from '@flowgram.ai/editor';
 import { I18n } from '@flowgram.ai/editor';
 
 
+import { ConditionPresetOp } from '@/components/condition-context/op';
 import { CodeEditorMini } from '@/components/code-editor-mini';
 import { CodeEditorMini } from '@/components/code-editor-mini';
 
 
-import { type JsonSchemaTypeRegistry } from '../manager';
+import { type JsonSchemaTypeRegistry } from '../types';
 
 
 export const objectRegistry: Partial<JsonSchemaTypeRegistry> = {
 export const objectRegistry: Partial<JsonSchemaTypeRegistry> = {
   type: 'object',
   type: 'object',
@@ -23,4 +24,8 @@ export const objectRegistry: Partial<JsonSchemaTypeRegistry> = {
       readonly={props.readonly}
       readonly={props.readonly}
     />
     />
   ),
   ),
+  conditionRule: {
+    [ConditionPresetOp.IS_EMPTY]: null,
+    [ConditionPresetOp.IS_NOT_EMPTY]: null,
+  },
 };
 };

+ 19 - 1
packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/string.tsx

@@ -9,7 +9,9 @@ import React from 'react';
 import { I18n } from '@flowgram.ai/editor';
 import { I18n } from '@flowgram.ai/editor';
 import { Input, TextArea } from '@douyinfe/semi-ui';
 import { Input, TextArea } from '@douyinfe/semi-ui';
 
 
-import { type JsonSchemaTypeRegistry } from '../manager';
+import { ConditionPresetOp } from '@/components/condition-context/op';
+
+import { type JsonSchemaTypeRegistry } from '../types';
 
 
 export const stringRegistry: Partial<JsonSchemaTypeRegistry> = {
 export const stringRegistry: Partial<JsonSchemaTypeRegistry> = {
   type: 'string',
   type: 'string',
@@ -30,4 +32,20 @@ export const stringRegistry: Partial<JsonSchemaTypeRegistry> = {
         {...props}
         {...props}
       />
       />
     ),
     ),
+  conditionRule: {
+    [ConditionPresetOp.EQ]: { type: 'string' },
+    [ConditionPresetOp.NEQ]: { type: 'string' },
+    [ConditionPresetOp.CONTAINS]: { type: 'string' },
+    [ConditionPresetOp.NOT_CONTAINS]: { type: 'string' },
+    [ConditionPresetOp.IN]: {
+      type: 'array',
+      items: { type: 'string' },
+    },
+    [ConditionPresetOp.NIN]: {
+      type: 'array',
+      items: { type: 'string' },
+    },
+    [ConditionPresetOp.IS_EMPTY]: null,
+    [ConditionPresetOp.IS_NOT_EMPTY]: null,
+  },
 };
 };

+ 7 - 0
packages/materials/form-materials/src/plugins/json-schema-preset/manager.ts → packages/materials/form-materials/src/plugins/json-schema-preset/types.ts

@@ -5,6 +5,8 @@
 
 
 import { JsonSchemaTypeRegistry as OriginJsonSchemaTypeRegistry } from '@flowgram.ai/json-schema';
 import { JsonSchemaTypeRegistry as OriginJsonSchemaTypeRegistry } from '@flowgram.ai/json-schema';
 
 
+import { IConditionRule, IConditionRuleFactory } from '@/components/condition-context/types';
+
 export interface ConstantRendererProps<Value = any> {
 export interface ConstantRendererProps<Value = any> {
   value?: Value;
   value?: Value;
   onChange?: (value: Value) => void;
   onChange?: (value: Value) => void;
@@ -16,4 +18,9 @@ export interface JsonSchemaTypeRegistry<Value = any> extends OriginJsonSchemaTyp
    * Render Constant Input
    * Render Constant Input
    */
    */
   ConstantRenderer: React.FC<ConstantRendererProps<Value>>;
   ConstantRenderer: React.FC<ConstantRendererProps<Value>>;
+
+  /**
+   * Condition Rules
+   */
+  conditionRule?: IConditionRule | IConditionRuleFactory;
 }
 }