import React, { isValidElement } from 'react'; import cls from 'classnames'; import PropTypes from 'prop-types'; import { strings, cssClasses } from '@douyinfe/semi-foundation/descriptions/constants'; import '@douyinfe/semi-foundation/descriptions/descriptions.scss'; import getDataAttr from '@douyinfe/semi-foundation/utils/getDataAttr'; import { isPlainObject } from 'lodash'; import DescriptionsContext, { DescriptionsAlign, DescriptionLayout } from './descriptions-context'; import Item from './item'; import DescriptionsFoundation, { DescriptionsAdapter } from "@douyinfe/semi-foundation/descriptions/foundation"; import BaseComponent from '../_base/baseComponent'; export type { DescriptionsItemProps } from './item'; export type DescriptionsSize = 'small' | 'medium' | 'large'; export interface Data { key?: React.ReactNode; value?: (() => React.ReactNode) | React.ReactNode; hidden?: boolean; span?: number; keyStyle?: React.CSSProperties } export interface DescriptionsProps { align?: DescriptionsAlign; row?: boolean; size?: DescriptionsSize; style?: React.CSSProperties; className?: string; children?: React.ReactNode; data?: Data[]; layout?: DescriptionLayout; column?: number } const prefixCls = cssClasses.PREFIX; class Descriptions extends BaseComponent { static Item = Item; static contextType = DescriptionsContext; static propTypes = { align: PropTypes.oneOf(strings.ALIGN_SET), row: PropTypes.bool, size: PropTypes.oneOf(strings.SIZE_SET), style: PropTypes.object, className: PropTypes.string, data: PropTypes.arrayOf(PropTypes.shape({ key: PropTypes.node, value: PropTypes.oneOfType([PropTypes.node, PropTypes.func]), hidden: PropTypes.bool, className: PropTypes.string, style: PropTypes.object, span: PropTypes.number, keyStyle: PropTypes.object })), layout: PropTypes.oneOf(strings.LAYOUT_SET), column: PropTypes.number, }; static defaultProps = { align: 'center', row: false, size: 'medium', data: [] as Array, layout: 'vertical', column: 3, }; foundation: DescriptionsFoundation; constructor(props: DescriptionsProps) { super(props); this.foundation = new DescriptionsFoundation(this.adapter); } get adapter(): DescriptionsAdapter { return { ...super.adapter, getColumns: () => { if (this.props.data?.length) { return this.props.data; } if (this.props.children) { return React.Children.toArray(this.props.children)?.map(item => { return isValidElement(item) ? ({ value: item.props.children, ...item.props, }) : []; }); } return []; } }; } renderChildrenList = () => { const props = this.props; const { layout, data, children } = props; if (layout === 'horizontal') { const horizontalList: Data[][] = this.foundation.getHorizontalList(); return horizontalList.map((row, index) => { return { row.map((item, itemIndex) => isPlainObject(item) ? {item.value} : null) }; }); } else { return data && data.length ? data.map((item, index) => ( isPlainObject(item) ? {item.value} : null )) : children; } }; render() { const { align, row, size, className, style, children, data, layout, ...rest } = this.props; const classNames = cls(prefixCls, className, { [`${prefixCls}-${align}`]: !row, [`${prefixCls}-double`]: row, [`${prefixCls}-double-${size}`]: row, [`${prefixCls}-horizontal`]: layout === 'horizontal', [`${prefixCls}-vertical`]: layout === 'vertical' }); return (
{this.renderChildrenList()}
); } } export default Descriptions;