Skip to content

refactor(form): LightFilter with explicit field helpers#9604

Merged
chenshuai2144 merged 3 commits intomasterfrom
cursor/lightform-explicit-api-1690
May 2, 2026
Merged

refactor(form): LightFilter with explicit field helpers#9604
chenshuai2144 merged 3 commits intomasterfrom
cursor/lightform-explicit-api-1690

Conversation

@chenshuai2144
Copy link
Copy Markdown
Contributor

@chenshuai2144 chenshuai2144 commented Apr 23, 2026

Summary

The light inline filter is LightFilter again (layout in src/form/layouts/LightFilter).

  • Layout: <LightFilter>...</LightFilter> (default export)
  • Fields: LightFilter.input, LightFilter.select, etc. (static properties on the same object)
  • Types: LightFilterProps, LightFilterFooterRender (replaces the interim LightForm* names)
  • Context / Schema / ProTable: formComponentType / layoutType = 'LightFilter', isLightFilter on table toolbar
  • CSS: root class ant-pro-form-light-filter unchanged

Submitted by Cursor

Open in Web Open in Cursor 

Summary by CodeRabbit

发布说明

  • 重构

    • 统一了过滤器字段组件的使用方式,通过 LightFilter 的组合字段组件来构建筛选器,提高了代码的一致性和可维护性。
    • 优化了轻量级过滤器的内部架构,改进了字段属性的传递机制。
  • 类型更新

    • 扩展了表单组件类型定义,以支持 LightFilter 作为新的表单组件类型。

…lter

LightFilter no longer injects proFieldProps.light; use lightForm.input, lightForm.select, etc. to opt in.
ProTable light filter still merges light: true for search columns. BaseForm/LightFilter sets formComponentType for context. Export lightForm from the package. Update demos and tests.

Co-authored-by: 陈帅 <wasd2144@hotmail.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

📝 Walkthrough

高层概述

LightFilter 组件从使用 ProForm* 组件重构为使用自身的命名空间字段组件(如 LightFilter.selectLightFilter.input 等),并调整类型定义、导出方式和内部实现逻辑。

变更概览

变更组别 / 文件 变更摘要
演示更新
demos/form/QueryFilter/light-filter-collapse.tsx, demos/form/QueryFilter/light-filter.tsx
将演示中的 ProFormSelectProFormDateTimePicker 等组件替换为 LightFilter.selectLightFilter.dateTime 等命名空间组件,保留原有的配置选项。
类型定义扩展
src/form/BaseForm/BaseForm.tsx, src/form/FieldContext.tsx
formComponentType 类型扩展以支持 'LightFilter' 类型字符串,使表单可支持 LightFilter 变体。
核心组件重构
src/form/layouts/LightFilter/index.tsx
重命名类型为 LightFilterLayoutProps,将 LightFilter 转为默认导出并通过 Object.assign 附加字段组件,更新 BaseFormformComponentType 参数,调整 memoization 依赖。
字段组件映射
src/form/layouts/LightFilter/lightFilterFieldComponents.tsx
新增模块,定义 lightFilterFieldComponents 对象,通过 createLightFilterField 包装器为各类 ProForm* 组件强制注入 light: true 标志。
导出和样式调整
src/form/layouts/index.ts, src/form/layouts/LightFilter/style.ts, src/form/components/SchemaForm/index.tsx
调整 LightFilter 重导出为默认导出,更新样式生成器中的变量名,修改 LightFilter 的导入方式。
表格和下拉菜单更新
src/table/Table.tsx, src/table/components/Form/FormRender.tsx, src/utils/components/DropdownFooter/index.tsx
更新注释和逻辑以支持 LightFilter 模式下自动注入 light: true 标志,复用共享的 LightFilterFooterRender 类型。
测试更新
tests/form/base.test.tsx, tests/form/filter.react.test.tsx, tests/form/lightFilter.test.tsx
将测试中的 ProForm* 组件替换为 LightFilter.* 命名空间组件,更新标签并添加断言验证轻量级字段标签的行为。

📊 审查难度评估

🎯 3 (中等复杂度) | ⏱️ ~25 分钟

变更涉及多个文件但模式一致(组件 API 迁移),包含类型定义更新和 memoization 逻辑调整,需要验证导出方式变更和字段组件集成的正确性。

小诗

🐰 从 ProForm 跃向 LightFilter 之巢,
字段组件齐整,命名如歌;
包装器巧妙注入光之标志,
默认导出映照新的航向——
轻盈优雅,引领表单之变。

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题清晰准确地概括了主要改动:为LightFilter添加显式字段助手的重构
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/lightform-explicit-api-1690

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces lightForm, a utility designed to explicitly enable light styles for form fields, moving away from automatic injection within LightFilter. The changes include the implementation of the lightForm object and its helper createLightFormField, updates to BaseForm and FieldContext types to include LightFilter, and extensive refactoring of demos and tests to adopt the new syntax. Review feedback highlights an opportunity to improve type safety and IntelliSense in the createLightFormField helper using generics, as well as a need for consistency in the formComponentType type definition across the codebase.

