SectionRow.tsx 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /* eslint-disable max-len */
  2. /* eslint-disable @typescript-eslint/ban-types */
  3. /* eslint-disable eqeqeq */
  4. import React, { PureComponent, isValidElement, ReactNode } from 'react';
  5. import PropTypes from 'prop-types';
  6. import classnames from 'classnames';
  7. import { get, isSet } from 'lodash';
  8. import Store from '@douyinfe/semi-foundation/utils/Store';
  9. import { cssClasses, strings } from '@douyinfe/semi-foundation/table/constants';
  10. import { filterColumns } from '@douyinfe/semi-foundation/table/utils';
  11. import BaseRow from './BaseRow';
  12. import TableContext, { TableContextProps } from '../table-context';
  13. import {
  14. ColumnProps,
  15. RenderGroupSection,
  16. OnGroupedRow,
  17. TableComponents,
  18. Virtualized,
  19. RowKey,
  20. OnRowReturnObject
  21. } from '../interface';
  22. export interface SectionRowProps {
  23. record?: Record<string, any>;
  24. index?: number;
  25. columns?: ColumnProps[];
  26. group?: (string | number)[];
  27. groupKey: string | number;
  28. data?: Record<string, any>[];
  29. renderGroupSection?: RenderGroupSection; // render group title
  30. onGroupedRow?: OnGroupedRow<Record<string, any>>;
  31. clickGroupedRowToExpand?: boolean;
  32. components?: TableComponents;
  33. expanded?: boolean;
  34. prefixCls?: string;
  35. onExpand?: (willExpanded: boolean, groupKey: number | string, e: React.MouseEvent) => void;
  36. virtualized?: Virtualized;
  37. style?: React.CSSProperties;
  38. renderExpandIcon?: (record: Record<string, any>, isNested: boolean, groupKey: string | number) => ReactNode | null;
  39. className?: string;
  40. store?: Store;
  41. rowKey?: RowKey<any>;
  42. }
  43. /**
  44. * Grouping component title row
  45. */
  46. class SectionRow extends PureComponent<SectionRowProps> {
  47. static contextType = TableContext;
  48. static propTypes = {
  49. record: PropTypes.object,
  50. index: PropTypes.number,
  51. columns: PropTypes.array,
  52. group: PropTypes.object.isRequired,
  53. groupKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
  54. data: PropTypes.array,
  55. renderGroupSection: PropTypes.func, // render group title
  56. onGroupedRow: PropTypes.func,
  57. clickGroupedRowToExpand: PropTypes.bool,
  58. components: PropTypes.object,
  59. expanded: PropTypes.bool,
  60. prefixCls: PropTypes.string,
  61. onExpand: PropTypes.func,
  62. virtualized: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
  63. style: PropTypes.object,
  64. renderExpandIcon: PropTypes.func, // passing to baseRow
  65. className: PropTypes.string,
  66. store: PropTypes.object,
  67. rowKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.func]),
  68. };
  69. static defaultProps = {
  70. prefixCls: cssClasses.PREFIX,
  71. components: {
  72. body: {
  73. row: 'tr',
  74. cell: 'td',
  75. },
  76. },
  77. };
  78. context: TableContextProps;
  79. onRow = (...args: any[]): OnRowReturnObject => {
  80. const { onGroupedRow, clickGroupedRowToExpand, onExpand, groupKey, expanded } = this.props;
  81. const rowProps: { onClick?: (e: React.MouseEvent) => void } = {};
  82. if (typeof onGroupedRow === 'function') {
  83. Object.assign(rowProps, onGroupedRow(...args));
  84. }
  85. return {
  86. ...rowProps,
  87. onClick: (e: React.MouseEvent) => {
  88. if (typeof onExpand === 'function' && clickGroupedRowToExpand) {
  89. onExpand(!expanded, groupKey, e);
  90. }
  91. if (typeof rowProps.onClick === 'function') {
  92. rowProps.onClick(e);
  93. }
  94. },
  95. };
  96. };
  97. collectGroupedData = () => {
  98. const { data, group, rowKey } = this.props;
  99. if (Array.isArray(data) && data.length && isSet(group)) {
  100. return data.filter(record => {
  101. const realRowKey = typeof rowKey === 'function' ? rowKey(record) : get(record, rowKey);
  102. return realRowKey != null && realRowKey !== '' && group.has(realRowKey);
  103. });
  104. }
  105. return [];
  106. };
  107. renderExpandIcon = (record: any) => {
  108. const { renderExpandIcon, groupKey } = this.props;
  109. if (typeof renderExpandIcon === 'function') {
  110. return renderExpandIcon(record, false, groupKey);
  111. }
  112. return null;
  113. };
  114. isInnerColumnKey(key: any) {
  115. if (key != null) {
  116. return [strings.DEFAULT_KEY_COLUMN_EXPAND, strings.DEFAULT_KEY_COLUMN_SELECTION].includes(key);
  117. }
  118. return false;
  119. }
  120. render() {
  121. const {
  122. record,
  123. columns: propColumns = [],
  124. prefixCls,
  125. className,
  126. expanded,
  127. renderGroupSection,
  128. components,
  129. index,
  130. store,
  131. group,
  132. groupKey,
  133. virtualized,
  134. style,
  135. } = this.props;
  136. const props: { colSpan?: number } = {};
  137. let column = {};
  138. let children: ReactNode = null;
  139. // render title
  140. const cell = typeof renderGroupSection === 'function' ? renderGroupSection(groupKey, [...group]) : null;
  141. if (isValidElement(cell)) {
  142. children = cell;
  143. } else if (cell && Object.prototype.toString.call(cell) === '[object Object]') {
  144. const { children: cellChildren, ...restProps } = cell as { children?: ReactNode };
  145. children = cellChildren;
  146. column = { ...restProps };
  147. }
  148. // Filter out scroll-bar column
  149. props.colSpan = filterColumns(propColumns).length;
  150. const columns = [{ render: () => ({ props, children }), ...column }];
  151. const rowCls = classnames(className, `${prefixCls}-row-section`, {
  152. on: expanded,
  153. });
  154. const { getCellWidths } = this.context;
  155. const baseRowCellWidths = getCellWidths(columns, null, true);
  156. return (
  157. <BaseRow
  158. components={components}
  159. virtualized={virtualized}
  160. index={index}
  161. onRow={this.onRow}
  162. expanded={expanded}
  163. expandIcon
  164. isSection
  165. record={record}
  166. replaceClassName={rowCls}
  167. expandableRow
  168. renderExpandIcon={this.renderExpandIcon}
  169. rowKey={groupKey}
  170. columns={columns}
  171. store={store}
  172. style={style}
  173. cellWidths={baseRowCellWidths}
  174. />
  175. );
  176. }
  177. }
  178. export default SectionRow;