@gravity-ui/react-data-table 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.3.0](https://github.com/gravity-ui/react-data-table/compare/v1.2.0...v1.3.0) (2024-02-28)
4
+
5
+
6
+ ### Features
7
+
8
+ * add custom colspan for table row ([3316f62](https://github.com/gravity-ui/react-data-table/commit/3316f6283a1f504035c381f1baed6245f086e086))
9
+
3
10
  ## [1.2.0](https://github.com/gravity-ui/react-data-table/compare/v1.1.0...v1.2.0) (2023-09-05)
4
11
 
5
12
 
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # React Data Table
1
+ # React Data Table · [![npm package](https://img.shields.io/npm/v/@gravity-ui/react-data-table)](https://www.npmjs.com/package/@gravity-ui/react-data-table) [![CI](https://img.shields.io/github/actions/workflow/status/gravity-ui/react-data-table/.github/workflows/ci.yml?label=CI&logo=github)](https://github.com/gravity-ui/react-data-table/actions/workflows/ci.yml?query=branch:main) [![storybook](https://img.shields.io/badge/Storybook-deployed-ff4685)](https://preview.gravity-ui.com/react-data-table/)
2
2
 
3
3
  A React component for rendering tables.
4
4
 
@@ -28,6 +28,7 @@ of the sort list. A simple Click sorts the table by this column only. Sorting or
28
28
  | visibleRowIndex | `Function` | | | A method `(row, index) => number` that returns the row index shown in the column enabled by the `displayIndices` flag. Use it to specify a correct row index when applying external sorting |
29
29
  | onRowClick | `Function` | | | Click listener for a row `(row, index, event) => void` |
30
30
  | nullBeforeNumbers | `Boolean` | | | A flag that sets the position of `null`/`undefined` values when sorting. If true, `null`/`undefined` values are shown at the top in the case of ascending order and at the bottom in the case of descending order. If `false`/`undefined`, they are shown at the bottom |
31
+ | getColSpansOfRow | `Function` | | | Configuring column spanning for each row `({ row, columns, index, headerData, span, footer, odd }) => {[colName: string]: number} / undefined` |
31
32
 
32
33
  ## Settings
33
34
 
@@ -47,7 +48,7 @@ of the sort list. A simple Click sorts the table by this column only. Sorting or
47
48
  | dynamicRenderMinSize | `Number` | `1` | A minimum number of rows to be rendered in any case, even if a smaller number of rows fills the container height completely (this makes sense if dynamicRender is enabled). The value is passed [to the `minSize` property of the ReactList component](https://github.com/coderiety/react-list#minsize-defaults-to-1). |
48
49
  | dynamicRenderUseStaticSize | `Boolean` | `false` | [ReactList.useStaticSize](https://github.com/caseywebdev/react-list#usestaticsize-defaults-to-false) |
49
50
  | dynamicRenderThreshold | `Number` | | [ReactList.threshold](https://github.com/caseywebdev/react-list#threshold-defaults-to-100) |
50
- | dynamicRenderScrollParentGetter | `Funciction` | | [ReactList.scrollParentGetter](https://github.com/caseywebdev/react-list#scrollparentgetter-defaults-to-finding-the-nearest-scrollable-parent) |
51
+ | dynamicRenderScrollParentGetter | `Function` | | [ReactList.scrollParentGetter](https://github.com/caseywebdev/react-list#scrollparentgetter-defaults-to-finding-the-nearest-scrollable-parent) |
51
52
  | dynamicRenderScrollParentViewportSizeGetter | `Function` | | [ReactList.scrollParentViewportSizeGetter](https://github.com/caseywebdev/react-list#scrollparentviewportsizegetter-defaults-to-scrollparents-viewport-size) |
52
53
  | sortable | `Boolean` | `true` | Enable sorting for the entire table |
53
54
  | externalSort | `Boolean` | `false` | Disable data sorting on the component side. [Read more](#externalSort) |
@@ -9,6 +9,22 @@ interface CustomIcons {
9
9
  ICON_ASC: React.ReactNode;
10
10
  ICON_DESC: React.ReactNode;
11
11
  }
12
+ export interface TableRowProps<T> {
13
+ row: T;
14
+ index: number;
15
+ columns: DataColumns<T>;
16
+ className?: string;
17
+ odd?: boolean;
18
+ footer?: boolean;
19
+ headerData?: boolean;
20
+ onClick?: (row: T, index: number, event: React.MouseEvent<HTMLTableRowElement>) => void;
21
+ span?: {
22
+ [colName: string]: number;
23
+ };
24
+ getColSpansOfRow?: (p: Omit<TableRowProps<T>, 'getColSpansOfRow' | 'onClick' | 'className'>) => {
25
+ [colName: string]: number;
26
+ } | undefined;
27
+ }
12
28
  interface TableHeadProps<T> {
13
29
  dataColumns: DataColumns<T>;
14
30
  headColumns: HeadColumns<T>;
@@ -128,6 +144,9 @@ interface TableProps<T> {
128
144
  onSort: DataTableView<T>['onSort'];
129
145
  renderEmptyRow: unknown;
130
146
  nullBeforeNumbers?: boolean;
147
+ getColSpansOfRow?: (p: Omit<TableRowProps<T>, 'getColSpansOfRow' | 'onClick' | 'className'>) => {
148
+ [colName: string]: number;
149
+ } | undefined;
131
150
  }
132
151
  interface TableState {
133
152
  movingFooterStyle?: {
@@ -153,6 +172,7 @@ declare class Table<T> extends React.PureComponent<TableProps<T>, TableState> {
153
172
  startIndex: PropTypes.Requireable<number>;
154
173
  onSort: PropTypes.Requireable<(...args: any[]) => any>;
155
174
  renderEmptyRow: PropTypes.Requireable<(...args: any[]) => any>;
175
+ getColSpansOfRow: PropTypes.Requireable<(...args: any[]) => any>;
156
176
  };
157
177
  state: TableState;
158
178
  _onWindowResize?: () => void;
@@ -214,6 +234,7 @@ interface DataTableViewState<T> extends SortOrderWithSortColumns {
214
234
  declare type HeadPositionInner = HeadPosition | false;
215
235
  declare class DataTableView<T> extends React.Component<DataTableProps<T>, DataTableViewState<T>> {
216
236
  static propTypes: {
237
+ getColSpansOfRow: PropTypes.Requireable<(...args: any[]) => any>;
217
238
  columns: PropTypes.Validator<any[]>;
218
239
  headerData: PropTypes.Requireable<any[]>;
219
240
  data: PropTypes.Validator<any[]>;
@@ -50,8 +50,18 @@ class TableRow extends React.PureComponent {
50
50
  };
51
51
  }
52
52
  render() {
53
- const { className, columns, row, index, odd, footer, span, headerData } = this.props;
53
+ const { className, columns, row, index, odd, footer, span, getColSpansOfRow, headerData } = this.props;
54
+ const colSpans = getColSpansOfRow ? getColSpansOfRow(this.props) : undefined;
55
+ let restColSpan = 0;
54
56
  return (React.createElement("tr", { className: b('row', { odd, footer, 'header-data': headerData }, className), onClick: this.onClick }, columns.map((column, columnIndex) => {
57
+ if (colSpans) {
58
+ if (--restColSpan > 0) {
59
+ return null;
60
+ }
61
+ if (colSpans[column.name] > 1) {
62
+ restColSpan = colSpans[column.name];
63
+ }
64
+ }
55
65
  let rowSpan;
56
66
  if (span) {
57
67
  if (span[column.name] === 0) {
@@ -69,7 +79,7 @@ class TableRow extends React.PureComponent {
69
79
  header: false,
70
80
  footer,
71
81
  headerData,
72
- }), rowSpan: rowSpan, onClick: column._getOnClick({ row, index, footer, headerData }) }, column._renderValue({ value, row, index, footer, headerData })));
82
+ }), colSpan: colSpans ? colSpans[column.name] : undefined, rowSpan: rowSpan, onClick: column._getOnClick({ row, index, footer, headerData }) }, column._renderValue({ value, row, index, footer, headerData })));
73
83
  })));
74
84
  }
75
85
  }
@@ -378,9 +388,9 @@ class Table extends React.PureComponent {
378
388
  return this.renderRowImpl(rowData, index, { headerData: true });
379
389
  };
380
390
  this.renderRowImpl = (row, index, { onRowClick, odd, span, footer, headerData } = {}) => {
381
- const { columns: { dataColumns }, rowClassName, rowKey, } = this.props;
391
+ const { columns: { dataColumns }, rowClassName, rowKey, getColSpansOfRow, } = this.props;
382
392
  const className = typeof rowClassName === 'function' ? rowClassName(row, index, footer, headerData) : '';
383
- return (React.createElement(TableRow, { key: rowKey(row, index), className: className, columns: dataColumns, row: row, index: index, span: span, odd: odd, onClick: onRowClick, footer: footer, headerData: headerData }));
393
+ return (React.createElement(TableRow, { getColSpansOfRow: getColSpansOfRow, key: rowKey(row, index), className: className, columns: dataColumns, row: row, index: index, span: span, odd: odd, onClick: onRowClick, footer: footer, headerData: headerData }));
384
394
  };
385
395
  this.renderTable = (items, ref) => {
386
396
  const { footerData, columns: { dataColumns }, settings: { stickyHead }, } = this.props;
@@ -520,6 +530,7 @@ Table.propTypes = {
520
530
  startIndex: PropTypes.number,
521
531
  onSort: PropTypes.func,
522
532
  renderEmptyRow: PropTypes.func,
533
+ getColSpansOfRow: PropTypes.func,
523
534
  };
524
535
  const MemoizedCell = React.memo(CellImpl);
525
536
  function CellImpl(props) {
@@ -646,7 +657,7 @@ class DataTableView extends React.Component {
646
657
  ? Object.assign({}, externalToInternalSortOrder(nextProps.sortOrder, nextProps.settings)) : undefined));
647
658
  }
648
659
  render() {
649
- const { headerData, data, footerData, columns, startIndex, emptyDataMessage, rowClassName, rowKey, onRowClick, theme, renderEmptyRow, nullBeforeNumbers, } = this.props;
660
+ const { getColSpansOfRow, headerData, data, footerData, columns, startIndex, emptyDataMessage, rowClassName, rowKey, onRowClick, theme, renderEmptyRow, nullBeforeNumbers, } = this.props;
650
661
  const { settings, sortOrder, sortColumns } = this.state;
651
662
  const { highlightRows = false, stripedRows = false, headerMod = false } = settings;
652
663
  const tableClassName = b({
@@ -659,7 +670,7 @@ class DataTableView extends React.Component {
659
670
  if (settings.dynamicRender && dataColumns.dataColumns.some((column) => column.group)) {
660
671
  console.warn('Simultaneously used grouping cells and dynamic render. The table will render unpredictable.');
661
672
  }
662
- return (React.createElement(Table, { ref: this._tableRef, className: tableClassName, settings: settings, startIndex: startIndex, columns: dataColumns, emptyDataMessage: emptyDataMessage, renderEmptyRow: renderEmptyRow, rowClassName: rowClassName, rowKey: rowKey || DataTableView.defaultProps.rowKey, onRowClick: onRowClick, headerData: headerData, data: getSortedData(data, dataColumns.dataColumns, {
673
+ return (React.createElement(Table, { ref: this._tableRef, getColSpansOfRow: getColSpansOfRow, className: tableClassName, settings: settings, startIndex: startIndex, columns: dataColumns, emptyDataMessage: emptyDataMessage, renderEmptyRow: renderEmptyRow, rowClassName: rowClassName, rowKey: rowKey || DataTableView.defaultProps.rowKey, onRowClick: onRowClick, headerData: headerData, data: getSortedData(data, dataColumns.dataColumns, {
663
674
  sortOrder,
664
675
  sortColumns,
665
676
  }, {
@@ -710,6 +721,7 @@ class DataTableView extends React.Component {
710
721
  }
711
722
  }
712
723
  DataTableView.propTypes = {
724
+ getColSpansOfRow: PropTypes.func,
713
725
  columns: PropTypes.array.isRequired,
714
726
  headerData: PropTypes.array,
715
727
  data: PropTypes.array.isRequired,
@@ -1,5 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import ReactList from 'react-list';
3
+ import type { TableRowProps } from './DataTable';
3
4
  import { ASCENDING, CENTER, DESCENDING, FIXED, LEFT, LEGACY_THEME, MOVING, RIGHT, YCLOUD_THEME } from './constants';
4
5
  declare type HeaderData<T> = T & {
5
6
  headerIndex?: number;
@@ -26,6 +27,9 @@ export interface DataTableProps<T> {
26
27
  onRowClick?: (row: T, index: number, event: React.MouseEvent<HTMLTableRowElement>) => void;
27
28
  onError?: (error: unknown) => void;
28
29
  nullBeforeNumbers?: boolean;
30
+ getColSpansOfRow?: (p: Omit<TableRowProps<T>, 'getColSpansOfRow' | 'onClick' | 'className'>) => {
31
+ [colName: string]: number;
32
+ } | undefined;
29
33
  }
30
34
  export interface Column<T> {
31
35
  name: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/react-data-table",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "DataTable component",
5
5
  "main": "build/esm/lib/index.js",
6
6
  "types": "build/esm/lib/index.d.ts",
@@ -16,6 +16,7 @@
16
16
  "lint:styles": "stylelint 'src/**/*.scss'",
17
17
  "lint": "run-p lint:*",
18
18
  "prettier": "prettier '**/*.{md,json,yaml,yml}'",
19
+ "dev": "npm run start",
19
20
  "start": "start-storybook -p 7007",
20
21
  "build-storybook": "build-storybook -c .storybook -o storybook-static",
21
22
  "typecheck": "npm run build:compile -- --noEmit",