1
0

index.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import React, { isValidElement } from 'react';
  2. import cls from 'classnames';
  3. import PropTypes from 'prop-types';
  4. import { strings, cssClasses } from '@douyinfe/semi-foundation/descriptions/constants';
  5. import '@douyinfe/semi-foundation/descriptions/descriptions.scss';
  6. import getDataAttr from '@douyinfe/semi-foundation/utils/getDataAttr';
  7. import { isPlainObject } from 'lodash';
  8. import DescriptionsContext, { DescriptionsAlign, DescriptionLayout } from './descriptions-context';
  9. import Item from './item';
  10. import DescriptionsFoundation, { DescriptionsAdapter } from "@douyinfe/semi-foundation/descriptions/foundation";
  11. import BaseComponent from '../_base/baseComponent';
  12. export type { DescriptionsItemProps } from './item';
  13. export type DescriptionsSize = 'small' | 'medium' | 'large';
  14. export interface Data {
  15. key?: React.ReactNode;
  16. value?: (() => React.ReactNode) | React.ReactNode;
  17. hidden?: boolean;
  18. span?: number
  19. }
  20. export interface DescriptionsProps {
  21. align?: DescriptionsAlign;
  22. row?: boolean;
  23. size?: DescriptionsSize;
  24. style?: React.CSSProperties;
  25. className?: string;
  26. children?: React.ReactNode;
  27. data?: Data[];
  28. layout?: DescriptionLayout;
  29. column?: number
  30. }
  31. const prefixCls = cssClasses.PREFIX;
  32. class Descriptions extends BaseComponent<DescriptionsProps> {
  33. static Item = Item;
  34. static contextType = DescriptionsContext;
  35. static propTypes = {
  36. align: PropTypes.oneOf(strings.ALIGN_SET),
  37. row: PropTypes.bool,
  38. size: PropTypes.oneOf(strings.SIZE_SET),
  39. style: PropTypes.object,
  40. className: PropTypes.string,
  41. data: PropTypes.arrayOf(PropTypes.shape({
  42. key: PropTypes.node,
  43. value: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
  44. hidden: PropTypes.bool,
  45. className: PropTypes.string,
  46. style: PropTypes.object
  47. })),
  48. layout: PropTypes.oneOf(strings.LAYOUT_SET),
  49. column: PropTypes.number,
  50. };
  51. static defaultProps = {
  52. align: 'center',
  53. row: false,
  54. size: 'medium',
  55. data: [] as Array<Data>,
  56. layout: 'vertical',
  57. column: 3,
  58. };
  59. foundation: DescriptionsFoundation;
  60. constructor(props: DescriptionsProps) {
  61. super(props);
  62. this.foundation = new DescriptionsFoundation<DescriptionsProps>(this.adapter);
  63. }
  64. get adapter(): DescriptionsAdapter<DescriptionsProps> {
  65. return {
  66. ...super.adapter,
  67. getColumns: ()=>{
  68. if (this.props.data?.length) {
  69. return this.props.data;
  70. }
  71. if (this.props.children) {
  72. return React.Children.toArray(this.props.children)?.map(item => {
  73. return isValidElement(item)?({
  74. value: item.props.children,
  75. ...item.props,
  76. }):[];
  77. });
  78. }
  79. return [];
  80. }
  81. };
  82. }
  83. renderChildrenList = () => {
  84. const props = this.props;
  85. const { layout, data, children } = props;
  86. if (layout === 'horizontal') {
  87. const horizontalList: Data[][] = this.foundation.getHorizontalList();
  88. return horizontalList.map((row, index)=> {
  89. return <tr key={index}>{
  90. row.map((item, itemIndex)=>
  91. isPlainObject(item) ? <Item itemKey={item.key} {...item} key={index+'-'+itemIndex}>{item.value}</Item> : null)
  92. }</tr>;
  93. });
  94. } else {
  95. return data && data.length ?
  96. data.map((item, index) => (
  97. isPlainObject(item) ? <Item itemKey={item.key} {...item} key={index}>{item.value}</Item> : null
  98. )) :
  99. children;
  100. }
  101. };
  102. render() {
  103. const { align, row, size, className, style, children, data, layout, ...rest } = this.props;
  104. const classNames = cls(prefixCls, className, {
  105. [`${prefixCls}-${align}`]: !row,
  106. [`${prefixCls}-double`]: row,
  107. [`${prefixCls}-double-${size}`]: row,
  108. [`${prefixCls}-horizontal`]: layout === 'horizontal',
  109. [`${prefixCls}-vertical`]: layout === 'vertical'
  110. });
  111. return (
  112. <div className={classNames} style={style} {...getDataAttr(rest)}>
  113. <table>
  114. <tbody>
  115. <DescriptionsContext.Provider value={{ align, layout }}>
  116. {this.renderChildrenList()}
  117. </DescriptionsContext.Provider>
  118. </tbody>
  119. </table>
  120. </div>
  121. );
  122. }
  123. }
  124. export default Descriptions;