Comment on lines +24 to +31
const createLightFormField = (Field: React.ComponentType<Record<string, any>>) => {
const LightField = (props: Record<string, any>) => {
const { proFieldProps, ...rest } = props;
return <Field {...rest} proFieldProps={{ light: true, ...proFieldProps }} />;
};
LightField.displayName = 'LightFormField';
return LightField;
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The createLightFormField helper currently uses Record<string, any>, which causes a complete loss of type safety and IntelliSense for the resulting components (e.g., lightForm.input will not show ProFormTextProps). Additionally, using a hardcoded displayName makes debugging difficult in React DevTools. Using generics and a dynamic displayName would significantly improve the developer experience.

const createLightFormField = <P extends Record<string, any>>(
  Field: React.ComponentType<P>,
) => {
  const LightField: React.FC<P> = (props) => {
    const { proFieldProps, ...rest } = props;
    return (
      <Field
        {...(rest as P)}
        proFieldProps={{ light: true, ...proFieldProps }}
      />
    );
  };
  LightField.displayName = `LightForm(${Field.displayName || Field.name || 'Component'})`;
  return LightField;
};

isKeyPressSubmit?: boolean;
/** Form 组件的类型,内部使用 */
formComponentType?: 'DrawerForm' | 'ModalForm' | 'QueryFilter';
formComponentType?: 'DrawerForm' | 'ModalForm' | 'QueryFilter' | 'LightFilter';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The formComponentType definition here is more restrictive than the one updated in FieldContext.tsx. To maintain consistency and allow for custom form layouts without type errors, it should also include | string (or | (string & {}) to preserve IDE autocomplete for the literals).

Suggested change
formComponentType?: 'DrawerForm' | 'ModalForm' | 'QueryFilter' | 'LightFilter';
formComponentType?: 'DrawerForm' | 'ModalForm' | 'QueryFilter' | 'LightFilter' | string;

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.56%. Comparing base (4829ba9) to head (69c0b1e).
⚠️ Report is 3 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #9604      +/-   ##
==========================================
+ Coverage   88.48%   88.56%   +0.07%     
==========================================
  Files         368      369       +1     
  Lines       11255    11402     +147     
  Branches     4156     4225      +69     
==========================================
+ Hits         9959    10098     +139     
- Misses       1143     1151       +8     
  Partials      153      153              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…port

- Remove LightFilter component; layout lives in layouts/LightForm (default export)
- LightForm.input, LightForm.select, etc. are static fields on the same component
- Schema layoutType and formComponentType use LightForm; ProTable search uses LightForm
- Rename LightFilterFooterRender to LightFormFooterRender; update docs

BREAKING CHANGE: LightFilter and standalone lightForm export removed; use LightForm and LightForm.*

Co-authored-by: 陈帅 <wasd2144@hotmail.com>
@cursor cursor Bot changed the title feat(form): explicit lightForm API for LightFilter refactor(form): LightForm replaces LightFilter (unified API) Apr 23, 2026
Restore layout path src/form/layouts/LightFilter, formComponentType and layoutType LightFilter,
LightFilterFooterRender, isLightFilter; field helpers remain LightFilter.input etc.

Co-authored-by: 陈帅 <wasd2144@hotmail.com>
@cursor cursor Bot changed the title refactor(form): LightForm replaces LightFilter (unified API) refactor(form): LightFilter with explicit field helpers Apr 23, 2026
@chenshuai2144 chenshuai2144 marked this pull request as ready for review April 23, 2026 17:49
Copilot AI review requested due to automatic review settings April 23, 2026 17:49
@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Apr 23, 2026
@dosubot dosubot Bot added the form label Apr 23, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the inline “light” filter form to reintroduce LightFilter as the primary layout component and adds explicit field helpers (e.g. LightFilter.input, LightFilter.select) to opt into light-mode field behavior across forms, schema form, and ProTable integration.

Changes:

  • Rework LightFilter to be the default export and attach LightFilter.* static field helpers that force proFieldProps.light = true.
  • Update ProTable form rendering to better support LightFilter (including defaulting proFieldProps.light for LightFilter search fields).
  • Update tests and demos to use the new LightFilter.* helpers and align types (LightFilterProps, LightFilterFooterRender) and internal metadata (formComponentType = 'LightFilter').

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/form/lightFilter.test.tsx Updates LightFilter tests to use LightFilter.* helpers and adds coverage for non-helper fields not rendering light labels.
tests/form/filter.react.test.tsx Renames suite and migrates LightFilter usages to LightFilter.* helpers while keeping QueryFilter coverage intact.
tests/form/base.test.tsx Migrates ProFormSelect.SearchSelect usage under LightFilter to LightFilter.searchSelect.
src/utils/components/DropdownFooter/index.tsx Centralizes LightFilterFooterRender type import from src/form/typing.
src/table/components/Form/FormRender.tsx Ensures LightFilter-driven search fields default to proFieldProps.light: true unless explicitly set.
src/table/Table.tsx Updates LightFilter-related comment for toolbar behavior.
src/form/layouts/index.ts Switches LightFilter export to default as LightFilter from the layout module.
src/form/layouts/LightFilter/style.ts Minor cleanup/rename in LightFilter styling token handling.
src/form/layouts/LightFilter/lightFilterFieldComponents.tsx Introduces LightFilter.* field helper components that wrap ProForm fields with proFieldProps.light=true.
src/form/layouts/LightFilter/index.tsx Refactors LightFilter layout, sets formComponentType="LightFilter", attaches helpers via Object.assign, and adds default export.
src/form/components/SchemaForm/index.tsx Updates LightFilter import to use the default export.
src/form/FieldContext.tsx Expands formComponentType typing to include 'LightFilter' (but currently still widened by `
src/form/BaseForm/BaseForm.tsx Extends formComponentType union to include 'LightFilter'.
demos/form/QueryFilter/light-filter.tsx Migrates LightFilter demo fields to LightFilter.* helpers and removes redundant imports.
demos/form/QueryFilter/light-filter-collapse.tsx Migrates collapse demo fields to LightFilter.* helpers and removes redundant imports.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 236 to 240
formRef: userFormRef,
variant,
ignoreRules,
footerRender,
popoverProps,
...reset
Comment thread src/form/FieldContext.tsx
) => void;
/** Form 组件的类型 */
formComponentType?: string;
formComponentType?: 'DrawerForm' | 'ModalForm' | 'QueryFilter' | 'LightFilter' | string;
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
demos/form/QueryFilter/light-filter.tsx (1)

93-94: ⚠️ Potential issue | 🟡 Minor

类型与选项不一致:underlined 缺失

LightFilterVariant 类型只允许 'outlined' | 'filled' | 'borderless',但 Radio 组里新增了 underlined 选项(line 184)。一旦用户点击该选项,setVariant 会写入类型未声明的值,随后作为 variant 传给 LightFilter,既破坏类型契约,也可能让 LightFilter 落到非预期分支。

🛠️ 建议修复
-type LightFilterVariant = 'outlined' | 'filled' | 'borderless';
+type LightFilterVariant = 'outlined' | 'filled' | 'borderless' | 'underlined';

同时需确认 LightFiltervariant 属性(当前类型为 'outlined' | 'filled' | 'borderless')是否也需要扩展为 'underlined';若不支持请从 demo 中移除该按钮。

Also applies to: 181-185

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@demos/form/QueryFilter/light-filter.tsx` around lines 93 - 94,
LightFilterVariant union only allows 'outlined'|'filled'|'borderless' but the
Radio group adds 'underlined', causing setVariant to write an undeclared value
and pass it to LightFilter; either add 'underlined' to the LightFilterVariant
type and ensure the LightFilter component's variant prop/type also accepts
'underlined' (update its prop/interface) or remove the 'underlined' radio option
from the demo (and any setVariant usage); check usages of setVariant and the
LightFilter component to keep types consistent.
🧹 Nitpick comments (7)
src/utils/components/DropdownFooter/index.tsx (1)

7-7: 类型导入重构正确,但建议修复导入顺序

类型导入本身符合 PR 目标,成功使用了集中化的 LightFilterFooterRender 类型定义。使用 import type 语法也是正确的。

不过,文件中存在导入顺序问题(第 1-3 行)。根据编码规范,导入应按以下顺序组织:React → 第三方库 → Ant Design → pro-components 内部 → 相对路径 → 类型导入。

♻️ 建议的导入顺序修复
+import React, { useContext } from 'react';
+import { clsx } from 'clsx';
 import { Button, ConfigProvider } from 'antd';
-import { clsx } from 'clsx';
-import React, { useContext } from 'react';
 import { useIntl } from '../../../provider';
 import { useStyle } from './style';

 import type { LightFilterFooterRender } from '../../../form/typing';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/components/DropdownFooter/index.tsx` at line 7, Reorder the imports
in DropdownFooter so they follow the project's convention (React first,
third-party libs next, Ant Design, pro-components internals, relative paths, and
type-only imports last); specifically move the "import type {
LightFilterFooterRender }" to after the other runtime imports and ensure the
React import appears at the top and any Ant Design/pro-components imports sit
before the relative ./DropdownFooter references so the LightFilterFooterRender
type import is the final import in the module.
src/form/FieldContext.tsx (1)

24-24: 联合类型中的 | string 会让字面量提示失效

'DrawerForm' | 'ModalForm' | 'QueryFilter' | 'LightFilter' | string 会被 TS 归并为 string,IDE 无法给出字面量自动补全。若希望保留补全又允许任意字符串,推荐使用 (string & {}) 技巧:

♻️ 建议修改
-  formComponentType?: 'DrawerForm' | 'ModalForm' | 'QueryFilter' | 'LightFilter' | string;
+  formComponentType?:
+    | 'DrawerForm'
+    | 'ModalForm'
+    | 'QueryFilter'
+    | 'LightFilter'
+    | (string & {});

As per coding guidelines: "Use literal union types to define limited option sets"。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/form/FieldContext.tsx` at line 24, The union type for formComponentType
currently ends with "| string" which collapses the whole union to plain string
and disables literal autocomplete; update the type declaration in
FieldContext.tsx for the formComponentType property (the symbol to change) to
use the expandable string trick—replace "| string" with "& (string & {})" style
(i.e., make the union include (string & {}) instead of plain string) so the
literal members ('DrawerForm' | 'ModalForm' | 'QueryFilter' | 'LightFilter')
remain autocomplete-friendly while still allowing arbitrary strings.
demos/form/QueryFilter/light-filter-collapse.tsx (1)

15-24: 静态字段助手使用小写命名,与 PascalCase 组件命名规范不一致

LightFilter.selectLightFilter.dateTime(以及 PR 中的 LightFilter.searchSelectLightFilter.input 等)作为组件使用,按规范组件名应为 PascalCase(如 LightFilter.SelectLightFilter.DateTime)。这会影响 JSX 惯用可读性(小写在 JSX 中通常代表内置 host 元素),也对外暴露为公共 API,后续难以变更。建议在当前重构窗口内统一改为 PascalCase。

As per coding guidelines: "Use PascalCase for component names, such as ProForm, ProTable"。

请在合入前确认此命名选择是否为有意设计(例如与 QueryFilter / ProForm 的已有子组件命名对齐后确实选用了 camelCase),若无刻意考虑建议统一为 PascalCase。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@demos/form/QueryFilter/light-filter-collapse.tsx` around lines 15 - 24, The
file uses camelCase subcomponents (LightFilter.select, LightFilter.dateTime,
etc.) which violates the PascalCase component naming convention; change these
usages to PascalCase (LightFilter.Select, LightFilter.DateTime, and likewise
LightFilter.SearchSelect, LightFilter.Input) and update any other occurrences in
the PR (e.g., LightFilter.searchSelect, LightFilter.input) to match; if the
LightFilter module currently exports only camelCase names, update its export
surface to provide PascalCase exports or add PascalCase aliases for backward
compatibility (adjust the LightFilter component/file where those subcomponents
are defined), then run the build/tests to ensure no regressions and confirm
whether this rename is intentional if any existing public API relied on
camelCase.
tests/form/lightFilter.test.tsx (1)

13-26: 补充断言:验证裸 ProFormText 仍正常渲染为普通表单项

当前用例只断言了 .ant-pro-core-field-label 不存在,建议再断言内部 input(例如 container.querySelector('input[id="name1"]') 或 role='textbox')确实被渲染,避免后续如果连普通控件都没渲染成功时,该用例仍然会错误通过。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/form/lightFilter.test.tsx` around lines 13 - 26, The test for
LightFilter currently only asserts that the light field label is absent; add an
assertion that the raw ProFormText control actually renders by checking for its
input or textbox role (e.g., query for input with id "name1" or
getByRole('textbox')) to ensure ProFormText inside LightFilter still renders as
a normal form item; update the test case that uses LightFilter and ProFormText
to include this extra expectation so the test fails if the underlying input
isn't rendered.
src/form/layouts/LightFilter/index.tsx (2)

87-102: useMemo 依赖项建议使用已解构的 items

解构出的 itemsprops.items 在引用上等价,但混用会让 lint/阅读成本增加,且若未来重命名 props 容易漏改。建议统一使用 items

-  }, [props.items, collapse]);
+  }, [items, collapse]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/form/layouts/LightFilter/index.tsx` around lines 87 - 102, The useMemo
dependency currently references props.items while the body uses the destructured
items variable; update the dependency array to use items (and keep collapse) so
it reads [items, collapse] to avoid mixed references and potential lint/rename
issues in the useMemo that computes collapseItems and outsideItems in the
LightFilter component.

311-318: displayName 赋值可直接在 LightFilterComponent 上设置,无需类型断言

  1. lightFilterFieldComponents 已通过 as const 标记为只读(lightFilterFieldComponents.tsx:60),无需额外的只读标记。

  2. Object.assign 在运行时修改后,可直接在 LightFilterComponent.displayName = 'LightFilter' 后再执行 Object.assign,避免类型断言:

    LightFilterComponent.displayName = 'LightFilter';
    Object.assign(LightFilter, lightFilterFieldComponents);
    
  3. 关于泛型推断:typeof LightFilterComponent 通过交叉类型保留了泛型签名。当前实现应能支持泛型调用,但建议在后续使用中若有 <LightFilter<MyForm>> 的场景时确认类型推断正常工作。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/form/layouts/LightFilter/index.tsx` around lines 311 - 318, Set the
