@snack-uikit/table 0.26.7 → 0.27.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,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # 0.27.0 (2025-01-23)
7
+
8
+
9
+ ### BREAKING CHANGES
10
+
11
+
12
+ * **PDS-926:** add bulkActions prop, remove onDelete and toolbarBefore props ([e9e9afd](https://github.com/cloud-ru-tech/snack-uikit/commit/e9e9afdd0e69ed505bee6157151879fe01bcaf57))
13
+
14
+
15
+
16
+
6
17
  ## 0.26.7 (2025-01-22)
7
18
 
8
19
  ### Only dependencies have been changed
package/README.md CHANGED
@@ -127,19 +127,18 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
127
127
  | className | `string` | - | CSS-класс |
128
128
  | loading | `boolean` | - | Состояние загрузки |
129
129
  | onRefresh | `() => void` | - | Колбек обновления данных |
130
- | onDelete | `(selectionState: RowSelectionState, resetRowSelection: (defaultState?: boolean) => void) => void` | - | Колбек удаления выбранных |
131
130
  | outline | `boolean` | - | Внешний бордер для тулбара и таблицы |
132
131
  | columnFilters | `ReactNode` | - | Фильтры |
133
132
  | dataFiltered | `boolean` | - | |
134
133
  | dataError | `boolean` | - | |
135
- | exportSettings | `{ fileName: string; filterData?: boolean; exportToCSV?(args: ExportProps<TData>): void; exportToXLSX?(args: ExportProps<TData>): void; }` | - | Настройки экспорта в тулбаре |
136
- | moreActions | `Action[]` | - | Элементы выпадающего списка кнопки с действиями |
137
134
  | noDataState | `EmptyStateProps` | - | Экран при отстутствии данных |
138
135
  | noResultsState | `EmptyStateProps` | - | Экран при отстутствии результатов поиска или фильтров |
139
136
  | errorDataState | `EmptyStateProps` | - | Экран при ошибке запроса |
140
137
  | suppressToolbar | `boolean` | - | Отключение тулбара |
141
- | toolbarBefore | `ReactNode` | - | Дополнительный слот в `Toolbar` перед строкой поиска |
138
+ | bulkActions | `BulkAction[]` | - | Список действия для массовых операций |
139
+ | moreActions | `Action[]` | - | Элементы выпадающего списка кнопки с действиями |
142
140
  | toolbarAfter | `ReactNode` | - | Дополнительный слот в `Toolbar` после строки поиска |
141
+ | exportSettings | `{ fileName: string; filterData?: boolean; exportToCSV?(args: ExportProps<TData>): void; exportToXLSX?(args: ExportProps<TData>): void; }` | - | Настройки экспорта в тулбаре |
143
142
  | suppressPagination | `boolean` | - | Отключение пагинации |
144
143
  | manualSorting | `boolean` | - | |
145
144
  | manualPagination | `boolean` | - | |
@@ -188,19 +187,18 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
188
187
  | className | `string` | - | CSS-класс |
189
188
  | loading | `boolean` | - | Состояние загрузки |
190
189
  | onRefresh | `() => void` | - | Колбек обновления данных |
191
- | onDelete | `(selectionState: RowSelectionState, resetRowSelection: (defaultState?: boolean) => void) => void` | - | Колбек удаления выбранных |
192
190
  | outline | `boolean` | - | Внешний бордер для тулбара и таблицы |
193
191
  | columnFilters | `ReactNode` | - | Фильтры |
194
192
  | dataFiltered | `boolean` | - | |
195
193
  | dataError | `boolean` | - | |
196
- | exportSettings | `{ fileName: string; filterData?: boolean; exportToCSV?(args: ExportProps<TData>): void; exportToXLSX?(args: ExportProps<TData>): void; }` | - | Настройки экспорта в тулбаре |
197
- | moreActions | `Action[]` | - | Элементы выпадающего списка кнопки с действиями |
198
194
  | noDataState | `EmptyStateProps` | - | Экран при отстутствии данных |
199
195
  | noResultsState | `EmptyStateProps` | - | Экран при отстутствии результатов поиска или фильтров |
200
196
  | errorDataState | `EmptyStateProps` | - | Экран при ошибке запроса |
201
197
  | suppressToolbar | `boolean` | - | Отключение тулбара |
202
- | toolbarBefore | `ReactNode` | - | Дополнительный слот в `Toolbar` перед строкой поиска |
198
+ | bulkActions | `BulkAction[]` | - | Список действия для массовых операций |
199
+ | moreActions | `Action[]` | - | Элементы выпадающего списка кнопки с действиями |
203
200
  | toolbarAfter | `ReactNode` | - | Дополнительный слот в `Toolbar` после строки поиска |
201
+ | exportSettings | `{ fileName: string; filterData?: boolean; exportToCSV?(args: ExportProps<TData>): void; exportToXLSX?(args: ExportProps<TData>): void; }` | - | Настройки экспорта в тулбаре |
204
202
  | suppressPagination | `boolean` | - | Отключение пагинации |
205
203
  | manualSorting | `boolean` | true | |
206
204
  | manualPagination | `boolean` | true | |
@@ -1,6 +1,6 @@
1
1
  import { TableProps } from '../types';
2
2
  /** Компонент таблицы */
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, savedState, expanding, ...rest }: TableProps<TData>): import("react/jsx-runtime").JSX.Element;
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, pageSize, pageCount, loading, outline, moreActions, exportSettings, dataFiltered, dataError, noDataState, noResultsState, errorDataState, suppressToolbar, toolbarAfter, suppressPagination, manualSorting, manualPagination, manualFiltering, autoResetPageIndex, scrollRef, scrollContainerRef, getRowId, enableFuzzySearch, savedState, expanding, bulkActions: bulkActionsProp, ...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: Record<string, string>;
@@ -55,7 +55,6 @@ function Table(_a) {
55
55
  className,
56
56
  onRowClick,
57
57
  onRefresh,
58
- onDelete,
59
58
  pageSize = constants_1.DEFAULT_PAGE_SIZE,
60
59
  pageCount,
61
60
  loading = false,
@@ -68,7 +67,6 @@ function Table(_a) {
68
67
  noResultsState,
69
68
  errorDataState,
70
69
  suppressToolbar = false,
71
- toolbarBefore,
72
70
  toolbarAfter,
73
71
  suppressPagination = false,
74
72
  manualSorting = false,
@@ -80,9 +78,10 @@ function Table(_a) {
80
78
  getRowId,
81
79
  enableFuzzySearch,
82
80
  savedState,
83
- expanding
81
+ expanding,
82
+ bulkActions: bulkActionsProp
84
83
  } = _a,
85
- 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", "savedState", "expanding"]);
84
+ rest = __rest(_a, ["data", "rowPinning", "columnDefinitions", "keepPinnedRows", "copyPinnedRows", "enableSelectPinned", "rowSelection", "search", "sorting", "columnFilters", "pagination", "className", "onRowClick", "onRefresh", "pageSize", "pageCount", "loading", "outline", "moreActions", "exportSettings", "dataFiltered", "dataError", "noDataState", "noResultsState", "errorDataState", "suppressToolbar", "toolbarAfter", "suppressPagination", "manualSorting", "manualPagination", "manualFiltering", "autoResetPageIndex", "scrollRef", "scrollContainerRef", "getRowId", "enableFuzzySearch", "savedState", "expanding", "bulkActions"]);
86
85
  const {
87
86
  state: globalFilter,
88
87
  onStateChange: onGlobalFilterChange
@@ -203,14 +202,12 @@ function Table(_a) {
203
202
  table.resetRowSelection();
204
203
  onRefresh === null || onRefresh === void 0 ? void 0 : onRefresh();
205
204
  }, [onRefresh, table]);
206
- const handleOnDelete = (0, react_1.useCallback)(() => {
207
- if (loading) {
208
- return;
209
- }
210
- if (onDelete) {
211
- onDelete(table.getState().rowSelection, table.resetRowSelection);
205
+ const bulkActions = (0, react_1.useMemo)(() => enableSelection ? bulkActionsProp === null || bulkActionsProp === void 0 ? void 0 : bulkActionsProp.map(action => Object.assign(Object.assign({}, action), {
206
+ onClick: () => {
207
+ var _a;
208
+ return (_a = action.onClick) === null || _a === void 0 ? void 0 : _a.call(action, table.getState().rowSelection, table.resetRowSelection);
212
209
  }
213
- }, [loading, onDelete, table]);
210
+ })) : undefined, [bulkActionsProp, enableSelection, table]);
214
211
  const handleOnCheck = (0, react_1.useCallback)(() => {
215
212
  if (!loading && !enableSelectPinned && table.getTopRows().length) {
216
213
  const centerRows = table.getCenterRows();
@@ -345,15 +342,14 @@ function Table(_a) {
345
342
  loading: search === null || search === void 0 ? void 0 : search.loading,
346
343
  placeholder: (search === null || search === void 0 ? void 0 : search.placeholder) || t('searchPlaceholder')
347
344
  },
348
- checked: table.getIsAllPageRowsSelected(),
349
- indeterminate: table.getIsSomePageRowsSelected(),
350
345
  className: styles_module_scss_1.default.toolbar,
351
346
  onRefresh: onRefresh ? handleOnRefresh : undefined,
352
- onDelete: enableSelection && onDelete ? handleOnDelete : undefined,
347
+ bulkActions: bulkActions,
348
+ selectionMode: (rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow) ? 'multiple' : 'single',
349
+ checked: table.getIsAllPageRowsSelected(),
350
+ indeterminate: table.getIsSomePageRowsSelected(),
353
351
  onCheck: enableSelection ? handleOnCheck : undefined,
354
352
  outline: outline,
355
- selectionMode: (rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow) ? 'multiple' : 'single',
356
- before: toolbarBefore,
357
353
  after: toolbarAfter || exportSettings ? (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, {
358
354
  children: [toolbarAfter, exportSettings && (0, jsx_runtime_1.jsx)(helperComponents_1.ExportButton, {
359
355
  settings: exportSettings,
@@ -5,6 +5,9 @@ import { WithSupportProps } from '@snack-uikit/utils';
5
5
  import { EmptyStateProps, ExportButtonProps, RowClickHandler } from '../helperComponents';
6
6
  import { TreeColumnDefinitionProps } from '../helperComponents/Cells/TreeCell';
7
7
  import { ColumnDefinition } from '../types';
8
+ type BulkAction = Omit<NonNullable<ToolbarProps['bulkActions']>[number], 'onClick'> & {
9
+ onClick?(selectionState: RowSelectionState, resetRowSelection: (defaultState?: boolean) => void): void;
10
+ };
8
11
  export type TableProps<TData extends object> = WithSupportProps<{
9
12
  /** Данные для отрисовки */
10
13
  data: TData[];
@@ -91,18 +94,12 @@ export type TableProps<TData extends object> = WithSupportProps<{
91
94
  loading?: boolean;
92
95
  /** Колбек обновления данных */
93
96
  onRefresh?(): void;
94
- /** Колбек удаления выбранных */
95
- onDelete?(selectionState: RowSelectionState, resetRowSelection: (defaultState?: boolean) => void): void;
96
97
  /** Внешний бордер для тулбара и таблицы */
97
98
  outline?: boolean;
98
99
  /** Фильтры */
99
100
  columnFilters?: ReactNode;
100
101
  dataFiltered?: boolean;
101
102
  dataError?: boolean;
102
- /** Настройки экспорта в тулбаре */
103
- exportSettings?: ExportButtonProps<TData>['settings'];
104
- /** Элементы выпадающего списка кнопки с действиями */
105
- moreActions?: ToolbarProps['moreActions'];
106
103
  /** Экран при отстутствии данных */
107
104
  noDataState?: EmptyStateProps;
108
105
  /** Экран при отстутствии результатов поиска или фильтров */
@@ -111,10 +108,14 @@ export type TableProps<TData extends object> = WithSupportProps<{
111
108
  errorDataState?: EmptyStateProps;
112
109
  /** Отключение тулбара */
113
110
  suppressToolbar?: boolean;
114
- /** Дополнительный слот в `Toolbar` перед строкой поиска */
115
- toolbarBefore?: ReactNode;
111
+ /** Список действия для массовых операций */
112
+ bulkActions?: BulkAction[];
113
+ /** Элементы выпадающего списка кнопки с действиями */
114
+ moreActions?: ToolbarProps['moreActions'];
116
115
  /** Дополнительный слот в `Toolbar` после строки поиска */
117
116
  toolbarAfter?: ReactNode;
117
+ /** Настройки экспорта в тулбаре */
118
+ exportSettings?: ExportButtonProps<TData>['settings'];
118
119
  /** Отключение пагинации */
119
120
  suppressPagination?: boolean;
120
121
  manualSorting?: boolean;
@@ -179,3 +180,4 @@ export type ServerTableProps<TData extends object> = Omit<TableProps<TData>, 'pa
179
180
  optionsLabel?: string;
180
181
  };
181
182
  };
183
+ export {};
@@ -1,6 +1,6 @@
1
1
  import { TableProps } from '../types';
2
2
  /** Компонент таблицы */
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, savedState, expanding, ...rest }: TableProps<TData>): import("react/jsx-runtime").JSX.Element;
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, pageSize, pageCount, loading, outline, moreActions, exportSettings, dataFiltered, dataError, noDataState, noResultsState, errorDataState, suppressToolbar, toolbarAfter, suppressPagination, manualSorting, manualPagination, manualFiltering, autoResetPageIndex, scrollRef, scrollContainerRef, getRowId, enableFuzzySearch, savedState, expanding, bulkActions: bulkActionsProp, ...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: Record<string, string>;
@@ -32,7 +32,7 @@ import { getColumnStyleVars, getCurrentlyConfiguredHeaderWidth, getInitColumnSiz
32
32
  export function Table(_a) {
33
33
  var { data, rowPinning = {
34
34
  top: [],
35
- }, 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, savedState, expanding } = _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", "savedState", "expanding"]);
35
+ }, columnDefinitions, keepPinnedRows = false, copyPinnedRows = false, enableSelectPinned = false, rowSelection: rowSelectionProp, search, sorting: sortingProp, columnFilters, pagination: paginationProp, className, onRowClick, onRefresh, pageSize = DEFAULT_PAGE_SIZE, pageCount, loading = false, outline = false, moreActions, exportSettings, dataFiltered, dataError, noDataState, noResultsState, errorDataState, suppressToolbar = false, toolbarAfter, suppressPagination = false, manualSorting = false, manualPagination = false, manualFiltering = false, autoResetPageIndex = false, scrollRef, scrollContainerRef, getRowId, enableFuzzySearch, savedState, expanding, bulkActions: bulkActionsProp } = _a, rest = __rest(_a, ["data", "rowPinning", "columnDefinitions", "keepPinnedRows", "copyPinnedRows", "enableSelectPinned", "rowSelection", "search", "sorting", "columnFilters", "pagination", "className", "onRowClick", "onRefresh", "pageSize", "pageCount", "loading", "outline", "moreActions", "exportSettings", "dataFiltered", "dataError", "noDataState", "noResultsState", "errorDataState", "suppressToolbar", "toolbarAfter", "suppressPagination", "manualSorting", "manualPagination", "manualFiltering", "autoResetPageIndex", "scrollRef", "scrollContainerRef", "getRowId", "enableFuzzySearch", "savedState", "expanding", "bulkActions"]);
36
36
  const { state: globalFilter, onStateChange: onGlobalFilterChange } = useStateControl(search, '');
37
37
  const { state: rowSelection, onStateChange: onRowSelectionChange } = useStateControl(rowSelectionProp, {});
38
38
  const defaultPaginationState = useMemo(() => ({
@@ -132,14 +132,9 @@ export function Table(_a) {
132
132
  table.resetRowSelection();
133
133
  onRefresh === null || onRefresh === void 0 ? void 0 : onRefresh();
134
134
  }, [onRefresh, table]);
135
- const handleOnDelete = useCallback(() => {
136
- if (loading) {
137
- return;
138
- }
139
- if (onDelete) {
140
- onDelete(table.getState().rowSelection, table.resetRowSelection);
141
- }
142
- }, [loading, onDelete, table]);
135
+ const bulkActions = useMemo(() => enableSelection
136
+ ? bulkActionsProp === null || bulkActionsProp === void 0 ? void 0 : bulkActionsProp.map(action => (Object.assign(Object.assign({}, action), { onClick: () => { var _a; return (_a = action.onClick) === null || _a === void 0 ? void 0 : _a.call(action, table.getState().rowSelection, table.resetRowSelection); } })))
137
+ : undefined, [bulkActionsProp, enableSelection, table]);
143
138
  const handleOnCheck = useCallback(() => {
144
139
  if (!loading && !enableSelectPinned && table.getTopRows().length) {
145
140
  const centerRows = table.getCenterRows();
@@ -247,7 +242,7 @@ export function Table(_a) {
247
242
  onChange: onGlobalFilterChange,
248
243
  loading: search === null || search === void 0 ? void 0 : search.loading,
249
244
  placeholder: (search === null || search === void 0 ? void 0 : search.placeholder) || t('searchPlaceholder'),
250
- }, 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 }))] })) }));
245
+ }, className: styles.toolbar, onRefresh: onRefresh ? handleOnRefresh : undefined, bulkActions: bulkActions, selectionMode: (rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow) ? 'multiple' : 'single', checked: table.getIsAllPageRowsSelected(), indeterminate: table.getIsSomePageRowsSelected(), onCheck: enableSelection ? handleOnCheck : undefined, outline: outline, 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 }))] })) }));
251
246
  }
