| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 | 
							- import React, { PureComponent, ReactNode, CSSProperties } from 'react';
 
- import { omit, isString } from 'lodash';
 
- import PropTypes from 'prop-types';
 
- import { cssClasses, strings } from '@douyinfe/semi-foundation/card/constants';
 
- import '@douyinfe/semi-foundation/card/card.scss';
 
- import Meta from './meta';
 
- import cls from 'classnames';
 
- import Skeleton from '../skeleton';
 
- import Typography from '../typography';
 
- import Space from '../space';
 
- const prefixcls = cssClasses.PREFIX;
 
- export type Shadows = 'hover' | 'always';
 
- export { MetaProps } from './meta';
 
- export { CardGroupProps } from './cardGroup';
 
- export interface CardProps {
 
-     /** Operation group at the bottom of the card content area */
 
-     actions?: ReactNode[];
 
-     /** Card content area inline style */
 
-     bodyStyle?: CSSProperties;
 
-     /** Whether there is an outer border */
 
-     bordered?: boolean;
 
-     /** Style class name */
 
-     className?: string;
 
-     /** Cover */
 
-     cover?: ReactNode;
 
-     /** Additional additions to the right of the title */
 
-     headerExtraContent?: ReactNode;
 
-     /** Custom end of page */
 
-     footer?: ReactNode;
 
-     /** Whether there is an edge between the bottom of the page and the content area */
 
-     footerLine?: boolean;
 
-     /** Inline style at the end of the page */
 
-     footerStyle?: CSSProperties;
 
-     /** Custom head */
 
-     header?: ReactNode;
 
-     /** Whether there is an edge line between the head and the content area */
 
-     headerLine?: boolean;
 
-     /** Head inline style */
 
-     headerStyle?: CSSProperties;
 
-     /** Whether to preload */
 
-     loading?: boolean;
 
-     /** Set shadow */
 
-     shadows?: Shadows;
 
-     /** Card inline style */
 
-     style?: CSSProperties;
 
-     /** Title */
 
-     title?: ReactNode;
 
-     /** aria label */
 
-     'aria-label'?: string;
 
- }
 