displayName directly on LightFilterComponent instead of using a type assertion
on LightFilter: assign LightFilterComponent.displayName = 'LightFilter' before
calling Object.assign(LightFilter, lightFilterFieldComponents); then create the
LightFilter export as you do (e.g., const LightFilter = LightFilterComponent as
typeof LightFilterComponent & typeof lightFilterFieldComponents and
Object.assign afterwards) so you can remove the (LightFilter as { displayName?:
string }) type assertion; reference LightFilterComponent,
lightFilterFieldComponents, and LightFilter when making these edits.
src/form/layouts/LightFilter/lightFilterFieldComponents.tsx (1)

24-31: 建议:通过 forwardRef 透传 ref,并收紧包装器类型

  1. 目前 FieldWrapper 未使用 forwardRef,会吞掉被包装 ProForm 组件的 ref(formRef/nativeElement 不受影响,但单字段 ref 链路被切断)。根据代码规范,组件应使用 forwardRef 实现 ref 传递。
  2. Record<string, any> 会完全丢失被包装组件原有的 props 类型(如 ProFormTextname/fieldProps 等),使用 LightFilter.input 时用户将失去类型提示与检查。可以用泛型保留原组件的 props 类型。
♻️ 参考实现
-const createLightFilterField = (Field: React.ComponentType<Record<string, any>>) => {
-  const FieldWrapper = (props: Record<string, any>) => {
-    const { proFieldProps, ...rest } = props;
-    return <Field {...rest} proFieldProps={{ light: true, ...proFieldProps }} />;
-  };
-  FieldWrapper.displayName = 'LightFilterField';
-  return FieldWrapper;
-};
+const createLightFilterField = <P extends { proFieldProps?: any }>(
+  Field: React.ComponentType<P>,
+) => {
+  const FieldWrapper = React.forwardRef<any, P>((props, ref) => {
+    const { proFieldProps, ...rest } = props;
+    return (
+      <Field
+        ref={ref as any}
+        {...(rest as P)}
+        proFieldProps={{ light: true, ...proFieldProps }}
+      />
+    );
+  });
+  FieldWrapper.displayName = 'LightFilterField';
+  return FieldWrapper;
+};

