@snack-uikit/table 0.37.34 → 0.37.36-preview-ae5449cf.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,22 @@
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
+ ## <small>0.37.35 (2026-02-18)</small>
7
+
8
+ ### Only dependencies have been changed
9
+ * [@snack-uikit/chips@0.28.14]($PUBLIC_PROJECT_URL/blob/master/packages/chips/CHANGELOG.md)
10
+ * [@snack-uikit/icons@0.27.6]($PUBLIC_PROJECT_URL/blob/master/packages/icons/CHANGELOG.md)
11
+ * [@snack-uikit/info-block@0.6.37]($PUBLIC_PROJECT_URL/blob/master/packages/info-block/CHANGELOG.md)
12
+ * [@snack-uikit/list@0.32.13]($PUBLIC_PROJECT_URL/blob/master/packages/list/CHANGELOG.md)
13
+ * [@snack-uikit/pagination@0.10.23]($PUBLIC_PROJECT_URL/blob/master/packages/pagination/CHANGELOG.md)
14
+ * [@snack-uikit/toggles@0.13.25]($PUBLIC_PROJECT_URL/blob/master/packages/toggles/CHANGELOG.md)
15
+ * [@snack-uikit/toolbar@0.14.18]($PUBLIC_PROJECT_URL/blob/master/packages/toolbar/CHANGELOG.md)
16
+ * [@snack-uikit/truncate-string@0.7.8]($PUBLIC_PROJECT_URL/blob/master/packages/truncate-string/CHANGELOG.md)
17
+
18
+
19
+
20
+
21
+
6
22
  ## <small>0.37.34 (2026-02-16)</small>
7
23
 
