@snack-uikit/table 0.19.6 → 0.20.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 +11 -7
- package/dist/components/Table/Table.d.ts +1 -1
- package/dist/components/Table/Table.js +24 -11
- package/dist/components/Table/hooks/usePageReset.d.ts +2 -1
- package/dist/components/Table/hooks/usePageReset.js +4 -2
- package/dist/components/types.d.ts +12 -5
- package/dist/helperComponents/ExportButton/ExportButton.d.ts +17 -3
- package/dist/helperComponents/ExportButton/ExportButton.js +15 -4
- package/dist/helperComponents/TablePagination/TablePagination.d.ts +2 -1
- package/dist/helperComponents/TablePagination/TablePagination.js +5 -2
- package/package.json +2 -2
- package/src/components/Table/Table.tsx +40 -16
- package/src/components/Table/hooks/usePageReset.ts +5 -1
- package/src/components/types.ts +13 -5
- package/src/helperComponents/ExportButton/ExportButton.tsx +45 -6
- package/src/helperComponents/TablePagination/TablePagination.tsx +10 -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.20.0 (2024-07-10)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **FF-5031:** fix results value view vith non empty filteredTopRows ([49fd328](https://github.com/cloud-ru-tech/snack-uikit/commit/49fd32812bc4a253af8331c649b3dd6b26cde795))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
* **FF-5031:** activate autoResetPageIndex option ([9491074](https://github.com/cloud-ru-tech/snack-uikit/commit/9491074d85507a413c7202fe6050488f0de03dd4))
|
|
17
|
+
* **FF-5031:** add pagination.optionsRender; fix loading skeleton count ([0f518f5](https://github.com/cloud-ru-tech/snack-uikit/commit/0f518f592945b53eb2be18fad50f87251c85b902))
|
|
18
|
+
* **FF-5031:** fix pinned rows selection from toolbar checkbox ([caa0633](https://github.com/cloud-ru-tech/snack-uikit/commit/caa063317ee2b98e1b1e7915d1a159f909699ffa))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### BREAKING CHANGES
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
* **FF-5031:** expand export settings - add formats and filter settings ([b0a6f5a](https://github.com/cloud-ru-tech/snack-uikit/commit/b0a6f5a3650a68762cf0570c1ca7c36de0f201a2))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
6
29
|
## 0.19.6 (2024-07-09)
|
|
7
30
|
|
|
8
31
|
### Only dependencies have been changed
|
package/README.md
CHANGED
|
@@ -111,14 +111,16 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
|
|
|
111
111
|
|------|------|---------------|-------------|
|
|
112
112
|
| columnDefinitions* | `ColumnDefinition<TData>[]` | - | Определение внешнего вида и функционала колонок |
|
|
113
113
|
| data* | `TData[]` | - | Данные для отрисовки |
|
|
114
|
-
| keepPinnedRows | `boolean` | - | Параметр
|
|
115
|
-
|
|
|
114
|
+
| keepPinnedRows | `boolean` | - | Параметр отвечает за отображение закрепленных строк на всех страницах таблицы |
|
|
115
|
+
| copyPinnedRows | `boolean` | - | Параметр отвечает за сохранение закрепленных строк в теле таблицы |
|
|
116
|
+
| enableSelectPinned | `boolean` | - | Параметр отвечает за чекбокс выбора закрепленных строк |
|
|
116
117
|
| sorting | `{ initialState?: SortingState; state?: SortingState; onChange?(state: SortingState): void; }` | - | Параметры отвечают за возможность сортировки, их стоит использовать если нужно отслеживать состояние <br> <strong>initialState</strong>: Начальное состояние сортировки <br> <strong>state</strong>: Состояние сортировки, жестко устанавливаемое снаружи <br> <strong>onChange</strong>: Колбэк на изменение сортировки |
|
|
117
118
|
| 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>: Колбэк на выбор строк |
|
|
118
119
|
| 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 строки поиска |
|
|
119
120
|
| enableFuzzySearch | `boolean` | - | Включить нечеткий поиск |
|
|
120
121
|
| pageSize | `number` | 10 | Максимальное кол-во строк на страницу |
|
|
121
|
-
| pagination | `{ state?: PaginationState; options?: number[]; optionsLabel?: string; onChange?(state: PaginationState): void; }` | 'Rows volume: ' <br> <strong>onChange</strong>: Колбэк на изменение пагинации | Параметры отвечают за пагинацию в таблице <br> <strong>state</strong>: Состояние строки поиска, жестко устанавливаемое снаружи <br> <strong>options</strong>: Варианты в выпадающем селекторе для установки кол-ва строк на страницу <br> <strong>optionsLabel</strong>: Текст для селектора кол-ва строк на страницу |
|
|
122
|
+
| 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>: Текст для селектора кол-ва строк на страницу |
|
|
123
|
+
| autoResetPageIndex | `boolean` | - | Автоматический сброс пагинации к первой странице при изменении данных или состояния (e.g фильтры, сортировки, и т.д) |
|
|
122
124
|
| pageCount | `number` | - | Кол-во страниц (используется для внешнего управления) |
|
|
123
125
|
| onRowClick | `RowClickHandler<TData>` | - | Колбэк клика по строке |
|
|
124
126
|
| className | `string` | - | CSS-класс |
|
|
@@ -129,7 +131,7 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
|
|
|
129
131
|
| columnFilters | `ReactNode` | - | Фильтры |
|
|
130
132
|
| dataFiltered | `boolean` | - | |
|
|
131
133
|
| dataError | `boolean` | - | |
|
|
132
|
-
|
|
|
134
|
+
| exportSettings | `{ fileName: string; format?: Format; filterData?: boolean; }` | - | Настройки экспорта в тулбаре |
|
|
133
135
|
| moreActions | `Action[]` | - | Элементы выпадающего списка кнопки с действиями |
|
|
134
136
|
| noDataState | `EmptyStateProps` | - | Экран при отстутствии данных |
|
|
135
137
|
| noResultsState | `EmptyStateProps` | - | Экран при отстутствии результатов поиска или фильтров |
|
|
@@ -171,11 +173,13 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
|
|
|
171
173
|
| onChangePage* | `(offset: number, limit: number) => void` | - | |
|
|
172
174
|
| columnDefinitions* | `ColumnDefinition<TData>[]` | - | Определение внешнего вида и функционала колонок |
|
|
173
175
|
| loading | `boolean` | - | Состояние загрузки |
|
|
174
|
-
| keepPinnedRows | `boolean` |
|
|
175
|
-
|
|
|
176
|
+
| keepPinnedRows | `boolean` | false | Параметр отвечает за отображение закрепленных строк на всех страницах таблицы |
|
|
177
|
+
| copyPinnedRows | `boolean` | false | Параметр отвечает за сохранение закрепленных строк в теле таблицы |
|
|
178
|
+
| enableSelectPinned | `boolean` | - | Параметр отвечает за чекбокс выбора закрепленных строк |
|
|
176
179
|
| sorting | `{ initialState?: SortingState; state?: SortingState; onChange?(state: SortingState): void; }` | - | Параметры отвечают за возможность сортировки, их стоит использовать если нужно отслеживать состояние <br> <strong>initialState</strong>: Начальное состояние сортировки <br> <strong>state</strong>: Состояние сортировки, жестко устанавливаемое снаружи <br> <strong>onChange</strong>: Колбэк на изменение сортировки |
|
|
177
180
|
| 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>: Колбэк на выбор строк |
|
|
178
181
|
| enableFuzzySearch | `boolean` | - | Включить нечеткий поиск |
|
|
182
|
+
| autoResetPageIndex | `boolean` | - | Автоматический сброс пагинации к первой странице при изменении данных или состояния (e.g фильтры, сортировки, и т.д) |
|
|
179
183
|
| onRowClick | `RowClickHandler<TData>` | - | Колбэк клика по строке |
|
|
180
184
|
| className | `string` | - | CSS-класс |
|
|
181
185
|
| onRefresh | `() => void` | - | Колбек обновления данных |
|
|
@@ -184,7 +188,7 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
|
|
|
184
188
|
| columnFilters | `ReactNode` | - | Фильтры |
|
|
185
189
|
| dataFiltered | `boolean` | - | |
|
|
186
190
|
| dataError | `boolean` | - | |
|
|
187
|
-
|
|
|
191
|
+
| exportSettings | `{ fileName: string; format?: Format; filterData?: boolean; }` | - | Настройки экспорта в тулбаре |
|
|
188
192
|
| moreActions | `Action[]` | - | Элементы выпадающего списка кнопки с действиями |
|
|
189
193
|
| noDataState | `EmptyStateProps` | - | Экран при отстутствии данных |
|
|
190
194
|
| noResultsState | `EmptyStateProps` | - | Экран при отстутствии результатов поиска или фильтров |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TableProps } from '../types';
|
|
2
2
|
/** Компонент таблицы */
|
|
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,
|
|
3
|
+
export declare function Table<TData extends object>({ data, rowPinning, columnDefinitions, keepPinnedRows, copyPinnedRows, enableSelectPinned, rowSelection: rowSelectionProp, search, sorting: sortingProp, columnFilters, pagination: paginationProp, className, onRowClick, onRefresh, onDelete, pageSize, pageCount, loading, outline, moreActions, exportSettings, dataFiltered, dataError, noDataState, noResultsState, errorDataState, suppressToolbar, toolbarBefore, toolbarAfter, suppressPagination, manualSorting, manualPagination, manualFiltering, autoResetPageIndex, 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: {
|
|
@@ -30,7 +30,7 @@ import { getColumnStyleVars, getCurrentlyConfiguredHeaderWidth } from './utils';
|
|
|
30
30
|
export function Table(_a) {
|
|
31
31
|
var { data, rowPinning = {
|
|
32
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,
|
|
33
|
+
}, columnDefinitions, keepPinnedRows = false, copyPinnedRows = 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, exportSettings, dataFiltered, dataError, noDataState, noResultsState, errorDataState, suppressToolbar = false, toolbarBefore, toolbarAfter, suppressPagination = false, manualSorting = false, manualPagination = false, manualFiltering = false, autoResetPageIndex = false, scrollRef, scrollContainerRef, getRowId, enableFuzzySearch } = _a, rest = __rest(_a, ["data", "rowPinning", "columnDefinitions", "keepPinnedRows", "copyPinnedRows", "enableSelectPinned", "rowSelection", "search", "sorting", "columnFilters", "pagination", "className", "onRowClick", "onRefresh", "onDelete", "pageSize", "pageCount", "loading", "outline", "moreActions", "exportSettings", "dataFiltered", "dataError", "noDataState", "noResultsState", "errorDataState", "suppressToolbar", "toolbarBefore", "toolbarAfter", "suppressPagination", "manualSorting", "manualPagination", "manualFiltering", "autoResetPageIndex", "scrollRef", "scrollContainerRef", "getRowId", "enableFuzzySearch"]);
|
|
34
34
|
const { state: globalFilter, onStateChange: onGlobalFilterChange } = useStateControl(search, '');
|
|
35
35
|
const { state: rowSelection, onStateChange: onRowSelectionChange } = useStateControl(rowSelectionProp, {});
|
|
36
36
|
const defaultPaginationState = useMemo(() => ({
|
|
@@ -93,13 +93,17 @@ export function Table(_a) {
|
|
|
93
93
|
onSortingChange,
|
|
94
94
|
getSortedRowModel: getSortedRowModel(),
|
|
95
95
|
onPaginationChange,
|
|
96
|
-
autoResetPageIndex
|
|
96
|
+
autoResetPageIndex,
|
|
97
97
|
getPaginationRowModel: getPaginationRowModel(),
|
|
98
98
|
getCoreRowModel: getCoreRowModel(),
|
|
99
99
|
columnResizeMode: 'onEnd',
|
|
100
100
|
keepPinnedRows,
|
|
101
101
|
});
|
|
102
|
-
const { loadingTable } = useLoadingTable({
|
|
102
|
+
const { loadingTable } = useLoadingTable({
|
|
103
|
+
pageSize: Math.min(Math.max(pageSize, 5), DEFAULT_PAGE_SIZE),
|
|
104
|
+
columnDefinitions: tableColumns,
|
|
105
|
+
columnPinning,
|
|
106
|
+
});
|
|
103
107
|
const handleOnRefresh = useCallback(() => {
|
|
104
108
|
table.resetRowSelection();
|
|
105
109
|
onRefresh === null || onRefresh === void 0 ? void 0 : onRefresh();
|
|
@@ -113,15 +117,22 @@ export function Table(_a) {
|
|
|
113
117
|
}
|
|
114
118
|
}, [loading, onDelete, table]);
|
|
115
119
|
const handleOnCheck = useCallback(() => {
|
|
116
|
-
if (!loading &&
|
|
117
|
-
table.
|
|
120
|
+
if (!loading && !enableSelectPinned && table.getTopRows().length) {
|
|
121
|
+
const centerRows = table.getCenterRows();
|
|
122
|
+
const isSomeRowsSelected = table.getIsSomePageRowsSelected();
|
|
123
|
+
const isAllCenterRowsSelected = centerRows.every(row => row.getIsSelected());
|
|
124
|
+
if (isAllCenterRowsSelected) {
|
|
125
|
+
table.resetRowSelection();
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
centerRows.forEach(row => row.toggleSelected(isSomeRowsSelected ? true : undefined));
|
|
118
129
|
return;
|
|
119
130
|
}
|
|
120
|
-
if (!loading &&
|
|
121
|
-
table.
|
|
131
|
+
if (!loading && (rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow)) {
|
|
132
|
+
table.toggleAllPageRowsSelected();
|
|
122
133
|
return;
|
|
123
134
|
}
|
|
124
|
-
}, [loading, rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow, table]);
|
|
135
|
+
}, [loading, rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow, table, enableSelectPinned]);
|
|
125
136
|
const columnSizeVarsRef = useRef();
|
|
126
137
|
const headers = table.getFlatHeaders();
|
|
127
138
|
const columnSizeVars = useMemo(() => {
|
|
@@ -173,17 +184,19 @@ export function Table(_a) {
|
|
|
173
184
|
const filteredTopRows = table.getState().globalFilter
|
|
174
185
|
? topRows.filter(tr => tableFilteredRowsIds.includes(tr.id))
|
|
175
186
|
: topRows;
|
|
187
|
+
const centerRows = copyPinnedRows ? tableRows : tableCenterRows;
|
|
176
188
|
const { t } = useLocale('Table');
|
|
177
189
|
const emptyStates = useEmptyState({ noDataState, noResultsState, errorDataState });
|
|
178
190
|
const cssPageSize = useMemo(() => {
|
|
179
|
-
const tempPageSize = !suppressPagination ? tablePagination === null || tablePagination === void 0 ? void 0 : tablePagination.pageSize : pageSize;
|
|
191
|
+
const tempPageSize = (!suppressPagination ? tablePagination === null || tablePagination === void 0 ? void 0 : tablePagination.pageSize : pageSize) + filteredTopRows.length;
|
|
180
192
|
return !tableRows.length ? Math.min(Math.max(tempPageSize, 5), DEFAULT_PAGE_SIZE) : tempPageSize;
|
|
181
|
-
}, [pageSize, suppressPagination, tablePagination === null || tablePagination === void 0 ? void 0 : tablePagination.pageSize, tableRows.length]);
|
|
193
|
+
}, [filteredTopRows.length, pageSize, suppressPagination, tablePagination === null || tablePagination === void 0 ? void 0 : tablePagination.pageSize, tableRows.length]);
|
|
182
194
|
usePageReset({
|
|
183
195
|
manualPagination,
|
|
184
196
|
maximumAvailablePage: pageCount || data.length / pagination.pageSize,
|
|
185
197
|
pagination,
|
|
186
198
|
onPaginationChange,
|
|
199
|
+
autoResetPageIndex,
|
|
187
200
|
});
|
|
188
201
|
return (_jsx(_Fragment, { children: _jsxs("div", Object.assign({ style: {
|
|
189
202
|
'--page-size': cssPageSize,
|
|
@@ -192,7 +205,7 @@ export function Table(_a) {
|
|
|
192
205
|
onChange: onGlobalFilterChange,
|
|
193
206
|
loading: search === null || search === void 0 ? void 0 : search.loading,
|
|
194
207
|
placeholder: (search === null || search === void 0 ? void 0 : search.placeholder) || t('searchPlaceholder'),
|
|
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 ||
|
|
208
|
+
}, 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 || exportSettings ? (_jsxs(_Fragment, { children: [toolbarAfter, exportSettings && (_jsx(ExportButton, { settings: exportSettings, columnDefinitions: columnDefinitions, data: data, topRows: filteredTopRows, centerRows: centerRows }))] })) : 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: [centerRows.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, centerRows.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 + filteredTopRows.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, optionsRender: paginationProp === null || paginationProp === void 0 ? void 0 : paginationProp.optionsRender }))] })) }));
|
|
196
209
|
}
|
|
197
210
|
Table.getStatusColumnDef = getStatusColumnDef;
|
|
198
211
|
Table.statusAppearances = STATUS_APPEARANCE;
|
|
@@ -4,6 +4,7 @@ type UsePageResetProps = {
|
|
|
4
4
|
maximumAvailablePage: number;
|
|
5
5
|
pagination: PaginationState;
|
|
6
6
|
onPaginationChange(state: PaginationState): void;
|
|
7
|
+
autoResetPageIndex: boolean;
|
|
7
8
|
};
|
|
8
|
-
export declare function usePageReset({ manualPagination, pagination, maximumAvailablePage, onPaginationChange, }: UsePageResetProps): void;
|
|
9
|
+
export declare function usePageReset({ manualPagination, pagination, maximumAvailablePage, onPaginationChange, autoResetPageIndex, }: UsePageResetProps): void;
|
|
9
10
|
export {};
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { useEffect } from 'react';
|
|
2
|
-
export function usePageReset({ manualPagination, pagination, maximumAvailablePage, onPaginationChange, }) {
|
|
2
|
+
export function usePageReset({ manualPagination, pagination, maximumAvailablePage, onPaginationChange, autoResetPageIndex, }) {
|
|
3
3
|
useEffect(() => {
|
|
4
|
+
if (autoResetPageIndex)
|
|
5
|
+
return;
|
|
4
6
|
const { pageIndex } = pagination;
|
|
5
7
|
if (!manualPagination && pageIndex > 0 && pageIndex >= maximumAvailablePage) {
|
|
6
8
|
onPaginationChange(Object.assign(Object.assign({}, pagination), { pageIndex: 0 }));
|
|
7
9
|
}
|
|
8
|
-
}, [maximumAvailablePage, manualPagination, onPaginationChange, pagination]);
|
|
10
|
+
}, [maximumAvailablePage, manualPagination, onPaginationChange, pagination, autoResetPageIndex]);
|
|
9
11
|
}
|
|
@@ -2,16 +2,18 @@ import { PaginationState, Row, RowPinningState, RowSelectionOptions, RowSelectio
|
|
|
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 { EmptyStateProps, RowClickHandler } from '../helperComponents';
|
|
5
|
+
import { EmptyStateProps, ExportButtonProps, RowClickHandler } from '../helperComponents';
|
|
6
6
|
import { ColumnDefinition } from '../types';
|
|
7
7
|
export type TableProps<TData extends object> = WithSupportProps<{
|
|
8
8
|
/** Данные для отрисовки */
|
|
9
9
|
data: TData[];
|
|
10
10
|
/** Определение внешнего вида и функционала колонок */
|
|
11
11
|
columnDefinitions: ColumnDefinition<TData>[];
|
|
12
|
-
/** Параметр
|
|
12
|
+
/** Параметр отвечает за отображение закрепленных строк на всех страницах таблицы @default false*/
|
|
13
13
|
keepPinnedRows?: boolean;
|
|
14
|
-
/** Параметр
|
|
14
|
+
/** Параметр отвечает за сохранение закрепленных строк в теле таблицы @default false*/
|
|
15
|
+
copyPinnedRows?: boolean;
|
|
16
|
+
/** Параметр отвечает за чекбокс выбора закрепленных строк */
|
|
15
17
|
enableSelectPinned?: boolean;
|
|
16
18
|
/** Параметры отвечают за возможность сортировки, их стоит использовать если нужно отслеживать состояние <br>
|
|
17
19
|
* <strong>initialState</strong>: Начальное состояние сортировки <br>
|
|
@@ -66,7 +68,12 @@ export type TableProps<TData extends object> = WithSupportProps<{
|
|
|
66
68
|
options?: number[];
|
|
67
69
|
optionsLabel?: string;
|
|
68
70
|
onChange?(state: PaginationState): void;
|
|
71
|
+
optionsRender?(value: string | number, idx: number): string | number;
|
|
69
72
|
};
|
|
73
|
+
/** Автоматический сброс пагинации к первой странице при изменении данных или состояния
|
|
74
|
+
* (e.g фильтры, сортировки, и т.д)
|
|
75
|
+
* */
|
|
76
|
+
autoResetPageIndex?: boolean;
|
|
70
77
|
/** Кол-во страниц (используется для внешнего управления) */
|
|
71
78
|
pageCount?: number;
|
|
72
79
|
/** Колбэк клика по строке */
|
|
@@ -85,8 +92,8 @@ export type TableProps<TData extends object> = WithSupportProps<{
|
|
|
85
92
|
columnFilters?: ReactNode;
|
|
86
93
|
dataFiltered?: boolean;
|
|
87
94
|
dataError?: boolean;
|
|
88
|
-
/**
|
|
89
|
-
|
|
95
|
+
/** Настройки экспорта в тулбаре */
|
|
96
|
+
exportSettings?: ExportButtonProps<TData>['settings'];
|
|
90
97
|
/** Элементы выпадающего списка кнопки с действиями */
|
|
91
98
|
moreActions?: ToolbarProps['moreActions'];
|
|
92
99
|
/** Экран при отстутствии данных */
|
|
@@ -1,10 +1,24 @@
|
|
|
1
|
+
import { Row } from '@tanstack/react-table';
|
|
1
2
|
import { ColumnDefinition } from '../../types';
|
|
2
|
-
type
|
|
3
|
+
type Format = {
|
|
4
|
+
csv?: boolean;
|
|
5
|
+
xslx?: boolean;
|
|
6
|
+
};
|
|
7
|
+
export type ExportButtonProps<TData extends object> = {
|
|
3
8
|
/** Данные для отрисовки */
|
|
4
9
|
data: TData[];
|
|
5
10
|
/** Определение внешнего вида и функционала колонок */
|
|
6
11
|
columnDefinitions: ColumnDefinition<TData>[];
|
|
7
|
-
|
|
12
|
+
settings: {
|
|
13
|
+
/** Название файла при экспорте */
|
|
14
|
+
fileName: string;
|
|
15
|
+
/** Доступные форматы экспорта */
|
|
16
|
+
format?: Format;
|
|
17
|
+
/** Настройка фильтрации данных */
|
|
18
|
+
filterData?: boolean;
|
|
19
|
+
};
|
|
20
|
+
topRows: Row<TData>[];
|
|
21
|
+
centerRows: Row<TData>[];
|
|
8
22
|
};
|
|
9
|
-
export declare function ExportButton<TData extends object>({
|
|
23
|
+
export declare function ExportButton<TData extends object>({ settings, data, columnDefinitions, topRows, centerRows, }: ExportButtonProps<TData>): import("react/jsx-runtime").JSX.Element;
|
|
10
24
|
export {};
|
|
@@ -1,27 +1,38 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from 'react';
|
|
2
|
+
import { useMemo, useState } from 'react';
|
|
3
3
|
import { ButtonFunction } from '@snack-uikit/button';
|
|
4
4
|
import { DownloadSVG } from '@snack-uikit/icons';
|
|
5
5
|
import { Droplist } from '@snack-uikit/list';
|
|
6
6
|
import { useLocale } from '@snack-uikit/locale';
|
|
7
7
|
import { exportToCSV, exportToXLSX } from '../../exportTable';
|
|
8
|
-
export function ExportButton({
|
|
8
|
+
export function ExportButton({ settings, data, columnDefinitions, topRows, centerRows, }) {
|
|
9
9
|
const [isOpen, setIsOpen] = useState(false);
|
|
10
10
|
const { t } = useLocale('Table');
|
|
11
|
+
const { fileName, filterData = true } = settings;
|
|
12
|
+
const format = Object.assign({ csv: true, xslx: true }, settings.format);
|
|
13
|
+
const filteredData = useMemo(() => {
|
|
14
|
+
let newData = data;
|
|
15
|
+
if (filterData) {
|
|
16
|
+
newData = [...topRows, ...centerRows].map(row => row.original);
|
|
17
|
+
}
|
|
18
|
+
return newData;
|
|
19
|
+
}, [centerRows, data, filterData, topRows]);
|
|
11
20
|
return (_jsx(Droplist, { trigger: 'clickAndFocusVisible', open: isOpen, onOpenChange: setIsOpen, scroll: true, placement: 'bottom-end', items: [
|
|
12
21
|
{
|
|
13
22
|
content: { option: t('export') + 'CSV' },
|
|
14
23
|
onClick: () => {
|
|
15
|
-
exportToCSV({ fileName, columnDefinitions, data });
|
|
24
|
+
exportToCSV({ fileName, columnDefinitions, data: filteredData });
|
|
16
25
|
setIsOpen(false);
|
|
17
26
|
},
|
|
27
|
+
hidden: !format.csv,
|
|
18
28
|
},
|
|
19
29
|
{
|
|
20
30
|
content: { option: t('export') + 'XLSX' },
|
|
21
31
|
onClick: () => {
|
|
22
|
-
exportToXLSX({ fileName, columnDefinitions, data });
|
|
32
|
+
exportToXLSX({ fileName, columnDefinitions, data: filteredData });
|
|
23
33
|
setIsOpen(false);
|
|
24
34
|
},
|
|
35
|
+
hidden: !format.xslx,
|
|
25
36
|
},
|
|
26
37
|
], children: _jsx(ButtonFunction, { size: 'm', icon: _jsx(DownloadSVG, {}) }) }));
|
|
27
38
|
}
|
|
@@ -3,6 +3,7 @@ export type TablePaginationProps<TData> = {
|
|
|
3
3
|
table: Table<TData>;
|
|
4
4
|
options?: number[];
|
|
5
5
|
optionsLabel?: string;
|
|
6
|
+
optionsRender?(value: number, idx: number): string | number;
|
|
6
7
|
pageCount?: number;
|
|
7
8
|
};
|
|
8
|
-
export declare function TablePagination<TData>({ table, options: optionsProp, optionsLabel: optionsLabelProp, }: TablePaginationProps<TData>): import("react/jsx-runtime").JSX.Element | null;
|
|
9
|
+
export declare function TablePagination<TData>({ table, options: optionsProp, optionsLabel: optionsLabelProp, optionsRender, }: TablePaginationProps<TData>): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -4,7 +4,7 @@ import { ChipChoice } from '@snack-uikit/chips';
|
|
|
4
4
|
import { useLocale } from '@snack-uikit/locale';
|
|
5
5
|
import { Pagination } from '@snack-uikit/pagination';
|
|
6
6
|
import styles from './styles.module.css';
|
|
7
|
-
export function TablePagination({ table, options: optionsProp, optionsLabel: optionsLabelProp, }) {
|
|
7
|
+
export function TablePagination({ table, options: optionsProp, optionsLabel: optionsLabelProp, optionsRender, }) {
|
|
8
8
|
const { t } = useLocale('Table');
|
|
9
9
|
const optionsLabel = optionsLabelProp !== null && optionsLabelProp !== void 0 ? optionsLabelProp : t('rowsOptionsLabel');
|
|
10
10
|
const handlePaginationOnChange = useCallback((pageIndex) => {
|
|
@@ -13,7 +13,10 @@ export function TablePagination({ table, options: optionsProp, optionsLabel: opt
|
|
|
13
13
|
const handleRowsVolumeOnChange = useCallback((value) => {
|
|
14
14
|
table.setPageSize(Number(value));
|
|
15
15
|
}, [table]);
|
|
16
|
-
const options = useMemo(() => optionsProp === null || optionsProp === void 0 ? void 0 : optionsProp.sort((a, b) => a - b).map(
|
|
16
|
+
const options = useMemo(() => optionsProp === null || optionsProp === void 0 ? void 0 : optionsProp.sort((a, b) => a - b).map((value, idx) => ({
|
|
17
|
+
label: String(optionsRender ? optionsRender(value, idx) : value),
|
|
18
|
+
value: String(value),
|
|
19
|
+
})), [optionsProp, optionsRender]);
|
|
17
20
|
const tablePaginationState = table.getState().pagination;
|
|
18
21
|
if (table.getPageCount() <= 1 && !options) {
|
|
19
22
|
return null;
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
6
|
"title": "Table",
|
|
7
|
-
"version": "0.
|
|
7
|
+
"version": "0.20.0",
|
|
8
8
|
"sideEffects": [
|
|
9
9
|
"*.css",
|
|
10
10
|
"*.woff",
|
|
@@ -57,5 +57,5 @@
|
|
|
57
57
|
"peerDependencies": {
|
|
58
58
|
"@snack-uikit/locale": "*"
|
|
59
59
|
},
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "58701999be0e38e97b7182901945b3657231e58c"
|
|
61
61
|
}
|
|
@@ -51,6 +51,7 @@ export function Table<TData extends object>({
|
|
|
51
51
|
},
|
|
52
52
|
columnDefinitions,
|
|
53
53
|
keepPinnedRows = false,
|
|
54
|
+
copyPinnedRows = false,
|
|
54
55
|
enableSelectPinned = false,
|
|
55
56
|
rowSelection: rowSelectionProp,
|
|
56
57
|
search,
|
|
@@ -66,7 +67,7 @@ export function Table<TData extends object>({
|
|
|
66
67
|
loading = false,
|
|
67
68
|
outline = false,
|
|
68
69
|
moreActions,
|
|
69
|
-
|
|
70
|
+
exportSettings,
|
|
70
71
|
dataFiltered,
|
|
71
72
|
dataError,
|
|
72
73
|
noDataState,
|
|
@@ -79,6 +80,7 @@ export function Table<TData extends object>({
|
|
|
79
80
|
manualSorting = false,
|
|
80
81
|
manualPagination = false,
|
|
81
82
|
manualFiltering = false,
|
|
83
|
+
autoResetPageIndex = false,
|
|
82
84
|
scrollRef,
|
|
83
85
|
scrollContainerRef,
|
|
84
86
|
getRowId,
|
|
@@ -164,14 +166,18 @@ export function Table<TData extends object>({
|
|
|
164
166
|
onSortingChange,
|
|
165
167
|
getSortedRowModel: getSortedRowModel(),
|
|
166
168
|
onPaginationChange,
|
|
167
|
-
autoResetPageIndex
|
|
169
|
+
autoResetPageIndex,
|
|
168
170
|
getPaginationRowModel: getPaginationRowModel(),
|
|
169
171
|
getCoreRowModel: getCoreRowModel(),
|
|
170
172
|
columnResizeMode: 'onEnd',
|
|
171
173
|
keepPinnedRows,
|
|
172
174
|
});
|
|
173
175
|
|
|
174
|
-
const { loadingTable } = useLoadingTable({
|
|
176
|
+
const { loadingTable } = useLoadingTable({
|
|
177
|
+
pageSize: Math.min(Math.max(pageSize, 5), DEFAULT_PAGE_SIZE),
|
|
178
|
+
columnDefinitions: tableColumns,
|
|
179
|
+
columnPinning,
|
|
180
|
+
});
|
|
175
181
|
|
|
176
182
|
const handleOnRefresh = useCallback(() => {
|
|
177
183
|
table.resetRowSelection();
|
|
@@ -189,16 +195,25 @@ export function Table<TData extends object>({
|
|
|
189
195
|
}, [loading, onDelete, table]);
|
|
190
196
|
|
|
191
197
|
const handleOnCheck = useCallback(() => {
|
|
192
|
-
if (!loading &&
|
|
193
|
-
table.
|
|
198
|
+
if (!loading && !enableSelectPinned && table.getTopRows().length) {
|
|
199
|
+
const centerRows = table.getCenterRows();
|
|
200
|
+
const isSomeRowsSelected = table.getIsSomePageRowsSelected();
|
|
201
|
+
const isAllCenterRowsSelected = centerRows.every(row => row.getIsSelected());
|
|
202
|
+
|
|
203
|
+
if (isAllCenterRowsSelected) {
|
|
204
|
+
table.resetRowSelection();
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
centerRows.forEach(row => row.toggleSelected(isSomeRowsSelected ? true : undefined));
|
|
194
209
|
return;
|
|
195
210
|
}
|
|
196
211
|
|
|
197
|
-
if (!loading &&
|
|
198
|
-
table.
|
|
212
|
+
if (!loading && rowSelectionProp?.multiRow) {
|
|
213
|
+
table.toggleAllPageRowsSelected();
|
|
199
214
|
return;
|
|
200
215
|
}
|
|
201
|
-
}, [loading, rowSelectionProp?.multiRow, table]);
|
|
216
|
+
}, [loading, rowSelectionProp?.multiRow, table, enableSelectPinned]);
|
|
202
217
|
|
|
203
218
|
const columnSizeVarsRef = useRef<Record<string, string>>();
|
|
204
219
|
const headers = table.getFlatHeaders();
|
|
@@ -262,21 +277,23 @@ export function Table<TData extends object>({
|
|
|
262
277
|
const filteredTopRows = table.getState().globalFilter
|
|
263
278
|
? topRows.filter(tr => tableFilteredRowsIds.includes(tr.id))
|
|
264
279
|
: topRows;
|
|
280
|
+
const centerRows = copyPinnedRows ? tableRows : tableCenterRows;
|
|
265
281
|
|
|
266
282
|
const { t } = useLocale('Table');
|
|
267
283
|
const emptyStates = useEmptyState({ noDataState, noResultsState, errorDataState });
|
|
268
284
|
|
|
269
285
|
const cssPageSize = useMemo(() => {
|
|
270
|
-
const tempPageSize = !suppressPagination ? tablePagination?.pageSize : pageSize;
|
|
286
|
+
const tempPageSize = (!suppressPagination ? tablePagination?.pageSize : pageSize) + filteredTopRows.length;
|
|
271
287
|
|
|
272
288
|
return !tableRows.length ? Math.min(Math.max(tempPageSize, 5), DEFAULT_PAGE_SIZE) : tempPageSize;
|
|
273
|
-
}, [pageSize, suppressPagination, tablePagination?.pageSize, tableRows.length]);
|
|
289
|
+
}, [filteredTopRows.length, pageSize, suppressPagination, tablePagination?.pageSize, tableRows.length]);
|
|
274
290
|
|
|
275
291
|
usePageReset({
|
|
276
292
|
manualPagination,
|
|
277
293
|
maximumAvailablePage: pageCount || data.length / pagination.pageSize,
|
|
278
294
|
pagination,
|
|
279
295
|
onPaginationChange,
|
|
296
|
+
autoResetPageIndex,
|
|
280
297
|
});
|
|
281
298
|
|
|
282
299
|
return (
|
|
@@ -307,11 +324,17 @@ export function Table<TData extends object>({
|
|
|
307
324
|
selectionMode={rowSelectionProp?.multiRow ? 'multiple' : 'single'}
|
|
308
325
|
before={toolbarBefore}
|
|
309
326
|
after={
|
|
310
|
-
toolbarAfter ||
|
|
327
|
+
toolbarAfter || exportSettings ? (
|
|
311
328
|
<>
|
|
312
329
|
{toolbarAfter}
|
|
313
|
-
{
|
|
314
|
-
<ExportButton
|
|
330
|
+
{exportSettings && (
|
|
331
|
+
<ExportButton
|
|
332
|
+
settings={exportSettings}
|
|
333
|
+
columnDefinitions={columnDefinitions}
|
|
334
|
+
data={data}
|
|
335
|
+
topRows={filteredTopRows}
|
|
336
|
+
centerRows={centerRows}
|
|
337
|
+
/>
|
|
315
338
|
)}
|
|
316
339
|
</>
|
|
317
340
|
) : undefined
|
|
@@ -336,7 +359,7 @@ export function Table<TData extends object>({
|
|
|
336
359
|
</SkeletonContextProvider>
|
|
337
360
|
) : (
|
|
338
361
|
<>
|
|
339
|
-
{
|
|
362
|
+
{centerRows.length || filteredTopRows.length ? <HeaderRow /> : null}
|
|
340
363
|
{filteredTopRows.length ? (
|
|
341
364
|
<div className={styles.topRowWrapper}>
|
|
342
365
|
{filteredTopRows.map(row => (
|
|
@@ -345,7 +368,7 @@ export function Table<TData extends object>({
|
|
|
345
368
|
</div>
|
|
346
369
|
) : null}
|
|
347
370
|
|
|
348
|
-
{
|
|
371
|
+
{centerRows.map(row => (
|
|
349
372
|
<BodyRow key={row.id} row={row} onRowClick={onRowClick} />
|
|
350
373
|
))}
|
|
351
374
|
|
|
@@ -353,7 +376,7 @@ export function Table<TData extends object>({
|
|
|
353
376
|
emptyStates={emptyStates}
|
|
354
377
|
dataError={dataError}
|
|
355
378
|
dataFiltered={dataFiltered || Boolean(table.getState().globalFilter)}
|
|
356
|
-
tableRowsLength={tableRows.length}
|
|
379
|
+
tableRowsLength={tableRows.length + filteredTopRows.length}
|
|
357
380
|
/>
|
|
358
381
|
</>
|
|
359
382
|
)}
|
|
@@ -369,6 +392,7 @@ export function Table<TData extends object>({
|
|
|
369
392
|
options={paginationProp?.options}
|
|
370
393
|
optionsLabel={paginationProp?.optionsLabel}
|
|
371
394
|
pageCount={pageCount}
|
|
395
|
+
optionsRender={paginationProp?.optionsRender}
|
|
372
396
|
/>
|
|
373
397
|
)}
|
|
374
398
|
</div>
|
|
@@ -6,6 +6,7 @@ type UsePageResetProps = {
|
|
|
6
6
|
maximumAvailablePage: number;
|
|
7
7
|
pagination: PaginationState;
|
|
8
8
|
onPaginationChange(state: PaginationState): void;
|
|
9
|
+
autoResetPageIndex: boolean;
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
export function usePageReset({
|
|
@@ -13,12 +14,15 @@ export function usePageReset({
|
|
|
13
14
|
pagination,
|
|
14
15
|
maximumAvailablePage,
|
|
15
16
|
onPaginationChange,
|
|
17
|
+
autoResetPageIndex,
|
|
16
18
|
}: UsePageResetProps) {
|
|
17
19
|
useEffect(() => {
|
|
20
|
+
if (autoResetPageIndex) return;
|
|
21
|
+
|
|
18
22
|
const { pageIndex } = pagination;
|
|
19
23
|
|
|
20
24
|
if (!manualPagination && pageIndex > 0 && pageIndex >= maximumAvailablePage) {
|
|
21
25
|
onPaginationChange({ ...pagination, pageIndex: 0 });
|
|
22
26
|
}
|
|
23
|
-
}, [maximumAvailablePage, manualPagination, onPaginationChange, pagination]);
|
|
27
|
+
}, [maximumAvailablePage, manualPagination, onPaginationChange, pagination, autoResetPageIndex]);
|
|
24
28
|
}
|
package/src/components/types.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { ReactNode, RefObject } from 'react';
|
|
|
11
11
|
import { ToolbarProps } from '@snack-uikit/toolbar';
|
|
12
12
|
import { WithSupportProps } from '@snack-uikit/utils';
|
|
13
13
|
|
|
14
|
-
import { EmptyStateProps, RowClickHandler } from '../helperComponents';
|
|
14
|
+
import { EmptyStateProps, ExportButtonProps, RowClickHandler } from '../helperComponents';
|
|
15
15
|
import { ColumnDefinition } from '../types';
|
|
16
16
|
|
|
17
17
|
export type TableProps<TData extends object> = WithSupportProps<{
|
|
@@ -19,9 +19,11 @@ export type TableProps<TData extends object> = WithSupportProps<{
|
|
|
19
19
|
data: TData[];
|
|
20
20
|
/** Определение внешнего вида и функционала колонок */
|
|
21
21
|
columnDefinitions: ColumnDefinition<TData>[];
|
|
22
|
-
/** Параметр
|
|
22
|
+
/** Параметр отвечает за отображение закрепленных строк на всех страницах таблицы @default false*/
|
|
23
23
|
keepPinnedRows?: boolean;
|
|
24
|
-
/** Параметр
|
|
24
|
+
/** Параметр отвечает за сохранение закрепленных строк в теле таблицы @default false*/
|
|
25
|
+
copyPinnedRows?: boolean;
|
|
26
|
+
/** Параметр отвечает за чекбокс выбора закрепленных строк */
|
|
25
27
|
enableSelectPinned?: boolean;
|
|
26
28
|
/** Параметры отвечают за возможность сортировки, их стоит использовать если нужно отслеживать состояние <br>
|
|
27
29
|
* <strong>initialState</strong>: Начальное состояние сортировки <br>
|
|
@@ -79,8 +81,14 @@ export type TableProps<TData extends object> = WithSupportProps<{
|
|
|
79
81
|
options?: number[];
|
|
80
82
|
optionsLabel?: string;
|
|
81
83
|
onChange?(state: PaginationState): void;
|
|
84
|
+
optionsRender?(value: string | number, idx: number): string | number;
|
|
82
85
|
};
|
|
83
86
|
|
|
87
|
+
/** Автоматический сброс пагинации к первой странице при изменении данных или состояния
|
|
88
|
+
* (e.g фильтры, сортировки, и т.д)
|
|
89
|
+
* */
|
|
90
|
+
autoResetPageIndex?: boolean;
|
|
91
|
+
|
|
84
92
|
/** Кол-во страниц (используется для внешнего управления) */
|
|
85
93
|
pageCount?: number;
|
|
86
94
|
|
|
@@ -107,8 +115,8 @@ export type TableProps<TData extends object> = WithSupportProps<{
|
|
|
107
115
|
dataFiltered?: boolean;
|
|
108
116
|
dataError?: boolean;
|
|
109
117
|
|
|
110
|
-
/**
|
|
111
|
-
|
|
118
|
+
/** Настройки экспорта в тулбаре */
|
|
119
|
+
exportSettings?: ExportButtonProps<TData>['settings'];
|
|
112
120
|
|
|
113
121
|
/** Элементы выпадающего списка кнопки с действиями */
|
|
114
122
|
moreActions?: ToolbarProps['moreActions'];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Row } from '@tanstack/react-table';
|
|
2
|
+
import { useMemo, useState } from 'react';
|
|
2
3
|
|
|
3
4
|
import { ButtonFunction } from '@snack-uikit/button';
|
|
4
5
|
import { DownloadSVG } from '@snack-uikit/icons';
|
|
@@ -8,19 +9,55 @@ import { useLocale } from '@snack-uikit/locale';
|
|
|
8
9
|
import { exportToCSV, exportToXLSX } from '../../exportTable';
|
|
9
10
|
import { ColumnDefinition } from '../../types';
|
|
10
11
|
|
|
11
|
-
type
|
|
12
|
+
type Format = {
|
|
13
|
+
csv?: boolean;
|
|
14
|
+
xslx?: boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type ExportButtonProps<TData extends object> = {
|
|
12
18
|
/** Данные для отрисовки */
|
|
13
19
|
data: TData[];
|
|
14
20
|
/** Определение внешнего вида и функционала колонок */
|
|
15
21
|
columnDefinitions: ColumnDefinition<TData>[];
|
|
16
22
|
|
|
17
|
-
|
|
23
|
+
settings: {
|
|
24
|
+
/** Название файла при экспорте */
|
|
25
|
+
fileName: string;
|
|
26
|
+
|
|
27
|
+
/** Доступные форматы экспорта */
|
|
28
|
+
format?: Format;
|
|
29
|
+
|
|
30
|
+
/** Настройка фильтрации данных */
|
|
31
|
+
filterData?: boolean;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
topRows: Row<TData>[];
|
|
35
|
+
centerRows: Row<TData>[];
|
|
18
36
|
};
|
|
19
37
|
|
|
20
|
-
export function ExportButton<TData extends object>({
|
|
38
|
+
export function ExportButton<TData extends object>({
|
|
39
|
+
settings,
|
|
40
|
+
data,
|
|
41
|
+
columnDefinitions,
|
|
42
|
+
topRows,
|
|
43
|
+
centerRows,
|
|
44
|
+
}: ExportButtonProps<TData>) {
|
|
21
45
|
const [isOpen, setIsOpen] = useState<boolean>(false);
|
|
22
46
|
const { t } = useLocale('Table');
|
|
23
47
|
|
|
48
|
+
const { fileName, filterData = true } = settings;
|
|
49
|
+
const format: Format = Object.assign({ csv: true, xslx: true }, settings.format);
|
|
50
|
+
|
|
51
|
+
const filteredData = useMemo(() => {
|
|
52
|
+
let newData = data;
|
|
53
|
+
|
|
54
|
+
if (filterData) {
|
|
55
|
+
newData = [...topRows, ...centerRows].map(row => row.original);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return newData;
|
|
59
|
+
}, [centerRows, data, filterData, topRows]);
|
|
60
|
+
|
|
24
61
|
return (
|
|
25
62
|
<Droplist
|
|
26
63
|
trigger='clickAndFocusVisible'
|
|
@@ -32,16 +69,18 @@ export function ExportButton<TData extends object>({ fileName, data, columnDefin
|
|
|
32
69
|
{
|
|
33
70
|
content: { option: t('export') + 'CSV' },
|
|
34
71
|
onClick: () => {
|
|
35
|
-
exportToCSV<TData>({ fileName, columnDefinitions, data });
|
|
72
|
+
exportToCSV<TData>({ fileName, columnDefinitions, data: filteredData });
|
|
36
73
|
setIsOpen(false);
|
|
37
74
|
},
|
|
75
|
+
hidden: !format.csv,
|
|
38
76
|
},
|
|
39
77
|
{
|
|
40
78
|
content: { option: t('export') + 'XLSX' },
|
|
41
79
|
onClick: () => {
|
|
42
|
-
exportToXLSX<TData>({ fileName, columnDefinitions, data });
|
|
80
|
+
exportToXLSX<TData>({ fileName, columnDefinitions, data: filteredData });
|
|
43
81
|
setIsOpen(false);
|
|
44
82
|
},
|
|
83
|
+
hidden: !format.xslx,
|
|
45
84
|
},
|
|
46
85
|
]}
|
|
47
86
|
>
|
|
@@ -11,6 +11,7 @@ export type TablePaginationProps<TData> = {
|
|
|
11
11
|
table: Table<TData>;
|
|
12
12
|
options?: number[];
|
|
13
13
|
optionsLabel?: string;
|
|
14
|
+
optionsRender?(value: number, idx: number): string | number;
|
|
14
15
|
pageCount?: number;
|
|
15
16
|
};
|
|
16
17
|
|
|
@@ -18,6 +19,7 @@ export function TablePagination<TData>({
|
|
|
18
19
|
table,
|
|
19
20
|
options: optionsProp,
|
|
20
21
|
optionsLabel: optionsLabelProp,
|
|
22
|
+
optionsRender,
|
|
21
23
|
}: TablePaginationProps<TData>) {
|
|
22
24
|
const { t } = useLocale('Table');
|
|
23
25
|
const optionsLabel = optionsLabelProp ?? t('rowsOptionsLabel');
|
|
@@ -37,8 +39,14 @@ export function TablePagination<TData>({
|
|
|
37
39
|
);
|
|
38
40
|
|
|
39
41
|
const options = useMemo(
|
|
40
|
-
() =>
|
|
41
|
-
|
|
42
|
+
() =>
|
|
43
|
+
optionsProp
|
|
44
|
+
?.sort((a, b) => a - b)
|
|
45
|
+
.map((value, idx) => ({
|
|
46
|
+
label: String(optionsRender ? optionsRender(value, idx) : value),
|
|
47
|
+
value: String(value),
|
|
48
|
+
})),
|
|
49
|
+
[optionsProp, optionsRender],
|
|
42
50
|
);
|
|
43
51
|
|
|
44
52
|
const tablePaginationState = table.getState().pagination;
|