As per coding guidelines: "Use forwardRef to implement component ref passing" 与 "Avoid using any type; define types as precisely as possible"。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/form/layouts/LightFilter/lightFilterFieldComponents.tsx` around lines 24
- 31, createLightFilterField currently defines FieldWrapper without forwardRef
and uses Record<string, any>, which swallows the wrapped component's ref and its
original prop types; change createLightFilterField to be generic (e.g., <P>) so
it preserves the wrapped Field's props and replace FieldWrapper with
React.forwardRef to forward the ref to Field, merging props so proFieldProps
includes { light: true, ...proFieldProps } while keeping the rest of P's props
and the forwarded ref intact; keep FieldWrapper.displayName = 'LightFilterField'
after creating the forwarded-ref component to preserve debugging names.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@demos/form/QueryFilter/light-filter.tsx`:
- Around line 264-267: The LightFilter.fieldSet usage currently nests
LightFilter.input (nameSet -> LightFilter.input) which causes child inputs to
receive light=true and renders them as bubble FieldLabel; replace the nested
LightFilter.input components inside LightFilter.fieldSet with non-light form
controls such as ProFormText so the children are not injected with light and the
FieldSet preserves inline layout — update the block using LightFilter.fieldSet
name="nameSet" to render ProFormText placeholders for "姓" and "名" instead of
LightFilter.input.

