refactor(form): LightFilter with explicit field helpers#9604
refactor(form): LightFilter with explicit field helpers#9604chenshuai2144 merged 3 commits intomasterfrom
Conversation
…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>
📝 Walkthrough高层概述将 变更概览
📊 审查难度评估🎯 3 (中等复杂度) | ⏱️ ~25 分钟 变更涉及多个文件但模式一致(组件 API 迁移),包含类型定义更新和 memoization 逻辑调整,需要验证导出方式变更和字段组件集成的正确性。 小诗
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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.
| 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; | ||
| }; |
There was a problem hiding this comment.
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'; |
There was a problem hiding this comment.
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).
| formComponentType?: 'DrawerForm' | 'ModalForm' | 'QueryFilter' | 'LightFilter'; | |
| formComponentType?: 'DrawerForm' | 'ModalForm' | 'QueryFilter' | 'LightFilter' | string; |
Codecov Report✅ All modified and coverable lines are covered by tests. 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. 🚀 New features to boost your workflow:
|
…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>
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>
There was a problem hiding this comment.
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
LightFilterto be the default export and attachLightFilter.*static field helpers that forceproFieldProps.light = true. - Update ProTable form rendering to better support
LightFilter(including defaultingproFieldProps.lightfor 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.
| formRef: userFormRef, | ||
| variant, | ||
| ignoreRules, | ||
| footerRender, | ||
| popoverProps, | ||
| ...reset |
| ) => void; | ||
| /** Form 组件的类型 */ | ||
| formComponentType?: string; | ||
| formComponentType?: 'DrawerForm' | 'ModalForm' | 'QueryFilter' | 'LightFilter' | string; |
There was a problem hiding this comment.
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';同时需确认
LightFilter的variant属性(当前类型为'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.select、LightFilter.dateTime(以及 PR 中的LightFilter.searchSelect、LightFilter.input等)作为组件使用,按规范组件名应为 PascalCase(如LightFilter.Select、LightFilter.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解构出的
items与props.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上设置,无需类型断言
lightFilterFieldComponents已通过as const标记为只读(lightFilterFieldComponents.tsx:60),无需额外的只读标记。
Object.assign在运行时修改后,可直接在LightFilterComponent.displayName = 'LightFilter'后再执行Object.assign,避免类型断言:LightFilterComponent.displayName = 'LightFilter'; Object.assign(LightFilter, lightFilterFieldComponents);关于泛型推断:
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,并收紧包装器类型
- 目前
FieldWrapper未使用forwardRef,会吞掉被包装 ProForm 组件的 ref(formRef/nativeElement 不受影响,但单字段 ref 链路被切断)。根据代码规范,组件应使用forwardRef实现 ref 传递。Record<string, any>会完全丢失被包装组件原有的 props 类型(如ProFormText的name/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
forwardRefto implement component ref passing" 与 "Avoid usinganytype; 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
📒 Files selected for processing (15)
demos/form/QueryFilter/light-filter-collapse.tsxdemos/form/QueryFilter/light-filter.tsxsrc/form/BaseForm/BaseForm.tsxsrc/form/FieldContext.tsxsrc/form/components/SchemaForm/index.tsxsrc/form/layouts/LightFilter/index.tsxsrc/form/layouts/LightFilter/lightFilterFieldComponents.tsxsrc/form/layouts/LightFilter/style.tssrc/form/layouts/index.tssrc/table/Table.tsxsrc/table/components/Form/FormRender.tsxsrc/utils/components/DropdownFooter/index.tsxtests/form/base.test.tsxtests/form/filter.react.test.tsxtests/form/lightFilter.test.tsx
| <LightFilter.fieldSet name="nameSet" label="姓名"> | ||
| <LightFilter.input placeholder="姓" /> | ||
| <LightFilter.input placeholder="名" /> | ||
| </LightFilter.fieldSet> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# 查看 ProFormFieldSet 如何渲染 children,是否会覆盖子项的 light 标记
fd -t f FieldSet src/form/components/FieldSet | xargs -r catRepository: 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=20Repository: 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.tsxRepository: ant-design/pro-components
Length of output: 3493
🏁 Script executed:
# Search for createLightFilterField definition
rg "createLightFilterField" src/ -A 5 -B 2Repository: 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.tsxRepository: 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 -lRepository: ant-design/pro-components
Length of output: 189
🏁 Script executed:
# Read the ProFormFieldSet implementation
cat src/form/components/FieldSet/index.tsxRepository: 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.tsxRepository: 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 3Repository: 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 -50Repository: 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 -80Repository: ant-design/pro-components
Length of output: 3090
🏁 Script executed:
# Search for FieldLabel to understand what rendering happens with light=true
rg "FieldLabel" src/ -lRepository: 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 -100Repository: 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 -50Repository: 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.
| <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.
| 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]); |
There was a problem hiding this comment.
light 默认注入的判断可收紧,避免覆盖显式 undefined
当前逻辑:
proFieldProps: {
...(competentName === 'LightFilter' && item.proFieldProps?.light === undefined
? { light: true }
: {}),
...item.proFieldProps,
...
}
item.proFieldProps?.light === undefined在light未设置时为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.
| 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.
Summary
The light inline filter is
LightFilteragain (layout insrc/form/layouts/LightFilter).<LightFilter>...</LightFilter>(default export)LightFilter.input,LightFilter.select, etc. (static properties on the same object)LightFilterProps,LightFilterFooterRender(replaces the interimLightForm*names)formComponentType/layoutType='LightFilter',isLightFilteron table toolbarant-pro-form-light-filterunchangedSummary by CodeRabbit
发布说明
重构
LightFilter的组合字段组件来构建筛选器,提高了代码的一致性和可维护性。类型更新
LightFilter作为新的表单组件类型。