8
24
  * feat(LK-7075): added expanding column minsize param ([a216a36](https://github.com/cloud-ru-tech/snack-uikit/commit/a216a36))
package/README.md CHANGED
@@ -117,7 +117,7 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
117
117
  | name | type | default value | description |
118
118
  |------|------|---------------|-------------|
119
119
  | columnSettings* | `{ enableDrag?: boolean; enableSettingsMenu?: boolean; }` | - | |
120
- | savedState* | `{ id: string; filterQueryKey?: string; resize?: boolean; columnSettings?: boolean; }` | - | |
120
+ | savedState* | `Pick<ToolbarPersistConfig<Record<string, unknown>>, "serializer" \| "parser"> & { id: string; filterQueryKey?: string; resize?: boolean; columnSettings?: boolean; }` | - | |
121
121
  | tableColumns* | `ColumnDefinition<TData>[]` | - | |
122
122
  ## useColumnSettings
123
123
  ### Props
@@ -125,7 +125,7 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
125
125
  |------|------|---------------|-------------|
126
126
  | pinnedGroups* | `PinnedGroupsState<TData>` | - | |
127
127
  | columnDefinitions* | `ColumnDefinition<TData>[]` | - | Определение внешнего вида и функционала колонок |
128
- | savedState | `{ id: string; filterQueryKey?: string; resize?: boolean; columnSettings?: boolean; }` | - | Конфиг для сохранения состояния в localStorage и queryParams. <br> Поле id должно быть уникальным для разных таблиц в рамках приложения. <br> Для корректной работы необходимо наличие id в конфиге columnDefinitions |
128
+ | savedState | `Pick<ToolbarPersistConfig<TFilters>, "serializer" \| "parser"> & { id: string; filterQueryKey?: string; resize?: boolean; columnSettings?: boolean; }` | - | Конфиг для сохранения состояния в localStorage и queryParams. <br> Поле id должно быть уникальным для разных таблиц в рамках приложения. <br> Для корректной работы необходимо наличие id в конфиге columnDefinitions |
129
129
  | columnsSettings | `{ enableDrag?: boolean; enableSettingsMenu?: boolean; }` | - | Параметры отвечают за настройки колонок <br> <strong>enableDrag</strong>: Включение сортировки порядка столбцов вручную перетаскиванием <br> <strong>enableSettingsMenu</strong>: Включение настроек показа колонок <br> |
130
130
  | rowSelection | `{ initialState?: RowSelectionState; state?: RowSelectionState; enable?: boolean \| ((row: Row<TData>) => boolean); multiRow?: boolean; onChange?(state: RowSelectionState): void; appearance?: RowAppearance; }` | - | Параметры отвечают за возможность выбора строк <br> <strong>initialState</strong>: Начальное состояние выбора строк <br> <strong>state</strong>: Состояние выбора строк, жестко устанавливаемое снаружи <br> <strong>enable</strong>: Колбэк определяющий можно ли выбрать строку <br> <strong>appearance</strong>: Режим отображения недоступной для выбора строки. Опции: RowAppearance.Disabled (по дефолту) - серый фон, чекбокс/радиобаттон скрыт, RowAppearance.HideToggler - обычный фон, чекбокс/радиобаттон скрыт <br> <strong>multiRow</strong>: Мульти-выбор строк (включен по-умолчанию, когда включается выбор) <br> <strong>onChange</strong>: Колбэк на выбор строк |
131
131
  | expanding | `{ getSubRows: (element: TData) => TData[]; expandingColumnDefinition: TreeColumnDefinitionProps<TData>; state?: ExpandedState; onChange?(state: ExpandedState): void; }` | - | Параметр отвечает за общие настройки раскрывающихся строк <br> <strong>getSubRows</strong>: Метод отвечает за получение дочерних строк <br> <strong>expandingColumnDefinition</strong>: Описание колонок для дочерних строк <br> <strong>state</strong>: Состояние открытых строк <br> <strong>onExpandedChange</strong>: Колбэк на раскрытие строк <br> |
@@ -214,7 +214,7 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
214
214
  | scrollRef | `RefObject<HTMLElement>` | - | Ссылка на элемент, обозначающий самый конец прокручиваемого списка |
215
215
  | scrollContainerRef | `RefObject<HTMLElement>` | - | Ссылка на контейнер, который скроллится |
216
216
  | rowPinning | `Pick<RowPinningState, "top">` | { top: [], } | Определение какие строки должны быть закреплены в таблице |
217
- | savedState | `{ id: string; filterQueryKey?: string; resize?: boolean; columnSettings?: boolean; }` | - | Конфиг для сохранения состояния в localStorage и queryParams. <br> Поле id должно быть уникальным для разных таблиц в рамках приложения. <br> Для корректной работы необходимо наличие id в конфиге columnDefinitions |
217
+ | savedState | `Pick<ToolbarPersistConfig<TFilters>, "serializer" \| "parser"> & { id: string; filterQueryKey?: string; resize?: boolean; columnSettings?: boolean; }` | - | Конфиг для сохранения состояния в localStorage и queryParams. <br> Поле id должно быть уникальным для разных таблиц в рамках приложения. <br> Для корректной работы необходимо наличие id в конфиге columnDefinitions |
218
218
  | getRowBackgroundColor | `(data: TData) => TableRowColor` | - | Функция для определения цвета фона строки на основе данных строки @param data - данные строки таблицы @returns цвет фона строки или undefined, если цвет не должен применяться |
219
219
  | pagination | `{ state?: PaginationState; options?: number[]; optionsLabel?: string; onChange?(state: PaginationState): void; optionsRender?(value: string \| number, idx: number): string \| number; }` | 'Rows volume: ' <br> <strong>onChange</strong>: Колбэк на изменение пагинации | Параметры отвечают за пагинацию в таблице <br> <strong>state</strong>: Состояние строки поиска, жестко устанавливаемое снаружи <br> <strong>options</strong>: Варианты в выпадающем селекторе для установки кол-ва строк на страницу <br> <strong>optionsLabel</strong>: Текст для селектора кол-ва строк на страницу |
220
220
  | autoResetPageIndex | `boolean` | - | Автоматический сброс пагинации к первой странице при изменении данных или состояния (e.g фильтры, сортировки, и т.д) |
@@ -251,7 +251,7 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
251
251
  |------|------|---------------|-------------|
252
252
  | onChangePage* | `(offset: number, limit: number) => void` | - | |
253
253
  | columnDefinitions* | `ColumnDefinition<TData>[]` | - | Определение внешнего вида и функционала колонок |
254
- | savedState | `{ id: string; filterQueryKey?: string; resize?: boolean; columnSettings?: boolean; }` | - | Конфиг для сохранения состояния в localStorage и queryParams. <br> Поле id должно быть уникальным для разных таблиц в рамках приложения. <br> Для корректной работы необходимо наличие id в конфиге columnDefinitions |
254
+ | savedState | `Pick<ToolbarPersistConfig<TFilters>, "serializer" \| "parser"> & { id: string; filterQueryKey?: string; resize?: boolean; columnSettings?: boolean; }` | - | Конфиг для сохранения состояния в localStorage и queryParams. <br> Поле id должно быть уникальным для разных таблиц в рамках приложения. <br> Для корректной работы необходимо наличие id в конфиге columnDefinitions |
255
255
  | columnsSettings | `{ enableDrag?: boolean; enableSettingsMenu?: boolean; }` | - | Параметры отвечают за настройки колонок <br> <strong>enableDrag</strong>: Включение сортировки порядка столбцов вручную перетаскиванием <br> <strong>enableSettingsMenu</strong>: Включение настроек показа колонок <br> |
256
256
  | rowSelection | `{ initialState?: RowSelectionState; state?: RowSelectionState; enable?: boolean \| ((row: Row<TData>) => boolean); multiRow?: boolean; onChange?(state: RowSelectionState): void; appearance?: RowAppearance; }` | - | Параметры отвечают за возможность выбора строк <br> <strong>initialState</strong>: Начальное состояние выбора строк <br> <strong>state</strong>: Состояние выбора строк, жестко устанавливаемое снаружи <br> <strong>enable</strong>: Колбэк определяющий можно ли выбрать строку <br> <strong>appearance</strong>: Режим отображения недоступной для выбора строки. Опции: RowAppearance.Disabled (по дефолту) - серый фон, чекбокс/радиобаттон скрыт, RowAppearance.HideToggler - обычный фон, чекбокс/радиобаттон скрыт <br> <strong>multiRow</strong>: Мульти-выбор строк (включен по-умолчанию, когда включается выбор) <br> <strong>onChange</strong>: Колбэк на выбор строк |
257
257
  | expanding | `{ getSubRows: (element: TData) => TData[]; expandingColumnDefinition: TreeColumnDefinitionProps<TData>; state?: ExpandedState; onChange?(state: ExpandedState): void; }` | - | Параметр отвечает за общие настройки раскрывающихся строк <br> <strong>getSubRows</strong>: Метод отвечает за получение дочерних строк <br> <strong>expandingColumnDefinition</strong>: Описание колонок для дочерних строк <br> <strong>state</strong>: Состояние открытых строк <br> <strong>onExpandedChange</strong>: Колбэк на раскрытие строк <br> |
@@ -112,7 +112,7 @@ function Table(_a) {
112
112
  const isPaginationValid = (0, validators_1.validatePaging)(dataAsSettings === null || dataAsSettings === void 0 ? void 0 : dataAsSettings.pagination);
113
113
  const isSortingValid = (0, validators_1.validateSorting)(dataAsSettings === null || dataAsSettings === void 0 ? void 0 : dataAsSettings.ordering);
114
114
  const isSearchValid = !(dataAsSettings === null || dataAsSettings === void 0 ? void 0 : dataAsSettings.search) || typeof (dataAsSettings === null || dataAsSettings === void 0 ? void 0 : dataAsSettings.search) === 'string';
115
- const isFilterValid = Boolean((columnFilters === null || columnFilters === void 0 ? void 0 : columnFilters.filters) && (0, validators_1.validateFilter)(dataAsSettings.filter, columnFilters.filters));
115
+ const isFilterValid = !(columnFilters === null || columnFilters === void 0 ? void 0 : columnFilters.filters) || Boolean((0, validators_1.validateFilter)(dataAsSettings.filter, columnFilters.filters));
116
116
  return isPaginationValid && isSortingValid && isSearchValid && isFilterValid;
117
117
  }, [columnFilters === null || columnFilters === void 0 ? void 0 : columnFilters.filters]);
118
118
  const enableSelection = Boolean(rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.enable);
@@ -175,8 +175,8 @@ function Table(_a) {
175
175
  if ((rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.enable) !== undefined) {
176
176
  isCurrentRowSelected = typeof rowSelectionProp.enable === 'boolean' ? rowSelectionProp.enable : rowSelectionProp.enable(row);
177
177
  }
178
- return isParentSelected && isCurrentRowSelected;
179
- }, [rowSelectionProp]);
178
+ return isParentSelected && isCurrentRowSelected && (row.getIsPinned() && enableSelectPinned || !row.getIsPinned());
179
+ }, [rowSelectionProp, enableSelectPinned]);
180
180
  const table = (0, react_table_1.useReactTable)({
181
181
  data,
182
182
  columns: enabledTableColumns,
@@ -266,22 +266,11 @@ function Table(_a) {
266
266
  })) : undefined, [bulkActionsProp, enableSelection, table]);
