import React, { useContext, useMemo } from 'react'; import { List, Avatar, Skeleton, ConfigProvider } from 'infrad'; import type { ProCardProps } from 'infrad-pro-card'; import type { GetComponentProps } from './index'; import ProCard from 'infrad-pro-card'; import useMergedState from 'rc-util/lib/hooks/useMergedState'; import type { ListGridType } from 'infrad/lib/list'; import type { ExpandableConfig } from 'infrad/lib/table/interface'; import { RightOutlined } from 'infra-design-icons'; import classNames from 'classnames'; export type RenderExpandIconProps = { prefixCls: string; expanded: boolean; expandIcon: | React.ReactNode | ((props: { onExpand: (expanded: boolean) => void; expanded: boolean; record: RecordType; }) => React.ReactNode); onExpand: (expanded: boolean) => void; record: RecordType; }; export function renderExpandIcon({ prefixCls, expandIcon = , onExpand, expanded, record, }: RenderExpandIconProps) { let icon = expandIcon; const expandClassName = `${prefixCls}-row-expand-icon`; const onClick: React.MouseEventHandler = (event) => { onExpand(!expanded); event.stopPropagation(); }; if (typeof expandIcon === 'function') { icon = expandIcon({ expanded, onExpand, record }); } return ( {icon} ); } export type ItemProps = { title?: React.ReactNode; subTitle?: React.ReactNode; checkbox?: React.ReactNode; className?: string; prefixCls?: string; item?: any; subheader?: { title: React.ReactNode; actions: React.ReactNode[]; }; index: number; selected?: boolean; avatar?: React.ReactNode; content?: React.ReactNode; actions?: React.ReactNode[]; extra?: React.ReactNode; description?: React.ReactNode; loading?: boolean; style?: React.CSSProperties; grid?: ListGridType; expand?: boolean; rowSupportExpand?: boolean; cardActionProps?: 'actions' | 'extra'; onExpand?: (expand: boolean) => void; expandable?: ExpandableConfig; showActions?: 'hover' | 'always'; showExtra?: 'hover' | 'always'; type?: 'new' | 'top' | 'inline' | 'subheader'; isEditable: boolean; recordKey: string | number | undefined; cardProps?: ProCardProps; record: RecordType; onRow?: GetComponentProps; onItem?: GetComponentProps; itemHeaderRender?: | ((item: RecordType, index: number, defaultDom: JSX.Element | null) => React.ReactNode) | false; itemTitleRender?: | ((item: RecordType, index: number, defaultDom: JSX.Element | null) => React.ReactNode) | false; }; function ProListItem(props: ItemProps) { const { prefixCls: customizePrefixCls } = props; const { getPrefixCls } = useContext(ConfigProvider.ConfigContext); const prefixCls = getPrefixCls('pro-list', customizePrefixCls); const defaultClassName = `${prefixCls}-row`; const { title, subTitle, content, itemTitleRender, prefixCls: restPrefixCls, actions, item, recordKey, avatar, cardProps, description, isEditable, checkbox, index, selected, loading, expand: propsExpand, onExpand: propsOnExpand, expandable: expandableConfig, rowSupportExpand, showActions, showExtra, type, style, className: propsClassName = defaultClassName, record, onRow, onItem, itemHeaderRender, cardActionProps, extra, ...rest } = props; const { expandedRowRender, expandIcon, expandRowByClick, indentSize = 8, expandedRowClassName, } = expandableConfig || {}; const [expanded, onExpand] = useMergedState(!!propsExpand, { value: propsExpand, onChange: propsOnExpand, }); const className = classNames( { [`${defaultClassName}-selected`]: !cardProps && selected, [`${defaultClassName}-show-action-hover`]: showActions === 'hover', [`${defaultClassName}-type-${type}`]: !!type, [`${defaultClassName}-editable`]: isEditable, [`${defaultClassName}-show-extra-hover`]: showExtra === 'hover', }, defaultClassName, ); const extraClassName = classNames({ [`${propsClassName}-extra`]: showExtra === 'hover', }); const needExpanded = expanded || Object.values(expandableConfig || {}).length === 0; const expandedRowDom = expandedRowRender && expandedRowRender(record, index, indentSize, expanded); const extraDom = useMemo(() => { if (!actions || cardActionProps === 'actions') { return undefined; } return [
e.stopPropagation()}> {actions}
, ]; }, [actions, cardActionProps]); const actionsDom = useMemo(() => { if (!actions || !cardActionProps || cardActionProps === 'extra') { return undefined; } return [
e.stopPropagation()}> {actions}
, ]; }, [actions, cardActionProps]); const titleDom = title || subTitle ? (
{title &&
{title}
} {subTitle &&
{subTitle}
}
) : null; const metaTitle = (itemTitleRender && itemTitleRender?.(record, index, titleDom)) ?? titleDom; const metaDom = metaTitle || avatar || subTitle || description ? ( {description} } /> ) : null; const rowClassName = classNames({ [`${className}-item-has-checkbox`]: checkbox, [`${className}-item-has-avatar`]: avatar, [className]: className, }); const cardTitleDom = useMemo(() => { if (avatar || title) { return ( <> {avatar && ( )} {title} ); } return null; }, [avatar, getPrefixCls, title]); const defaultDom = !cardProps ? ( {extra}} {...onRow?.(record, index)} {...onItem?.(record, index)} onClick={(e) => { onRow?.(record, index)?.onClick?.(e); onItem?.(record, index)?.onClick?.(e); if (expandRowByClick) { onExpand(!expanded); } }} >
{!!checkbox &&
{checkbox}
} {Object.values(expandableConfig || {}).length > 0 && rowSupportExpand && renderExpandIcon({ prefixCls, expandIcon, onExpand, expanded, record, })}
{(itemHeaderRender && itemHeaderRender?.(record, index, metaDom)) ?? metaDom}
{needExpanded && (content || expandedRowDom) && (
{content} {expandedRowRender && rowSupportExpand && (
{expandedRowDom}
)}
)}
) : (
{itemTitleRender && itemTitleRender?.(record, index, titleDom)} {content}
); if (!cardProps) { return defaultDom; } return (
{defaultDom}
); } export default ProListItem;