@snack-uikit/table 0.18.0 → 0.19.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 +23 -0
- package/README.md +6 -0
- package/dist/components/Table/Table.d.ts +1 -1
- package/dist/components/Table/Table.js +15 -4
- package/dist/components/Table/styles.module.css +8 -0
- package/dist/components/types.d.ts +8 -3
- package/dist/helperComponents/Cells/SelectionCell/SelectionCell.d.ts +1 -1
- package/dist/helperComponents/Cells/SelectionCell/SelectionCell.js +2 -2
- package/package.json +6 -6
- package/src/components/Table/Table.tsx +29 -4
- package/src/components/Table/styles.module.scss +10 -0
- package/src/components/types.ts +15 -3
- package/src/helperComponents/Cells/SelectionCell/SelectionCell.tsx +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,29 @@
|
|
|
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.19.0 (2024-06-06)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **PDS-287:** add row pinning functionality to table ([f33a911](https://github.com/cloud-ru-tech/snack-uikit/commit/f33a9116d78de8ab09a01a0db22999e09c7fd773))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## 0.18.1 (2024-06-06)
|
|
18
|
+
|
|
19
|
+
### Only dependencies have been changed
|
|
20
|
+
* [@snack-uikit/chips@0.14.7](https://github.com/cloud-ru-tech/snack-uikit/blob/master/packages/chips/CHANGELOG.md)
|
|
21
|
+
* [@snack-uikit/info-block@0.4.0](https://github.com/cloud-ru-tech/snack-uikit/blob/master/packages/info-block/CHANGELOG.md)
|
|
22
|
+
* [@snack-uikit/list@0.13.5](https://github.com/cloud-ru-tech/snack-uikit/blob/master/packages/list/CHANGELOG.md)
|
|
23
|
+
* [@snack-uikit/toolbar@0.7.40](https://github.com/cloud-ru-tech/snack-uikit/blob/master/packages/toolbar/CHANGELOG.md)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
6
29
|
# 0.18.0 (2024-06-03)
|
|
7
30
|
|
|
8
31
|
|
package/README.md
CHANGED
|
@@ -111,6 +111,8 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
|
|
|
111
111
|
|------|------|---------------|-------------|
|
|
112
112
|
| columnDefinitions* | `ColumnDefinition<TData>[]` | - | Определение внешнего вида и функционала колонок |
|
|
113
113
|
| data* | `TData[]` | - | Данные для отрисовки |
|
|
114
|
+
| keepPinnedRows | `boolean` | - | Параметр овтечает за сохранение закрепленных строк на всех страницах таблицы |
|
|
115
|
+
| enableSelectPinned | `boolean` | - | Параметр овтечает за чекбокс выбора закрепленных строк |
|
|
114
116
|
| sorting | `{ initialState?: SortingState; state?: SortingState; onChange?(state: SortingState): void; }` | - | Параметры отвечают за возможность сортировки, их стоит использовать если нужно отслеживать состояние <br> <strong>initialState</strong>: Начальное состояние сортировки <br> <strong>state</strong>: Состояние сортировки, жестко устанавливаемое снаружи <br> <strong>onChange</strong>: Колбэк на изменение сортировки |
|
|
115
117
|
| rowSelection | `{ initialState?: RowSelectionState; state?: RowSelectionState; enable?: boolean \| ((row: Row<TData>) => boolean); multiRow?: boolean; onChange?(state: RowSelectionState): void; }` | - | Параметры отвечают за возможность выбора строк <br> <strong>initialState</strong>: Начальное состояние выбора строк <br> <strong>state</strong>: Состояние выбора строк, жестко устанавливаемое снаружи <br> <strong>enable</strong>: Колбэк определяющий можно ли выбрать строку <br> <strong>multiRow</strong>: Мульти-выбор строк (включен по-умолчанию, когда включается выбор) <br> <strong>onChange</strong>: Колбэк на выбор строк |
|
|
116
118
|
| search | `{ initialState?: string; state?: string; placeholder?: string; loading?: boolean; onChange?(value: string): void; }` | 'Search'<br> <strong>loading</strong>: Состояние загрузки в строке поиска <br> <strong>onChange</strong>: Колбэк на изменение данных в строке поиска | Параметры отвечают за глобальный поиск в таблице <br> <strong>initialState</strong>: Начальное состояние строки поиска <br> <strong>state</strong>: Состояние строки поиска, жестко устанавливаемое снаружи <br> <strong>placeholder</strong>: Placeholder строки поиска |
|
|
@@ -142,6 +144,7 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
|
|
|
142
144
|
| getRowId | `(originalRow: TData, index: number, parent?: Row<TData>) => string` | - | Дополнительная функция используется для получения уникального идентификатора для любой заданной строки |
|
|
143
145
|
| scrollRef | `RefObject<HTMLElement>` | - | Ссылка на элемент, обозначающий самый конец прокручиваемого списка |
|
|
144
146
|
| scrollContainerRef | `RefObject<HTMLElement>` | - | Ссылка на контейнер, который скроллится |
|
|
147
|
+
| rowPinning | `Pick<RowPinningState, "top">` | { top: [], } | Определение какие строки должны быть закреплены в таблице |
|
|
145
148
|
## Table.getStatusColumnDef
|
|
146
149
|
Вспомогательная функция для создания ячейки со статусом
|
|
147
150
|
### Props
|
|
@@ -168,6 +171,8 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
|
|
|
168
171
|
| onChangePage* | `(offset: number, limit: number) => void` | - | |
|
|
169
172
|
| columnDefinitions* | `ColumnDefinition<TData>[]` | - | Определение внешнего вида и функционала колонок |
|
|
170
173
|
| loading | `boolean` | - | Состояние загрузки |
|
|
174
|
+
| keepPinnedRows | `boolean` | - | Параметр овтечает за сохранение закрепленных строк на всех страницах таблицы |
|
|
175
|
+
| enableSelectPinned | `boolean` | - | Параметр овтечает за чекбокс выбора закрепленных строк |
|
|
171
176
|
| sorting | `{ initialState?: SortingState; state?: SortingState; onChange?(state: SortingState): void; }` | - | Параметры отвечают за возможность сортировки, их стоит использовать если нужно отслеживать состояние <br> <strong>initialState</strong>: Начальное состояние сортировки <br> <strong>state</strong>: Состояние сортировки, жестко устанавливаемое снаружи <br> <strong>onChange</strong>: Колбэк на изменение сортировки |
|
|
172
177
|
| rowSelection | `{ initialState?: RowSelectionState; state?: RowSelectionState; enable?: boolean \| ((row: Row<TData>) => boolean); multiRow?: boolean; onChange?(state: RowSelectionState): void; }` | - | Параметры отвечают за возможность выбора строк <br> <strong>initialState</strong>: Начальное состояние выбора строк <br> <strong>state</strong>: Состояние выбора строк, жестко устанавливаемое снаружи <br> <strong>enable</strong>: Колбэк определяющий можно ли выбрать строку <br> <strong>multiRow</strong>: Мульти-выбор строк (включен по-умолчанию, когда включается выбор) <br> <strong>onChange</strong>: Колбэк на выбор строк |
|
|
173
178
|
| enableFuzzySearch | `boolean` | - | Включить нечеткий поиск |
|
|
@@ -194,6 +199,7 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
|
|
|
194
199
|
| getRowId | `(originalRow: TData, index: number, parent?: Row<TData>) => string` | - | Дополнительная функция используется для получения уникального идентификатора для любой заданной строки |
|
|
195
200
|
| scrollRef | `RefObject<HTMLElement>` | - | Ссылка на элемент, обозначающий самый конец прокручиваемого списка |
|
|
196
201
|
| scrollContainerRef | `RefObject<HTMLElement>` | - | Ссылка на контейнер, который скроллится |
|
|
202
|
+
| rowPinning | `Pick<RowPinningState, "top">` | - | Определение какие строки должны быть закреплены в таблице |
|
|
197
203
|
| items | `TData[]` | - | Данные для отрисовки |
|
|
198
204
|
| total | `number` | 10 | Общее кол-во строк |
|
|
199
205
|
| limit | `number` | 10 | Кол-во строк на страницу |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TableProps } from '../types';
|
|
2
2
|
/** Компонент таблицы */
|
|
3
|
-
export declare function Table<TData extends object>({ data, columnDefinitions, rowSelection: rowSelectionProp, search, sorting: sortingProp, columnFilters, pagination: paginationProp, className, onRowClick, onRefresh, onDelete, pageSize, pageCount, loading, outline, moreActions, exportFileName, dataFiltered, dataError, noDataState, noResultsState, errorDataState, suppressToolbar, toolbarBefore, toolbarAfter, suppressPagination, manualSorting, manualPagination, manualFiltering, scrollRef, scrollContainerRef, getRowId, enableFuzzySearch, ...rest }: TableProps<TData>): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
export declare function Table<TData extends object>({ data, rowPinning, columnDefinitions, keepPinnedRows, enableSelectPinned, rowSelection: rowSelectionProp, search, sorting: sortingProp, columnFilters, pagination: paginationProp, className, onRowClick, onRefresh, onDelete, pageSize, pageCount, loading, outline, moreActions, exportFileName, dataFiltered, dataError, noDataState, noResultsState, errorDataState, suppressToolbar, toolbarBefore, toolbarAfter, suppressPagination, manualSorting, manualPagination, manualFiltering, scrollRef, scrollContainerRef, getRowId, enableFuzzySearch, ...rest }: TableProps<TData>): import("react/jsx-runtime").JSX.Element;
|
|
4
4
|
export declare namespace Table {
|
|
5
5
|
var getStatusColumnDef: typeof import("../../helperComponents").getStatusColumnDef;
|
|
6
6
|
var statusAppearances: {
|
|
@@ -28,7 +28,9 @@ import styles from './styles.module.css';
|
|
|
28
28
|
import { getColumnStyleVars, getCurrentlyConfiguredHeaderWidth } from './utils';
|
|
29
29
|
/** Компонент таблицы */
|
|
30
30
|
export function Table(_a) {
|
|
31
|
-
var { data,
|
|
31
|
+
var { data, rowPinning = {
|
|
32
|
+
top: [],
|
|
33
|
+
}, columnDefinitions, keepPinnedRows = false, enableSelectPinned = false, rowSelection: rowSelectionProp, search, sorting: sortingProp, columnFilters, pagination: paginationProp, className, onRowClick, onRefresh, onDelete, pageSize = DEFAULT_PAGE_SIZE, pageCount, loading = false, outline = false, moreActions, exportFileName, dataFiltered, dataError, noDataState, noResultsState, errorDataState, suppressToolbar = false, toolbarBefore, toolbarAfter, suppressPagination = false, manualSorting = false, manualPagination = false, manualFiltering = false, scrollRef, scrollContainerRef, getRowId, enableFuzzySearch } = _a, rest = __rest(_a, ["data", "rowPinning", "columnDefinitions", "keepPinnedRows", "enableSelectPinned", "rowSelection", "search", "sorting", "columnFilters", "pagination", "className", "onRowClick", "onRefresh", "onDelete", "pageSize", "pageCount", "loading", "outline", "moreActions", "exportFileName", "dataFiltered", "dataError", "noDataState", "noResultsState", "errorDataState", "suppressToolbar", "toolbarBefore", "toolbarAfter", "suppressPagination", "manualSorting", "manualPagination", "manualFiltering", "scrollRef", "scrollContainerRef", "getRowId", "enableFuzzySearch"]);
|
|
32
34
|
const { state: globalFilter, onStateChange: onGlobalFilterChange } = useStateControl(search, '');
|
|
33
35
|
const { state: rowSelection, onStateChange: onRowSelectionChange } = useStateControl(rowSelectionProp, {});
|
|
34
36
|
const defaultPaginationState = useMemo(() => ({
|
|
@@ -41,10 +43,10 @@ export function Table(_a) {
|
|
|
41
43
|
const tableColumns = useMemo(() => {
|
|
42
44
|
let cols = columnDefinitions;
|
|
43
45
|
if (enableSelection) {
|
|
44
|
-
cols = [getSelectionCellColumnDef(), ...cols];
|
|
46
|
+
cols = [getSelectionCellColumnDef(enableSelectPinned), ...cols];
|
|
45
47
|
}
|
|
46
48
|
return cols;
|
|
47
|
-
}, [columnDefinitions, enableSelection]);
|
|
49
|
+
}, [columnDefinitions, enableSelection, enableSelectPinned]);
|
|
48
50
|
const columnPinning = useMemo(() => {
|
|
49
51
|
var _a;
|
|
50
52
|
const pinningState = { left: [], right: [] };
|
|
@@ -65,6 +67,7 @@ export function Table(_a) {
|
|
|
65
67
|
rowSelection,
|
|
66
68
|
sorting,
|
|
67
69
|
pagination,
|
|
70
|
+
rowPinning,
|
|
68
71
|
},
|
|
69
72
|
pageCount,
|
|
70
73
|
defaultColumn: {
|
|
@@ -94,6 +97,7 @@ export function Table(_a) {
|
|
|
94
97
|
getPaginationRowModel: getPaginationRowModel(),
|
|
95
98
|
getCoreRowModel: getCoreRowModel(),
|
|
96
99
|
columnResizeMode: 'onEnd',
|
|
100
|
+
keepPinnedRows,
|
|
97
101
|
});
|
|
98
102
|
const { loadingTable } = useLoadingTable({ pageSize, columnDefinitions: tableColumns, columnPinning });
|
|
99
103
|
const handleOnRefresh = useCallback(() => {
|
|
@@ -160,8 +164,15 @@ export function Table(_a) {
|
|
|
160
164
|
columnSizeVarsRef.current = columnSizeVars;
|
|
161
165
|
}, [columnSizeVars]);
|
|
162
166
|
const tableRows = table.getRowModel().rows;
|
|
167
|
+
const tableCenterRows = table.getCenterRows();
|
|
168
|
+
const tableFilteredRows = table.getFilteredRowModel().rows;
|
|
169
|
+
const tableFilteredRowsIds = tableFilteredRows.map(row => row.id);
|
|
170
|
+
const topRows = table.getTopRows();
|
|
163
171
|
const loadingTableRows = loadingTable.getRowModel().rows;
|
|
164
172
|
const tablePagination = table.getState().pagination;
|
|
173
|
+
const filteredTopRows = table.getState().globalFilter
|
|
174
|
+
? topRows.filter(tr => tableFilteredRowsIds.includes(tr.id))
|
|
175
|
+
: topRows;
|
|
165
176
|
const { t } = useLocale('Table');
|
|
166
177
|
const emptyStates = useEmptyState({ noDataState, noResultsState, errorDataState });
|
|
167
178
|
const cssPageSize = useMemo(() => {
|
|
@@ -181,7 +192,7 @@ export function Table(_a) {
|
|
|
181
192
|
onChange: onGlobalFilterChange,
|
|
182
193
|
loading: search === null || search === void 0 ? void 0 : search.loading,
|
|
183
194
|
placeholder: (search === null || search === void 0 ? void 0 : search.placeholder) || t('searchPlaceholder'),
|
|
184
|
-
}, checked: table.getIsAllPageRowsSelected(), indeterminate: table.getIsSomePageRowsSelected(), className: styles.toolbar, onRefresh: onRefresh ? handleOnRefresh : undefined, onDelete: enableSelection && onDelete ? handleOnDelete : undefined, onCheck: enableSelection ? handleOnCheck : undefined, outline: outline, selectionMode: (rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow) ? 'multiple' : 'single', before: toolbarBefore, after: toolbarAfter || exportFileName ? (_jsxs(_Fragment, { children: [toolbarAfter, exportFileName && (_jsx(ExportButton, { fileName: exportFileName, columnDefinitions: columnDefinitions, data: data }))] })) : undefined, moreActions: moreActions }), columnFilters && _jsxs("div", { className: styles.filtersWrapper, children: [" ", columnFilters, " "] })] })), _jsx("div", { className: styles.scrollWrapper, "data-outline": outline || undefined, children: _jsxs(Scroll, { size: 's', className: styles.table, ref: scrollContainerRef, children: [_jsx("div", { className: styles.tableContent, style: columnSizeVars, children: _jsx(TableContext.Provider, { value: { table }, children: loading ? (_jsxs(SkeletonContextProvider, { loading: true, children: [_jsx(HeaderRow, {}), loadingTableRows.map(row => (_jsx(BodyRow, { row: row }, row.id)))] })) : (_jsxs(_Fragment, { children: [
|
|
195
|
+
}, checked: table.getIsAllPageRowsSelected(), indeterminate: table.getIsSomePageRowsSelected(), className: styles.toolbar, onRefresh: onRefresh ? handleOnRefresh : undefined, onDelete: enableSelection && onDelete ? handleOnDelete : undefined, onCheck: enableSelection ? handleOnCheck : undefined, outline: outline, selectionMode: (rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow) ? 'multiple' : 'single', before: toolbarBefore, after: toolbarAfter || exportFileName ? (_jsxs(_Fragment, { children: [toolbarAfter, exportFileName && (_jsx(ExportButton, { fileName: exportFileName, columnDefinitions: columnDefinitions, data: data }))] })) : undefined, moreActions: moreActions }), columnFilters && _jsxs("div", { className: styles.filtersWrapper, children: [" ", columnFilters, " "] })] })), _jsx("div", { className: styles.scrollWrapper, "data-outline": outline || undefined, children: _jsxs(Scroll, { size: 's', className: styles.table, ref: scrollContainerRef, children: [_jsx("div", { className: styles.tableContent, style: columnSizeVars, children: _jsx(TableContext.Provider, { value: { table }, children: loading ? (_jsxs(SkeletonContextProvider, { loading: true, children: [_jsx(HeaderRow, {}), loadingTableRows.map(row => (_jsx(BodyRow, { row: row }, row.id)))] })) : (_jsxs(_Fragment, { children: [tableCenterRows.length || filteredTopRows.length ? _jsx(HeaderRow, {}) : null, filteredTopRows.length ? (_jsx("div", { className: styles.topRowWrapper, children: filteredTopRows.map(row => (_jsx(BodyRow, { row: row, onRowClick: onRowClick }, row.id))) })) : null, tableCenterRows.map(row => (_jsx(BodyRow, { row: row, onRowClick: onRowClick }, row.id))), _jsx(TableEmptyState, { emptyStates: emptyStates, dataError: dataError, dataFiltered: dataFiltered || Boolean(table.getState().globalFilter), tableRowsLength: tableRows.length })] })) }) }), _jsx("div", { className: styles.scrollStub, ref: scrollRef })] }) }), !suppressPagination && (_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 }))] })) }));
|
|
185
196
|
}
|
|
186
197
|
Table.getStatusColumnDef = getStatusColumnDef;
|
|
187
198
|
Table.statusAppearances = STATUS_APPEARANCE;
|
|
@@ -54,4 +54,12 @@
|
|
|
54
54
|
height:calc(var(--dimension-025m, 2px) / 2);
|
|
55
55
|
margin-top:calc(var(--dimension-025m, 2px) / -2);
|
|
56
56
|
background:transparent;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.topRowWrapper{
|
|
60
|
+
position:sticky;
|
|
61
|
+
z-index:3;
|
|
62
|
+
top:calc(var(--size-table-line-height, 40px));
|
|
63
|
+
margin-bottom:calc(-1 * var(--border-width-table, 1px));
|
|
64
|
+
border-bottom:var(--border-width-table, 1px) solid var(--sys-neutral-decor-default, #dfe2ec);
|
|
57
65
|
}
|
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import { PaginationState, Row, RowSelectionOptions, RowSelectionState, SortingState } from '@tanstack/react-table';
|
|
1
|
+
import { PaginationState, Row, RowPinningState, RowSelectionOptions, RowSelectionState, SortingState } from '@tanstack/react-table';
|
|
2
2
|
import { ReactNode, RefObject } from 'react';
|
|
3
3
|
import { ToolbarProps } from '@snack-uikit/toolbar';
|
|
4
4
|
import { WithSupportProps } from '@snack-uikit/utils';
|
|
5
|
-
import { RowClickHandler } from '../helperComponents';
|
|
6
|
-
import { EmptyStateProps } from '../helperComponents/TableEmptyState';
|
|
5
|
+
import { EmptyStateProps, RowClickHandler } from '../helperComponents';
|
|
7
6
|
import { ColumnDefinition } from '../types';
|
|
8
7
|
export type TableProps<TData extends object> = WithSupportProps<{
|
|
9
8
|
/** Данные для отрисовки */
|
|
10
9
|
data: TData[];
|
|
11
10
|
/** Определение внешнего вида и функционала колонок */
|
|
12
11
|
columnDefinitions: ColumnDefinition<TData>[];
|
|
12
|
+
/** Параметр овтечает за сохранение закрепленных строк на всех страницах таблицы */
|
|
13
|
+
keepPinnedRows?: boolean;
|
|
14
|
+
/** Параметр овтечает за чекбокс выбора закрепленных строк */
|
|
15
|
+
enableSelectPinned?: boolean;
|
|
13
16
|
/** Параметры отвечают за возможность сортировки, их стоит использовать если нужно отслеживать состояние <br>
|
|
14
17
|
* <strong>initialState</strong>: Начальное состояние сортировки <br>
|
|
15
18
|
* <strong>state</strong>: Состояние сортировки, жестко устанавливаемое снаружи <br>
|
|
@@ -109,6 +112,8 @@ export type TableProps<TData extends object> = WithSupportProps<{
|
|
|
109
112
|
scrollRef?: RefObject<HTMLElement>;
|
|
110
113
|
/** Ссылка на контейнер, который скроллится */
|
|
111
114
|
scrollContainerRef?: RefObject<HTMLElement>;
|
|
115
|
+
/** Определение какие строки должны быть закреплены в таблице */
|
|
116
|
+
rowPinning?: Pick<RowPinningState, 'top'>;
|
|
112
117
|
}>;
|
|
113
118
|
export type ServerTableProps<TData extends object> = Omit<TableProps<TData>, 'pageSize' | 'pageCount' | 'pagination' | 'search' | 'data'> & {
|
|
114
119
|
/** Данные для отрисовки */
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { ColumnDefinition } from '../../../types';
|
|
2
|
-
export declare function getSelectionCellColumnDef<TData>(): ColumnDefinition<TData>;
|
|
2
|
+
export declare function getSelectionCellColumnDef<TData>(enableSelectPinned: boolean): ColumnDefinition<TData>;
|
|
@@ -23,7 +23,7 @@ function SelectionCell(_a) {
|
|
|
23
23
|
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
24
24
|
_jsx("div", { onClick: handleCellClick, className: styles.selectionCell, "data-test-id": TEST_IDS.rowSelect, children: isMulti ? _jsx(Checkbox, Object.assign({}, props, { size: 's' })) : _jsx(Radio, Object.assign({}, props, { size: 's' })) }));
|
|
25
25
|
}
|
|
26
|
-
export function getSelectionCellColumnDef() {
|
|
26
|
+
export function getSelectionCellColumnDef(enableSelectPinned) {
|
|
27
27
|
return {
|
|
28
28
|
id: 'selectionCell',
|
|
29
29
|
pinned: COLUMN_PIN_POSITION.Left,
|
|
@@ -33,7 +33,7 @@ export function getSelectionCellColumnDef() {
|
|
|
33
33
|
enableResizing: false,
|
|
34
34
|
cell: ({ row, table }) => {
|
|
35
35
|
const disabled = !row.getCanSelect();
|
|
36
|
-
if (disabled)
|
|
36
|
+
if (disabled || (!enableSelectPinned && row.getIsPinned()))
|
|
37
37
|
return null;
|
|
38
38
|
const { enableMultiRowSelection } = table.options;
|
|
39
39
|
const isMulti = typeof enableMultiRowSelection === 'boolean' ? enableMultiRowSelection : true;
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
6
|
"title": "Table",
|
|
7
|
-
"version": "0.
|
|
7
|
+
"version": "0.19.0",
|
|
8
8
|
"sideEffects": [
|
|
9
9
|
"*.css",
|
|
10
10
|
"*.woff",
|
|
@@ -33,16 +33,16 @@
|
|
|
33
33
|
"scripts": {},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@snack-uikit/button": "0.17.1",
|
|
36
|
-
"@snack-uikit/chips": "0.14.
|
|
36
|
+
"@snack-uikit/chips": "0.14.7",
|
|
37
37
|
"@snack-uikit/icon-predefined": "0.5.1",
|
|
38
38
|
"@snack-uikit/icons": "0.21.0",
|
|
39
|
-
"@snack-uikit/info-block": "0.
|
|
40
|
-
"@snack-uikit/list": "0.13.
|
|
39
|
+
"@snack-uikit/info-block": "0.4.0",
|
|
40
|
+
"@snack-uikit/list": "0.13.5",
|
|
41
41
|
"@snack-uikit/pagination": "0.6.8",
|
|
42
42
|
"@snack-uikit/scroll": "0.6.0",
|
|
43
43
|
"@snack-uikit/skeleton": "0.3.4",
|
|
44
44
|
"@snack-uikit/toggles": "0.9.10",
|
|
45
|
-
"@snack-uikit/toolbar": "0.7.
|
|
45
|
+
"@snack-uikit/toolbar": "0.7.40",
|
|
46
46
|
"@snack-uikit/truncate-string": "0.4.17",
|
|
47
47
|
"@snack-uikit/typography": "0.6.2",
|
|
48
48
|
"@snack-uikit/utils": "3.3.0",
|
|
@@ -57,5 +57,5 @@
|
|
|
57
57
|
"peerDependencies": {
|
|
58
58
|
"@snack-uikit/locale": "*"
|
|
59
59
|
},
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "2073ec039b8c391a322e0ad3016fabbe6dfb54bd"
|
|
61
61
|
}
|
|
@@ -46,7 +46,12 @@ import { getColumnStyleVars, getCurrentlyConfiguredHeaderWidth } from './utils';
|
|
|
46
46
|
/** Компонент таблицы */
|
|
47
47
|
export function Table<TData extends object>({
|
|
48
48
|
data,
|
|
49
|
+
rowPinning = {
|
|
50
|
+
top: [],
|
|
51
|
+
},
|
|
49
52
|
columnDefinitions,
|
|
53
|
+
keepPinnedRows = false,
|
|
54
|
+
enableSelectPinned = false,
|
|
50
55
|
rowSelection: rowSelectionProp,
|
|
51
56
|
search,
|
|
52
57
|
sorting: sortingProp,
|
|
@@ -78,6 +83,7 @@ export function Table<TData extends object>({
|
|
|
78
83
|
scrollContainerRef,
|
|
79
84
|
getRowId,
|
|
80
85
|
enableFuzzySearch,
|
|
86
|
+
|
|
81
87
|
...rest
|
|
82
88
|
}: TableProps<TData>) {
|
|
83
89
|
const { state: globalFilter, onStateChange: onGlobalFilterChange } = useStateControl<string>(search, '');
|
|
@@ -85,6 +91,7 @@ export function Table<TData extends object>({
|
|
|
85
91
|
rowSelectionProp,
|
|
86
92
|
{},
|
|
87
93
|
);
|
|
94
|
+
|
|
88
95
|
const defaultPaginationState = useMemo(
|
|
89
96
|
() => ({
|
|
90
97
|
pageIndex: 0,
|
|
@@ -103,10 +110,10 @@ export function Table<TData extends object>({
|
|
|
103
110
|
const tableColumns: ColumnDefinition<TData>[] = useMemo(() => {
|
|
104
111
|
let cols: ColumnDefinition<TData>[] = columnDefinitions;
|
|
105
112
|
if (enableSelection) {
|
|
106
|
-
cols = [getSelectionCellColumnDef(), ...cols];
|
|
113
|
+
cols = [getSelectionCellColumnDef(enableSelectPinned), ...cols];
|
|
107
114
|
}
|
|
108
115
|
return cols;
|
|
109
|
-
}, [columnDefinitions, enableSelection]);
|
|
116
|
+
}, [columnDefinitions, enableSelection, enableSelectPinned]);
|
|
110
117
|
|
|
111
118
|
const columnPinning = useMemo(() => {
|
|
112
119
|
const pinningState: Required<ColumnPinningState> = { left: [], right: [] };
|
|
@@ -128,6 +135,7 @@ export function Table<TData extends object>({
|
|
|
128
135
|
rowSelection,
|
|
129
136
|
sorting,
|
|
130
137
|
pagination,
|
|
138
|
+
rowPinning,
|
|
131
139
|
},
|
|
132
140
|
pageCount,
|
|
133
141
|
defaultColumn: {
|
|
@@ -160,6 +168,7 @@ export function Table<TData extends object>({
|
|
|
160
168
|
getPaginationRowModel: getPaginationRowModel(),
|
|
161
169
|
getCoreRowModel: getCoreRowModel(),
|
|
162
170
|
columnResizeMode: 'onEnd',
|
|
171
|
+
keepPinnedRows,
|
|
163
172
|
});
|
|
164
173
|
|
|
165
174
|
const { loadingTable } = useLoadingTable({ pageSize, columnDefinitions: tableColumns, columnPinning });
|
|
@@ -243,9 +252,17 @@ export function Table<TData extends object>({
|
|
|
243
252
|
}, [columnSizeVars]);
|
|
244
253
|
|
|
245
254
|
const tableRows = table.getRowModel().rows;
|
|
255
|
+
const tableCenterRows = table.getCenterRows();
|
|
256
|
+
const tableFilteredRows = table.getFilteredRowModel().rows;
|
|
257
|
+
const tableFilteredRowsIds = tableFilteredRows.map(row => row.id);
|
|
258
|
+
const topRows = table.getTopRows();
|
|
246
259
|
const loadingTableRows = loadingTable.getRowModel().rows;
|
|
247
260
|
const tablePagination = table.getState().pagination;
|
|
248
261
|
|
|
262
|
+
const filteredTopRows = table.getState().globalFilter
|
|
263
|
+
? topRows.filter(tr => tableFilteredRowsIds.includes(tr.id))
|
|
264
|
+
: topRows;
|
|
265
|
+
|
|
249
266
|
const { t } = useLocale('Table');
|
|
250
267
|
const emptyStates = useEmptyState({ noDataState, noResultsState, errorDataState });
|
|
251
268
|
|
|
@@ -319,8 +336,16 @@ export function Table<TData extends object>({
|
|
|
319
336
|
</SkeletonContextProvider>
|
|
320
337
|
) : (
|
|
321
338
|
<>
|
|
322
|
-
{
|
|
323
|
-
{
|
|
339
|
+
{tableCenterRows.length || filteredTopRows.length ? <HeaderRow /> : null}
|
|
340
|
+
{filteredTopRows.length ? (
|
|
341
|
+
<div className={styles.topRowWrapper}>
|
|
342
|
+
{filteredTopRows.map(row => (
|
|
343
|
+
<BodyRow key={row.id} row={row} onRowClick={onRowClick} />
|
|
344
|
+
))}
|
|
345
|
+
</div>
|
|
346
|
+
) : null}
|
|
347
|
+
|
|
348
|
+
{tableCenterRows.map(row => (
|
|
324
349
|
<BodyRow key={row.id} row={row} onRowClick={onRowClick} />
|
|
325
350
|
))}
|
|
326
351
|
|
|
@@ -66,3 +66,13 @@
|
|
|
66
66
|
margin-top: calc($dimension-025m / -2);
|
|
67
67
|
background: transparent;
|
|
68
68
|
}
|
|
69
|
+
|
|
70
|
+
.topRowWrapper {
|
|
71
|
+
position: sticky;
|
|
72
|
+
z-index: 3;
|
|
73
|
+
top: calc($size-table-line-height);
|
|
74
|
+
|
|
75
|
+
margin-bottom: calc(-1 * $border-width-table);
|
|
76
|
+
|
|
77
|
+
border-bottom: $border-width-table solid $sys-neutral-decor-default;
|
|
78
|
+
}
|
package/src/components/types.ts
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
PaginationState,
|
|
3
|
+
Row,
|
|
4
|
+
RowPinningState,
|
|
5
|
+
RowSelectionOptions,
|
|
6
|
+
RowSelectionState,
|
|
7
|
+
SortingState,
|
|
8
|
+
} from '@tanstack/react-table';
|
|
2
9
|
import { ReactNode, RefObject } from 'react';
|
|
3
10
|
|
|
4
11
|
import { ToolbarProps } from '@snack-uikit/toolbar';
|
|
5
12
|
import { WithSupportProps } from '@snack-uikit/utils';
|
|
6
13
|
|
|
7
|
-
import { RowClickHandler } from '../helperComponents';
|
|
8
|
-
import { EmptyStateProps } from '../helperComponents/TableEmptyState';
|
|
14
|
+
import { EmptyStateProps, RowClickHandler } from '../helperComponents';
|
|
9
15
|
import { ColumnDefinition } from '../types';
|
|
10
16
|
|
|
11
17
|
export type TableProps<TData extends object> = WithSupportProps<{
|
|
@@ -13,6 +19,10 @@ export type TableProps<TData extends object> = WithSupportProps<{
|
|
|
13
19
|
data: TData[];
|
|
14
20
|
/** Определение внешнего вида и функционала колонок */
|
|
15
21
|
columnDefinitions: ColumnDefinition<TData>[];
|
|
22
|
+
/** Параметр овтечает за сохранение закрепленных строк на всех страницах таблицы */
|
|
23
|
+
keepPinnedRows?: boolean;
|
|
24
|
+
/** Параметр овтечает за чекбокс выбора закрепленных строк */
|
|
25
|
+
enableSelectPinned?: boolean;
|
|
16
26
|
/** Параметры отвечают за возможность сортировки, их стоит использовать если нужно отслеживать состояние <br>
|
|
17
27
|
* <strong>initialState</strong>: Начальное состояние сортировки <br>
|
|
18
28
|
* <strong>state</strong>: Состояние сортировки, жестко устанавливаемое снаружи <br>
|
|
@@ -132,6 +142,8 @@ export type TableProps<TData extends object> = WithSupportProps<{
|
|
|
132
142
|
scrollRef?: RefObject<HTMLElement>;
|
|
133
143
|
/** Ссылка на контейнер, который скроллится */
|
|
134
144
|
scrollContainerRef?: RefObject<HTMLElement>;
|
|
145
|
+
/** Определение какие строки должны быть закреплены в таблице */
|
|
146
|
+
rowPinning?: Pick<RowPinningState, 'top'>;
|
|
135
147
|
}>;
|
|
136
148
|
|
|
137
149
|
export type ServerTableProps<TData extends object> = Omit<
|
|
@@ -27,7 +27,7 @@ function SelectionCell({ isMulti, onChange, ...props }: SelectionCellProps) {
|
|
|
27
27
|
);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
export function getSelectionCellColumnDef<TData>(): ColumnDefinition<TData> {
|
|
30
|
+
export function getSelectionCellColumnDef<TData>(enableSelectPinned: boolean): ColumnDefinition<TData> {
|
|
31
31
|
return {
|
|
32
32
|
id: 'selectionCell',
|
|
33
33
|
pinned: COLUMN_PIN_POSITION.Left,
|
|
@@ -38,7 +38,7 @@ export function getSelectionCellColumnDef<TData>(): ColumnDefinition<TData> {
|
|
|
38
38
|
cell: ({ row, table }) => {
|
|
39
39
|
const disabled = !row.getCanSelect();
|
|
40
40
|
|
|
41
|
-
if (disabled) return null;
|
|
41
|
+
if (disabled || (!enableSelectPinned && row.getIsPinned())) return null;
|
|
42
42
|
|
|
43
43
|
const { enableMultiRowSelection } = table.options;
|
|
44
44
|
|