- class Card extends PureComponent<CardProps> {
 
-     static Meta = Meta;
 
-     static propTypes = {
 
-         actions: PropTypes.array,
 
-         bodyStyle: PropTypes.object,
 
-         bordered: PropTypes.bool,
 
-         children: PropTypes.node,
 
-         className: PropTypes.string,
 
-         cover: PropTypes.node,
 
-         footer: PropTypes.node,
 
-         footerLine: PropTypes.bool,
 
-         footerStyle: PropTypes.object,
 
-         header: PropTypes.node,
 
-         headerExtraContent: PropTypes.node,
 
-         headerLine: PropTypes.bool,
 
-         headerStyle: PropTypes.object,
 
-         loading: PropTypes.bool,
 
-         shadows: PropTypes.oneOf(strings.SHADOWS),
 
-         style: PropTypes.object,
 
-         title: PropTypes.node,
 
-         'aria-label': PropTypes.string,
 
-     };
 
-     static defaultProps = {
 
-         bordered: true,
 
-         footerLine: false,
 
-         headerLine: true,
 
-         loading: false
 
-     };
 
-     renderHeader = (): ReactNode => {
 
-         const {
 
-             title,
 
-             headerExtraContent,
 
-             header,
 
-             headerLine,
 
-             headerStyle
 
-         } = this.props;
 
-         const headerCls = cls(`${prefixcls}-header`, {
 
-             [`${prefixcls}-header-bordered`]: Boolean(headerLine)
 
-         });
 
-         const headerWrapperCls = cls(`${prefixcls}-header-wrapper`);
 
-         const titleCls = cls(`${prefixcls}-header-wrapper-title`, {
 
-             [`${prefixcls}-header-wrapper-spacing`]: Boolean(headerExtraContent)
 
-         });
 
-         if (header || headerExtraContent || title) {
 
-             return (
 
-                 <div style={headerStyle} className={headerCls}>
 
-                     {
 
-                         header || ( // Priority of header over title and headerExtraContent
 
-                             <div className={headerWrapperCls}>
 
-                                 {headerExtraContent &&
 
-                                     (
 
-                                         <div className={`${prefixcls}-header-wrapper-extra`}>
 
-                                             {headerExtraContent}
 
-                                         </div>
 
-                                     )
 
-                                 }
 
-                                 {title &&
 
-                                     (
 
-                                         <div className={titleCls}>
 
-                                             {
 
-                                                 isString(title) ?
 
-                                                     (
 
-                                                         <Typography.Title
 
-                                                             heading={6}
 
-                                                             ellipsis={{ showTooltip: true, rows: 1 }}
 
-                                                         >
 
-                                                             {title}
 
-                                                         </Typography.Title>
 
-                                                     ) :
 
-                                                     title
 
-                                             }
 
-                                         </div>
 
-                                     )
 
-                                 }
 
-                             </div>
 
-                         )
 
-                     }
 
-                 </div>
 
-             );
 
-         }
 
-         return null;
 
-     };
 
-     renderCover = (): ReactNode => {
 
-         const {
 
-             cover
 
-         } = this.props;
 
-         const coverCls = cls(`${prefixcls}-cover`);
 
-         return cover && <div className={coverCls}>{cover}</div>;
 
-     };
 
-     renderBody = (): ReactNode => {
 
-         const {
 
-             bodyStyle,
 
-             children,
 
-             actions,
 
-             loading
 
-         } = this.props;
 
-         const bodyCls = cls(`${prefixcls}-body`);
 
-         const actionsCls = cls(`${prefixcls}-body-actions`);
 
-         const actionsItemCls = cls(`${prefixcls}-body-actions-item`);
 
-         const placeholder = (
 
-             <div>
 
-                 <Skeleton.Title />
 
-                 <br />
 
-                 <Skeleton.Paragraph rows={3} />
 
-             </div>
 
-         );
 
-         return (
 
-             <div style={bodyStyle} className={bodyCls}>
 
-                 {children && (
 
-                     <Skeleton placeholder={placeholder} loading={loading} active>
 
-                         {children}
 
-                     </Skeleton>
 
-                 )}
 
-                 {
 
-                     Array.isArray(actions) &&
 
-                     (
 
-                         <div className={actionsCls}>
 
-                             <Space spacing={12}>
 
-                                 {actions.map((item, idx) => (
 
-                                     <div key={idx} className={actionsItemCls}>{item}</div>
 
-                                 ))}
 
-                             </Space>
 
-                         </div>
 
-                     )
 
-                 }
 
-             </div>
 
-         );
 
-     };
 
-     renderFooter = (): ReactNode => {
 
-         const {
 
-             footer,
 
-             footerLine,
 
-             footerStyle
 
-         } = this.props;
 
-         const footerCls = cls(`${prefixcls}-footer`, {
 
-             [`${prefixcls}-footer-bordered`]: footerLine
 
-         });
 
-         return footer && <div style={footerStyle} className={footerCls}>{footer}</div>;
 
-     };
 
-     render(): ReactNode {
 
-         const {
 
-             bordered,
 
-             shadows,
 
-             style,
 
-             className,
 
-             ...otherProps
 
-         } = this.props;
 
-         const others = omit(otherProps, [ // Remove APIs in otherProps that do not need to be hung on the outer node
 
-             'actions',
 
-             'bodyStyle',
 
-             'cover',
 
-             'headerExtraContent',
 
-             'footer',
 
-             'footerLine',
 
-             'footerStyle',
 
-             'header',
 
-             'headerLine',
 
-             'headerStyle',
 
-             'loading',
 
-             'title'
 
-         ]);
 
-         const cardCls = cls(prefixcls, className, {
 
-             [`${prefixcls}-bordered`]: bordered,
 
-             [`${prefixcls}-shadows`]: shadows,
 
-             [`${prefixcls}-shadows-${shadows}`]: shadows
 
-         });
 
-         return (
 
-             <div {...others} aria-busy={this.props.loading} className={cardCls} style={style}>
 
-                 {this.renderHeader()}
 
-                 {this.renderCover()}
 
-                 {this.renderBody()}
 
-                 {this.renderFooter()}
 
-             </div>
 
-         );
 
-     }
 
- }
 
- export default Card;
 
 
  |