In `@src/table/components/Form/FormRender.tsx`:
- Around line 184-193: The default-injection for light in proFieldProps is too
permissive and can be overwritten by an explicit undefined; in the mapping that
builds proFieldProps (referencing competentName, item.proFieldProps and
proFieldKey), change the condition so you only inject { light: true } when
competentName === 'LightFilter' AND the "light" property is not present on
item.proFieldProps (use 'light' in (item.proFieldProps ?? {}) to detect
presence), ensuring you don't get overridden by an explicit undefined or miss
cases where proFieldProps is null.

---

Outside diff comments:
In `@demos/form/QueryFilter/light-filter.tsx`:
- Around line 93-94: LightFilterVariant union only allows
'outlined'|'filled'|'borderless' but the Radio group adds 'underlined', causing
setVariant to write an undeclared value and pass it to LightFilter; either add
'underlined' to the LightFilterVariant type and ensure the LightFilter
component's variant prop/type also accepts 'underlined' (update its
prop/interface) or remove the 'underlined' radio option from the demo (and any
setVariant usage); check usages of setVariant and the LightFilter component to
keep types consistent.

---

Nitpick comments:
In `@demos/form/QueryFilter/light-filter-collapse.tsx`:
- Around line 15-24: The file uses camelCase subcomponents (LightFilter.select,
LightFilter.dateTime, etc.) which violates the PascalCase component naming
convention; change these usages to PascalCase (LightFilter.Select,
LightFilter.DateTime, and likewise LightFilter.SearchSelect, LightFilter.Input)
and update any other occurrences in the PR (e.g., LightFilter.searchSelect,
LightFilter.input) to match; if the LightFilter module currently exports only
camelCase names, update its export surface to provide PascalCase exports or add
PascalCase aliases for backward compatibility (adjust the LightFilter
component/file where those subcomponents are defined), then run the build/tests
to ensure no regressions and confirm whether this rename is intentional if any
existing public API relied on camelCase.