252
247
  Table.getStatusColumnDef = getStatusColumnDef;
253
248
  Table.statusAppearances = STATUS_APPEARANCE;
@@ -5,6 +5,9 @@ import { WithSupportProps } from '@snack-uikit/utils';
5
5
  import { EmptyStateProps, ExportButtonProps, RowClickHandler } from '../helperComponents';
6
6
  import { TreeColumnDefinitionProps } from '../helperComponents/Cells/TreeCell';
7
7
  import { ColumnDefinition } from '../types';
8
+ type BulkAction = Omit<NonNullable<ToolbarProps['bulkActions']>[number], 'onClick'> & {
9
+ onClick?(selectionState: RowSelectionState, resetRowSelection: (defaultState?: boolean) => void): void;
10
+ };
8
11
  export type TableProps<TData extends object> = WithSupportProps<{
9
12
  /** Данные для отрисовки */
10
13
  data: TData[];
@@ -91,18 +94,12 @@ export type TableProps<TData extends object> = WithSupportProps<{
91
94
  loading?: boolean;
92
95
  /** Колбек обновления данных */
93
96
  onRefresh?(): void;
94
- /** Колбек удаления выбранных */
95
- onDelete?(selectionState: RowSelectionState, resetRowSelection: (defaultState?: boolean) => void): void;
96
97
  /** Внешний бордер для тулбара и таблицы */
97
98
  outline?: boolean;
98
99
  /** Фильтры */
99
100
  columnFilters?: ReactNode;
100
101
  dataFiltered?: boolean;
101
102
  dataError?: boolean;
102
- /** Настройки экспорта в тулбаре */
103
- exportSettings?: ExportButtonProps<TData>['settings'];
104
- /** Элементы выпадающего списка кнопки с действиями */
105
- moreActions?: ToolbarProps['moreActions'];
106
103
  /** Экран при отстутствии данных */
107
104
  noDataState?: EmptyStateProps;
108
105
  /** Экран при отстутствии результатов поиска или фильтров */
@@ -111,10 +108,14 @@ export type TableProps<TData extends object> = WithSupportProps<{
111
108
  errorDataState?: EmptyStateProps;
112
109
  /** Отключение тулбара */
113
110
  suppressToolbar?: boolean;
114
- /** Дополнительный слот в `Toolbar` перед строкой поиска */
115
- toolbarBefore?: ReactNode;
111
+ /** Список действия для массовых операций */
112
+ bulkActions?: BulkAction[];
113
+ /** Элементы выпадающего списка кнопки с действиями */
114
+ moreActions?: ToolbarProps['moreActions'];
116
115
  /** Дополнительный слот в `Toolbar` после строки поиска */
117
116
  toolbarAfter?: ReactNode;
117
+ /** Настройки экспорта в тулбаре */
118
+ exportSettings?: ExportButtonProps<TData>['settings'];
118
119
  /** Отключение пагинации */
119
120
  suppressPagination?: boolean;
120
121
  manualSorting?: boolean;
@@ -179,3 +180,4 @@ export type ServerTableProps<TData extends object> = Omit<TableProps<TData>, 'pa
179
180
  optionsLabel?: string;
180
181
  };
181
182
  };
183
+ export {};
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public"
5
5
  },