267
267
  const isAllRowsMode = toolbarCheckBoxMode === types_1.ToolbarCheckBoxMode.AllRows;
268
268
  const handleOnToolbarCheck = (0, react_1.useCallback)(() => {
269
- if (!loading && !enableSelectPinned && table.getTopRows().length) {
270
- const centerRows = table.getCenterRows();
271
- const isSomeRowsSelected = isAllRowsMode ? table.getIsSomeRowsSelected() : table.getIsSomePageRowsSelected();
272
- const isAllCenterRowsSelected = centerRows.every(row => row.getIsSelected());
273
- if (isAllCenterRowsSelected) {
274
- table.resetRowSelection();
275
- return;
276
- }
277
- centerRows.forEach(row => row.toggleSelected(isSomeRowsSelected ? true : undefined));
278
- return;
279
- }
280
269
  if (!loading && (rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow)) {
281
270
  isAllRowsMode ? table.toggleAllRowsSelected() : table.toggleAllPageRowsSelected();
282
271
  return;
283
272
  }
284
- }, [isAllRowsMode, loading, rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow, table, enableSelectPinned]);
273
+ }, [isAllRowsMode, loading, rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow, table]);
285
274
  const columnSizeVarsRef = (0, react_1.useRef)();
286
275
  const headers = table.getFlatHeaders();