In `@src/form/FieldContext.tsx`:
- Line 24: The union type for formComponentType currently ends with "| string"
which collapses the whole union to plain string and disables literal
autocomplete; update the type declaration in FieldContext.tsx for the
formComponentType property (the symbol to change) to use the expandable string
trick—replace "| string" with "& (string & {})" style (i.e., make the union
include (string & {}) instead of plain string) so the literal members
('DrawerForm' | 'ModalForm' | 'QueryFilter' | 'LightFilter') remain
autocomplete-friendly while still allowing arbitrary strings.

In `@src/form/layouts/LightFilter/index.tsx`:
- Around line 87-102: The useMemo dependency currently references props.items
while the body uses the destructured items variable; update the dependency array
to use items (and keep collapse) so it reads [items, collapse] to avoid mixed
references and potential lint/rename issues in the useMemo that computes
collapseItems and outsideItems in the LightFilter component.
- Around line 311-318: Set the displayName directly on LightFilterComponent
instead of using a type assertion on LightFilter: assign
LightFilterComponent.displayName = 'LightFilter' before calling
Object.assign(LightFilter, lightFilterFieldComponents); then create the
LightFilter export as you do (e.g., const LightFilter = LightFilterComponent as
typeof LightFilterComponent & typeof lightFilterFieldComponents and
Object.assign afterwards) so you can remove the (LightFilter as { displayName?:
string }) type assertion; reference LightFilterComponent,
lightFilterFieldComponents, and LightFilter when making these edits.

In `@src/form/layouts/LightFilter/lightFilterFieldComponents.tsx`:
- Around line 24-31: createLightFilterField currently defines FieldWrapper
without forwardRef and uses Record<string, any>, which swallows the wrapped
component's ref and its original prop types; change createLightFilterField to be
generic (e.g., <P>) so it preserves the wrapped Field's props and replace
FieldWrapper with React.forwardRef to forward the ref to Field, merging props so
proFieldProps includes { light: true, ...proFieldProps } while keeping the rest
of P's props and the forwarded ref intact; keep FieldWrapper.displayName =
'LightFilterField' after creating the forwarded-ref component to preserve
debugging names.

In `@src/utils/components/DropdownFooter/index.tsx`:
- Line 7: Reorder the imports in DropdownFooter so they follow the project's
convention (React first, third-party libs next, Ant Design, pro-components
internals, relative paths, and type-only imports last); specifically move the
"import type { LightFilterFooterRender }" to after the other runtime imports and
ensure the React import appears at the top and any Ant Design/pro-components
imports sit before the relative ./DropdownFooter references so the
LightFilterFooterRender type import is the final import in the module.

In `@tests/form/lightFilter.test.tsx`:
- Around line 13-26: The test for LightFilter currently only asserts that the
light field label is absent; add an assertion that the raw ProFormText control
actually renders by checking for its input or textbox role (e.g., query for
input with id "name1" or getByRole('textbox')) to ensure ProFormText inside
LightFilter still renders as a normal form item; update the test case that uses
LightFilter and ProFormText to include this extra expectation so the test fails
if the underlying input isn't rendered.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9a3d5c10-be9a-45f3-b7eb-3ff7a16853cf

📥 Commits

Reviewing files that changed from the base of the PR and between bdbf841 and 69c0b1e.