6
6
  "title": "Table",
7
- "version": "0.26.7",
7
+ "version": "0.27.0",
8
8
  "sideEffects": [
9
9
  "*.css",
10
10
  "*.woff",
@@ -36,20 +36,20 @@
36
36
  "license": "Apache-2.0",
37
37
  "scripts": {},
38
38
  "dependencies": {
39
- "@snack-uikit/button": "0.19.5",
40
- "@snack-uikit/chips": "0.24.0",
41
- "@snack-uikit/icon-predefined": "0.7.2",
42
- "@snack-uikit/icons": "0.24.1",
43
- "@snack-uikit/info-block": "0.6.8",
44
- "@snack-uikit/list": "0.23.0",
45
- "@snack-uikit/pagination": "0.10.0",
46
- "@snack-uikit/scroll": "0.9.2",
47
- "@snack-uikit/skeleton": "0.6.1",
48
- "@snack-uikit/toggles": "0.13.4",
49
- "@snack-uikit/toolbar": "0.9.18",
50
- "@snack-uikit/truncate-string": "0.6.5",
51
- "@snack-uikit/typography": "0.8.3",
52
- "@snack-uikit/utils": "3.6.0",
39
+ "@snack-uikit/button": "0.19.6",
40
+ "@snack-uikit/chips": "0.24.1",
41
+ "@snack-uikit/icon-predefined": "0.7.3",
42
+ "@snack-uikit/icons": "0.24.2",
43
+ "@snack-uikit/info-block": "0.6.9",
44
+ "@snack-uikit/list": "0.23.1",
45
+ "@snack-uikit/pagination": "0.10.1",
46
+ "@snack-uikit/scroll": "0.9.3",
47
+ "@snack-uikit/skeleton": "0.6.2",
48
+ "@snack-uikit/toggles": "0.13.5",
49
+ "@snack-uikit/toolbar": "0.10.0",
50
+ "@snack-uikit/truncate-string": "0.6.6",
51
+ "@snack-uikit/typography": "0.8.4",
52
+ "@snack-uikit/utils": "3.7.0",
53
53
  "@tanstack/match-sorter-utils": "8.11.8",
54
54
  "@tanstack/react-table": "8.12.0",
55
55
  "classnames": "2.5.1",
@@ -61,5 +61,5 @@
61
61
  "peerDependencies": {
62
62
  "@snack-uikit/locale": "*"
63
63
  },
64
- "gitHead": "546ae486452e74e78f65fd9ce0044c13b058872c"
64
+ "gitHead": "3528e78aec23804dca44d311947c1dcd4ed3792b"
65
65
  }
@@ -18,7 +18,7 @@ import { RefObject, useCallback, useEffect, useMemo, useRef } from 'react';
18
18
  import { useLocale } from '@snack-uikit/locale';
19
19
  import { Scroll } from '@snack-uikit/scroll';
20
20
  import { SkeletonContextProvider } from '@snack-uikit/skeleton';
21
- import { Toolbar } from '@snack-uikit/toolbar';
21
+ import { Toolbar, ToolbarProps } from '@snack-uikit/toolbar';
22
22
  import { TruncateString } from '@snack-uikit/truncate-string';
23
23
  import { extractSupportProps } from '@snack-uikit/utils';
24
24
 
@@ -70,7 +70,6 @@ export function Table<TData extends object>({
70
70
  className,
71
71
  onRowClick,
72
72
  onRefresh,
73
- onDelete,
74
73
  pageSize = DEFAULT_PAGE_SIZE,
75
74
  pageCount,
76
75
  loading = false,
@@ -83,7 +82,6 @@ export function Table<TData extends object>({
83
82
  noResultsState,
84
83
  errorDataState,
85
84
  suppressToolbar = false,
86
- toolbarBefore,
87
85
  toolbarAfter,
88
86
  suppressPagination = false,
89
87
  manualSorting = false,
@@ -96,6 +94,7 @@ export function Table<TData extends object>({
96
94
  enableFuzzySearch,
97
95
  savedState,
98
96
  expanding,
97
+ bulkActions: bulkActionsProp,
99
98
  ...rest
100
99
  }: TableProps<TData>) {
101
100
  const { state: globalFilter, onStateChange: onGlobalFilterChange } = useStateControl<string>(search, '');
@@ -219,15 +218,16 @@ export function Table<TData extends object>({
219
218
  onRefresh?.();
220
219
  }, [onRefresh, table]);
221
220
 
222
- const handleOnDelete = useCallback(() => {
223
- if (loading) {
224
- return;
225
- }
226
-
227
- if (onDelete) {
228
- onDelete(table.getState().rowSelection, table.resetRowSelection);
229
- }
230
- }, [loading, onDelete, table]);
221
+ const bulkActions: ToolbarProps['bulkActions'] = useMemo(
222
+ () =>
223
+ enableSelection
224
+ ? bulkActionsProp?.map(action => ({
225
+ ...action,
226
+ onClick: () => action.onClick?.(table.getState().rowSelection, table.resetRowSelection),
227
+ }))
228
+ : undefined,
229
+ [bulkActionsProp, enableSelection, table],
230
+ );
231
231
 
232
232
  const handleOnCheck = useCallback(() => {
233
233
  if (!loading && !enableSelectPinned && table.getTopRows().length) {
@@ -371,15 +371,14 @@ export function Table<TData extends object>({
371
371
  loading: search?.loading,
372
372
  placeholder: search?.placeholder || t('searchPlaceholder'),
373
373
  }}
374
- checked={table.getIsAllPageRowsSelected()}
375
- indeterminate={table.getIsSomePageRowsSelected()}
376
374
  className={styles.toolbar}
377
375
  onRefresh={onRefresh ? handleOnRefresh : undefined}
378
- onDelete={enableSelection && onDelete ? handleOnDelete : undefined}
376
+ bulkActions={bulkActions}
377
+ selectionMode={rowSelectionProp?.multiRow ? 'multiple' : 'single'}
378
+ checked={table.getIsAllPageRowsSelected()}
379
+ indeterminate={table.getIsSomePageRowsSelected()}
379
380
  onCheck={enableSelection ? handleOnCheck : undefined}
380
381
  outline={outline}
381
- selectionMode={rowSelectionProp?.multiRow ? 'multiple' : 'single'}
382
- before={toolbarBefore}
383
382
  after={
384
383
  toolbarAfter || exportSettings ? (
385
384
  <>
@@ -15,6 +15,10 @@ import { EmptyStateProps, ExportButtonProps, RowClickHandler } from '../helperCo
15
15
  import { TreeColumnDefinitionProps } from '../helperComponents/Cells/TreeCell';
16
16
  import { ColumnDefinition } from '../types';
17
17
 
18
+ type BulkAction = Omit<NonNullable<ToolbarProps['bulkActions']>[number], 'onClick'> & {
19
+ onClick?(selectionState: RowSelectionState, resetRowSelection: (defaultState?: boolean) => void): void;
20
+ };
21
+
18
22
  export type TableProps<TData extends object> = WithSupportProps<{
19
23
  /** Данные для отрисовки */
20
24
  data: TData[];
@@ -111,9 +115,6 @@ export type TableProps<TData extends object> = WithSupportProps<{
111
115
  /** Колбек обновления данных */
112
116
  onRefresh?(): void;
113
117
 
114
- /** Колбек удаления выбранных */
115
- onDelete?(selectionState: RowSelectionState, resetRowSelection: (defaultState?: boolean) => void): void;
116
-
117
118
  /** Внешний бордер для тулбара и таблицы */
118
119
  outline?: boolean;
119
120
 
@@ -123,12 +124,6 @@ export type TableProps<TData extends object> = WithSupportProps<{
123
124
  dataFiltered?: boolean;
124
125
  dataError?: boolean;
125
126
 
126
- /** Настройки экспорта в тулбаре */
127
- exportSettings?: ExportButtonProps<TData>['settings'];
128
-
129
- /** Элементы выпадающего списка кнопки с действиями */
130
- moreActions?: ToolbarProps['moreActions'];
131
-
132
127
  /** Экран при отстутствии данных */
133
128
  noDataState?: EmptyStateProps;
134
129
  /** Экран при отстутствии результатов поиска или фильтров */
@@ -138,10 +133,14 @@ export type TableProps<TData extends object> = WithSupportProps<{
138
133
 
139
134
  /** Отключение тулбара */
140
135
  suppressToolbar?: boolean;
141
- /** Дополнительный слот в `Toolbar` перед строкой поиска */
142
- toolbarBefore?: ReactNode;
136
+ /** Список действия для массовых операций */
137
+ bulkActions?: BulkAction[];
138
+ /** Элементы выпадающего списка кнопки с действиями */
139
+ moreActions?: ToolbarProps['moreActions'];
143
140
  /** Дополнительный слот в `Toolbar` после строки поиска */
144
141
  toolbarAfter?: ReactNode;
142
+ /** Настройки экспорта в тулбаре */
143
+ exportSettings?: ExportButtonProps<TData>['settings'];
145
144
 
146
145
  /** Отключение пагинации */
147
146
  suppressPagination?: boolean;
@@ -79,7 +79,7 @@
79
79
  @include styles-tokens-table.composite-var(styles-tokens-table.$sans-body-m);
80
80
  }
81
81
  .line {
82
- margin-left: calc(styles-tokens-table.$dimension-4m + styles-tokens-table.$dimension-025m);
82
+ margin-left: calc(#{styles-tokens-table.$dimension-4m} + #{styles-tokens-table.$dimension-025m});
83
83
  }
84
84
  .firstLine {
85
85
  margin-left: styles-tokens-table.$dimension-2m