287
276
  const columnSizes = (0, react_1.useMemo)(() => {
@@ -418,6 +407,8 @@ function Table(_a) {
418
407
  filter,
419
408
  search: globalFilter || ''
420
409
  },
410
+ serializer: savedState.serializer,
411
+ parser: savedState.parser,
421
412
  onLoad: state => {
422
413
  state.pagination && onPaginationChange((0, mappers_1.mapPaginationToTableState)(state.pagination));
423
414
  state.search && onGlobalFilterChange(state.search);
@@ -493,7 +484,7 @@ function Table(_a) {
493
484
  rowAutoHeight: rowAutoHeight,
494
485
  columnOrder: columnOrder,
495
486
  enableColumnsOrderSortByDrag: enableColumnsOrderSortByDrag,
496
- disabledRowAppearance: rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.appearance
487
+ disabledRowAppearance: types_1.RowAppearance.HideToggler
497
488
  }, row.id))
498
489
  }) : null, centerRows.map(row => (0, jsx_runtime_1.jsx)(helperComponents_1.BodyRow, {
499
490
  row: row,
@@ -4,7 +4,15 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.validateFilter = exports.validateSorting = exports.validatePaging = void 0;
7
- const validatePaging = value => typeof (value === null || value === void 0 ? void 0 : value.limit) === 'number' && typeof (value === null || value === void 0 ? void 0 : value.offset) === 'number';
7
+ const validatePaging = value => {
8
+ if (!value) {
9
+ return true;
10
+ }
11
+ if (typeof value !== 'object') {
12
+ return false;
13
+ }
14
+ return 'limit' in value && typeof value.limit === 'number' && 'offset' in value && typeof value.offset === 'number';
15
+ };
8
16
  exports.validatePaging = validatePaging;
9
17
  const validateSorting = value => !value || value.every(column => typeof (column === null || column === void 0 ? void 0 : column.field) === 'string' && typeof (column === null || column === void 0 ? void 0 : column.direction) === 'string');
10
18
  exports.validateSorting = validateSorting;
@@ -1,7 +1,7 @@
1
1
  import { PaginationState, Row, RowPinningState, RowSelectionOptions, RowSelectionState, SortingState } from '@tanstack/react-table';
2
2
  import { ReactNode, RefObject } from 'react';
3
3
  import { FiltersState } from '@snack-uikit/chips';
4
- import { FilterRow, ToolbarProps } from '@snack-uikit/toolbar';
4
+ import { FilterRow, ToolbarPersistConfig, ToolbarProps } from '@snack-uikit/toolbar';
5
5
  import { ValueOf, WithSupportProps } from '@snack-uikit/utils';
6
6
  import { TABLE_ROW_COLOR } from '../constants';
7
7
  import { EmptyStateProps, ExportButtonProps, RowClickHandler, TreeColumnDefinitionProps } from '../helperComponents';
@@ -144,7 +144,7 @@ type BaseTableProps<TData extends object, TFilters extends FiltersState = Record
144
144
  * Поле id должно быть уникальным для разных таблиц в рамках приложения. <br>
145
145
  * Для корректной работы необходимо наличие id в конфиге columnDefinitions
146
146
  * */
147
- savedState?: {
147
+ savedState?: Pick<ToolbarPersistConfig<TFilters>, 'serializer' | 'parser'> & {
148
148
  id: string;
149
149
  filterQueryKey?: string;
150
150
  resize?: boolean;
@@ -110,18 +110,18 @@
110
110
  .bodyRow[data-clickable]{
111
111
  cursor:pointer;
112
112
  }
113
- .bodyRow:not([data-disabled]):hover::before{
113
+ .bodyRow:not([data-row-appearance=disabled]):hover::before{
114
114
  height:0;
115
115
  }
116
- .bodyRow:not([data-disabled]):not([data-selected]):hover, .bodyRow:not([data-disabled]):not([data-selected])[data-actions-opened]{
116
+ .bodyRow:not([data-row-appearance=disabled]):not([data-selected]):hover, .bodyRow:not([data-row-appearance=disabled]):not([data-selected])[data-actions-opened]{
117
117
  background-color:color-mix(in srgb, var(--sys-neutral-accent-default, #787b8a), var(--snack-ui-table-row-background) calc((1 - var(--opacity-a008, 0.08)) * 100%));
118
118
  border-color:var(--sys-neutral-decor-hovered, #cfd2dc);
119
119
  }
120
- .bodyRow:not([data-disabled]):not([data-selected]):hover .rowPinnedCells, .bodyRow:not([data-disabled]):not([data-selected])[data-actions-opened] .rowPinnedCells{
120
+ .bodyRow:not([data-row-appearance=disabled]):not([data-selected]):hover .rowPinnedCells, .bodyRow:not([data-row-appearance=disabled]):not([data-selected])[data-actions-opened] .rowPinnedCells{
121
121
  background-color:color-mix(in srgb, var(--sys-neutral-accent-default, #787b8a), var(--snack-ui-table-row-background) calc((1 - var(--opacity-a008, 0.08)) * 100%));
122
122
  border-color:inherit;
123
123
  }
124
- .bodyRow:not([data-disabled]):hover + .bodyRow::before{
124
+ .bodyRow:not([data-row-appearance=disabled]):hover + .bodyRow::before{
125
125
  height:0;
126
126
  }
127
127
 
@@ -24,7 +24,7 @@ import { DEFAULT_EXPANDED, DEFAULT_PAGE_SIZE, DEFAULT_ROW_SELECTION, DEFAULT_SOR
24
24
  import { CellAutoResizeContext, useCellAutoResizeController } from '../../contexts';
25
25
  import { BodyRow, ColumnsSettings, ExportButton, getColumnId, getRowActionsColumnDef, getStatusColumnDef, HeaderRow, STATUS_APPEARANCE, TableContext, TableEmptyState, TablePagination, useEmptyState, } from '../../helperComponents';
26
26
  import { fuzzyFilter } from '../../utils';
27
- import { ToolbarCheckBoxMode } from '../types';
27
+ import { RowAppearance, ToolbarCheckBoxMode } from '../types';
28
28
  import { useColumnOrderByDrag, useColumnSettings, useFilters, useLoadingTable, usePageReset, useStateControl, } from './hooks';
29
29
  import styles from './styles.module.css';
30
30
  import { getColumnStyleVars, getCurrentlyConfiguredHeaderWidth, getInitColumnSizeFromLocalStorage, getPinnedGroups, getTableColumnsDefinitions, saveStateToLocalStorage, } from './utils';
@@ -50,7 +50,7 @@ export function Table(_a) {
50
50
  const isPaginationValid = validatePaging(dataAsSettings === null || dataAsSettings === void 0 ? void 0 : dataAsSettings.pagination);
51
51
  const isSortingValid = validateSorting(dataAsSettings === null || dataAsSettings === void 0 ? void 0 : dataAsSettings.ordering);
52
52
  const isSearchValid = !(dataAsSettings === null || dataAsSettings === void 0 ? void 0 : dataAsSettings.search) || typeof (dataAsSettings === null || dataAsSettings === void 0 ? void 0 : dataAsSettings.search) === 'string';
53
- const isFilterValid = Boolean((columnFilters === null || columnFilters === void 0 ? void 0 : columnFilters.filters) && validateFilter(dataAsSettings.filter, columnFilters.filters));
53
+ const isFilterValid = !(columnFilters === null || columnFilters === void 0 ? void 0 : columnFilters.filters) || Boolean(validateFilter(dataAsSettings.filter, columnFilters.filters));
54
54
  return isPaginationValid && isSortingValid && isSearchValid && isFilterValid;
55
55
  }, [columnFilters === null || columnFilters === void 0 ? void 0 : columnFilters.filters]);
56
56
  const enableSelection = Boolean(rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.enable);
@@ -100,8 +100,8 @@ export function Table(_a) {
100
100
  isCurrentRowSelected =
101
101
  typeof rowSelectionProp.enable === 'boolean' ? rowSelectionProp.enable : rowSelectionProp.enable(row);
102
102
  }
103
- return isParentSelected && isCurrentRowSelected;
104
- }, [rowSelectionProp]);
103
+ return (isParentSelected && isCurrentRowSelected && ((row.getIsPinned() && enableSelectPinned) || !row.getIsPinned()));
104
+ }, [rowSelectionProp, enableSelectPinned]);
105
105
  const table = useReactTable({
106
106
  data,
107
107
  columns: enabledTableColumns,
@@ -181,22 +181,11 @@ export function Table(_a) {
181
181
  : undefined, [bulkActionsProp, enableSelection, table]);
182
182
  const isAllRowsMode = toolbarCheckBoxMode === ToolbarCheckBoxMode.AllRows;
183
183
  const handleOnToolbarCheck = useCallback(() => {
184
- if (!loading && !enableSelectPinned && table.getTopRows().length) {
185
- const centerRows = table.getCenterRows();
186
- const isSomeRowsSelected = isAllRowsMode ? table.getIsSomeRowsSelected() : table.getIsSomePageRowsSelected();
187
- const isAllCenterRowsSelected = centerRows.every(row => row.getIsSelected());
188
- if (isAllCenterRowsSelected) {
189
- table.resetRowSelection();
190
- return;
191
- }
192
- centerRows.forEach(row => row.toggleSelected(isSomeRowsSelected ? true : undefined));
193
- return;
194
- }
195
184
  if (!loading && (rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow)) {
196
185
  isAllRowsMode ? table.toggleAllRowsSelected() : table.toggleAllPageRowsSelected();
197
186
  return;
198
187
  }
199
- }, [isAllRowsMode, loading, rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow, table, enableSelectPinned]);
188
+ }, [isAllRowsMode, loading, rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow, table]);
200
189
  const columnSizeVarsRef = useRef();
201
190
  const headers = table.getFlatHeaders();
202
191
  const columnSizes = useMemo(() => {
@@ -300,6 +289,8 @@ export function Table(_a) {
300
289
  filter,
301
290
  search: globalFilter || '',
302
291
  },
292
+ serializer: savedState.serializer,
293
+ parser: savedState.parser,
303
294
  onLoad: state => {
304
295
  state.pagination && onPaginationChange(mapPaginationToTableState(state.pagination));
305
296
  state.search && onGlobalFilterChange(state.search);
@@ -310,7 +301,7 @@ export function Table(_a) {
310
301
  }
311
302
  },
312
303
  }
313
- : undefined, bulkActions: bulkActions, selectionMode: (rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow) ? 'multiple' : 'single', checked: checked, indeterminate: indeterminate, onCheck: enableSelection ? handleOnToolbarCheck : undefined, outline: outline, after: toolbarAfter || exportSettings || areColumnsSettingsEnabled ? (_jsxs(_Fragment, { children: [toolbarAfter, exportSettings && (_jsx(ExportButton, { settings: exportSettings, columnDefinitions: columnDefinitions, data: data, topRows: filteredTopRows, centerRows: centerRows })), areColumnsSettingsEnabled && (_jsx(ColumnsSettings, { columnsSettings: columnsSettings, enabledColumns: enabledColumns, setEnabledColumns: setEnabledColumns }))] })) : undefined, moreActions: moreActions, filterRow: patchedFilter, "data-test-id": TEST_IDS.toolbar }) })), _jsxs(Scroll, { size: 's', className: styles.table, ref: scrollContainerRef, "data-outline": outline || undefined, children: [_jsx("div", { className: styles.tableContent, style: columnSizes.vars, children: _jsx(CellAutoResizeContext.Provider, { value: { updateCellMap }, children: _jsx(DndContext, Object.assign({}, dndContextProps, { children: _jsx(TableContext.Provider, { value: { table, getRowBackgroundColor }, children: (!infiniteLoading || !data.length) && loading ? (_jsxs(SkeletonContextProvider, { loading: true, children: [_jsx(HeaderRow, { rowAutoHeight: rowAutoHeight, columnOrder: columnOrder }), loadingTableRows.map(row => (_jsx(BodyRow, { row: row, rowAutoHeight: rowAutoHeight, columnOrder: columnOrder, disabledRowAppearance: rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.appearance }, row.id)))] })) : (_jsxs(_Fragment, { children: [centerRows.length || filteredTopRows.length ? (_jsx(HeaderRow, { rowAutoHeight: rowAutoHeight, columnOrder: columnOrder, enableColumnsOrderSortByDrag: enableColumnsOrderSortByDrag })) : null, filteredTopRows.length ? (_jsx("div", { className: styles.topRowWrapper, children: filteredTopRows.map(row => (_jsx(BodyRow, { row: row, onRowClick: onRowClick, rowAutoHeight: rowAutoHeight, columnOrder: columnOrder, enableColumnsOrderSortByDrag: enableColumnsOrderSortByDrag, disabledRowAppearance: rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.appearance }, row.id))) })) : null, centerRows.map(row => (_jsx(BodyRow, { row: row, onRowClick: onRowClick, rowAutoHeight: rowAutoHeight, columnOrder: columnOrder, enableColumnsOrderSortByDrag: enableColumnsOrderSortByDrag, disabledRowAppearance: rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.appearance }, row.id))), data.length > 0 && infiniteLoading && loading && !dataError && (_jsx(SkeletonContextProvider, { loading: true, children: loadingTableRows.slice(0, 3).map(row => (_jsx(BodyRow, { row: row, columnOrder: columnOrder, enableColumnsOrderSortByDrag: enableColumnsOrderSortByDrag, disabledRowAppearance: rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.appearance }, row.id))) })), _jsx(TableEmptyState, { emptyStates: emptyStates, dataError: dataError, dataFiltered: dataFiltered || Boolean(table.getState().globalFilter), tableRowsLength: tableRows.length + filteredTopRows.length })] })) }) })) }) }), _jsx("div", { className: styles.scrollStub, ref: scrollRef })] }), showPagination && (_jsx(TablePagination, { table: table, options: paginationProp === null || paginationProp === void 0 ? void 0 : paginationProp.options, optionsLabel: paginationProp === null || paginationProp === void 0 ? void 0 : paginationProp.optionsLabel, pageCount: pageCount, optionsRender: paginationProp === null || paginationProp === void 0 ? void 0 : paginationProp.optionsRender }))] })));
304
+ : undefined, bulkActions: bulkActions, selectionMode: (rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow) ? 'multiple' : 'single', checked: checked, indeterminate: indeterminate, onCheck: enableSelection ? handleOnToolbarCheck : undefined, outline: outline, after: toolbarAfter || exportSettings || areColumnsSettingsEnabled ? (_jsxs(_Fragment, { children: [toolbarAfter, exportSettings && (_jsx(ExportButton, { settings: exportSettings, columnDefinitions: columnDefinitions, data: data, topRows: filteredTopRows, centerRows: centerRows })), areColumnsSettingsEnabled && (_jsx(ColumnsSettings, { columnsSettings: columnsSettings, enabledColumns: enabledColumns, setEnabledColumns: setEnabledColumns }))] })) : undefined, moreActions: moreActions, filterRow: patchedFilter, "data-test-id": TEST_IDS.toolbar }) })), _jsxs(Scroll, { size: 's', className: styles.table, ref: scrollContainerRef, "data-outline": outline || undefined, children: [_jsx("div", { className: styles.tableContent, style: columnSizes.vars, children: _jsx(CellAutoResizeContext.Provider, { value: { updateCellMap }, children: _jsx(DndContext, Object.assign({}, dndContextProps, { children: _jsx(TableContext.Provider, { value: { table, getRowBackgroundColor }, children: (!infiniteLoading || !data.length) && loading ? (_jsxs(SkeletonContextProvider, { loading: true, children: [_jsx(HeaderRow, { rowAutoHeight: rowAutoHeight, columnOrder: columnOrder }), loadingTableRows.map(row => (_jsx(BodyRow, { row: row, rowAutoHeight: rowAutoHeight, columnOrder: columnOrder, disabledRowAppearance: rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.appearance }, row.id)))] })) : (_jsxs(_Fragment, { children: [centerRows.length || filteredTopRows.length ? (_jsx(HeaderRow, { rowAutoHeight: rowAutoHeight, columnOrder: columnOrder, enableColumnsOrderSortByDrag: enableColumnsOrderSortByDrag })) : null, filteredTopRows.length ? (_jsx("div", { className: styles.topRowWrapper, children: filteredTopRows.map(row => (_jsx(BodyRow, { row: row, onRowClick: onRowClick, rowAutoHeight: rowAutoHeight, columnOrder: columnOrder, enableColumnsOrderSortByDrag: enableColumnsOrderSortByDrag, disabledRowAppearance: RowAppearance.HideToggler }, row.id))) })) : null, centerRows.map(row => (_jsx(BodyRow, { row: row, onRowClick: onRowClick, rowAutoHeight: rowAutoHeight, columnOrder: columnOrder, enableColumnsOrderSortByDrag: enableColumnsOrderSortByDrag, disabledRowAppearance: rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.appearance }, row.id))), data.length > 0 && infiniteLoading && loading && !dataError && (_jsx(SkeletonContextProvider, { loading: true, children: loadingTableRows.slice(0, 3).map(row => (_jsx(BodyRow, { row: row, columnOrder: columnOrder, enableColumnsOrderSortByDrag: enableColumnsOrderSortByDrag, disabledRowAppearance: rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.appearance }, row.id))) })), _jsx(TableEmptyState, { emptyStates: emptyStates, dataError: dataError, dataFiltered: dataFiltered || Boolean(table.getState().globalFilter), tableRowsLength: tableRows.length + filteredTopRows.length })] })) }) })) }) }), _jsx("div", { className: styles.scrollStub, ref: scrollRef })] }), showPagination && (_jsx(TablePagination, { table: table, options: paginationProp === null || paginationProp === void 0 ? void 0 : paginationProp.options, optionsLabel: paginationProp === null || paginationProp === void 0 ? void 0 : paginationProp.optionsLabel, pageCount: pageCount, optionsRender: paginationProp === null || paginationProp === void 0 ? void 0 : paginationProp.optionsRender }))] })));
314
305
  }