📒 Files selected for processing (15)
  • demos/form/QueryFilter/light-filter-collapse.tsx
  • demos/form/QueryFilter/light-filter.tsx
  • src/form/BaseForm/BaseForm.tsx
  • src/form/FieldContext.tsx
  • src/form/components/SchemaForm/index.tsx
  • src/form/layouts/LightFilter/index.tsx
  • src/form/layouts/LightFilter/lightFilterFieldComponents.tsx
  • src/form/layouts/LightFilter/style.ts
  • src/form/layouts/index.ts
  • src/table/Table.tsx
  • src/table/components/Form/FormRender.tsx
  • src/utils/components/DropdownFooter/index.tsx
  • tests/form/base.test.tsx
  • tests/form/filter.react.test.tsx
  • tests/form/lightFilter.test.tsx

Comment on lines +264 to +267
<LightFilter.fieldSet name="nameSet" label="姓名">
<LightFilter.input placeholder="姓" />
<LightFilter.input placeholder="名" />
</LightFilter.fieldSet>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 查看 ProFormFieldSet 如何渲染 children,是否会覆盖子项的 light 标记
fd -t f FieldSet src/form/components/FieldSet | xargs -r cat

Repository: ant-design/pro-components

Length of output: 51


🏁 Script executed:

# Find the QueryFilter light-filter demo file
fd -type f "light-filter.tsx" demos/

Repository: ant-design/pro-components

Length of output: 239


🏁 Script executed:

# Find LightFilter component source files
fd -type f -path "*/LightFilter*" src/

Repository: ant-design/pro-components

Length of output: 239


🏁 Script executed:

# Search for how LightFilter components are defined and how they inject light prop
rg "LightFilter\." src/ -A 3 -B 1 --max-count=20

Repository: ant-design/pro-components

Length of output: 571


🏁 Script executed:

# Correct syntax for fd
fd -t f "light-filter.tsx" demos/

Repository: ant-design/pro-components

Length of output: 108


🏁 Script executed:

# Find and read the lightFilterFieldComponents to understand createLightFilterField
cat src/form/layouts/LightFilter/lightFilterFieldComponents.tsx

Repository: ant-design/pro-components

Length of output: 3493


🏁 Script executed:

# Search for createLightFilterField definition
rg "createLightFilterField" src/ -A 5 -B 2

Repository: ant-design/pro-components

Length of output: 4170


🏁 Script executed:

# Read the light-filter.tsx demo file around lines 264-267
sed -n '260,270p' demos/form/QueryFilter/light-filter.tsx

Repository: ant-design/pro-components

Length of output: 548


🏁 Script executed:

# Find and read ProFormFieldSet to understand how it renders children
fd -t f "FieldSet" src/form/components/ | grep -i "\.tsx$"

Repository: ant-design/pro-components

Length of output: 51


🏁 Script executed:

# Search for ProFormFieldSet implementation
rg "ProFormFieldSet" src/form/components -l

Repository: ant-design/pro-components

Length of output: 189


🏁 Script executed:

# Read the ProFormFieldSet implementation
cat src/form/components/FieldSet/index.tsx

Repository: ant-design/pro-components

Length of output: 4505


🏁 Script executed:

# Also check the formSet.tsx which might have related logic
cat src/form/components/SchemaForm/valueType/formSet.tsx

Repository: ant-design/pro-components

Length of output: 790


🏁 Script executed:

# Search for how ProFormFieldSet handles children and proFieldProps
rg "proFieldProps" src/form/components/FieldSet -A 3 -B 3

Repository: ant-design/pro-components

Length of output: 51


🏁 Script executed:

# Search for how the 'light' prop is used in ProFormText and other form components
rg "light" src/form/components/Text -A 2 -B 2 | head -50

Repository: ant-design/pro-components

Length of output: 51


🏁 Script executed:

# Check if there's any special handling of light prop in the FormItem wrapper
rg "proFieldProps.*light" src/ -A 3 -B 3 | head -80

Repository: ant-design/pro-components

Length of output: 3090


🏁 Script executed:

# Search for FieldLabel to understand what rendering happens with light=true
rg "FieldLabel" src/ -l

Repository: ant-design/pro-components

Length of output: 779


🏁 Script executed:

# Check the FieldLabel component to understand the light mode rendering
cat src/utils/components/FieldLabel/index.tsx | head -100

Repository: ant-design/pro-components

Length of output: 2686


🏁 Script executed:

# Verify how ProFormFieldSet children are rendered when they have light=true
rg "displayName.*ProFormComponent" src/form/components -B 5 -A 2 | head -50

Repository: ant-design/pro-components

Length of output: 3179


LightFilter.fieldSet 内部不应使用 LightFilter.input

LightFilter.* 组件会强制注入 proFieldProps.light = true,使其作为 LightFilter 的顶层筛选项时渲染为 FieldLabel 气泡样式。但在 LightFilter.fieldSet 内部使用 LightFilter.input 时,子项也会被注入 light=true,导致 FieldSet 的行内输入框被错误地渲染成气泡样式,破坏了 FieldSet 的行内布局。

