Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions demos/form/QueryFilter/light-filter-collapse.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import {
LightFilter,
ProFormDateTimePicker,
ProFormSelect,
} from '@ant-design/pro-components';
import { LightFilter } from '@ant-design/pro-components';
import { message } from 'antd';

const Demo = () => {
Expand All @@ -16,7 +12,7 @@ const Demo = () => {
message.success('提交成功');
}}
>
<ProFormSelect
<LightFilter.select
name="sex"
label="性别"
showSearch
Expand All @@ -25,7 +21,7 @@ const Demo = () => {
woman: '女',
}}
/>
<ProFormDateTimePicker name="time" label="时间" />
<LightFilter.dateTime name="time" label="时间" />
</LightFilter>
);
};
Expand Down
62 changes: 23 additions & 39 deletions demos/form/QueryFilter/light-filter.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,4 @@
import {
LightFilter,
ProFormCascader,
ProFormCheckbox,
ProFormDatePicker,
ProFormDateRangePicker,
ProFormDateTimePicker,
ProFormDateTimeRangePicker,
ProFormDigit,
ProFormFieldSet,
ProFormSelect,
ProFormSlider,
ProFormSwitch,
ProFormText,
ProFormTimePicker,
ProFormTreeSelect,
} from '@ant-design/pro-components';
import { LightFilter } from '@ant-design/pro-components';
import { Radio, Space, TreeSelect } from 'antd';
import type { SizeType } from 'antd/lib/config-provider/SizeContext';
import dayjs from 'dayjs';
Expand Down Expand Up @@ -210,7 +194,7 @@ const Demo = () => {
console.log('筛选提交:', values);
}}
>
<ProFormSelect
<LightFilter.select
name="sex"
label="性别"
showSearch
Expand All @@ -221,7 +205,7 @@ const Demo = () => {
woman: '女',
}}
/>
<ProFormSelect
<LightFilter.select
name="area"
label="地区"
mode="multiple"
Expand All @@ -234,12 +218,12 @@ const Demo = () => {
long: '这是一个很长的用来测试溢出的项目',
}}
/>
<ProFormCheckbox.Group
<LightFilter.checkboxGroup
name="checkboxGroup"
label="标签"
options={['A', 'B', 'C', 'D', 'E', 'F']}
/>
<ProFormTreeSelect
<LightFilter.treeSelect
label="树形选择"
name="treeSelect"
fieldProps={{
Expand All @@ -250,7 +234,7 @@ const Demo = () => {
placeholder: '请选择',
}}
/>
<ProFormCascader
<LightFilter.cascader
name="region"
label="区域"
width="md"
Expand All @@ -259,28 +243,28 @@ const Demo = () => {
placeholder: '请选择省/市/区',
}}
/>
<ProFormSwitch name="open" label="开关" />
<ProFormSwitch name="status" label="状态" secondary />
<ProFormDigit name="count" label="数量" min={0} max={9999} />
<ProFormSlider name="range" label="范围" range />
<ProFormSlider name="slider" label="滑块" />
<ProFormText name="keyword" label="关键词" placeholder="请输入关键词" />
<ProFormText
<LightFilter.switch name="open" label="开关" />
<LightFilter.switch name="status" label="状态" secondary />
<LightFilter.digit name="count" label="数量" min={0} max={9999} />
<LightFilter.slider name="range" label="范围" range />
<LightFilter.slider name="slider" label="滑块" />
<LightFilter.input name="keyword" label="关键词" placeholder="请输入关键词" />
<LightFilter.input
name="address"
label="地址"
secondary
placeholder="请输入地址"
/>
<ProFormDatePicker name="date" label="日期" allowClear={false} />
<ProFormDateRangePicker name="dateRange" label="日期范围" />
<ProFormDateTimePicker name="datetime" label="日期时间" />
<ProFormDateTimeRangePicker name="datetimeRange" label="日期时间范围" />
<ProFormTimePicker name="time" label="时间" />
<ProFormTimePicker.RangePicker name="timeRange" label="时间范围" />
<ProFormFieldSet name="nameSet" label="姓名">
<ProFormText placeholder="姓" />
<ProFormText placeholder="名" />
</ProFormFieldSet>
<LightFilter.date name="date" label="日期" allowClear={false} />
<LightFilter.dateRange name="dateRange" label="日期范围" />
<LightFilter.dateTime name="datetime" label="日期时间" />
<LightFilter.dateTimeRange name="datetimeRange" label="日期时间范围" />
<LightFilter.time name="time" label="时间" />
<LightFilter.timePickerRange name="timeRange" label="时间范围" />
<LightFilter.fieldSet name="nameSet" label="姓名">
<LightFilter.input placeholder="姓" />
<LightFilter.input placeholder="名" />
</LightFilter.fieldSet>
Comment on lines +264 to +267
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.