315
306
  Table.getStatusColumnDef = getStatusColumnDef;
316
307
  Table.statusAppearances = STATUS_APPEARANCE;
@@ -1,5 +1,12 @@
1
- export const validatePaging = (value) => typeof (value === null || value === void 0 ? void 0 : value.limit) === 'number' &&
2
- typeof (value === null || value === void 0 ? void 0 : value.offset) === 'number';
1
+ export const validatePaging = (value) => {
2
+ if (!value) {
3
+ return true;
4
+ }
5
+ if (typeof value !== 'object') {
6
+ return false;
7
+ }
8
+ return 'limit' in value && typeof value.limit === 'number' && 'offset' in value && typeof value.offset === 'number';
9
+ };
3
10
  export const validateSorting = (value) => !value ||
4
11
  value.every(column => typeof (column === null || column === void 0 ? void 0 : column.field) === 'string' && typeof (column === null || column === void 0 ? void 0 : column.direction) === 'string');
5
12
  export const validateFilter = (value, filterSettings) => typeof value === 'object' &&
@@ -1,7 +1,7 @@
1
1
  import { PaginationState, Row, RowPinningState, RowSelectionOptions, RowSelectionState, SortingState } from '@tanstack/react-table';
2
2
  import { ReactNode, RefObject } from 'react';
3
3
  import { FiltersState } from '@snack-uikit/chips';
4
- import { FilterRow, ToolbarProps } from '@snack-uikit/toolbar';
4
+ import { FilterRow, ToolbarPersistConfig, ToolbarProps } from '@snack-uikit/toolbar';
5
5
  import { ValueOf, WithSupportProps } from '@snack-uikit/utils';
6
6
  import { TABLE_ROW_COLOR } from '../constants';
7
7
  import { EmptyStateProps, ExportButtonProps, RowClickHandler, TreeColumnDefinitionProps } from '../helperComponents';
@@ -144,7 +144,7 @@ type BaseTableProps<TData extends object, TFilters extends FiltersState = Record
144
144
  * Поле id должно быть уникальным для разных таблиц в рамках приложения. <br>
145
145
  * Для корректной работы необходимо наличие id в конфиге columnDefinitions
146
146
  * */
147
- savedState?: {
147
+ savedState?: Pick<ToolbarPersistConfig<TFilters>, 'serializer' | 'parser'> & {
148
148
  id: string;
149
149
  filterQueryKey?: string;
150
150
  resize?: boolean;
@@ -110,18 +110,18 @@
110
110
  .bodyRow[data-clickable]{
111
111
  cursor:pointer;
112
112
  }
113
- .bodyRow:not([data-disabled]):hover::before{
113
+ .bodyRow:not([data-row-appearance=disabled]):hover::before{
114
114
  height:0;
115
115
  }
116
- .bodyRow:not([data-disabled]):not([data-selected]):hover, .bodyRow:not([data-disabled]):not([data-selected])[data-actions-opened]{
116
+ .bodyRow:not([data-row-appearance=disabled]):not([data-selected]):hover, .bodyRow:not([data-row-appearance=disabled]):not([data-selected])[data-actions-opened]{
117
117
  background-color:color-mix(in srgb, var(--sys-neutral-accent-default, #787b8a), var(--snack-ui-table-row-background) calc((1 - var(--opacity-a008, 0.08)) * 100%));
118
118
  border-color:var(--sys-neutral-decor-hovered, #cfd2dc);
119
119
  }
120
- .bodyRow:not([data-disabled]):not([data-selected]):hover .rowPinnedCells, .bodyRow:not([data-disabled]):not([data-selected])[data-actions-opened] .rowPinnedCells{
120
+ .bodyRow:not([data-row-appearance=disabled]):not([data-selected]):hover .rowPinnedCells, .bodyRow:not([data-row-appearance=disabled]):not([data-selected])[data-actions-opened] .rowPinnedCells{
121
121
  background-color:color-mix(in srgb, var(--sys-neutral-accent-default, #787b8a), var(--snack-ui-table-row-background) calc((1 - var(--opacity-a008, 0.08)) * 100%));
122
122
  border-color:inherit;
123
123
  }
124
- .bodyRow:not([data-disabled]):hover + .bodyRow::before{
124
+ .bodyRow:not([data-row-appearance=disabled]):hover + .bodyRow::before{
125
125
  height:0;
126
126
  }
127
127
 
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public"
5
5
  },
6
6
  "title": "Table",
7
- "version": "0.37.34",
7
+ "version": "0.37.36-preview-ae5449cf.0",
8
8
  "sideEffects": [
9
9
  "*.css",
10
10
  "*.woff",
@@ -42,16 +42,16 @@
42
42
  "@dnd-kit/sortable": "10.0.0",
43
43
  "@dnd-kit/utilities": "3.2.2",
44
44
  "@snack-uikit/button": "0.19.17",
45
- "@snack-uikit/chips": "0.28.13",
46
- "@snack-uikit/icons": "0.27.5",
47
- "@snack-uikit/info-block": "0.6.36",
48
- "@snack-uikit/list": "0.32.12",
49
- "@snack-uikit/pagination": "0.10.22",
45
+ "@snack-uikit/chips": "0.28.14",
46
+ "@snack-uikit/icons": "0.27.6",
47
+ "@snack-uikit/info-block": "0.6.37",
48
+ "@snack-uikit/list": "0.32.13",
49
+ "@snack-uikit/pagination": "0.10.23",
50
50
  "@snack-uikit/scroll": "0.10.6",
51
51
  "@snack-uikit/skeleton": "0.6.10",
52
- "@snack-uikit/toggles": "0.13.24",
53
- "@snack-uikit/toolbar": "0.14.17",
54
- "@snack-uikit/truncate-string": "0.7.7",
52
+ "@snack-uikit/toggles": "0.13.25",
53
+ "@snack-uikit/toolbar": "0.14.18",
54
+ "@snack-uikit/truncate-string": "0.7.8",
55
55
  "@snack-uikit/typography": "0.8.12",
56
56
  "@snack-uikit/utils": "4.0.1",
57
57
  "@tanstack/match-sorter-utils": "8.11.8",
@@ -65,5 +65,5 @@
65
65
  "peerDependencies": {
66
66
  "@snack-uikit/locale": "*"
67
67
  },
68
- "gitHead": "7342fbaed272bfd1c382432826c0ef53311c7ada"
68
+ "gitHead": "2b7d2b664595517f72f9522b5173f908ebe4b5fc"
69
69
  }
@@ -50,7 +50,7 @@ import {
50
50
  } from '../../helperComponents';
51
51
  import { ColumnDefinition } from '../../types';
52
52
  import { fuzzyFilter } from '../../utils';
53
- import { TableProps, ToolbarCheckBoxMode } from '../types';
53
+ import { RowAppearance, TableProps, ToolbarCheckBoxMode } from '../types';
54
54
  import {
55
55
  useColumnOrderByDrag,
56
56
  useColumnSettings,
@@ -157,9 +157,8 @@ export function Table<TData extends object, TFilters extends FiltersState = Reco
157
157
  const isPaginationValid = validatePaging(dataAsSettings?.pagination);
158
158
  const isSortingValid = validateSorting(dataAsSettings?.ordering);
159
159
  const isSearchValid = !dataAsSettings?.search || typeof dataAsSettings?.search === 'string';
160
- const isFilterValid = Boolean(
161
- columnFilters?.filters && validateFilter(dataAsSettings.filter, columnFilters.filters),
162
- );
160
+ const isFilterValid =
161
+ !columnFilters?.filters || Boolean(validateFilter(dataAsSettings.filter, columnFilters.filters));
163
162
 
164
163
  return isPaginationValid && isSortingValid && isSearchValid && isFilterValid;
165
164
  },
@@ -232,9 +231,11 @@ export function Table<TData extends object, TFilters extends FiltersState = Reco
232
231
  isCurrentRowSelected =
233
232
  typeof rowSelectionProp.enable === 'boolean' ? rowSelectionProp.enable : rowSelectionProp.enable(row);
234
233
  }
235
- return isParentSelected && isCurrentRowSelected;
234
+ return (
235
+ isParentSelected && isCurrentRowSelected && ((row.getIsPinned() && enableSelectPinned) || !row.getIsPinned())
236
+ );
236
237
  },
237
- [rowSelectionProp],
238
+ [rowSelectionProp, enableSelectPinned],
238
239
  );
239
240
 
240
241
  const table = useReactTable<TData>({
@@ -332,25 +333,11 @@ export function Table<TData extends object, TFilters extends FiltersState = Reco
332
333
  const isAllRowsMode = toolbarCheckBoxMode === ToolbarCheckBoxMode.AllRows;
333
334
 
334
335
  const handleOnToolbarCheck = useCallback(() => {
335
- if (!loading && !enableSelectPinned && table.getTopRows().length) {
336
- const centerRows = table.getCenterRows();
337
- const isSomeRowsSelected = isAllRowsMode ? table.getIsSomeRowsSelected() : table.getIsSomePageRowsSelected();
338
- const isAllCenterRowsSelected = centerRows.every(row => row.getIsSelected());
339
-
340
- if (isAllCenterRowsSelected) {
341
- table.resetRowSelection();
342
- return;
343
- }
344
-
345
- centerRows.forEach(row => row.toggleSelected(isSomeRowsSelected ? true : undefined));
346
- return;
347
- }
348
-
349
336
  if (!loading && rowSelectionProp?.multiRow) {
350
337
  isAllRowsMode ? table.toggleAllRowsSelected() : table.toggleAllPageRowsSelected();
351
338
  return;
352
339
  }
353
- }, [isAllRowsMode, loading, rowSelectionProp?.multiRow, table, enableSelectPinned]);
340
+ }, [isAllRowsMode, loading, rowSelectionProp?.multiRow, table]);
354
341
 
355
342
  const columnSizeVarsRef = useRef<Record<string, string>>();
356
343
  const headers = table.getFlatHeaders();
@@ -490,6 +477,8 @@ export function Table<TData extends object, TFilters extends FiltersState = Reco
490
477
  filter,
491
478
  search: globalFilter || '',
492
479
  },
480
+ serializer: savedState.serializer,
481
+ parser: savedState.parser,
493
482
  onLoad: state => {
494
483
  state.pagination && onPaginationChange(mapPaginationToTableState(state.pagination));
495
484
  state.search && onGlobalFilterChange(state.search);
@@ -576,7 +565,7 @@ export function Table<TData extends object, TFilters extends FiltersState = Reco
576
565
  rowAutoHeight={rowAutoHeight}
577
566
  columnOrder={columnOrder}
578
567
  enableColumnsOrderSortByDrag={enableColumnsOrderSortByDrag}
579
- disabledRowAppearance={rowSelectionProp?.appearance}
568
+ disabledRowAppearance={RowAppearance.HideToggler}
580
569
  />
581
570
  ))}
582
571
  </div>
@@ -1,9 +1,17 @@
1
1
  import { RequestPayloadParams } from '@cloud-ru/ft-request-payload-transform';
2
2
  import { ChipChoiceRowProps } from '@snack-uikit/chips';
3
3
 
4
- export const validatePaging = (value: unknown): value is RequestPayloadParams['pagination'] =>
5
- typeof (value as RequestPayloadParams['pagination'])?.limit === 'number' &&
6
- typeof (value as RequestPayloadParams['pagination'])?.offset === 'number';
4
+ export const validatePaging = (value: unknown): value is RequestPayloadParams['pagination'] => {
5
+ if (!value) {
6
+ return true;
7
+ }
8
+
9
+ if (typeof value !== 'object') {
10
+ return false;
11
+ }
12
+
13
+ return 'limit' in value && typeof value.limit === 'number' && 'offset' in value && typeof value.offset === 'number';
14
+ };
7
15
 
8
16
  export const validateSorting = (value: unknown): value is RequestPayloadParams['ordering'] =>
9
17
  !value ||
@@ -9,7 +9,7 @@ import {
9
9
  import { ReactNode, RefObject } from 'react';
10
10
 
11
11
  import { FiltersState } from '@snack-uikit/chips';
12
- import { FilterRow, ToolbarProps } from '@snack-uikit/toolbar';
12
+ import { FilterRow, ToolbarPersistConfig, ToolbarProps } from '@snack-uikit/toolbar';
13
13
  import { ValueOf, WithSupportProps } from '@snack-uikit/utils';
14
14
 
15
15
  import { TABLE_ROW_COLOR } from '../constants';
@@ -177,7 +177,7 @@ type BaseTableProps<TData extends object, TFilters extends FiltersState = Record
177
177
  * Поле id должно быть уникальным для разных таблиц в рамках приложения. <br>
178
178
  * Для корректной работы необходимо наличие id в конфиге columnDefinitions
179
179
  * */
180
- savedState?: {
180
+ savedState?: Pick<ToolbarPersistConfig<TFilters>, 'serializer' | 'parser'> & {
181
181
  id: string;
182
182
  filterQueryKey?: string;
183
183
  resize?: boolean;
@@ -154,7 +154,7 @@ $snack-ui-table-row-background: var(--snack-ui-table-row-background);
154
154
  cursor: pointer;
155
155
  }
156
156
 
157
- &:not([data-disabled]) {
157
+ &:not([data-row-appearance='disabled']) {
158
158
  &:hover {
159
159
  &::before {
160
160
  height: 0;