@synerise/ds-table 0.54.0 → 0.55.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
@@ -3,6 +3,23 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [0.55.0](https://github.com/synerise/synerise-design/compare/@synerise/ds-table@0.54.0...@synerise/ds-table@0.55.0) (2024-07-05)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * fixed missing dependencies ([f718fb7](https://github.com/synerise/synerise-design/commit/f718fb7e954a19857ea4b6bbd417e3fe290fd2dc))
12
+ * **table:** fix remount virtual rows ([284e4ef](https://github.com/synerise/synerise-design/commit/284e4ef46188362b5e23c2fb2c1d18544f3c9680))
13
+
14
+
15
+ ### Features
16
+
17
+ * **table:** added prop to exclude selection for rows ([2607c00](https://github.com/synerise/synerise-design/commit/2607c0048fa7abddfc249d7fc4eeb2b9142ae5c1))
18
+
19
+
20
+
21
+
22
+
6
23
  # [0.54.0](https://github.com/synerise/synerise-design/compare/@synerise/ds-table@0.53.2...@synerise/ds-table@0.54.0) (2024-07-02)
7
24
 
8
25
 
package/README.md CHANGED
@@ -98,6 +98,15 @@ This type of table requires a specific type of dataSource which has to contain a
98
98
  | onChange | Callback executed when selection changes | (selectedRowKeys: React.ReactText[], selectedRows: T[]) => void | - |
99
99
  | limit | Max length of selection rows array | number | - |
100
100
  | independentSelectionExpandedRows | Allows to select parent and child rows independently | boolean | - |
101
+ | checkRowSelectionStatus | Validator function record selection status | (record: T) => SelectionStatus | - |
102
+
103
+ #### SelectionStatus
104
+
105
+ | Property | Description | Type | Default |
106
+ | --------------- | ------------------------------------------------ | --------------------------------------------------------------- | ------- |
107
+ | unavailable | Skips rendering checkbox if true | boolean | - |
108
+ | disabled | Renders checkbox in disabled state | boolean | - |
109
+
101
110
 
102
111
  #### RowStar
103
112
 
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  declare const _default: React.ForwardRefExoticComponent<{
3
- children: ((string | number | boolean | {} | React.ReactElement<any, string | React.JSXElementConstructor<any>> | React.ReactNodeArray | React.ReactPortal | React.ReactNode[]) & (boolean | React.ReactChild | React.ReactFragment | React.ReactPortal)) | null | undefined;
3
+ children: ((string | number | boolean | {} | React.ReactElement<any, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | React.ReactPortal | React.ReactNode[]) & (boolean | React.ReactChild | React.ReactFragment | React.ReactPortal)) | null | undefined;
4
4
  onClick?: (() => void) | undefined;
5
5
  active?: boolean | undefined;
6
6
  starTooltip?: React.ReactNode;
@@ -1,4 +1,4 @@
1
- import * as React from 'react';
1
+ import React from 'react';
2
2
  import { DSTableProps, RowType } from '../Table.types';
3
- declare function DefaultTable<T extends object & RowType<T>>(props: DSTableProps<T>): React.ReactElement;
3
+ declare function DefaultTable<T extends object & RowType<T>>(props: DSTableProps<T>): React.JSX.Element;
4
4
  export default DefaultTable;
@@ -10,18 +10,18 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
10
10
 
11
11
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
12
12
 
13
- import * as React from 'react';
13
+ import React, { useCallback, useEffect, useMemo } from 'react';
14
14
  import { compact, isEqual } from 'lodash';
15
15
  import Table from 'antd/lib/table';
16
16
  import { FormattedMessage } from 'react-intl';
17
17
  import Result from '@synerise/ds-result';
18
- import usePrevious from '@synerise/ds-utils/dist/usePrevious/usePrevious';
18
+ import { usePrevious } from '@synerise/ds-utils';
19
19
  import { columnsToSortState, useSortState } from '../ColumnSortMenu/useSortState';
20
20
  import { columnWithSortButtons } from '../ColumnSortMenu/columnWithSortButtons';
21
21
  import { useRowKey } from '../hooks/useRowKey';
22
22
  import { useRowStar } from '../hooks/useRowStar/useRowStar';
23
23
  import { RowSelectionColumn } from '../RowSelection';
24
- import { getChildrenColumnName } from '../utils/getChildrenColumnName'; // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
+ import { getChildrenColumnName, isRecordSelectable } from '../utils';
25
25
 
26
26
  function DefaultTable(props) {
27
27
  var _selection$selections;
@@ -47,17 +47,17 @@ function DefaultTable(props) {
47
47
  var _useRowKey = useRowKey(rowKey),
48
48
  getRowKey = _useRowKey.getRowKey;
49
49
 
50
- var starColumn = React.useMemo(function () {
50
+ var starColumn = useMemo(function () {
51
51
  return getRowStarColumn(_objectSpread({}, props, {
52
52
  getRowKey: getRowKey
53
53
  }));
54
54
  }, [getRowKey, getRowStarColumn, props]);
55
- React.useEffect(function () {
55
+ useEffect(function () {
56
56
  if (!isEqual(previousColumns, columns)) {
57
57
  sortStateApi.updateColumnsData(columnsToSortState(columns));
58
58
  }
59
59
  }, [columns, previousColumns, sortStateApi]);
60
- var RenderRow = React.useCallback(function (row) {
60
+ var RenderRow = useCallback(function (row) {
61
61
  var children = row.children,
62
62
  rowProps = _objectWithoutPropertiesLoose(row, _excluded);
63
63
 
@@ -102,15 +102,16 @@ function DefaultTable(props) {
102
102
  value = _ref2[1];
103
103
  return _objectSpread({}, acc, (_objectSpread2 = {}, _objectSpread2[key] = value, _objectSpread2));
104
104
  }, {});
105
- var selectedRecords = React.useMemo(function () {
105
+ var selectedRecords = useMemo(function () {
106
106
  if (selection) {
107
107
  var _ref4 = selection,
108
- selectedRowKeys = _ref4.selectedRowKeys;
108
+ selectedRowKeys = _ref4.selectedRowKeys,
109
+ checkRowSelectionStatus = _ref4.checkRowSelectionStatus;
109
110
  var selectedRows = [];
110
111
  dataSource && dataSource.forEach(function (row) {
111
112
  var key = getRowKey(row);
112
113
 
113
- if (key && selectedRowKeys.indexOf(key) >= 0) {
114
+ if (key && selectedRowKeys.indexOf(key) >= 0 && isRecordSelectable(row, checkRowSelectionStatus)) {
114
115
  selectedRows = [].concat(selectedRows, [row]);
115
116
  }
116
117
 
@@ -120,7 +121,7 @@ function DefaultTable(props) {
120
121
  rowChildren.forEach(function (child) {
121
122
  var childKey = getRowKey(child);
122
123
 
123
- if (childKey && selectedRowKeys.indexOf(childKey) >= 0) {
124
+ if (childKey && selectedRowKeys.indexOf(childKey) >= 0 && isRecordSelectable(child, checkRowSelectionStatus)) {
124
125
  selectedRows = [].concat(selectedRows, [child]);
125
126
  }
126
127
  });
@@ -130,13 +131,14 @@ function DefaultTable(props) {
130
131
  }
131
132
 
132
133
  return [];
133
- }, [dataSource, getRowKey, selection, childrenColumnName]);
134
- var renderRowSelection = React.useCallback(function (key, record) {
134
+ }, [childrenColumnName, dataSource, getRowKey, selection]);
135
+ var renderRowSelection = useCallback(function (key, record) {
135
136
  var _ref5 = selection,
136
137
  selectedRowKeys = _ref5.selectedRowKeys,
137
138
  limit = _ref5.limit,
138
139
  independentSelectionExpandedRows = _ref5.independentSelectionExpandedRows,
139
- onChange = _ref5.onChange;
140
+ onChange = _ref5.onChange,
141
+ checkRowSelectionStatus = _ref5.checkRowSelectionStatus;
140
142
  return /*#__PURE__*/React.createElement(RowSelectionColumn, {
141
143
  rowKey: rowKey,
142
144
  record: record,
@@ -146,43 +148,40 @@ function DefaultTable(props) {
146
148
  onChange: onChange,
147
149
  selectedRecords: selectedRecords,
148
150
  tableLocale: locale,
151
+ checkRowSelectionStatus: checkRowSelectionStatus,
149
152
  childrenColumnName: childrenColumnName
150
153
  });
151
154
  }, [locale, rowKey, selectedRecords, selection, childrenColumnName]);
152
- return (
153
- /*#__PURE__*/
154
- // @ts-ignore
155
- React.createElement(Table, _extends({}, props, {
156
- "data-popup-container": true,
157
- columns: [].concat(prependedColumns, decoratedColumns),
158
- expandable: _objectSpread({
159
- expandIconColumnIndex: -1
160
- }, expandable),
161
- locale: _objectSpread({}, locale, {
162
- emptyText: /*#__PURE__*/React.createElement(Result, {
163
- description: (locale == null ? void 0 : locale.emptyText) || /*#__PURE__*/React.createElement(FormattedMessage, {
164
- id: "DS.TABLE.EMPTY_TEXT"
165
- }),
166
- type: "no-results",
167
- noSearchResults: true
168
- })
169
- }) // @ts-ignore
170
- ,
171
- title: title,
172
- showSorterTooltip: false,
173
- components: _objectSpread({
174
- body: {
175
- row: RenderRow
176
- }
177
- }, decoratedComponents) // @ts-ignore
178
- ,
179
- rowSelection: selection && _objectSpread({}, selection, {
180
- selections: selection == null || (_selection$selections = selection.selections) == null ? void 0 : _selection$selections.filter(Boolean),
181
- columnWidth: 64,
182
- renderCell: renderRowSelection
155
+ return /*#__PURE__*/React.createElement(Table, _extends({}, props, {
156
+ "data-popup-container": true,
157
+ columns: [].concat(prependedColumns, decoratedColumns),
158
+ expandable: _objectSpread({
159
+ expandIconColumnIndex: -1
160
+ }, expandable),
161
+ locale: _objectSpread({}, locale, {
162
+ emptyText: /*#__PURE__*/React.createElement(Result, {
163
+ description: (locale == null ? void 0 : locale.emptyText) || /*#__PURE__*/React.createElement(FormattedMessage, {
164
+ id: "DS.TABLE.EMPTY_TEXT"
165
+ }),
166
+ type: "no-results",
167
+ noSearchResults: true
183
168
  })
184
- }))
185
- );
169
+ }) // @ts-ignore
170
+ ,
171
+ title: title,
172
+ showSorterTooltip: false,
173
+ components: _objectSpread({
174
+ body: {
175
+ row: RenderRow
176
+ }
177
+ }, decoratedComponents) // @ts-ignore
178
+ ,
179
+ rowSelection: selection && _objectSpread({}, selection, {
180
+ selections: selection == null || (_selection$selections = selection.selections) == null ? void 0 : _selection$selections.filter(Boolean),
181
+ columnWidth: 64,
182
+ renderCell: renderRowSelection
183
+ })
184
+ }));
186
185
  }
187
186
 
188
187
  export default DefaultTable;
@@ -1,4 +1,4 @@
1
- import * as React from 'react';
1
+ import React from 'react';
2
2
  import { RowSelectionProps } from './RowSelectionColumn.types';
3
3
  import { RowType } from '../Table.types';
4
- export declare function RowSelectionColumn<T extends object & RowType<T>>({ rowKey, record, limit, independentSelectionExpandedRows, selectedRowKeys, selectedRecords, tableLocale, onChange, childrenColumnName, }: RowSelectionProps<T>): React.ReactElement | null;
4
+ export declare function RowSelectionColumn<T extends object & RowType<T>>({ rowKey, record, limit, independentSelectionExpandedRows, selectedRowKeys, selectedRecords, tableLocale, onChange, checkRowSelectionStatus, childrenColumnName, }: RowSelectionProps<T>): React.JSX.Element | null;
@@ -1,8 +1,8 @@
1
- import * as React from 'react';
1
+ import React, { useCallback, useMemo } from 'react';
2
2
  import Tooltip from '@synerise/ds-tooltip';
3
3
  import Button from '@synerise/ds-button';
4
4
  import { useRowKey } from '../hooks/useRowKey';
5
- // eslint-disable-next-line import/prefer-default-export
5
+ import { getRecordSelectionStatus, isRecordSelectable } from '../utils';
6
6
  export function RowSelectionColumn(_ref) {
7
7
  var rowKey = _ref.rowKey,
8
8
  record = _ref.record,
@@ -12,6 +12,7 @@ export function RowSelectionColumn(_ref) {
12
12
  selectedRecords = _ref.selectedRecords,
13
13
  tableLocale = _ref.tableLocale,
14
14
  onChange = _ref.onChange,
15
+ checkRowSelectionStatus = _ref.checkRowSelectionStatus,
15
16
  childrenColumnName = _ref.childrenColumnName;
16
17
 
17
18
  var _useRowKey = useRowKey(rowKey),
@@ -19,44 +20,49 @@ export function RowSelectionColumn(_ref) {
19
20
 
20
21
  var recordKey = getRowKey(record);
21
22
  var rowChildren = record[childrenColumnName];
22
- var checkedChildren = React.useMemo(function () {
23
+ var isSelectable = useCallback(function (item) {
24
+ return isRecordSelectable(item, checkRowSelectionStatus);
25
+ }, [checkRowSelectionStatus]);
26
+ var checkedChildren = useMemo(function () {
23
27
  return (rowChildren == null ? void 0 : rowChildren.filter(function (child) {
24
28
  var childKey = getRowKey(child);
25
- return childKey && selectedRowKeys.indexOf(childKey) >= 0;
29
+ return childKey && selectedRowKeys.indexOf(childKey) >= 0 && isSelectable(child);
26
30
  })) || [];
27
- }, [getRowKey, rowChildren, selectedRowKeys]);
28
- var allChildrenSelected = React.useMemo(function () {
29
- return !!(rowChildren != null && rowChildren.every(function (child) {
31
+ }, [isSelectable, getRowKey, rowChildren, selectedRowKeys]);
32
+ var allChildrenSelected = useMemo(function () {
33
+ return !!(rowChildren != null && rowChildren.filter(isSelectable).every(function (child) {
30
34
  var childKey = getRowKey(child);
31
35
  return childKey && selectedRowKeys.indexOf(childKey) >= 0;
32
36
  }));
33
- }, [getRowKey, rowChildren, selectedRowKeys]);
34
- var isIndeterminate = React.useMemo(function () {
37
+ }, [getRowKey, isSelectable, rowChildren, selectedRowKeys]);
38
+ var isIndeterminate = useMemo(function () {
35
39
  if (Array.isArray(rowChildren) && !independentSelectionExpandedRows) {
36
- return checkedChildren.length > 0 && checkedChildren.length < ((rowChildren == null ? void 0 : rowChildren.length) || 0);
40
+ var clickableChildren = rowChildren == null ? void 0 : rowChildren.filter(isSelectable);
41
+ return checkedChildren.length > 0 && checkedChildren.length < (clickableChildren.length || 0);
37
42
  }
38
43
 
39
44
  return false;
40
- }, [checkedChildren.length, independentSelectionExpandedRows, rowChildren]);
41
- var isChecked = React.useMemo(function () {
45
+ }, [checkedChildren.length, independentSelectionExpandedRows, isSelectable, rowChildren]);
46
+ var isChecked = useMemo(function () {
42
47
  if (Array.isArray(rowChildren) && !independentSelectionExpandedRows) {
43
48
  return isChecked || allChildrenSelected;
44
49
  }
45
50
 
46
51
  return recordKey !== undefined && selectedRowKeys && selectedRowKeys.indexOf(recordKey) >= 0;
47
52
  }, [allChildrenSelected, independentSelectionExpandedRows, rowChildren, recordKey, selectedRowKeys]);
48
- var handleSelectionChange = React.useCallback(function (isCheckedNext, changedRecord) {
53
+ var handleSelectionChange = useCallback(function (isCheckedNext, changedRecord) {
49
54
  var selectedRows = selectedRecords;
50
55
  var changedRecordChildren = changedRecord[childrenColumnName];
51
56
 
52
57
  if (isCheckedNext) {
53
58
  if (Array.isArray(changedRecordChildren) && !independentSelectionExpandedRows) {
54
- selectedRows = [].concat(selectedRows, changedRecordChildren);
59
+ var clickableChildren = changedRecordChildren.filter(isSelectable);
60
+ selectedRows = [].concat(selectedRows, clickableChildren);
55
61
  } else {
56
62
  selectedRows = [].concat(selectedRows, [changedRecord]);
57
63
  }
58
64
  } else if (Array.isArray(changedRecordChildren) && !independentSelectionExpandedRows) {
59
- var childrenKeys = changedRecordChildren.map(function (child) {
65
+ var childrenKeys = changedRecordChildren.filter(isSelectable).map(function (child) {
60
66
  return getRowKey(child);
61
67
  });
62
68
  selectedRows = selectedRows.filter(function (child) {
@@ -78,18 +84,23 @@ export function RowSelectionColumn(_ref) {
78
84
 
79
85
  return acc;
80
86
  }, []), selectedRows);
81
- }, [getRowKey, independentSelectionExpandedRows, onChange, recordKey, selectedRecords, childrenColumnName]);
82
- return recordKey !== undefined ? /*#__PURE__*/React.createElement(Tooltip, {
87
+ }, [getRowKey, independentSelectionExpandedRows, isSelectable, onChange, recordKey, selectedRecords, childrenColumnName]);
88
+
89
+ var _getRecordSelectionSt = getRecordSelectionStatus(checkRowSelectionStatus, record),
90
+ unavailable = _getRecordSelectionSt.unavailable,
91
+ disabled = _getRecordSelectionSt.disabled;
92
+
93
+ return recordKey !== undefined && !unavailable ? /*#__PURE__*/React.createElement(Tooltip, {
83
94
  title: tableLocale == null ? void 0 : tableLocale.selectRowTooltip,
84
95
  mouseLeaveDelay: 0
85
96
  }, /*#__PURE__*/React.createElement(Button.Checkbox, {
86
97
  key: "checkbox-" + recordKey,
87
98
  "data-testid": "ds-table-selection-button",
88
99
  checked: isChecked,
89
- disabled: !isChecked && Boolean(limit !== undefined && limit <= selectedRowKeys.length),
100
+ disabled: !isChecked && Boolean(limit !== undefined && limit <= selectedRowKeys.length) || disabled,
90
101
  indeterminate: isIndeterminate,
91
- onClick: function onClick(e) {
92
- e.stopPropagation();
102
+ onClick: function onClick(event) {
103
+ event.stopPropagation();
93
104
  },
94
105
  onChange: function onChange(isCheckedNext) {
95
106
  return handleSelectionChange(isCheckedNext, record);
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { TableProps } from 'rc-table/lib/Table';
3
- import { DSTableProps } from '../Table.types';
3
+ import { DSTableProps, RowSelection } from '../Table.types';
4
4
  export type RowSelectionProps<T> = {
5
5
  rowKey: TableProps<T>['rowKey'];
6
6
  independentSelectionExpandedRows?: boolean;
@@ -9,6 +9,7 @@ export type RowSelectionProps<T> = {
9
9
  limit?: number;
10
10
  record: T;
11
11
  tableLocale: DSTableProps<T>['locale'];
12
- onChange: (selectedRowKeys: React.ReactText[], selectedRecords: T[]) => void;
12
+ onChange: RowSelection<T>['onChange'];
13
+ checkRowSelectionStatus?: RowSelection<T>['checkRowSelectionStatus'];
13
14
  childrenColumnName: string;
14
15
  };
@@ -20,6 +20,10 @@ export type RowSelection<T> = Omit<TableRowSelection<T>, 'selections'> & {
20
20
  onChange: (selectedRowKeys: React.ReactText[], selectedRows: T[]) => void;
21
21
  limit?: number;
22
22
  independentSelectionExpandedRows?: boolean;
23
+ checkRowSelectionStatus?: (record: T) => {
24
+ disabled?: boolean;
25
+ unavailable?: boolean;
26
+ };
23
27
  };
24
28
  export interface Filter {
25
29
  tooltips: {
@@ -1,7 +1,7 @@
1
- import * as React from 'react';
1
+ import type { ReactElement, ReactText } from 'react';
2
2
  import { Props } from './TableSelection.types';
3
3
  declare function TableSelection<T extends {
4
- key: React.ReactText;
4
+ key: ReactText;
5
5
  children?: T[];
6
- }>({ dataSource, dataSourceFull, selection, rowKey, locale, childrenColumnName, }: Props<T>): React.ReactElement | null;
6
+ }>({ dataSource, dataSourceFull, selection, rowKey, locale, childrenColumnName, }: Props<T>): ReactElement | null;
7
7
  export default TableSelection;
@@ -1,4 +1,4 @@
1
- import * as React from 'react';
1
+ import React, { useCallback, useMemo } from 'react';
2
2
  import Dropdown from '@synerise/ds-dropdown';
3
3
  import Menu from '@synerise/ds-menu';
4
4
  import Button from '@synerise/ds-button';
@@ -6,7 +6,8 @@ import Tooltip from '@synerise/ds-tooltip';
6
6
  import Icon, { OptionVerticalM } from '@synerise/ds-icon';
7
7
  import * as S from '../Table.styles';
8
8
  import { SELECTION_ALL, SELECTION_INVERT } from '../Table';
9
- import { useRowKey } from '../hooks/useRowKey'; // @ts-ignore
9
+ import { useRowKey } from '../hooks/useRowKey';
10
+ import { isRecordSelectable } from '../utils'; // @ts-ignore
10
11
 
11
12
  function TableSelection(_ref) {
12
13
  var dataSource = _ref.dataSource,
@@ -21,7 +22,7 @@ function TableSelection(_ref) {
21
22
 
22
23
  var allData = dataSourceFull || dataSource;
23
24
  var isShowingSubset = dataSourceFull && dataSourceFull.length !== dataSource.length;
24
- var getRowsForKeys = React.useCallback(function (keys) {
25
+ var getRowsForKeys = useCallback(function (keys) {
25
26
  if (selection) {
26
27
  var rows = [];
27
28
  allData.forEach(function (record) {
@@ -50,9 +51,10 @@ function TableSelection(_ref) {
50
51
 
51
52
  return [];
52
53
  }, [allData, getRowKey, selection, childrenColumnName]);
53
- var selectAll = React.useCallback(function () {
54
+ var selectAll = useCallback(function () {
54
55
  if (dataSource && selection) {
55
- var selectedRowKeys = selection.selectedRowKeys;
56
+ var selectedRowKeys = selection.selectedRowKeys,
57
+ checkRowSelectionStatus = selection.checkRowSelectionStatus;
56
58
  var keys = isShowingSubset ? [].concat(selectedRowKeys) : [];
57
59
  dataSource.forEach(function (record) {
58
60
  var rowChildren = record[childrenColumnName];
@@ -60,21 +62,21 @@ function TableSelection(_ref) {
60
62
  if (Array.isArray(rowChildren)) {
61
63
  keys = [].concat(keys, rowChildren.reduce(function (acc, child) {
62
64
  var key = getRowKey(child);
63
- return key ? [].concat(acc, [key]) : acc;
65
+ return key && isRecordSelectable(child, checkRowSelectionStatus) ? [].concat(acc, [key]) : acc;
64
66
  }, []));
65
67
  }
66
68
 
67
69
  if (!Array.isArray(rowChildren) || selection.independentSelectionExpandedRows) {
68
70
  var key = getRowKey(record);
69
- keys = key !== undefined ? [].concat(keys, [key]) : [].concat(keys);
71
+ keys = key !== undefined && isRecordSelectable(record, checkRowSelectionStatus) ? [].concat(keys, [key]) : [].concat(keys);
70
72
  }
71
73
  });
72
74
  var uniqueKeys = Array.from(new Set(keys));
73
75
  var rows = getRowsForKeys(uniqueKeys);
74
76
  selection.onChange(uniqueKeys, rows);
75
77
  }
76
- }, [dataSource, selection, isShowingSubset, getRowsForKeys, getRowKey, childrenColumnName]);
77
- var unselectAll = React.useCallback(function () {
78
+ }, [childrenColumnName, dataSource, selection, isShowingSubset, getRowsForKeys, getRowKey]);
79
+ var unselectAll = useCallback(function () {
78
80
  if (selection) {
79
81
  if (isShowingSubset) {
80
82
  var selectedRowKeys = selection.selectedRowKeys;
@@ -104,14 +106,17 @@ function TableSelection(_ref) {
104
106
  }
105
107
  }
106
108
  }, [dataSource, getRowKey, getRowsForKeys, isShowingSubset, selection, childrenColumnName]);
107
- var getSelectableChildren = React.useCallback(function (children) {
109
+ var getSelectableChildren = useCallback(function (children) {
110
+ var selectionStatusValidator = selection && 'checkRowSelectionStatus' in selection ? selection.checkRowSelectionStatus : undefined;
108
111
  return children ? children.filter(function (child) {
109
- return getRowKey(child) !== undefined;
112
+ return isRecordSelectable(child, selectionStatusValidator) && getRowKey(child) !== undefined;
110
113
  }) : [];
111
- }, [getRowKey]);
112
- var selectInvert = React.useCallback(function () {
114
+ }, // eslint-disable-next-line react-hooks/exhaustive-deps
115
+ [getRowKey, selection == null ? void 0 : selection.checkRowSelectionStatus]);
116
+ var selectInvert = useCallback(function () {
113
117
  if (dataSource && selection) {
114
- var selectedRowKeys = selection.selectedRowKeys;
118
+ var selectedRowKeys = selection.selectedRowKeys,
119
+ checkRowSelectionStatus = selection.checkRowSelectionStatus;
115
120
  var keys = isShowingSubset ? [].concat(selectedRowKeys) : [];
116
121
  dataSource.forEach(function (record) {
117
122
  var rowChildren = record[childrenColumnName];
@@ -135,7 +140,7 @@ function TableSelection(_ref) {
135
140
 
136
141
  if (selectedRowKeys.includes(key)) {
137
142
  if (isShowingSubset) keys.splice(keys.indexOf(key), 1);
138
- } else {
143
+ } else if (isRecordSelectable(record, checkRowSelectionStatus)) {
139
144
  keys = [].concat(keys, [key]);
140
145
  }
141
146
  }
@@ -143,23 +148,28 @@ function TableSelection(_ref) {
143
148
  var rows = getRowsForKeys(keys);
144
149
  selection.onChange(keys, rows);
145
150
  }
146
- }, [dataSource, selection, isShowingSubset, getRowsForKeys, getSelectableChildren, getRowKey, childrenColumnName]);
147
- var isEmpty = React.useMemo(function () {
151
+ }, [childrenColumnName, dataSource, selection, isShowingSubset, getRowsForKeys, getSelectableChildren, getRowKey]);
152
+ var isEmpty = useMemo(function () {
148
153
  return dataSource.length === 0;
149
154
  }, [dataSource]);
150
- var allSelected = React.useMemo(function () {
151
- if (isEmpty || !selection) return false;
152
- var selectedRowKeys = selection.selectedRowKeys,
153
- independentSelectionExpandedRows = selection.independentSelectionExpandedRows;
154
- var allRecordsCount = dataSource.reduce(function (count, record) {
155
+ var allSelectableRecordsCount = useMemo(function () {
156
+ if (isEmpty || !selection) return 0;
157
+ var independentSelectionExpandedRows = selection.independentSelectionExpandedRows,
158
+ checkRowSelectionStatus = selection.checkRowSelectionStatus;
159
+ return dataSource.reduce(function (count, record) {
160
+ var isSelectable = +isRecordSelectable(record, checkRowSelectionStatus);
155
161
  var rowChildren = record[childrenColumnName];
156
162
 
157
163
  if (independentSelectionExpandedRows) {
158
- return Array.isArray(rowChildren) ? count + getSelectableChildren(rowChildren).length + 1 : count + 1;
164
+ return Array.isArray(rowChildren) ? count + getSelectableChildren(rowChildren).length + isSelectable : count + isSelectable;
159
165
  }
160
166
 
161
- return Array.isArray(rowChildren) ? count + getSelectableChildren(rowChildren).length : count + 1;
167
+ return Array.isArray(rowChildren) ? count + getSelectableChildren(rowChildren).length : count + isSelectable;
162
168
  }, 0);
169
+ }, [childrenColumnName, dataSource, getSelectableChildren, isEmpty, selection]);
170
+ var allSelected = useMemo(function () {
171
+ if (isEmpty || !selection) return false;
172
+ var selectedRowKeys = selection.selectedRowKeys;
163
173
  var selectedKeysInDataSourceCount = isShowingSubset ? dataSource.reduce(function (count, record) {
164
174
  var rowChildren = record[childrenColumnName];
165
175
 
@@ -177,17 +187,17 @@ function TableSelection(_ref) {
177
187
 
178
188
  return count;
179
189
  }, 0) : selectedRowKeys.length;
180
- return allRecordsCount === selectedKeysInDataSourceCount;
181
- }, [isEmpty, selection, dataSource, isShowingSubset, getSelectableChildren, getRowKey, childrenColumnName]);
190
+ return allSelectableRecordsCount === selectedKeysInDataSourceCount;
191
+ }, [isEmpty, selection, isShowingSubset, dataSource, allSelectableRecordsCount, childrenColumnName, getRowKey]);
182
192
  var selectionTooltipTitle = !allSelected ? locale == null ? void 0 : locale.selectAllTooltip : locale == null ? void 0 : locale.unselectAll;
183
193
  return selection != null && selection.selectedRowKeys ? /*#__PURE__*/React.createElement(S.Selection, {
184
194
  "data-popup-container": true
185
195
  }, /*#__PURE__*/React.createElement(Tooltip, {
186
196
  title: selectionTooltipTitle
187
197
  }, /*#__PURE__*/React.createElement(Button.Checkbox, {
188
- disabled: isEmpty,
198
+ disabled: isEmpty || allSelectableRecordsCount === 0,
189
199
  "data-testid": "ds-table-batch-selection-button",
190
- checked: allSelected,
200
+ checked: allSelected && allSelectableRecordsCount > 0,
191
201
  onChange: function onChange(isChecked) {
192
202
  if (isChecked) {
193
203
  selectAll();
@@ -197,7 +207,7 @@ function TableSelection(_ref) {
197
207
  },
198
208
  indeterminate: (selection == null ? void 0 : selection.selectedRowKeys.length) > 0 && !allSelected
199
209
  })), (selection == null ? void 0 : selection.selections) && /*#__PURE__*/React.createElement(Dropdown, {
200
- disabled: isEmpty,
210
+ disabled: isEmpty || allSelectableRecordsCount === 0,
201
211
  trigger: ['click'],
202
212
  overlay: /*#__PURE__*/React.createElement(S.SelectionMenu, null, selection == null ? void 0 : selection.selections.filter(Boolean).map(function (selectionMenuElement) {
203
213
  switch (selectionMenuElement) {
@@ -197,9 +197,7 @@ var VirtualTable = function VirtualTable(props, forwardedRef) {
197
197
  });
198
198
 
199
199
  var rowStarColumn = getRowStarColumn(propsForRowStar);
200
- var selectedRecords = getSelectedRecords();
201
-
202
- function getSelectedRecords() {
200
+ var selectedRecords = useMemo(function () {
203
201
  if (selection) {
204
202
  var _ref2 = selection,
205
203
  selectedRowKeys = _ref2.selectedRowKeys;
@@ -226,14 +224,14 @@ var VirtualTable = function VirtualTable(props, forwardedRef) {
226
224
  }
227
225
 
228
226
  return [];
229
- }
230
-
227
+ }, [allData, childrenColumnName, getRowKey, selection]);
231
228
  var renderRowSelection = useCallback(function (key, record) {
232
229
  var _ref3 = selection,
233
230
  selectedRowKeys = _ref3.selectedRowKeys,
234
231
  limit = _ref3.limit,
235
232
  independentSelectionExpandedRows = _ref3.independentSelectionExpandedRows,
236
- onChange = _ref3.onChange;
233
+ onChange = _ref3.onChange,
234
+ checkRowSelectionStatus = _ref3.checkRowSelectionStatus;
237
235
 
238
236
  var handleChange = function handleChange(keys, records) {
239
237
  if (isSticky && listScrollTopRef.current) {
@@ -252,6 +250,7 @@ var VirtualTable = function VirtualTable(props, forwardedRef) {
252
250
  onChange: handleChange,
253
251
  selectedRecords: selectedRecords,
254
252
  tableLocale: locale,
253
+ checkRowSelectionStatus: checkRowSelectionStatus,
255
254
  childrenColumnName: childrenColumnName
256
255
  });
257
256
  }, [isSticky, locale, rowKey, selectedRecords, selection, childrenColumnName]);
@@ -335,17 +334,19 @@ var VirtualTable = function VirtualTable(props, forwardedRef) {
335
334
 
336
335
  return infiniteLoaderItemHeight;
337
336
  }, [isSticky, infiniteScroll == null || (_infiniteScroll$prevP4 = infiniteScroll.prevPage) == null ? void 0 : _infiniteScroll$prevP4.hasMore]);
338
- var listInnerElementType = forwardRef(function (_ref4, innerElementRef) {
339
- var style = _ref4.style,
340
- rest = _objectWithoutPropertiesLoose(_ref4, _excluded);
341
-
342
- return /*#__PURE__*/React.createElement(S.InnerListElement, _extends({
343
- ref: innerElementRef,
344
- style: _objectSpread({}, style, {
345
- height: Number(style == null ? void 0 : style.height) + infiniteLoaderOffset + "px"
346
- })
347
- }, rest));
348
- });
337
+ var listInnerElementType = useMemo(function () {
338
+ return forwardRef(function (_ref4, innerElementRef) {
339
+ var style = _ref4.style,
340
+ rest = _objectWithoutPropertiesLoose(_ref4, _excluded);
341
+
342
+ return /*#__PURE__*/React.createElement(S.InnerListElement, _extends({
343
+ ref: innerElementRef,
344
+ style: _objectSpread({}, style, {
345
+ height: Number(style == null ? void 0 : style.height) + infiniteLoaderOffset + "px"
346
+ })
347
+ }, rest));
348
+ });
349
+ }, [infiniteLoaderOffset]);
349
350
  var scrollTo = useCallback(function (top) {
350
351
  if (!listRef.current) {
351
352
  return;
@@ -0,0 +1,8 @@
1
+ import { RowSelection } from '../Table.types';
2
+ export declare const getRecordSelectionStatus: <T>(checkRowSelectionStatus: ((record: T) => {
3
+ disabled?: boolean | undefined;
4
+ unavailable?: boolean | undefined;
5
+ }) | undefined, record: T) => {
6
+ unavailable: boolean | undefined;
7
+ disabled: boolean | undefined;
8
+ };
@@ -0,0 +1,10 @@
1
+ export var getRecordSelectionStatus = function getRecordSelectionStatus(checkRowSelectionStatus, record) {
2
+ var _ref = checkRowSelectionStatus && checkRowSelectionStatus(record) || {},
3
+ unavailable = _ref.unavailable,
4
+ disabled = _ref.disabled;
5
+
6
+ return {
7
+ unavailable: unavailable,
8
+ disabled: disabled
9
+ };
10
+ };
@@ -1,4 +1,8 @@
1
1
  export * from './getValueFromPath';
2
2
  export * from './locale';
3
+ export * from './locale';
3
4
  export * from './calculatePixels';
5
+ export * from './getRecordSelectionStatus';
4
6
  export * from './calculateColumnWidths';
7
+ export * from './getChildrenColumnName';
8
+ export * from './isRecordSelectable';
@@ -1,4 +1,8 @@
1
1
  export * from './getValueFromPath';
2
2
  export * from './locale';
3
+ export * from './locale';
3
4
  export * from './calculatePixels';
4
- export * from './calculateColumnWidths';
5
+ export * from './getRecordSelectionStatus';
6
+ export * from './calculateColumnWidths';
7
+ export * from './getChildrenColumnName';
8
+ export * from './isRecordSelectable';
@@ -0,0 +1,5 @@
1
+ import type { RowSelection } from '../Table.types';
2
+ export declare const isRecordSelectable: <T>(record: T, checkRowSelectionStatus?: ((record: T) => {
3
+ disabled?: boolean | undefined;
4
+ unavailable?: boolean | undefined;
5
+ }) | undefined) => boolean;
@@ -0,0 +1,12 @@
1
+ import { getRecordSelectionStatus } from './getRecordSelectionStatus';
2
+ export var isRecordSelectable = function isRecordSelectable(record, checkRowSelectionStatus) {
3
+ if (!checkRowSelectionStatus) {
4
+ return true;
5
+ }
6
+
7
+ var _getRecordSelectionSt = getRecordSelectionStatus(checkRowSelectionStatus, record),
8
+ unavailable = _getRecordSelectionSt.unavailable,
9
+ disabled = _getRecordSelectionSt.disabled;
10
+
11
+ return !(unavailable || disabled);
12
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synerise/ds-table",
3
- "version": "0.54.0",
3
+ "version": "0.55.0",
4
4
  "description": "Table UI Component for the Synerise Design System",
5
5
  "license": "ISC",
6
6
  "repository": "synerise/synerise-design",
@@ -33,31 +33,31 @@
33
33
  ],
34
34
  "types": "dist/index.d.ts",
35
35
  "dependencies": {
36
- "@synerise/ds-alert": "^0.8.17",
37
- "@synerise/ds-badge": "^0.7.1",
38
- "@synerise/ds-button": "^0.21.1",
39
- "@synerise/ds-button-group": "^0.7.3",
40
- "@synerise/ds-checkbox": "^0.12.1",
41
- "@synerise/ds-column-manager": "^0.11.61",
42
- "@synerise/ds-data-format": "^0.5.0",
43
- "@synerise/ds-dropdown": "^0.18.3",
44
- "@synerise/ds-flag": "^0.5.0",
45
- "@synerise/ds-icon": "^0.63.0",
46
- "@synerise/ds-input": "^0.23.0",
47
- "@synerise/ds-loader": "^0.3.9",
48
- "@synerise/ds-menu": "^0.19.3",
49
- "@synerise/ds-modal": "^0.17.32",
50
- "@synerise/ds-pagination": "^0.7.53",
51
- "@synerise/ds-result": "^0.6.58",
52
- "@synerise/ds-scrollbar": "^0.11.2",
53
- "@synerise/ds-search": "^0.8.95",
54
- "@synerise/ds-select": "^0.16.5",
55
- "@synerise/ds-skeleton": "^0.6.1",
56
- "@synerise/ds-status": "^0.6.11",
57
- "@synerise/ds-tags": "^0.9.3",
58
- "@synerise/ds-tooltip": "^0.14.31",
59
- "@synerise/ds-typography": "^0.15.0",
60
- "@synerise/ds-utils": "^0.27.0",
36
+ "@synerise/ds-alert": "^0.8.18",
37
+ "@synerise/ds-badge": "^0.8.0",
38
+ "@synerise/ds-button": "^0.21.2",
39
+ "@synerise/ds-button-group": "^0.7.4",
40
+ "@synerise/ds-checkbox": "^0.12.2",
41
+ "@synerise/ds-column-manager": "^0.11.62",
42
+ "@synerise/ds-data-format": "^0.5.1",
43
+ "@synerise/ds-dropdown": "^0.18.4",
44
+ "@synerise/ds-flag": "^0.5.1",
45
+ "@synerise/ds-icon": "^0.64.0",
46
+ "@synerise/ds-input": "^0.23.1",
47
+ "@synerise/ds-loader": "^0.3.10",
48
+ "@synerise/ds-menu": "^0.19.4",
49
+ "@synerise/ds-modal": "^0.17.33",
50
+ "@synerise/ds-pagination": "^0.7.54",
51
+ "@synerise/ds-result": "^0.6.59",
52
+ "@synerise/ds-scrollbar": "^0.11.3",
53
+ "@synerise/ds-search": "^0.9.0",
54
+ "@synerise/ds-select": "^0.16.6",
55
+ "@synerise/ds-skeleton": "^0.6.2",
56
+ "@synerise/ds-status": "^0.6.12",
57
+ "@synerise/ds-tags": "^0.9.4",
58
+ "@synerise/ds-tooltip": "^0.14.32",
59
+ "@synerise/ds-typography": "^0.15.1",
60
+ "@synerise/ds-utils": "^0.28.0",
61
61
  "@types/react-window": "^1.8.5",
62
62
  "classnames": "2.3.2",
63
63
  "copy-to-clipboard": "^3.3.1",
@@ -73,11 +73,9 @@
73
73
  "peerDependencies": {
74
74
  "@synerise/ds-core": "*",
75
75
  "antd": "4.7.0",
76
- "react": ">=16.9.0 < 17.0.0",
76
+ "react": ">=16.9.0 <= 17.0.2",
77
+ "react-dom": "^16.14.0",
77
78
  "styled-components": "5.0.1"
78
79
  },
79
- "devDependencies": {
80
- "@testing-library/react": "10.0.1"
81
- },
82
- "gitHead": "0692552b018dc9c8042f18c773f88890c9ad3270"
80
+ "gitHead": "6e5e5202d6c6f1c2caf6bfef799009813b437b3d"
83
81
  }