</LightFilter>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/form/BaseForm/BaseForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ export type BaseFormProps<T = Record<string, any>, U = Record<string, any>> = {
/** 是否回车提交 */
isKeyPressSubmit?: boolean;
/** Form 组件的类型,内部使用 */
formComponentType?: 'DrawerForm' | 'ModalForm' | 'QueryFilter';
formComponentType?: 'DrawerForm' | 'ModalForm' | 'QueryFilter' | 'LightFilter';
} & Omit<FormProps, 'onFinish'> &
CommonFormProps<T, U>;

Expand Down
2 changes: 1 addition & 1 deletion src/form/FieldContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export type FiledContextProps = {
},
) => void;
/** Form 组件的类型 */
formComponentType?: string;
formComponentType?: 'DrawerForm' | 'ModalForm' | 'QueryFilter' | 'LightFilter' | string;
/** 获取表单实例计数器 */
formKey?: string;

Expand Down
2 changes: 1 addition & 1 deletion src/form/components/SchemaForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
import type { ProFormInstance } from '../../BaseForm';
import type { ProFormProps } from '../../layouts';
import { DrawerForm } from '../../layouts/DrawerForm';
import { LightFilter } from '../../layouts/LightFilter';
import LightFilter from '../../layouts/LightFilter';
import { ModalForm } from '../../layouts/ModalForm';
import { ProForm } from '../../layouts/ProForm';
import { QueryFilter } from '../../layouts/QueryFilter';
Expand Down
82 changes: 18 additions & 64 deletions src/form/layouts/LightFilter/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,73 +5,29 @@ import { ConfigProvider } from 'antd';
import type { SizeType } from 'antd/lib/config-provider/SizeContext';
import type { TooltipPlacement } from 'antd/lib/tooltip';
import { clsx } from 'clsx';
import React, {
useContext,
useEffect,
useImperativeHandle,
useMemo,
useRef,
useState,
} from 'react';
import React, { useContext, useImperativeHandle, useMemo, useRef, useState } from 'react';
import { useIntl } from '../../../provider';
import { FieldLabel, FilterDropdown } from '../../../utils';
import type { CommonFormProps, ProFormInstance } from '../../BaseForm';
import { BaseForm } from '../../BaseForm';
import type { LightFilterFooterRender } from '../../typing';
import { lightFilterFieldComponents } from './lightFilterFieldComponents';
import { useStyle } from './style';

export type LightFilterProps<T, U = Record<string, any>> = {
export type LightFilterLayoutProps<T, U = Record<string, any>> = {
collapse?: boolean;
/**
* @name 收起的label dom
*
* @example collapseLabel={"收起"}
*/
collapseLabel?: React.ReactNode;
/**
* @name 组件样式变体
*/
variant?: 'outlined' | 'filled' | 'borderless';
/**
* @name 忽略rules,一般而言 LightFilter 应该不支持rules,默认是 false。
*/
ignoreRules?: boolean;

/**
* @name 自定义 footerRender
*
* @example 自定义清除
* footerRender={(onConfirm,onClear)=>{ return <a onClick={onClear}>清除</a> })}
*/
footerRender?: LightFilterFooterRender;

/**
* @name 支持配置弹出的位置
* @default bottomLeft
*/
placement?: TooltipPlacement;
/**
* @name 透传给内部 Popover 的属性(折叠态弹层)
*
* @description
* LightFilter 在折叠态会使用 Popover 将筛选项渲染到 body 下;
* 可通过该属性为弹层根节点添加自定义类名(如 classNames.root)以便做样式覆盖。
*
* @example
* popoverProps={{ classNames: { root: 'my-lightfilter-popover' } } }
*/
popoverProps?: Omit<
PopoverProps,
'children' | 'content' | 'trigger' | 'open' | 'onOpenChange' | 'placement'
>;
} & Omit<FormProps<T>, 'onFinish'> &
CommonFormProps<T, U>;

/**
* 单行的查询表单,一般用于配合 table 或者 list使用 有时也会用于 card 的额外区域
*
* @param props
*/
const LightFilterContainer: React.FC<{
items: React.ReactNode[];
prefixCls: string;
Expand Down Expand Up @@ -126,15 +82,7 @@ const LightFilterContainer: React.FC<{
label={intl.getMessage('form.lightFilter.more', '更多筛选')}
/>
);
}, [
collapseLabel,
collapse,
lightFilterClassName,
hashId,
variant,
size,
intl,
]);
}, [collapseLabel, collapse, lightFilterClassName, hashId, variant, size, intl]);

const { collapseItems, outsideItems } = useMemo(() => {
const collapseItemsArr: React.ReactNode[] = [];
Expand All @@ -151,7 +99,7 @@ const LightFilterContainer: React.FC<{
collapseItems: collapseItemsArr,
outsideItems: outsideItemsArr,
};
}, [props.items]);
}, [props.items, collapse]);

return wrapSSR(
<div
Expand Down Expand Up @@ -189,10 +137,8 @@ const LightFilterContainer: React.FC<{
placement: newPlacement,
variant: 'borderless',
},
// proFieldProps 会直接作为 ProField 的 props 传递过去
proFieldProps: {
...child.props.proFieldProps,
light: true,
label: child.props.label,
variant,
},
Expand All @@ -214,7 +160,7 @@ const LightFilterContainer: React.FC<{
}}
placement={placement}
popoverProps={popoverProps}
label={collapseLabelNode}
label={collapseLabelNode}
footerRender={footerRender}
footer={{
onConfirm: () => {
Expand Down Expand Up @@ -246,7 +192,7 @@ const LightFilterContainer: React.FC<{
return false;
},
};
if (moreValues.hasOwnProperty(name)) {
if (Object.prototype.hasOwnProperty.call(moreValues, name)) {
newFieldProps[child.props.valuePropName || 'value'] =
moreValues[name];
}
Expand Down Expand Up @@ -276,7 +222,9 @@ const LightFilterContainer: React.FC<{
);
};

function LightFilter<T = Record<string, any>>(props: LightFilterProps<T>) {
function LightFilterComponent<T = Record<string, any>>(
props: LightFilterLayoutProps<T>,
) {
const {
size,
collapse,
Expand All @@ -287,7 +235,6 @@ function LightFilter<T = Record<string, any>>(props: LightFilterProps<T>) {
placement,
formRef: userFormRef,
variant,
ignoreRules,
footerRender,
popoverProps,
...reset
Comment on lines 236 to 240
Expand All @@ -304,6 +251,7 @@ function LightFilter<T = Record<string, any>>(props: LightFilterProps<T>) {
return (
<BaseForm
size={size}
formComponentType="LightFilter"
initialValues={initialValues}
form={userForm}
contentRender={(items) => {
Expand All @@ -313,7 +261,6 @@ function LightFilter<T = Record<string, any>>(props: LightFilterProps<T>) {
prefixCls={prefixCls}
items={items?.flatMap((item: any) => {
if (!item || !item?.type) return item;
/** 如果是 ProFormGroup,直接拼接dom */
if (item?.type?.displayName === 'ProForm-Group')
return item.props.children;
return item;
Expand Down Expand Up @@ -361,4 +308,11 @@ function LightFilter<T = Record<string, any>>(props: LightFilterProps<T>) {
);
}

type LightFilterType = typeof LightFilterComponent & typeof lightFilterFieldComponents;
const LightFilter = LightFilterComponent as LightFilterType;
Object.assign(LightFilter, lightFilterFieldComponents);
(LightFilter as { displayName?: string }).displayName = 'LightFilter';

export { LightFilter };
export default LightFilter;
export type { LightFilterLayoutProps as LightFilterProps };
Loading
Loading