建议改用 ProFormText,这样子项不会被注入 light 标记,保留 FieldSet 的正确行内显示效果。

建议修复
        <LightFilter.fieldSet name="nameSet" label="姓名">
-          <LightFilter.input placeholder="姓" />
-          <LightFilter.input placeholder="名" />
+          <ProFormText placeholder="姓" />
+          <ProFormText placeholder="名" />
        </LightFilter.fieldSet>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<LightFilter.fieldSet name="nameSet" label="姓名">
<LightFilter.input placeholder="姓" />
<LightFilter.input placeholder="名" />
</LightFilter.fieldSet>
<LightFilter.fieldSet name="nameSet" label="姓名">
<ProFormText placeholder="姓" />
<ProFormText placeholder="名" />
</LightFilter.fieldSet>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@demos/form/QueryFilter/light-filter.tsx` around lines 264 - 267, The
LightFilter.fieldSet usage currently nests LightFilter.input (nameSet ->
LightFilter.input) which causes child inputs to receive light=true and renders
them as bubble FieldLabel; replace the nested LightFilter.input components
inside LightFilter.fieldSet with non-light form controls such as ProFormText so
the children are not injected with light and the FieldSet preserves inline
layout — update the block using LightFilter.fieldSet name="nameSet" to render
ProFormText placeholders for "姓" and "名" instead of LightFilter.input.

Comment on lines 184 to +193
proFieldProps: {
...(competentName === 'LightFilter' && item.proFieldProps?.light === undefined
? { light: true }
: {}),
...item.proFieldProps,
proFieldKey: columnKey ? `table-field-${columnKey}` : undefined,
},
};
});
}, [columns, type]);

const className = getPrefixCls('pro-table-search');
const formClassName = getPrefixCls('pro-table-form');

const competentName = useMemo(
() => getFormCompetent(isForm, searchConfig),
[searchConfig, isForm],
);
}, [columns, type, competentName]);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

light 默认注入的判断可收紧,避免覆盖显式 undefined

当前逻辑:

proFieldProps: {
  ...(competentName === 'LightFilter' && item.proFieldProps?.light === undefined
    ? { light: true }
    : {}),
  ...item.proFieldProps,
  ...
}
  • item.proFieldProps?.light === undefinedlight 未设置时为 true,此时注入 { light: true },随后 ...item.proFieldProps 展开;若用户将 light 显式写为 undefined,会把刚注入的 true 覆盖回 undefined
  • 另外,该条件依赖 item.proFieldProps 的可选链,当其为 null 时仍返回 undefined,可能与预期不符。

建议使用 'light' in (item.proFieldProps ?? {}) 判断,行为更精确:

♻️ 建议修改
-          proFieldProps: {
-            ...(competentName === 'LightFilter' && item.proFieldProps?.light === undefined
-              ? { light: true }
-              : {}),
-            ...item.proFieldProps,
+          proFieldProps: {
+            ...(competentName === 'LightFilter' &&
+            !('light' in (item.proFieldProps ?? {}))
+              ? { light: true }
+              : {}),
+            ...item.proFieldProps,
             proFieldKey: columnKey ? `table-field-${columnKey}` : undefined,
           },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
proFieldProps: {
...(competentName === 'LightFilter' && item.proFieldProps?.light === undefined
? { light: true }
: {}),
...item.proFieldProps,
proFieldKey: columnKey ? `table-field-${columnKey}` : undefined,
},
};
});
}, [columns, type]);
const className = getPrefixCls('pro-table-search');
const formClassName = getPrefixCls('pro-table-form');
const competentName = useMemo(
() => getFormCompetent(isForm, searchConfig),
[searchConfig, isForm],
);
}, [columns, type, competentName]);
proFieldProps: {
...(competentName === 'LightFilter' &&
!('light' in (item.proFieldProps ?? {}))
? { light: true }
: {}),
...item.proFieldProps,
proFieldKey: columnKey ? `table-field-${columnKey}` : undefined,
},
};
});
}, [columns, type, competentName]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/table/components/Form/FormRender.tsx` around lines 184 - 193, The
default-injection for light in proFieldProps is too permissive and can be
overwritten by an explicit undefined; in the mapping that builds proFieldProps
(referencing competentName, item.proFieldProps and proFieldKey), change the
condition so you only inject { light: true } when competentName ===
'LightFilter' AND the "light" property is not present on item.proFieldProps (use
'light' in (item.proFieldProps ?? {}) to detect presence), ensuring you don't
get overridden by an explicit undefined or miss cases where proFieldProps is
null.

@chenshuai2144 chenshuai2144 merged commit a3e1dc2 into master May 2, 2026
17 checks passed
@chenshuai2144 chenshuai2144 deleted the cursor/lightform-explicit-api-1690 branch May 2, 2026 03:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

form size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants