diff --git a/packages/card/src/components/CheckCard/index.tsx b/packages/card/src/components/CheckCard/index.tsx index b287aa433e52..1d80b8752b28 100644 --- a/packages/card/src/components/CheckCard/index.tsx +++ b/packages/card/src/components/CheckCard/index.tsx @@ -2,7 +2,9 @@ import { useMountMergeState } from '@ant-design/pro-utils'; import { Avatar, ConfigProvider } from 'antd'; import classNames from 'classnames'; +import type { MouseEventHandler } from 'react'; import React, { useContext, useEffect, useMemo } from 'react'; +import ProCardActions from '../Actions'; import type { CheckCardGroupProps } from './Group'; import CheckCardGroup, { CardLoading, CheckCardGroupConnext } from './Group'; import { useStyle } from './style'; @@ -16,11 +18,11 @@ interface CheckCardProps { /** Change 回调 */ onChange?: (checked: boolean) => void; /** Click 回调 */ - onClick?: (e: Event) => void; + onClick?: (event: MouseEventHandler | undefined) => void; /** 鼠标进入时的回调 */ - onMouseEnter?: (event: MouseEvent) => void; + onMouseEnter?: MouseEventHandler; /** 鼠标出来时的回调 */ - onMouseLeave?: (event: MouseEvent) => void; + onMouseLeave?: (event: MouseEventHandler | undefined) => void; /** * 默认是否勾选 * @@ -66,6 +68,12 @@ interface CheckCardProps { * @title 标题 */ title?: React.ReactNode; + /** + * 二级标题展示 + * + * @title 二级标题 + */ + subTitle?: React.ReactNode; /** * 描述展示 * @@ -111,6 +119,16 @@ interface CheckCardProps { * @title 操作栏 */ extra?: React.ReactNode; + + children?: React.ReactNode; + /** + * 内容区域的样式设计 + */ + bodyStyle?: React.CSSProperties; + /** + * 右下角的操作区 + */ + actions?: React.ReactNode[]; } export interface CheckCardState { @@ -134,7 +152,7 @@ const CheckCard: React.FC & { props?.onClick?.(e); const newChecked = !stateChecked; checkCardGroup?.toggleOption?.({ value: props.value }); - setStateChecked?.(newChecked); + setStateChecked?.(newChecked, e); }; // small => sm large => lg @@ -246,7 +264,14 @@ const CheckCard: React.FC & { const headerDom = (title ?? extra) != null && (
-
{title}
+
+
{title}
+ {props.subTitle ? ( +
+ {props.subTitle} +
+ ) : null} +
{extra && (
{extra}
)} @@ -282,6 +307,7 @@ const CheckCard: React.FC & { extra, hashId, prefixCls, + props.subTitle, title, ]); @@ -294,8 +320,20 @@ const CheckCard: React.FC & { handleClick(e); } }} + onMouseEnter={props.onMouseEnter} > {metaDom} + {props.children ? ( +
+ {props.children} +
+ ) : null} + {props.actions ? ( + + ) : null}
, ); }; diff --git a/packages/card/src/components/CheckCard/style.ts b/packages/card/src/components/CheckCard/style.ts index 6bf527bd6dd2..d5eea95df892 100644 --- a/packages/card/src/components/CheckCard/style.ts +++ b/packages/card/src/components/CheckCard/style.ts @@ -133,6 +133,10 @@ const genProStyle: GenerateStyle = (token) => { paddingInline: token.paddingSM, paddingBlock: token.padding, }, + '&-body': { + paddingInline: token.paddingSM, + paddingBlock: token.padding, + }, '&-avatar-header': { display: 'flex', alignItems: 'center' }, '&-avatar': { paddingInlineEnd: 8 }, '&-detail': { @@ -146,6 +150,12 @@ const genProStyle: GenerateStyle = (token) => { display: 'flex', alignItems: 'center', justifyContent: 'space-between', + lineHeight: token.lineHeight, + '&-left': { + display: 'flex', + alignItems: 'center', + gap: token.sizeSM, + }, }, '&-title': { overflow: 'hidden', @@ -154,6 +164,9 @@ const genProStyle: GenerateStyle = (token) => { fontSize: token.fontSize, whiteSpace: 'nowrap', textOverflow: 'ellipsis', + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', }, '&-description': { color: token.colorTextSecondary, diff --git a/packages/list/src/Item.tsx b/packages/list/src/Item.tsx index e308c1720725..6d8b0c272c3e 100644 --- a/packages/list/src/Item.tsx +++ b/packages/list/src/Item.tsx @@ -1,6 +1,6 @@ import { RightOutlined } from '@ant-design/icons'; -import type { ProCardProps } from '@ant-design/pro-card'; -import ProCard from '@ant-design/pro-card'; +import type { CheckCardProps } from '@ant-design/pro-card'; +import { CheckCard } from '@ant-design/pro-card'; import { ProProvider } from '@ant-design/pro-provider'; import { ConfigProvider, List, Skeleton } from 'antd'; @@ -91,7 +91,7 @@ export type ItemProps = { type?: 'new' | 'top' | 'inline' | 'subheader'; isEditable: boolean; recordKey: string | number | undefined; - cardProps?: ProCardProps; + cardProps?: CheckCardProps; record: RecordType; onRow?: GetComponentProps; onItem?: GetComponentProps; @@ -270,6 +270,7 @@ function ProListItem(props: ItemProps) { return null; }, [avatar, getPrefixCls, hashId, title]); + const itemProps = onItem?.(record, index); const defaultDom = !cardProps ? ( (props: ItemProps) { actions={extraDom} extra={!!extra &&
{extra}
} {...onRow?.(record, index)} - {...onItem?.(record, index)} + {...itemProps} onClick={(e) => { onRow?.(record, index)?.onClick?.(e); onItem?.(record, index)?.onClick?.(e); @@ -328,10 +329,11 @@ function ProListItem(props: ItemProps) {
) : ( - (props: ItemProps) { padding: 24, ...cardProps.bodyStyle, }} - {...onItem?.(record, index)} + {...(itemProps as CheckCardProps)} + onClick={(e: any) => { + cardProps?.onClick?.(e); + itemProps?.onClick?.(e); + }} >
@@ -349,7 +355,7 @@ function ProListItem(props: ItemProps) { {content}
-
+ ); if (!cardProps) { diff --git a/packages/list/src/ListView.tsx b/packages/list/src/ListView.tsx index 527a3a20e7f1..8bbd27e3e69b 100644 --- a/packages/list/src/ListView.tsx +++ b/packages/list/src/ListView.tsx @@ -1,4 +1,4 @@ -import type { ProCardProps } from '@ant-design/pro-card'; +import type { CheckCardProps } from '@ant-design/pro-card'; import { ProProvider } from '@ant-design/pro-provider'; import type { ActionType } from '@ant-design/pro-table'; import type { @@ -56,7 +56,7 @@ export type ListViewProps = Omit< /** Render 除了 header 之后的代码 */ itemHeaderRender?: ItemProps['itemHeaderRender']; itemTitleRender?: ItemProps['itemTitleRender']; - itemCardProps?: ProCardProps; + itemCardProps?: CheckCardProps; pagination?: PaginationConfig; }; @@ -255,9 +255,11 @@ function ListView( : rawData; if (data !== '-') listItemProps[column.listKey] = data; }); - let checkboxDom; + let checkboxDom: React.ReactNode; if (selectItemDom && selectItemDom.render) { - checkboxDom = selectItemDom.render(item, item, index) || undefined; + checkboxDom = + (selectItemDom.render(item, item, index) as React.ReactNode) || + undefined; } const { isEditable, recordKey } = actionRef.current?.isEditable({ ...item, index }) || {}; @@ -273,8 +275,16 @@ function ListView( ...itemCardProps, ...rest.grid, checked: isChecked, - onChecked: React.isValidElement(checkboxDom) - ? (checkboxDom?.props as any)?.onChange + onChange: React.isValidElement(checkboxDom) + ? (changeChecked) => { + return ( + React.isValidElement(checkboxDom) && + (checkboxDom?.props as any)?.onChange({ + nativeEvent: {}, + changeChecked, + }) + ); + } : undefined, } : undefined diff --git a/tests/card/__snapshots__/demo.test.ts.snap b/tests/card/__snapshots__/demo.test.ts.snap index 604ae378e880..acf35cd09bcc 100644 --- a/tests/card/__snapshots__/demo.test.ts.snap +++ b/tests/card/__snapshots__/demo.test.ts.snap @@ -46,9 +46,13 @@ exports[`card demos 📸 renders ./packages/card/src/components/CheckCard/demos/ class="ant-pro-checkcard-header" >
- 示例标题 +
+ 示例标题 +
@@ -87,9 +91,13 @@ exports[`card demos 📸 renders ./packages/card/src/components/CheckCard/demos/ class="ant-pro-checkcard-header" >
- 示例一 +
+ 示例一 +
- 示例 +
+ 示例 +
- 示例 +
+ 示例 +
@@ -244,9 +260,13 @@ exports[`card demos 📸 renders ./packages/card/src/components/CheckCard/demos/ class="ant-pro-checkcard-header" >
- 示例 +
+ 示例 +
@@ -294,9 +314,13 @@ exports[`card demos 📸 renders ./packages/card/src/components/CheckCard/demos/ class="ant-pro-checkcard-header" >
- Card title +
+ Card title +
- 示例二 +
+ 示例二 +
@@ -381,9 +409,13 @@ exports[`card demos 📸 renders ./packages/card/src/components/CheckCard/demos/ class="ant-pro-checkcard-header" >
- 默认描述区域不会进行折行 +
+ 默认描述区域不会进行折行 +
- 你可以通过排版组件进行省略 +
+ 你可以通过排版组件进行省略 +
- Card title +
+ Card title +
- Card title +
+ Card title +
- Card title +
+ Card title +
- Card A +
+ Card A +
- Card B +
+ Card B +
- 示例一 +
+ 示例一 +
- Spring Boot +
+ Spring Boot +
- SOFA Boot +
+ SOFA Boot +
- Node JS +
+ Node JS +
- Card A +
+ Card A +
- Card B +
+ Card B +
- Card C +
+ Card C +
- 🍎 Apple +
+ 🍎 Apple +
@@ -1047,9 +1135,13 @@ exports[`card demos 📸 renders ./packages/card/src/components/CheckCard/demos/ class="ant-pro-checkcard-header" >
- 🍐 Pear +
+ 🍐 Pear +
@@ -1068,9 +1160,13 @@ exports[`card demos 📸 renders ./packages/card/src/components/CheckCard/demos/ class="ant-pro-checkcard-header" >
- 🍊 Orange +
+ 🍊 Orange +
@@ -1439,9 +1535,13 @@ exports[`card demos 📸 renders ./packages/card/src/components/CheckCard/demos/ class="ant-pro-checkcard-header" >
- 🍊 Orange +
+ 🍊 Orange +
@@ -1460,9 +1560,13 @@ exports[`card demos 📸 renders ./packages/card/src/components/CheckCard/demos/ class="ant-pro-checkcard-header" >
- 🍐 Pear +
+ 🍐 Pear +
@@ -1481,9 +1585,13 @@ exports[`card demos 📸 renders ./packages/card/src/components/CheckCard/demos/ class="ant-pro-checkcard-header" >
- 🍎 Apple +
+ 🍎 Apple +
@@ -1895,9 +2003,13 @@ exports[`card demos 📸 renders ./packages/card/src/components/CheckCard/demos/ class="ant-pro-checkcard-header" >
- 图像分类 +
+ 图像分类 +
- 物体检测 +
+ 物体检测 +
- OCR自定义 +
+ OCR自定义 +
- OCR +
+ OCR +
- 视频分类 +
+ 视频分类 +
- 关键点检测 +
+ 关键点检测 +
- Card A +
+ Card A +
- Card B +
+ Card B +
- Card A +
+ Card A +
- Card B +
+ Card B +
- Card C +
+ Card C +
- Card title +
+ Card title +
- - - - - 示例 - - - blue - + + + + 示例 + + + blue + +
@@ -2554,9 +2714,13 @@ exports[`card demos 📸 renders ./packages/card/src/components/CheckCard/demos/ class="ant-pro-checkcard-header" >
- 标题内容过长会自动进行省略,标题内容过长会自动进行省略 +
+ 标题内容过长会自动进行省略,标题内容过长会自动进行省略 +
- - - - - 语雀的天空 - -
-
- + + + + 语雀的天空 + +
+
- 语雀专栏 - + + 语雀专栏 + +
-
-
-
- - - - - Ant Design - -
-
- + + + + Ant Design + +
+
- 语雀专栏 - + + 语雀专栏 + +
-
-
-
- - - - - 蚂蚁金服体验科技 - -
-
- + + + + 蚂蚁金服体验科技 + +
+
- 语雀专栏 - + + 语雀专栏 + +
-
-
-
- - - - - TechUI - -
-
- + + + + TechUI + +
+
- 语雀专栏 - + + 语雀专栏 + +
-
-
-
- - - - - TechUI 2.0 - -
-
- + + + + TechUI 2.0 + +
+
- 语雀专栏 - + + 语雀专栏 + +
-
-
-
- - - - - Bigfish - -
-
- + + + + Bigfish + +
+
- 语雀专栏 - + + 语雀专栏 + +
-
-
-
- - - - - Umi - -
-
- + + + + Umi + +
+
- 语雀专栏 - + + 语雀专栏 + +
-
-
-
- - - - - Ant Design Pro - -
-
- + + + + Ant Design Pro + +
+
- 语雀专栏 - + + 语雀专栏 + +
-
-
-
{ html.queryByText('修复')?.click(); }); }); + it('🚏 trigger list item event when has grid prop', async () => { const fn1 = jest.fn(); const fn2 = jest.fn(); @@ -829,15 +830,22 @@ describe('List', () => { act(() => { fireEvent.mouseEnter( - html.baseElement.querySelector('.ant-pro-list-row-card .ant-pro-card')!, + html.baseElement.querySelector( + '.ant-pro-list-row-card .ant-pro-checkcard', + )!, {}, ); fireEvent.click( - html.baseElement.querySelector('.ant-pro-list-row-card .ant-pro-card')!, + html.baseElement.querySelector( + '.ant-pro-list-row-card .ant-pro-checkcard', + )!, {}, ); }); - expect(fn1).toBeCalledWith('我是名称'); - expect(fn2).toBeCalledWith('我是名称'); + + await waitFor(() => { + expect(fn1).toBeCalledWith('我是名称'); + expect(fn2).toBeCalledWith('我是名称'); + }); }); });