@gravity-ui/react-data-table 1.1.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,19 @@
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
+
10
+ ## [1.2.0](https://github.com/gravity-ui/react-data-table/compare/v1.1.0...v1.2.0) (2023-09-05)
11
+
12
+
13
+ ### Features
14
+
15
+ * migrate to @bem-react/classname ([#32](https://github.com/gravity-ui/react-data-table/issues/32)) ([af0987e](https://github.com/gravity-ui/react-data-table/commit/af0987e65e68766747a7956ff8521014c6037648))
16
+
3
17
  ## [1.1.0](https://github.com/gravity-ui/react-data-table/compare/v1.0.3...v1.1.0) (2023-05-05)
4
18
 
5
19
 
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[]>;
@@ -1,5 +1,4 @@
1
1
  import { __rest } from "tslib";
2
- import cn from 'bem-cn-lite';
3
2
  import PropTypes from 'prop-types';
4
3
  import * as React from 'react';
5
4
  import ReactList from 'react-list';
@@ -7,7 +6,7 @@ import './DataTable.scss';
7
6
  import { ASCENDING, CENTER, DESCENDING, FIXED, INDEX_COLUMN, LEFT, MOVING, RIGHT } from './constants';
8
7
  import { positionStickySupported } from './featureSupport';
9
8
  import { HeightObserver } from './height-observer';
10
- import { externalToInternalSortOrder, getSortOrder, getSortedData, internalToExternalSortOrder, } from './util';
9
+ import { cn, externalToInternalSortOrder, getSortOrder, getSortedData, internalToExternalSortOrder, } from './util';
11
10
  const b = cn('data-table');
12
11
  const ICON_ASC = (React.createElement("svg", { className: b('icon'), viewBox: "0 0 10 6", width: "10", height: "6" },
13
12
  React.createElement("path", { fill: "currentColor", d: "M0 5h10l-5 -5z" })));
@@ -51,8 +50,18 @@ class TableRow extends React.PureComponent {
51
50
  };
52
51
  }
53
52
  render() {
54
- 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;
55
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
+ }
56
65
  let rowSpan;
57
66
  if (span) {
58
67
  if (span[column.name] === 0) {
@@ -70,7 +79,7 @@ class TableRow extends React.PureComponent {
70
79
  header: false,
71
80
  footer,
72
81
  headerData,
73
- }), 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 })));
74
83
  })));
75
84
  }
76
85
  }
@@ -379,9 +388,9 @@ class Table extends React.PureComponent {
379
388
  return this.renderRowImpl(rowData, index, { headerData: true });
380
389
  };
381
390
  this.renderRowImpl = (row, index, { onRowClick, odd, span, footer, headerData } = {}) => {
382
- const { columns: { dataColumns }, rowClassName, rowKey, } = this.props;
391
+ const { columns: { dataColumns }, rowClassName, rowKey, getColSpansOfRow, } = this.props;
383
392
  const className = typeof rowClassName === 'function' ? rowClassName(row, index, footer, headerData) : '';
384
- 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 }));
385
394
  };
386
395
  this.renderTable = (items, ref) => {
387
396
  const { footerData, columns: { dataColumns }, settings: { stickyHead }, } = this.props;
@@ -521,6 +530,7 @@ Table.propTypes = {
521
530
  startIndex: PropTypes.number,
522
531
  onSort: PropTypes.func,
523
532
  renderEmptyRow: PropTypes.func,
533
+ getColSpansOfRow: PropTypes.func,
524
534
  };
525
535
  const MemoizedCell = React.memo(CellImpl);
526
536
  function CellImpl(props) {
@@ -647,7 +657,7 @@ class DataTableView extends React.Component {
647
657
  ? Object.assign({}, externalToInternalSortOrder(nextProps.sortOrder, nextProps.settings)) : undefined));
648
658
  }
649
659
  render() {
650
- 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;
651
661
  const { settings, sortOrder, sortColumns } = this.state;
652
662
  const { highlightRows = false, stripedRows = false, headerMod = false } = settings;
653
663
  const tableClassName = b({
@@ -660,7 +670,7 @@ class DataTableView extends React.Component {
660
670
  if (settings.dynamicRender && dataColumns.dataColumns.some((column) => column.group)) {
661
671
  console.warn('Simultaneously used grouping cells and dynamic render. The table will render unpredictable.');
662
672
  }
663
- 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, {
664
674
  sortOrder,
665
675
  sortColumns,
666
676
  }, {
@@ -711,6 +721,7 @@ class DataTableView extends React.Component {
711
721
  }
712
722
  }
713
723
  DataTableView.propTypes = {
724
+ getColSpansOfRow: PropTypes.func,
714
725
  columns: PropTypes.array.isRequired,
715
726
  headerData: PropTypes.array,
716
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;
@@ -1,5 +1,6 @@
1
1
  import { ColumnExtended, NameToOrderTypeMap, SortOrderWithSortColumns } from './DataTable';
2
2
  import { OrderType, Settings, SortOrder, SortedDataItem } from './types';
3
+ export declare const cn: import("@bem-react/classname").ClassNameInitilizer;
3
4
  export declare type SlimColumn = {
4
5
  name: string;
5
6
  defaultOrder?: OrderType;
@@ -1,5 +1,7 @@
1
1
  import { __rest } from "tslib";
2
+ import { withNaming } from '@bem-react/classname';
2
3
  import { ASCENDING, DESCENDING } from './constants';
4
+ export const cn = withNaming({ e: '__', m: '_' });
3
5
  export function getSortOrder({ name: columnName, defaultOrder: columnDefaultOrder }, { sortOrder = {}, sortColumns = [] }, multiColumnSort = false, { defaultOrder: settingsDefaultOrder, disableSortReset, } = {}) {
4
6
  const defaultOrder = columnDefaultOrder || settingsDefaultOrder;
5
7
  const emptyResult = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/react-data-table",
3
- "version": "1.1.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",
@@ -37,12 +38,13 @@
37
38
  "peerDependencies": {
38
39
  "react": ">=16.14.0",
39
40
  "prop-types": ">=15.8.0",
40
- "bem-cn-lite": ">=4.0.0"
41
+ "@bem-react/classname": ">=1.6.0"
41
42
  },
42
43
  "publishConfig": {
43
44
  "access": "public"
44
45
  },
45
46
  "devDependencies": {
47
+ "@bem-react/classname": "^1.6.0",
46
48
  "@commitlint/cli": "15.0.0",
47
49
  "@commitlint/config-conventional": "15.0.0",
48
50
  "@gravity-ui/eslint-config": "^2.0.0",
@@ -59,7 +61,6 @@
59
61
  "@types/react-dom": "16.9.14",
60
62
  "@types/react-list": "0.8.7",
61
63
  "@typescript-eslint/eslint-plugin": "^5.50.0",
62
- "bem-cn-lite": "4.0.0",
63
64
  "copyfiles": "2.4.1",
64
65
  "css-loader": "5.2.7",
65
66
  "eslint": "8.6.0",