@snack-uikit/table 0.36.23 → 0.36.24

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,17 @@
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.36.24 (2025-07-24)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **FF-6453:** cell render for TreeCell, fix click on tree cell when selection is disabled ([d26c1ba](https://github.com/cloud-ru-tech/snack-uikit/commit/d26c1ba66819c80fd545539fc63e2a46477a0c0f))
12
+
13
+
14
+
15
+
16
+
6
17
  ## 0.36.23 (2025-07-23)
7
18
 
8
19
  ### Only dependencies have been changed
package/README.md CHANGED
@@ -179,6 +179,7 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
179
179
  |------|------|---------------|-------------|
180
180
  | onChangePage* | `(offset: number, limit: number) => void` | - | |
181
181
  | columnDefinitions* | `ColumnDefinition<TData>[]` | - | Определение внешнего вида и функционала колонок |
182
+ | loading | `boolean` | - | Состояние загрузки |
182
183
  | className | `string` | - | CSS-класс |
183
184
  | onRefresh | `() => void` | - | Колбек обновления данных |
184
185
  | moreActions | `Action[]` | - | Элементы выпадающего списка кнопки с действиями |
@@ -193,7 +194,6 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
193
194
  | enableFuzzySearch | `boolean` | - | Включить нечеткий поиск |
194
195
  | rowAutoHeight | `boolean` | - | |
195
196
  | onRowClick | `RowClickHandler<TData>` | - | Колбэк клика по строке |
196
- | loading | `boolean` | - | Состояние загрузки |
197
197
  | outline | `boolean` | - | Внешний бордер для тулбара и таблицы |
198
198
  | columnFilters | `Omit<ChipChoiceRowProps<TFilters>, "size" \| "data-test-id"> & { open?: boolean; onOpenChange?(isOpen: boolean): void; } & { initialOpen?: boolean; }` | - | Фильтры |
199
199
  | dataFiltered | `boolean` | - | Флаг, показывающий что данные были отфильтрованы при пустых данных |
@@ -3,6 +3,17 @@ import { ServerTableProps } from '../types';
3
3
  export declare function ServerTable<TData extends object, TFilters extends FiltersState = Record<string, unknown>>({ items, total, limit, offset, onChangePage, search: searchProp, pagination, columnFilters, manualSorting, manualPagination, manualFiltering, ...rest }: ServerTableProps<TData, TFilters>): import("react/jsx-runtime").JSX.Element;
4
4
  export declare namespace ServerTable {
5
5
  var getRowActionsColumnDef: typeof import("../../helperComponents").getRowActionsColumnDef;
6
- var statusAppearances: Record<string, string>;
6
+ var statusAppearances: {
7
+ readonly Primary: "primary";
8
+ readonly Neutral: "neutral";
9
+ readonly Red: "red";
10
+ readonly Orange: "orange";
11
+ readonly Yellow: "yellow";
12
+ readonly Green: "green";
13
+ readonly Blue: "blue";
14
+ readonly Violet: "violet";
15
+ readonly Pink: "pink";
16
+ readonly Loading: "loading";
17
+ };
7
18
  var getStatusColumnDef: typeof import("../../helperComponents").getStatusColumnDef;
8
19
  }
@@ -4,6 +4,17 @@ import { TableProps } from '../types';
4
4
  export declare function Table<TData extends object, TFilters extends FiltersState = Record<string, unknown>>({ data, rowPinning, columnDefinitions, keepPinnedRows, copyPinnedRows, enableSelectPinned, rowSelection: rowSelectionProp, search, sorting: sortingProp, columnFilters, pagination: paginationProp, className, onRowClick, onRefresh, pageSize, pageCount, loading, infiniteLoading, outline, moreActions, exportSettings, dataFiltered, dataError, noDataState, noResultsState, errorDataState, suppressToolbar, suppressSearch, toolbarAfter, suppressPagination, manualSorting, manualPagination: manualPaginationProp, manualFiltering, autoResetPageIndex, scrollRef, scrollContainerRef, getRowId, enableFuzzySearch, savedState, expanding, bulkActions: bulkActionsProp, rowAutoHeight, columnsSettings: columnsSettingsProp, ...rest }: TableProps<TData, TFilters>): import("react/jsx-runtime").JSX.Element;
5
5
  export declare namespace Table {
6
6
  var getStatusColumnDef: typeof import("../../helperComponents").getStatusColumnDef;
7
- var statusAppearances: Record<string, string>;
7
+ var statusAppearances: {
8
+ readonly Primary: "primary";
9
+ readonly Neutral: "neutral";
10
+ readonly Red: "red";
11
+ readonly Orange: "orange";
12
+ readonly Yellow: "yellow";
13
+ readonly Green: "green";
14
+ readonly Blue: "blue";
15
+ readonly Violet: "violet";
16
+ readonly Pink: "pink";
17
+ readonly Loading: "loading";
18
+ };
8
19
  var getRowActionsColumnDef: typeof import("../../helperComponents").getRowActionsColumnDef;
9
20
  }
@@ -227,7 +227,7 @@ function Table(_a) {
227
227
  onRowSelectionChange,
228
228
  enableGrouping: true,
229
229
  enableRowSelection,
230
- enableMultiRowSelection: rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow,
230
+ enableMultiRowSelection: (rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.enable) && (rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow),
231
231
  enableFilters: true,
232
232
  getSubRows: expanding === null || expanding === void 0 ? void 0 : expanding.getSubRows,
233
233
  filterFromLeafRows: Boolean(expanding),
@@ -17,7 +17,9 @@ function getTableColumnsDefinitions(_ref) {
17
17
  cols = [(0, helperComponents_1.getSelectionCellColumnDef)(enableSelectPinned), ...cols];
18
18
  }
19
19
  if (expanding) {
20
- cols = [(0, helperComponents_1.getTreeColumnDef)(expanding.expandingColumnDefinition), ...cols];
20
+ cols = [(0, helperComponents_1.getTreeColumnDef)(Object.assign(Object.assign({}, expanding.expandingColumnDefinition), {
21
+ enableSelection
22
+ })), ...cols];
21
23
  }
22
24
  return cols;
23
25
  }
@@ -1,2 +1,13 @@
1
- export declare const STATUS_APPEARANCE: Record<string, string>;
1
+ export declare const STATUS_APPEARANCE: {
2
+ readonly Primary: "primary";
3
+ readonly Neutral: "neutral";
4
+ readonly Red: "red";
5
+ readonly Orange: "orange";
6
+ readonly Yellow: "yellow";
7
+ readonly Green: "green";
8
+ readonly Blue: "blue";
9
+ readonly Violet: "violet";
10
+ readonly Pink: "pink";
11
+ readonly Loading: "loading";
12
+ };
2
13
  export declare const MIN_STATUS_CELL_SIZE = 16;
@@ -1,3 +1,4 @@
1
+ import { CellContext } from '@tanstack/react-table';
1
2
  import { ReactNode } from 'react';
2
3
  import { ColumnDefinition } from '../../../types';
3
4
  type BaseTreeColumnDef = {
@@ -14,15 +15,18 @@ type BaseTreeColumnDef = {
14
15
  };
15
16
  type TreeColumnDef = BaseTreeColumnDef & {
16
17
  header?: never;
17
- renderDescription?: never;
18
+ cell?: never;
18
19
  };
19
20
  type TreeColumnDefWithDescription<TData> = BaseTreeColumnDef & {
20
21
  /** Заголовок колонки */
21
- renderDescription?(cellValue: string, row: TData): string;
22
+ cell?(ctx: CellContext<TData, unknown>): ReactNode;
22
23
  /** Рендер функция заголовка колонки */
23
24
  header?: ColumnDefinition<TData>['header'];
24
25
  };
25
26
  export type TreeColumnDefinitionProps<TData> = TreeColumnDef | TreeColumnDefWithDescription<TData>;
27
+ type TreeColDefProps<TData> = TreeColumnDefinitionProps<TData> & {
28
+ enableSelection?: boolean;
29
+ };
26
30
  /** Вспомогательная функция для создания ячейки со статусом */
27
- export declare function getTreeColumnDef<TData>({ showToggle, icon, expandedIcon, collapsedIcon, header, accessorKey, }: TreeColumnDefinitionProps<TData>): ColumnDefinition<TData>;
31
+ export declare function getTreeColumnDef<TData>({ showToggle, icon, expandedIcon, collapsedIcon, header, accessorKey, cell: renderCell, enableSelection, }: TreeColDefProps<TData>): ColumnDefinition<TData>;
28
32
  export {};
@@ -34,80 +34,69 @@ function getTreeColumnDef(_ref) {
34
34
  size: 24
35
35
  }),
36
36
  header,
37
- accessorKey
38
- } = _ref;
39
- return {
40
- id: constants_2.TREE_CELL_ID,
41
- pinned: constants_1.COLUMN_PIN_POSITION.Left,
42
37
  accessorKey,
43
- noBodyCellPadding: true,
44
- noHeaderCellPadding: false,
45
- enableResizing: true,
46
- size: 150,
47
- maxSize: Number.MAX_SAFE_INTEGER,
48
- meta: {
49
- skipOnExport: false
50
- },
51
- enableSorting: false,
52
- header,
53
- cell: function TreeCell(_ref2) {
54
- let {
55
- row,
56
- cell
57
- } = _ref2;
38
+ cell: renderCell,
39
+ enableSelection
40
+ } = _ref;
41
+ const cell = function TreeCell(ctx) {
42
+ var _a;
43
+ const {
44
+ row,
45
+ cell
46
+ } = ctx;
47
+ const isExpanded = row.getIsExpanded();
48
+ const isExpandable = row.getCanExpand();
49
+ const isMultiSelect = row.getCanMultiSelect();
50
+ const parent = row.getParentRow();
51
+ const isRowsSelectionEnabled = row.getCanSelect();
52
+ const isAllSubRowsSelected = row.getIsAllSubRowsSelected();
53
+ const isSomeSubRowSelected = row.getIsSomeSelected();
54
+ const isRowSelected = row.getIsSelected();
55
+ const isLastChildRow = ((_a = parent === null || parent === void 0 ? void 0 : parent.subRows.at(-1)) === null || _a === void 0 ? void 0 : _a.id) === row.id;
56
+ const depth = row.depth;
57
+ const {
58
+ ref
59
+ } = (0, contexts_1.useCellResize)(constants_2.TREE_CELL_ID, cell);
60
+ const linesVisibilityByIndex = (0, react_1.useMemo)(() => {
58
61
  var _a;
59
- const isExpanded = row.getIsExpanded();
60
- const isExpandable = row.getCanExpand();
61
- const isMultiSelect = row.getCanMultiSelect();
62
- const parent = row.getParentRow();
63
- const isRowsSelectionEnabled = row.getCanSelect();
64
- const isAllSubRowsSelected = row.getIsAllSubRowsSelected();
65
- const isSomeSubRowSelected = row.getIsSomeSelected();
66
- const isRowSelected = row.getIsSelected();
67
- const isLastChildRow = ((_a = parent === null || parent === void 0 ? void 0 : parent.subRows.at(-1)) === null || _a === void 0 ? void 0 : _a.id) === row.id;
68
- const depth = row.depth;
69
- const {
70
- ref
71
- } = (0, contexts_1.useCellResize)(constants_2.TREE_CELL_ID, cell);
72
- const linesVisibilityByIndex = (0, react_1.useMemo)(() => {
62
+ const parents = [];
63
+ for (let i = depth; i >= 0; i--) {
64
+ parents[i] = i === depth ? row : (_a = parents.at(i + 1)) === null || _a === void 0 ? void 0 : _a.getParentRow();
65
+ }
66
+ return parents.map((parent, index) => {
73
67
  var _a;
74
- const parents = [];
75
- for (let i = depth; i >= 0; i--) {
76
- parents[i] = i === depth ? row : (_a = parents.at(i + 1)) === null || _a === void 0 ? void 0 : _a.getParentRow();
77
- }
78
- return parents.map((parent, index) => {
79
- var _a;
80
- if (!parent || parents.length === index + 1) return true;
81
- const child = parents[index + 1];
82
- return (child === null || child === void 0 ? void 0 : child.id) !== ((_a = parent.subRows.at(-1)) === null || _a === void 0 ? void 0 : _a.id) || (row === null || row === void 0 ? void 0 : row.id) === (child === null || child === void 0 ? void 0 : child.id);
68
+ if (!parent || parents.length === index + 1) return true;
69
+ const child = parents[index + 1];
70
+ return (child === null || child === void 0 ? void 0 : child.id) !== ((_a = parent.subRows.at(-1)) === null || _a === void 0 ? void 0 : _a.id) || (row === null || row === void 0 ? void 0 : row.id) === (child === null || child === void 0 ? void 0 : child.id);
71
+ });
72
+ }, [row, depth]);
73
+ const lines = (0, react_1.useMemo)(() => Array.from({
74
+ length: depth
75
+ }, (_, index) => (0, jsx_runtime_1.jsx)(TreeLine_1.TreeLine, {
76
+ visible: linesVisibilityByIndex.at(index),
77
+ className: index !== 0 ? styles_module_scss_1.default.line : styles_module_scss_1.default.firstLine,
78
+ halfHeight: index === depth - 1 && isLastChildRow
79
+ }, index)), [depth, linesVisibilityByIndex, isLastChildRow]);
80
+ (0, react_1.useEffect)(() => {
81
+ if (!isMultiSelect || !isExpandable || !isRowsSelectionEnabled) {
82
+ return;
83
+ }
84
+ if (isAllSubRowsSelected && !isRowSelected) {
85
+ row.toggleSelected(true, {
86
+ selectChildren: false
83
87
  });
84
- }, [row, depth]);
85
- const lines = (0, react_1.useMemo)(() => Array.from({
86
- length: depth
87
- }, (_, index) => (0, jsx_runtime_1.jsx)(TreeLine_1.TreeLine, {
88
- visible: linesVisibilityByIndex.at(index),
89
- className: index !== 0 ? styles_module_scss_1.default.line : styles_module_scss_1.default.firstLine,
90
- halfHeight: index === depth - 1 && isLastChildRow
91
- }, index)), [depth, linesVisibilityByIndex, isLastChildRow]);
92
- (0, react_1.useEffect)(() => {
93
- if (!isMultiSelect || !isExpandable || !isRowsSelectionEnabled) {
94
- return;
95
- }
96
- if (isAllSubRowsSelected && !isRowSelected) {
97
- row.toggleSelected(true, {
98
- selectChildren: false
99
- });
100
- return;
101
- }
102
- if (isRowSelected && !isAllSubRowsSelected && isSomeSubRowSelected) {
103
- row.toggleSelected(false, {
104
- selectChildren: false
105
- });
106
- return;
107
- }
108
- }, [isAllSubRowsSelected, isSomeSubRowSelected, row, isRowSelected, isMultiSelect, isExpandable, isRowsSelectionEnabled]);
109
- const toggleClickHandler = (0, react_1.useCallback)(event => {
110
- event.stopPropagation();
88
+ return;
89
+ }
90
+ if (isRowSelected && !isAllSubRowsSelected && isSomeSubRowSelected) {
91
+ row.toggleSelected(false, {
92
+ selectChildren: false
93
+ });
94
+ return;
95
+ }
96
+ }, [isAllSubRowsSelected, isSomeSubRowSelected, row, isRowSelected, isMultiSelect, isExpandable, isRowsSelectionEnabled]);
97
+ const toggleClickHandler = (0, react_1.useCallback)(event => {
98
+ event.stopPropagation();
99
+ if (enableSelection) {
111
100
  if (isMultiSelect) {
112
101
  const shouldToggleOn = !isAllSubRowsSelected && !isRowSelected;
113
102
  const selectChildren = isAllSubRowsSelected || isSomeSubRowSelected || shouldToggleOn;
@@ -119,68 +108,84 @@ function getTreeColumnDef(_ref) {
119
108
  row.toggleSelected(!isRowSelected, {
120
109
  selectChildren: false
121
110
  });
122
- }, [isMultiSelect, row, isAllSubRowsSelected, isSomeSubRowSelected, isRowSelected]);
123
- const chevronClickHandler = (0, react_1.useCallback)(event => {
124
- event.stopPropagation();
125
- row.toggleExpanded();
126
- }, [row]);
127
- const value = typeof cell.row.original === 'object' && Object.hasOwn(cell.row.original, accessorKey) ?
128
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
129
- // @ts-ignore
130
- cell.row.original[accessorKey] : cell.getValue();
131
- return (0, jsx_runtime_1.jsx)("div", {
132
- role: 'presentation',
133
- "data-test-id": constants_1.TEST_IDS.tree.node,
134
- className: styles_module_scss_1.default.treeCellContainer,
135
- onClick: toggleClickHandler,
136
- children: (0, jsx_runtime_1.jsxs)("div", {
137
- className: styles_module_scss_1.default.treeCell,
138
- ref: ref,
139
- children: [lines, Boolean(parent) && (0, jsx_runtime_1.jsx)(TreeLine_1.TreeLine, {
140
- horizontal: true,
141
- visible: true
142
- }), isExpandable && (0, jsx_runtime_1.jsx)(button_1.ButtonFunction, {
143
- size: 'xs',
144
- "data-test-id": constants_1.TEST_IDS.tree.chevron,
145
- icon: (0, jsx_runtime_1.jsx)(icons_1.ChevronRightSVG, {}),
111
+ }
112
+ }, [isMultiSelect, row, isAllSubRowsSelected, isSomeSubRowSelected, isRowSelected]);
113
+ const chevronClickHandler = (0, react_1.useCallback)(event => {
114
+ event.stopPropagation();
115
+ row.toggleExpanded();
116
+ }, [row]);
117
+ const value = typeof cell.row.original === 'object' && Object.hasOwn(cell.row.original, accessorKey) ?
118
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
119
+ // @ts-ignore
120
+ cell.row.original[accessorKey] : cell.getValue();
121
+ return (0, jsx_runtime_1.jsx)("div", {
122
+ role: 'presentation',
123
+ "data-test-id": constants_1.TEST_IDS.tree.node,
124
+ className: styles_module_scss_1.default.treeCellContainer,
125
+ onClick: toggleClickHandler,
126
+ children: (0, jsx_runtime_1.jsxs)("div", {
127
+ className: styles_module_scss_1.default.treeCell,
128
+ ref: ref,
129
+ children: [lines, Boolean(parent) && (0, jsx_runtime_1.jsx)(TreeLine_1.TreeLine, {
130
+ horizontal: true,
131
+ visible: true
132
+ }), isExpandable && (0, jsx_runtime_1.jsx)(button_1.ButtonFunction, {
133
+ size: 'xs',
134
+ "data-test-id": constants_1.TEST_IDS.tree.chevron,
135
+ icon: (0, jsx_runtime_1.jsx)(icons_1.ChevronRightSVG, {}),
136
+ onClick: chevronClickHandler,
137
+ className: styles_module_scss_1.default.cellExpandButton,
138
+ "data-expanded": isExpanded || undefined
139
+ }), (0, jsx_runtime_1.jsxs)("div", {
140
+ className: styles_module_scss_1.default.treeNodeContent,
141
+ "data-disabled": !isRowsSelectionEnabled || undefined,
142
+ "data-selected": isRowSelected || undefined,
143
+ "data-multiselect": isMultiSelect || undefined,
144
+ children: [showToggle && (0, jsx_runtime_1.jsx)("div", {
145
+ tabIndex: -1,
146
+ className: styles_module_scss_1.default.treeCheckboxWrap,
147
+ children: isMultiSelect ? (0, jsx_runtime_1.jsx)(toggles_1.Checkbox, {
148
+ size: 's',
149
+ disabled: !isRowsSelectionEnabled,
150
+ checked: isRowSelected,
151
+ "data-test-id": constants_1.TEST_IDS.tree.checkbox,
152
+ indeterminate: isSomeSubRowSelected && !isAllSubRowsSelected
153
+ }) : (0, jsx_runtime_1.jsx)(toggles_1.Radio, {
154
+ size: 's',
155
+ disabled: !isRowsSelectionEnabled,
156
+ "data-test-id": constants_1.TEST_IDS.tree.radio,
157
+ checked: isRowSelected
158
+ })
159
+ }), (0, jsx_runtime_1.jsxs)("div", {
160
+ role: 'presentation',
146
161
  onClick: chevronClickHandler,
147
- className: styles_module_scss_1.default.cellExpandButton,
148
- "data-expanded": isExpanded || undefined
162
+ className: styles_module_scss_1.default.cellUserToggleIcon,
163
+ children: [isExpandable && isExpanded && expandedIcon, isExpandable && !isExpanded && collapsedIcon]
149
164
  }), (0, jsx_runtime_1.jsxs)("div", {
150
- className: styles_module_scss_1.default.treeNodeContent,
151
- "data-disabled": !isRowsSelectionEnabled || undefined,
152
- "data-selected": isRowSelected || undefined,
153
- "data-multiselect": isMultiSelect || undefined,
154
- children: [showToggle && (0, jsx_runtime_1.jsx)("div", {
155
- tabIndex: -1,
156
- className: styles_module_scss_1.default.treeCheckboxWrap,
157
- children: isMultiSelect ? (0, jsx_runtime_1.jsx)(toggles_1.Checkbox, {
158
- size: 's',
159
- disabled: !isRowsSelectionEnabled,
160
- checked: isRowSelected,
161
- "data-test-id": constants_1.TEST_IDS.tree.checkbox,
162
- indeterminate: isSomeSubRowSelected && !isAllSubRowsSelected
163
- }) : (0, jsx_runtime_1.jsx)(toggles_1.Radio, {
164
- size: 's',
165
- disabled: !isRowsSelectionEnabled,
166
- "data-test-id": constants_1.TEST_IDS.tree.radio,
167
- checked: isRowSelected
168
- })
169
- }), (0, jsx_runtime_1.jsxs)("div", {
170
- role: 'presentation',
171
- onClick: chevronClickHandler,
172
- className: styles_module_scss_1.default.cellUserToggleIcon,
173
- children: [isExpandable && isExpanded && expandedIcon, isExpandable && !isExpanded && collapsedIcon]
174
- }), (0, jsx_runtime_1.jsxs)("div", {
175
- role: 'presentation',
176
- className: styles_module_scss_1.default.userContent,
177
- children: [!isExpandable && icon, (0, jsx_runtime_1.jsx)(truncate_string_1.TruncateString, {
178
- text: value
179
- })]
165
+ role: 'presentation',
166
+ className: styles_module_scss_1.default.userContent,
167
+ children: [!isExpandable && icon, renderCell ? renderCell(ctx) : (0, jsx_runtime_1.jsx)(truncate_string_1.TruncateString, {
168
+ text: value
180
169
  })]
181
170
  })]
182
- })
183
- });
184
- }
171
+ })]
172
+ })
173
+ });
174
+ };
175
+ return {
176
+ id: constants_2.TREE_CELL_ID,
177
+ pinned: constants_1.COLUMN_PIN_POSITION.Left,
178
+ accessorKey,
179
+ noBodyCellPadding: true,
180
+ noHeaderCellPadding: false,
181
+ enableResizing: true,
182
+ size: 150,
183
+ maxSize: Number.MAX_SAFE_INTEGER,
184
+ meta: {
185
+ skipOnExport: false
186
+ },
187
+ enableSorting: false,
188
+ header,
189
+ cell
185
190
  };
186
191
  }
@@ -20,6 +20,7 @@
20
20
  }
21
21
 
22
22
  .cellUserToggleIcon{
23
+ cursor:pointer;
23
24
  display:flex;
24
25
  align-items:center;
25
26
  box-sizing:border-box;
@@ -3,6 +3,17 @@ import { ServerTableProps } from '../types';
3
3
  export declare function ServerTable<TData extends object, TFilters extends FiltersState = Record<string, unknown>>({ items, total, limit, offset, onChangePage, search: searchProp, pagination, columnFilters, manualSorting, manualPagination, manualFiltering, ...rest }: ServerTableProps<TData, TFilters>): import("react/jsx-runtime").JSX.Element;
4
4
  export declare namespace ServerTable {
5
5
  var getRowActionsColumnDef: typeof import("../../helperComponents").getRowActionsColumnDef;
6
- var statusAppearances: Record<string, string>;
6
+ var statusAppearances: {
7
+ readonly Primary: "primary";
8
+ readonly Neutral: "neutral";
9
+ readonly Red: "red";
10
+ readonly Orange: "orange";
11
+ readonly Yellow: "yellow";
12
+ readonly Green: "green";
13
+ readonly Blue: "blue";
14
+ readonly Violet: "violet";
15
+ readonly Pink: "pink";
16
+ readonly Loading: "loading";
17
+ };
7
18
  var getStatusColumnDef: typeof import("../../helperComponents").getStatusColumnDef;
8
19
  }
@@ -4,6 +4,17 @@ import { TableProps } from '../types';
4
4
  export declare function Table<TData extends object, TFilters extends FiltersState = Record<string, unknown>>({ data, rowPinning, columnDefinitions, keepPinnedRows, copyPinnedRows, enableSelectPinned, rowSelection: rowSelectionProp, search, sorting: sortingProp, columnFilters, pagination: paginationProp, className, onRowClick, onRefresh, pageSize, pageCount, loading, infiniteLoading, outline, moreActions, exportSettings, dataFiltered, dataError, noDataState, noResultsState, errorDataState, suppressToolbar, suppressSearch, toolbarAfter, suppressPagination, manualSorting, manualPagination: manualPaginationProp, manualFiltering, autoResetPageIndex, scrollRef, scrollContainerRef, getRowId, enableFuzzySearch, savedState, expanding, bulkActions: bulkActionsProp, rowAutoHeight, columnsSettings: columnsSettingsProp, ...rest }: TableProps<TData, TFilters>): import("react/jsx-runtime").JSX.Element;
5
5
  export declare namespace Table {
6
6
  var getStatusColumnDef: typeof import("../../helperComponents").getStatusColumnDef;
7
- var statusAppearances: Record<string, string>;
7
+ var statusAppearances: {
8
+ readonly Primary: "primary";
9
+ readonly Neutral: "neutral";
10
+ readonly Red: "red";
11
+ readonly Orange: "orange";
12
+ readonly Yellow: "yellow";
13
+ readonly Green: "green";
14
+ readonly Blue: "blue";
15
+ readonly Violet: "violet";
16
+ readonly Pink: "pink";
17
+ readonly Loading: "loading";
18
+ };
8
19
  var getRowActionsColumnDef: typeof import("../../helperComponents").getRowActionsColumnDef;
9
20
  }
@@ -141,7 +141,7 @@ export function Table(_a) {
141
141
  onRowSelectionChange,
142
142
  enableGrouping: true,
143
143
  enableRowSelection,
144
- enableMultiRowSelection: rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow,
144
+ enableMultiRowSelection: (rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.enable) && (rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow),
145
145
  enableFilters: true,
146
146
  getSubRows: expanding === null || expanding === void 0 ? void 0 : expanding.getSubRows,
147
147
  filterFromLeafRows: Boolean(expanding),
@@ -5,7 +5,7 @@ export function getTableColumnsDefinitions({ columnDefinitions, enableSelection,
5
5
  cols = [getSelectionCellColumnDef(enableSelectPinned), ...cols];
6
6
  }
7
7
  if (expanding) {
8
- cols = [getTreeColumnDef(expanding.expandingColumnDefinition), ...cols];
8
+ cols = [getTreeColumnDef(Object.assign(Object.assign({}, expanding.expandingColumnDefinition), { enableSelection })), ...cols];
9
9
  }
10
10
  return cols;
11
11
  }
@@ -1,2 +1,13 @@
1
- export declare const STATUS_APPEARANCE: Record<string, string>;
1
+ export declare const STATUS_APPEARANCE: {
2
+ readonly Primary: "primary";
3
+ readonly Neutral: "neutral";
4
+ readonly Red: "red";
5
+ readonly Orange: "orange";
6
+ readonly Yellow: "yellow";
7
+ readonly Green: "green";
8
+ readonly Blue: "blue";
9
+ readonly Violet: "violet";
10
+ readonly Pink: "pink";
11
+ readonly Loading: "loading";
12
+ };
2
13
  export declare const MIN_STATUS_CELL_SIZE = 16;
@@ -1,3 +1,4 @@
1
+ import { CellContext } from '@tanstack/react-table';
1
2
  import { ReactNode } from 'react';
2
3
  import { ColumnDefinition } from '../../../types';
3
4
  type BaseTreeColumnDef = {
@@ -14,15 +15,18 @@ type BaseTreeColumnDef = {
14
15
  };
15
16
  type TreeColumnDef = BaseTreeColumnDef & {
16
17
  header?: never;
17
- renderDescription?: never;
18
+ cell?: never;
18
19
  };
19
20
  type TreeColumnDefWithDescription<TData> = BaseTreeColumnDef & {
20
21
  /** Заголовок колонки */
21
- renderDescription?(cellValue: string, row: TData): string;
22
+ cell?(ctx: CellContext<TData, unknown>): ReactNode;
22
23
  /** Рендер функция заголовка колонки */
23
24
  header?: ColumnDefinition<TData>['header'];
24
25
  };
25
26
  export type TreeColumnDefinitionProps<TData> = TreeColumnDef | TreeColumnDefWithDescription<TData>;
27
+ type TreeColDefProps<TData> = TreeColumnDefinitionProps<TData> & {
28
+ enableSelection?: boolean;
29
+ };
26
30
  /** Вспомогательная функция для создания ячейки со статусом */
27
- export declare function getTreeColumnDef<TData>({ showToggle, icon, expandedIcon, collapsedIcon, header, accessorKey, }: TreeColumnDefinitionProps<TData>): ColumnDefinition<TData>;
31
+ export declare function getTreeColumnDef<TData>({ showToggle, icon, expandedIcon, collapsedIcon, header, accessorKey, cell: renderCell, enableSelection, }: TreeColDefProps<TData>): ColumnDefinition<TData>;
28
32
  export {};
@@ -10,7 +10,80 @@ import { TREE_CELL_ID } from './constants';
10
10
  import styles from './styles.module.css';
11
11
  import { TreeLine } from './TreeLine';
12
12
  /** Вспомогательная функция для создания ячейки со статусом */
13
- export function getTreeColumnDef({ showToggle = false, icon = _jsx(FileSVG, { size: 24 }), expandedIcon = _jsx(FolderOpenSVG, { size: 24 }), collapsedIcon = _jsx(FolderSVG, { size: 24 }), header, accessorKey, }) {
13
+ export function getTreeColumnDef({ showToggle = false, icon = _jsx(FileSVG, { size: 24 }), expandedIcon = _jsx(FolderOpenSVG, { size: 24 }), collapsedIcon = _jsx(FolderSVG, { size: 24 }), header, accessorKey, cell: renderCell, enableSelection, }) {
14
+ const cell = function TreeCell(ctx) {
15
+ var _a;
16
+ const { row, cell } = ctx;
17
+ const isExpanded = row.getIsExpanded();
18
+ const isExpandable = row.getCanExpand();
19
+ const isMultiSelect = row.getCanMultiSelect();
20
+ const parent = row.getParentRow();
21
+ const isRowsSelectionEnabled = row.getCanSelect();
22
+ const isAllSubRowsSelected = row.getIsAllSubRowsSelected();
23
+ const isSomeSubRowSelected = row.getIsSomeSelected();
24
+ const isRowSelected = row.getIsSelected();
25
+ const isLastChildRow = ((_a = parent === null || parent === void 0 ? void 0 : parent.subRows.at(-1)) === null || _a === void 0 ? void 0 : _a.id) === row.id;
26
+ const depth = row.depth;
27
+ const { ref } = useCellResize(TREE_CELL_ID, cell);
28
+ const linesVisibilityByIndex = useMemo(() => {
29
+ var _a;
30
+ const parents = [];
31
+ for (let i = depth; i >= 0; i--) {
32
+ parents[i] = i === depth ? row : (_a = parents.at(i + 1)) === null || _a === void 0 ? void 0 : _a.getParentRow();
33
+ }
34
+ return parents.map((parent, index) => {
35
+ var _a;
36
+ if (!parent || parents.length === index + 1)
37
+ return true;
38
+ const child = parents[index + 1];
39
+ return (child === null || child === void 0 ? void 0 : child.id) !== ((_a = parent.subRows.at(-1)) === null || _a === void 0 ? void 0 : _a.id) || (row === null || row === void 0 ? void 0 : row.id) === (child === null || child === void 0 ? void 0 : child.id);
40
+ });
41
+ }, [row, depth]);
42
+ const lines = useMemo(() => Array.from({ length: depth }, (_, index) => (_jsx(TreeLine, { visible: linesVisibilityByIndex.at(index), className: index !== 0 ? styles.line : styles.firstLine, halfHeight: index === depth - 1 && isLastChildRow }, index))), [depth, linesVisibilityByIndex, isLastChildRow]);
43
+ useEffect(() => {
44
+ if (!isMultiSelect || !isExpandable || !isRowsSelectionEnabled) {
45
+ return;
46
+ }
47
+ if (isAllSubRowsSelected && !isRowSelected) {
48
+ row.toggleSelected(true, { selectChildren: false });
49
+ return;
50
+ }
51
+ if (isRowSelected && !isAllSubRowsSelected && isSomeSubRowSelected) {
52
+ row.toggleSelected(false, { selectChildren: false });
53
+ return;
54
+ }
55
+ }, [
56
+ isAllSubRowsSelected,
57
+ isSomeSubRowSelected,
58
+ row,
59
+ isRowSelected,
60
+ isMultiSelect,
61
+ isExpandable,
62
+ isRowsSelectionEnabled,
63
+ ]);
64
+ const toggleClickHandler = useCallback(event => {
65
+ event.stopPropagation();
66
+ if (enableSelection) {
67
+ if (isMultiSelect) {
68
+ const shouldToggleOn = !isAllSubRowsSelected && !isRowSelected;
69
+ const selectChildren = isAllSubRowsSelected || isSomeSubRowSelected || shouldToggleOn;
70
+ row.toggleSelected(shouldToggleOn, { selectChildren });
71
+ return;
72
+ }
73
+ row.toggleSelected(!isRowSelected, { selectChildren: false });
74
+ }
75
+ }, [isMultiSelect, row, isAllSubRowsSelected, isSomeSubRowSelected, isRowSelected]);
76
+ const chevronClickHandler = useCallback(event => {
77
+ event.stopPropagation();
78
+ row.toggleExpanded();
79
+ }, [row]);
80
+ const value = typeof cell.row.original === 'object' && Object.hasOwn(cell.row.original, accessorKey)
81
+ ? // eslint-disable-next-line @typescript-eslint/ban-ts-comment
82
+ // @ts-ignore
83
+ cell.row.original[accessorKey]
84
+ : cell.getValue();
85
+ return (_jsx("div", { role: 'presentation', "data-test-id": TEST_IDS.tree.node, className: styles.treeCellContainer, onClick: toggleClickHandler, children: _jsxs("div", { className: styles.treeCell, ref: ref, children: [lines, Boolean(parent) && _jsx(TreeLine, { horizontal: true, visible: true }), isExpandable && (_jsx(ButtonFunction, { size: 'xs', "data-test-id": TEST_IDS.tree.chevron, icon: _jsx(ChevronRightSVG, {}), onClick: chevronClickHandler, className: styles.cellExpandButton, "data-expanded": isExpanded || undefined })), _jsxs("div", { className: styles.treeNodeContent, "data-disabled": !isRowsSelectionEnabled || undefined, "data-selected": isRowSelected || undefined, "data-multiselect": isMultiSelect || undefined, children: [showToggle && (_jsx("div", { tabIndex: -1, className: styles.treeCheckboxWrap, children: isMultiSelect ? (_jsx(Checkbox, { size: 's', disabled: !isRowsSelectionEnabled, checked: isRowSelected, "data-test-id": TEST_IDS.tree.checkbox, indeterminate: isSomeSubRowSelected && !isAllSubRowsSelected })) : (_jsx(Radio, { size: 's', disabled: !isRowsSelectionEnabled, "data-test-id": TEST_IDS.tree.radio, checked: isRowSelected })) })), _jsxs("div", { role: 'presentation', onClick: chevronClickHandler, className: styles.cellUserToggleIcon, children: [isExpandable && isExpanded && expandedIcon, isExpandable && !isExpanded && collapsedIcon] }), _jsxs("div", { role: 'presentation', className: styles.userContent, children: [!isExpandable && icon, renderCell ? renderCell(ctx) : _jsx(TruncateString, { text: value })] })] })] }) }));
86
+ };
14
87
  return {
15
88
  id: TREE_CELL_ID,
16
89
  pinned: COLUMN_PIN_POSITION.Left,
@@ -25,75 +98,6 @@ export function getTreeColumnDef({ showToggle = false, icon = _jsx(FileSVG, { si
25
98
  },
26
99
  enableSorting: false,
27
100
  header,
28
- cell: function TreeCell({ row, cell }) {
29
- var _a;
30
- const isExpanded = row.getIsExpanded();
31
- const isExpandable = row.getCanExpand();
32
- const isMultiSelect = row.getCanMultiSelect();
33
- const parent = row.getParentRow();
34
- const isRowsSelectionEnabled = row.getCanSelect();
35
- const isAllSubRowsSelected = row.getIsAllSubRowsSelected();
36
- const isSomeSubRowSelected = row.getIsSomeSelected();
37
- const isRowSelected = row.getIsSelected();
38
- const isLastChildRow = ((_a = parent === null || parent === void 0 ? void 0 : parent.subRows.at(-1)) === null || _a === void 0 ? void 0 : _a.id) === row.id;
39
- const depth = row.depth;
40
- const { ref } = useCellResize(TREE_CELL_ID, cell);
41
- const linesVisibilityByIndex = useMemo(() => {
42
- var _a;
43
- const parents = [];
44
- for (let i = depth; i >= 0; i--) {
45
- parents[i] = i === depth ? row : (_a = parents.at(i + 1)) === null || _a === void 0 ? void 0 : _a.getParentRow();
46
- }
47
- return parents.map((parent, index) => {
48
- var _a;
49
- if (!parent || parents.length === index + 1)
50
- return true;
51
- const child = parents[index + 1];
52
- return (child === null || child === void 0 ? void 0 : child.id) !== ((_a = parent.subRows.at(-1)) === null || _a === void 0 ? void 0 : _a.id) || (row === null || row === void 0 ? void 0 : row.id) === (child === null || child === void 0 ? void 0 : child.id);
53
- });
54
- }, [row, depth]);
55
- const lines = useMemo(() => Array.from({ length: depth }, (_, index) => (_jsx(TreeLine, { visible: linesVisibilityByIndex.at(index), className: index !== 0 ? styles.line : styles.firstLine, halfHeight: index === depth - 1 && isLastChildRow }, index))), [depth, linesVisibilityByIndex, isLastChildRow]);
56
- useEffect(() => {
57
- if (!isMultiSelect || !isExpandable || !isRowsSelectionEnabled) {
58
- return;
59
- }
60
- if (isAllSubRowsSelected && !isRowSelected) {
61
- row.toggleSelected(true, { selectChildren: false });
62
- return;
63
- }
64
- if (isRowSelected && !isAllSubRowsSelected && isSomeSubRowSelected) {
65
- row.toggleSelected(false, { selectChildren: false });
66
- return;
67
- }
68
- }, [
69
- isAllSubRowsSelected,
70
- isSomeSubRowSelected,
71
- row,
72
- isRowSelected,
73
- isMultiSelect,
74
- isExpandable,
75
- isRowsSelectionEnabled,
76
- ]);
77
- const toggleClickHandler = useCallback(event => {
78
- event.stopPropagation();
79
- if (isMultiSelect) {
80
- const shouldToggleOn = !isAllSubRowsSelected && !isRowSelected;
81
- const selectChildren = isAllSubRowsSelected || isSomeSubRowSelected || shouldToggleOn;
82
- row.toggleSelected(shouldToggleOn, { selectChildren });
83
- return;
84
- }
85
- row.toggleSelected(!isRowSelected, { selectChildren: false });
86
- }, [isMultiSelect, row, isAllSubRowsSelected, isSomeSubRowSelected, isRowSelected]);
87
- const chevronClickHandler = useCallback(event => {
88
- event.stopPropagation();
89
- row.toggleExpanded();
90
- }, [row]);
91
- const value = typeof cell.row.original === 'object' && Object.hasOwn(cell.row.original, accessorKey)
92
- ? // eslint-disable-next-line @typescript-eslint/ban-ts-comment
93
- // @ts-ignore
94
- cell.row.original[accessorKey]
95
- : cell.getValue();
96
- return (_jsx("div", { role: 'presentation', "data-test-id": TEST_IDS.tree.node, className: styles.treeCellContainer, onClick: toggleClickHandler, children: _jsxs("div", { className: styles.treeCell, ref: ref, children: [lines, Boolean(parent) && _jsx(TreeLine, { horizontal: true, visible: true }), isExpandable && (_jsx(ButtonFunction, { size: 'xs', "data-test-id": TEST_IDS.tree.chevron, icon: _jsx(ChevronRightSVG, {}), onClick: chevronClickHandler, className: styles.cellExpandButton, "data-expanded": isExpanded || undefined })), _jsxs("div", { className: styles.treeNodeContent, "data-disabled": !isRowsSelectionEnabled || undefined, "data-selected": isRowSelected || undefined, "data-multiselect": isMultiSelect || undefined, children: [showToggle && (_jsx("div", { tabIndex: -1, className: styles.treeCheckboxWrap, children: isMultiSelect ? (_jsx(Checkbox, { size: 's', disabled: !isRowsSelectionEnabled, checked: isRowSelected, "data-test-id": TEST_IDS.tree.checkbox, indeterminate: isSomeSubRowSelected && !isAllSubRowsSelected })) : (_jsx(Radio, { size: 's', disabled: !isRowsSelectionEnabled, "data-test-id": TEST_IDS.tree.radio, checked: isRowSelected })) })), _jsxs("div", { role: 'presentation', onClick: chevronClickHandler, className: styles.cellUserToggleIcon, children: [isExpandable && isExpanded && expandedIcon, isExpandable && !isExpanded && collapsedIcon] }), _jsxs("div", { role: 'presentation', className: styles.userContent, children: [!isExpandable && icon, _jsx(TruncateString, { text: value })] })] })] }) }));
97
- },
101
+ cell,
98
102
  };
99
103
  }
@@ -20,6 +20,7 @@
20
20
  }
21
21
 
22
22
  .cellUserToggleIcon{
23
+ cursor:pointer;
23
24
  display:flex;
24
25
  align-items:center;
25
26
  box-sizing:border-box;
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public"
5
5
  },
6
6
  "title": "Table",
7
- "version": "0.36.23",
7
+ "version": "0.36.24",
8
8
  "sideEffects": [
9
9
  "*.css",
10
10
  "*.woff",
@@ -66,5 +66,5 @@
66
66
  "peerDependencies": {
67
67
  "@snack-uikit/locale": "*"
68
68
  },
69
- "gitHead": "f40ab395048226e33e85848bbc5ad7e5964b4b5d"
69
+ "gitHead": "bb2179dfa0dd290a2942170857c5b190630a2ee0"
70
70
  }
@@ -260,7 +260,7 @@ export function Table<TData extends object, TFilters extends FiltersState = Reco
260
260
  onRowSelectionChange,
261
261
  enableGrouping: true,
262
262
  enableRowSelection,
263
- enableMultiRowSelection: rowSelectionProp?.multiRow,
263
+ enableMultiRowSelection: rowSelectionProp?.enable && rowSelectionProp?.multiRow,
264
264
  enableFilters: true,
265
265
  getSubRows: expanding?.getSubRows,
266
266
  filterFromLeafRows: Boolean(expanding),
@@ -20,7 +20,7 @@ export function getTableColumnsDefinitions<TData extends object>({
20
20
  cols = [getSelectionCellColumnDef(enableSelectPinned), ...cols];
21
21
  }
22
22
  if (expanding) {
23
- cols = [getTreeColumnDef(expanding.expandingColumnDefinition), ...cols];
23
+ cols = [getTreeColumnDef({ ...expanding.expandingColumnDefinition, enableSelection }), ...cols];
24
24
  }
25
25
  return cols;
26
26
  }
@@ -1,4 +1,4 @@
1
- export const STATUS_APPEARANCE: Record<string, string> = {
1
+ export const STATUS_APPEARANCE = {
2
2
  Primary: 'primary',
3
3
  Neutral: 'neutral',
4
4
  Red: 'red',
@@ -28,18 +28,22 @@ type BaseTreeColumnDef = {
28
28
 
29
29
  type TreeColumnDef = BaseTreeColumnDef & {
30
30
  header?: never;
31
- renderDescription?: never;
31
+ cell?: never;
32
32
  };
33
33
 
34
34
  type TreeColumnDefWithDescription<TData> = BaseTreeColumnDef & {
35
35
  /** Заголовок колонки */
36
- renderDescription?(cellValue: string, row: TData): string;
36
+ cell?(ctx: CellContext<TData, unknown>): ReactNode;
37
37
  /** Рендер функция заголовка колонки */
38
38
  header?: ColumnDefinition<TData>['header'];
39
39
  };
40
40
 
41
41
  export type TreeColumnDefinitionProps<TData> = TreeColumnDef | TreeColumnDefWithDescription<TData>;
42
42
 
43
+ type TreeColDefProps<TData> = TreeColumnDefinitionProps<TData> & {
44
+ enableSelection?: boolean;
45
+ };
46
+
43
47
  /** Вспомогательная функция для создания ячейки со статусом */
44
48
  export function getTreeColumnDef<TData>({
45
49
  showToggle = false,
@@ -48,89 +52,79 @@ export function getTreeColumnDef<TData>({
48
52
  collapsedIcon = <FolderSVG size={24} />,
49
53
  header,
50
54
  accessorKey,
51
- }: TreeColumnDefinitionProps<TData>): ColumnDefinition<TData> {
52
- return {
53
- id: TREE_CELL_ID,
54
- pinned: COLUMN_PIN_POSITION.Left,
55
- accessorKey,
56
- noBodyCellPadding: true,
57
- noHeaderCellPadding: false,
58
- enableResizing: true,
59
- size: 150,
60
- maxSize: Number.MAX_SAFE_INTEGER,
61
- meta: {
62
- skipOnExport: false,
63
- },
64
- enableSorting: false,
65
- header,
66
- cell: function TreeCell<TData>({ row, cell }: CellContext<TData, unknown>) {
67
- const isExpanded = row.getIsExpanded();
68
- const isExpandable = row.getCanExpand();
69
- const isMultiSelect = row.getCanMultiSelect();
70
- const parent = row.getParentRow();
71
- const isRowsSelectionEnabled = row.getCanSelect();
72
- const isAllSubRowsSelected = row.getIsAllSubRowsSelected();
73
- const isSomeSubRowSelected = row.getIsSomeSelected();
74
- const isRowSelected = row.getIsSelected();
75
- const isLastChildRow = parent?.subRows.at(-1)?.id === row.id;
76
- const depth = row.depth;
77
- const { ref } = useCellResize(TREE_CELL_ID, cell);
78
-
79
- const linesVisibilityByIndex = useMemo(() => {
80
- const parents: (Row<TData> | undefined)[] = [];
81
- for (let i = depth; i >= 0; i--) {
82
- parents[i] = i === depth ? row : parents.at(i + 1)?.getParentRow();
83
- }
84
-
85
- return parents.map((parent, index) => {
86
- if (!parent || parents.length === index + 1) return true;
87
- const child = parents[index + 1];
88
-
89
- return child?.id !== parent.subRows.at(-1)?.id || row?.id === child?.id;
90
- });
91
- }, [row, depth]);
92
-
93
- const lines = useMemo(
94
- () =>
95
- Array.from({ length: depth }, (_, index) => (
96
- <TreeLine
97
- key={index}
98
- visible={linesVisibilityByIndex.at(index)}
99
- className={index !== 0 ? styles.line : styles.firstLine}
100
- halfHeight={index === depth - 1 && isLastChildRow}
101
- />
102
- )),
103
- [depth, linesVisibilityByIndex, isLastChildRow],
104
- );
105
-
106
- useEffect(() => {
107
- if (!isMultiSelect || !isExpandable || !isRowsSelectionEnabled) {
108
- return;
109
- }
110
-
111
- if (isAllSubRowsSelected && !isRowSelected) {
112
- row.toggleSelected(true, { selectChildren: false });
113
- return;
114
- }
115
-
116
- if (isRowSelected && !isAllSubRowsSelected && isSomeSubRowSelected) {
117
- row.toggleSelected(false, { selectChildren: false });
118
- return;
119
- }
120
- }, [
121
- isAllSubRowsSelected,
122
- isSomeSubRowSelected,
123
- row,
124
- isRowSelected,
125
- isMultiSelect,
126
- isExpandable,
127
- isRowsSelectionEnabled,
128
- ]);
129
-
130
- const toggleClickHandler: MouseEventHandler<HTMLElement> = useCallback(
131
- event => {
132
- event.stopPropagation();
133
-
55
+ cell: renderCell,
56
+ enableSelection,
57
+ }: TreeColDefProps<TData>): ColumnDefinition<TData> {
58
+ const cell: ColumnDefinition<TData>['cell'] = function TreeCell(ctx) {
59
+ const { row, cell } = ctx;
60
+ const isExpanded = row.getIsExpanded();
61
+ const isExpandable = row.getCanExpand();
62
+ const isMultiSelect = row.getCanMultiSelect();
63
+ const parent = row.getParentRow();
64
+ const isRowsSelectionEnabled = row.getCanSelect();
65
+ const isAllSubRowsSelected = row.getIsAllSubRowsSelected();
66
+ const isSomeSubRowSelected = row.getIsSomeSelected();
67
+ const isRowSelected = row.getIsSelected();
68
+ const isLastChildRow = parent?.subRows.at(-1)?.id === row.id;
69
+ const depth = row.depth;
70
+ const { ref } = useCellResize(TREE_CELL_ID, cell);
71
+
72
+ const linesVisibilityByIndex = useMemo(() => {
73
+ const parents: (Row<TData> | undefined)[] = [];
74
+ for (let i = depth; i >= 0; i--) {
75
+ parents[i] = i === depth ? row : parents.at(i + 1)?.getParentRow();
76
+ }
77
+
78
+ return parents.map((parent, index) => {
79
+ if (!parent || parents.length === index + 1) return true;
80
+ const child = parents[index + 1];
81
+
82
+ return child?.id !== parent.subRows.at(-1)?.id || row?.id === child?.id;
83
+ });
84
+ }, [row, depth]);
85
+
86
+ const lines = useMemo(
87
+ () =>
88
+ Array.from({ length: depth }, (_, index) => (
89
+ <TreeLine
90
+ key={index}
91
+ visible={linesVisibilityByIndex.at(index)}
92
+ className={index !== 0 ? styles.line : styles.firstLine}
93
+ halfHeight={index === depth - 1 && isLastChildRow}
94
+ />
95
+ )),
96
+ [depth, linesVisibilityByIndex, isLastChildRow],
97
+ );
98
+
99
+ useEffect(() => {
100
+ if (!isMultiSelect || !isExpandable || !isRowsSelectionEnabled) {
101
+ return;
102
+ }
103
+
104
+ if (isAllSubRowsSelected && !isRowSelected) {
105
+ row.toggleSelected(true, { selectChildren: false });
106
+ return;
107
+ }
108
+
109
+ if (isRowSelected && !isAllSubRowsSelected && isSomeSubRowSelected) {
110
+ row.toggleSelected(false, { selectChildren: false });
111
+ return;
112
+ }
113
+ }, [
114
+ isAllSubRowsSelected,
115
+ isSomeSubRowSelected,
116
+ row,
117
+ isRowSelected,
118
+ isMultiSelect,
119
+ isExpandable,
120
+ isRowsSelectionEnabled,
121
+ ]);
122
+
123
+ const toggleClickHandler: MouseEventHandler<HTMLElement> = useCallback(
124
+ event => {
125
+ event.stopPropagation();
126
+
127
+ if (enableSelection) {
134
128
  if (isMultiSelect) {
135
129
  const shouldToggleOn = !isAllSubRowsSelected && !isRowSelected;
136
130
  const selectChildren = isAllSubRowsSelected || isSomeSubRowSelected || shouldToggleOn;
@@ -141,83 +135,101 @@ export function getTreeColumnDef<TData>({
141
135
  }
142
136
 
143
137
  row.toggleSelected(!isRowSelected, { selectChildren: false });
144
- },
145
- [isMultiSelect, row, isAllSubRowsSelected, isSomeSubRowSelected, isRowSelected],
146
- );
147
-
148
- const chevronClickHandler: MouseEventHandler<HTMLElement> = useCallback(
149
- event => {
150
- event.stopPropagation();
151
- row.toggleExpanded();
152
- },
153
- [row],
154
- );
155
-
156
- const value =
157
- typeof cell.row.original === 'object' && Object.hasOwn(cell.row.original as object, accessorKey)
158
- ? // eslint-disable-next-line @typescript-eslint/ban-ts-comment
159
- // @ts-ignore
160
- cell.row.original[accessorKey]
161
- : cell.getValue<string>();
162
-
163
- return (
164
- <div
165
- role={'presentation'}
166
- data-test-id={TEST_IDS.tree.node}
167
- className={styles.treeCellContainer}
168
- onClick={toggleClickHandler}
169
- >
170
- <div className={styles.treeCell} ref={ref}>
171
- {lines}
172
- {Boolean(parent) && <TreeLine horizontal visible />}
173
- {isExpandable && (
174
- <ButtonFunction
175
- size='xs'
176
- data-test-id={TEST_IDS.tree.chevron}
177
- icon={<ChevronRightSVG />}
178
- onClick={chevronClickHandler}
179
- className={styles.cellExpandButton}
180
- data-expanded={isExpanded || undefined}
181
- />
182
- )}
183
- <div
184
- className={styles.treeNodeContent}
185
- data-disabled={!isRowsSelectionEnabled || undefined}
186
- data-selected={isRowSelected || undefined}
187
- data-multiselect={isMultiSelect || undefined}
188
- >
189
- {showToggle && (
190
- <div tabIndex={-1} className={styles.treeCheckboxWrap}>
191
- {isMultiSelect ? (
192
- <Checkbox
193
- size='s'
194
- disabled={!isRowsSelectionEnabled}
195
- checked={isRowSelected}
196
- data-test-id={TEST_IDS.tree.checkbox}
197
- indeterminate={isSomeSubRowSelected && !isAllSubRowsSelected}
198
- />
199
- ) : (
200
- <Radio
201
- size='s'
202
- disabled={!isRowsSelectionEnabled}
203
- data-test-id={TEST_IDS.tree.radio}
204
- checked={isRowSelected}
205
- />
206
- )}
207
- </div>
208
- )}
209
- <div role='presentation' onClick={chevronClickHandler} className={styles.cellUserToggleIcon}>
210
- {isExpandable && isExpanded && expandedIcon}
211
- {isExpandable && !isExpanded && collapsedIcon}
212
- </div>
213
- <div role='presentation' className={styles.userContent}>
214
- {!isExpandable && icon}
215
- <TruncateString text={value} />
138
+ }
139
+ },
140
+ [isMultiSelect, row, isAllSubRowsSelected, isSomeSubRowSelected, isRowSelected],
141
+ );
142
+
143
+ const chevronClickHandler: MouseEventHandler<HTMLElement> = useCallback(
144
+ event => {
145
+ event.stopPropagation();
146
+ row.toggleExpanded();
147
+ },
148
+ [row],
149
+ );
150
+
151
+ const value =
152
+ typeof cell.row.original === 'object' && Object.hasOwn(cell.row.original as object, accessorKey)
153
+ ? // eslint-disable-next-line @typescript-eslint/ban-ts-comment
154
+ // @ts-ignore
155
+ cell.row.original[accessorKey]
156
+ : cell.getValue<string>();
157
+
158
+ return (
159
+ <div
160
+ role={'presentation'}
161
+ data-test-id={TEST_IDS.tree.node}
162
+ className={styles.treeCellContainer}
163
+ onClick={toggleClickHandler}
164
+ >
165
+ <div className={styles.treeCell} ref={ref}>
166
+ {lines}
167
+ {Boolean(parent) && <TreeLine horizontal visible />}
168
+ {isExpandable && (
169
+ <ButtonFunction
170
+ size='xs'
171
+ data-test-id={TEST_IDS.tree.chevron}
172
+ icon={<ChevronRightSVG />}
173
+ onClick={chevronClickHandler}
174
+ className={styles.cellExpandButton}
175
+ data-expanded={isExpanded || undefined}
176
+ />
177
+ )}
178
+ <div
179
+ className={styles.treeNodeContent}
180
+ data-disabled={!isRowsSelectionEnabled || undefined}
181
+ data-selected={isRowSelected || undefined}
182
+ data-multiselect={isMultiSelect || undefined}
183
+ >
184
+ {showToggle && (
185
+ <div tabIndex={-1} className={styles.treeCheckboxWrap}>
186
+ {isMultiSelect ? (
187
+ <Checkbox
188
+ size='s'
189
+ disabled={!isRowsSelectionEnabled}
190
+ checked={isRowSelected}
191
+ data-test-id={TEST_IDS.tree.checkbox}
192
+ indeterminate={isSomeSubRowSelected && !isAllSubRowsSelected}
193
+ />
194
+ ) : (
195
+ <Radio
196
+ size='s'
197
+ disabled={!isRowsSelectionEnabled}
198
+ data-test-id={TEST_IDS.tree.radio}
199
+ checked={isRowSelected}
200
+ />
201
+ )}
216
202
  </div>
203
+ )}
204
+ <div role='presentation' onClick={chevronClickHandler} className={styles.cellUserToggleIcon}>
205
+ {isExpandable && isExpanded && expandedIcon}
206
+ {isExpandable && !isExpanded && collapsedIcon}
207
+ </div>
208
+ <div role='presentation' className={styles.userContent}>
209
+ {!isExpandable && icon}
210
+
211
+ {renderCell ? renderCell(ctx) : <TruncateString text={value} />}
217
212
  </div>
218
213
  </div>
219
214
  </div>
220
- );
215
+ </div>
216
+ );
217
+ };
218
+
219
+ return {
220
+ id: TREE_CELL_ID,
221
+ pinned: COLUMN_PIN_POSITION.Left,
222
+ accessorKey,
223
+ noBodyCellPadding: true,
224
+ noHeaderCellPadding: false,
225
+ enableResizing: true,
226
+ size: 150,
227
+ maxSize: Number.MAX_SAFE_INTEGER,
228
+ meta: {
229
+ skipOnExport: false,
221
230
  },
231
+ enableSorting: false,
232
+ header,
233
+ cell,
222
234
  };
223
235
  }
@@ -20,6 +20,7 @@
20
20
  }
21
21
 
22
22
  .cellUserToggleIcon {
23
+ cursor: pointer;
23
24
  display: flex;
24
25
  align-items: center;
25
26
  box-sizing: border-box;