@snack-uikit/table 0.7.2 → 0.8.1
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 +26 -0
- package/README.md +6 -6
- package/dist/components/Table/Table.d.ts +13 -6
- package/dist/components/Table/Table.js +3 -8
- package/dist/components/Table/constants.js +2 -3
- package/dist/components/TableEmptyState/TableEmptyState.js +1 -1
- package/dist/components/TablePagination/TablePagination.js +1 -1
- package/dist/constants.d.ts +12 -12
- package/dist/constants.js +12 -15
- package/dist/helperComponents/Cells/BodyCell/BodyCell.js +1 -1
- package/dist/helperComponents/Cells/HeaderCell/HeaderCell.js +1 -1
- package/dist/helperComponents/Cells/RowActionsCell/RowActionsCell.js +3 -3
- package/dist/helperComponents/Cells/SelectionCell/SelectionCell.js +3 -3
- package/dist/helperComponents/Cells/StatusCell/StatusCell.d.ts +4 -2
- package/dist/helperComponents/Cells/StatusCell/StatusCell.js +6 -6
- package/dist/helperComponents/Cells/StatusCell/constants.d.ts +12 -12
- package/dist/helperComponents/Cells/StatusCell/constants.js +12 -13
- package/dist/helperComponents/Cells/StatusCell/types.d.ts +3 -0
- package/dist/helperComponents/Cells/StatusCell/types.js +1 -0
- package/dist/helperComponents/ExportButton/ExportButton.js +2 -2
- package/dist/helperComponents/Rows/BodyRow.js +2 -2
- package/dist/helperComponents/Rows/HeaderRow.js +2 -2
- package/dist/helperComponents/Rows/PinnedCells.d.ts +3 -2
- package/dist/helperComponents/Rows/PinnedCells.js +1 -1
- package/dist/types.d.ts +6 -3
- package/package.json +15 -15
- package/src/components/Table/Table.tsx +4 -11
- package/src/components/Table/constants.ts +2 -3
- package/src/components/TableEmptyState/TableEmptyState.tsx +1 -1
- package/src/components/TablePagination/TablePagination.tsx +2 -2
- package/src/constants.ts +12 -12
- package/src/helperComponents/Cells/RowActionsCell/RowActionsCell.tsx +4 -4
- package/src/helperComponents/Cells/SelectionCell/SelectionCell.tsx +3 -3
- package/src/helperComponents/Cells/StatusCell/StatusCell.tsx +8 -5
- package/src/helperComponents/Cells/StatusCell/constants.ts +12 -12
- package/src/helperComponents/Cells/StatusCell/types.ts +5 -0
- package/src/helperComponents/ExportButton/ExportButton.tsx +2 -4
- package/src/helperComponents/Rows/BodyRow.tsx +3 -3
- package/src/helperComponents/Rows/HeaderRow.tsx +3 -3
- package/src/helperComponents/Rows/PinnedCells.tsx +4 -2
- package/src/types.ts +16 -11
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,32 @@
|
|
|
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.8.1 (2023-12-14)
|
|
7
|
+
|
|
8
|
+
### Only dependencies have been changed
|
|
9
|
+
* [@snack-uikit/chips@0.10.1](https://git.sbercloud.tech/sbercloud-ui/tokens-design-system/snack-uikit/-/blob/master/packages/chips/CHANGELOG.md)
|
|
10
|
+
* [@snack-uikit/droplist@0.12.1](https://git.sbercloud.tech/sbercloud-ui/tokens-design-system/snack-uikit/-/blob/master/packages/droplist/CHANGELOG.md)
|
|
11
|
+
* [@snack-uikit/icons@0.19.1](https://git.sbercloud.tech/sbercloud-ui/tokens-design-system/snack-uikit/-/blob/master/packages/icons/CHANGELOG.md)
|
|
12
|
+
* [@snack-uikit/pagination@0.5.3](https://git.sbercloud.tech/sbercloud-ui/tokens-design-system/snack-uikit/-/blob/master/packages/pagination/CHANGELOG.md)
|
|
13
|
+
* [@snack-uikit/toggles@0.9.1](https://git.sbercloud.tech/sbercloud-ui/tokens-design-system/snack-uikit/-/blob/master/packages/toggles/CHANGELOG.md)
|
|
14
|
+
* [@snack-uikit/toolbar@0.5.1](https://git.sbercloud.tech/sbercloud-ui/tokens-design-system/snack-uikit/-/blob/master/packages/toolbar/CHANGELOG.md)
|
|
15
|
+
* [@snack-uikit/truncate-string@0.4.1](https://git.sbercloud.tech/sbercloud-ui/tokens-design-system/snack-uikit/-/blob/master/packages/truncate-string/CHANGELOG.md)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# 0.8.0 (2023-12-14)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### BREAKING CHANGES
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
* **FF-3729:** replace enum with unions ([910db4a](https://github.com/cloud-ru-tech/snack-uikit/commit/910db4aa8231ccbc58e538e5c5c1f461b1dec275))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
6
32
|
## 0.7.2 (2023-12-07)
|
|
7
33
|
|
|
8
34
|
### Only dependencies have been changed
|
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
|
|
|
51
51
|
// id, size - обязательны при передаче pinned
|
|
52
52
|
id: 'firstName',
|
|
53
53
|
size: 140,
|
|
54
|
-
pinned:
|
|
54
|
+
pinned: 'left',
|
|
55
55
|
accessorKey: 'firstName',
|
|
56
56
|
header: 'Имя',
|
|
57
57
|
enableSorting: true,
|
|
@@ -111,9 +111,9 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
|
|
|
111
111
|
| data* | `TData[]` | - | Данные для отрисовки |
|
|
112
112
|
| sorting | `{ initialState?: SortingState; state?: SortingState; onChange?(state: SortingState): void; }` | - | Параметры отвечают за возможность сортировки, их стоит использовать если нужно отслеживать состояние <br> <strong>initialState</strong>: Начальное состояние сортировки <br> <strong>state</strong>: Состояние сортировки, жестко устанавливаемое снаружи <br> <strong>onChange</strong>: Колбэк на изменение сортировки |
|
|
113
113
|
| 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>: Колбэк на выбор строк |
|
|
114
|
-
| search | `{ initialValue?: string; state?: string; placeholder?: string; loading?: boolean; onChange?(value: string): void; }` |
|
|
115
|
-
| pageSize | `number` | 10 | Максимальное кол-во строк на страницу
|
|
116
|
-
| pagination | `{ state?: PaginationState; options?: number[]; optionsLabel?: string; onChange?(state: PaginationState): void; }` |
|
|
114
|
+
| search | `{ initialValue?: 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 строки поиска |
|
|
115
|
+
| pageSize | `number` | 10 | Максимальное кол-во строк на страницу |
|
|
116
|
+
| 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>: Текст для селектора кол-ва строк на страницу |
|
|
117
117
|
| pageCount | `number` | - | Кол-во страниц (используется для внешнего управления) |
|
|
118
118
|
| onRowClick | `RowClickHandler<TData>` | - | Колбэк клика по строке |
|
|
119
119
|
| className | `string` | - | CSS-класс |
|
|
@@ -124,8 +124,8 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
|
|
|
124
124
|
| columnFilters | `ReactNode` | - | Фильтры |
|
|
125
125
|
| exportFileName | `string` | - | Название файла при экспорте CSV/XLSX |
|
|
126
126
|
| moreActions | `Pick<DroplistItemSingleProps, "option" \| "caption" \| "description" \| "tagLabel" \| "disabled" \| "icon" \| "onClick">[]` | - | Элементы выпадающего списка кнопки с действиями |
|
|
127
|
-
| noDataState | `TableEmptyStateProps` | { icon: CrossSVG, appearance:
|
|
128
|
-
| noResultsState | `TableEmptyStateProps` | { icon: SearchSVG, appearance:
|
|
127
|
+
| noDataState | `TableEmptyStateProps` | { icon: CrossSVG, appearance: 'red', title: 'Data collection error', description: 'Try refreshing the page', } as const | Экран при отстутствии данных |
|
|
128
|
+
| noResultsState | `TableEmptyStateProps` | { icon: SearchSVG, appearance: 'neutral', title: 'Not found', description: 'Try entering another query', } as const | Экран при отстутствии результатов поиска |
|
|
129
129
|
| suppressToolbar | `boolean` | - | Отключение тулбара |
|
|
130
130
|
| suppressPagination | `boolean` | - | Отключение пагинации |
|
|
131
131
|
## Table.getStatusColumnDef
|
|
@@ -2,8 +2,7 @@ import { PaginationState, RowSelectionOptions, RowSelectionState, SortingState }
|
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import { ToolbarProps } from '@snack-uikit/toolbar';
|
|
4
4
|
import { WithSupportProps } from '@snack-uikit/utils';
|
|
5
|
-
import {
|
|
6
|
-
import { RowClickHandler, StatusAppearance } from '../../helperComponents';
|
|
5
|
+
import { RowClickHandler } from '../../helperComponents';
|
|
7
6
|
import { ColumnDefinition } from '../../types';
|
|
8
7
|
import { TableEmptyStateProps } from '../TableEmptyState';
|
|
9
8
|
export type TableProps<TData extends object> = WithSupportProps<{
|
|
@@ -95,10 +94,18 @@ export type TableProps<TData extends object> = WithSupportProps<{
|
|
|
95
94
|
/** Компонент таблицы */
|
|
96
95
|
export declare function Table<TData extends object>({ data, columnDefinitions, rowSelection: rowSelectionProp, search, sorting: sortingProp, columnFilters: columnFiltersProp, pagination: paginationProp, className, onRowClick, onRefresh, onDelete, pageSize, pageCount, loading, outline, moreActions, exportFileName, noDataState, noResultsState, suppressToolbar, suppressPagination, ...rest }: TableProps<TData>): import("react/jsx-runtime").JSX.Element;
|
|
97
96
|
export declare namespace Table {
|
|
98
|
-
var columnPinPositions: typeof ColumnPinPosition;
|
|
99
|
-
var columnAligns: typeof ColumnAlign;
|
|
100
97
|
var getStatusColumnDef: typeof import("../../helperComponents").getStatusColumnDef;
|
|
101
|
-
var statusAppearances:
|
|
98
|
+
var statusAppearances: {
|
|
99
|
+
readonly Primary: "primary";
|
|
100
|
+
readonly Neutral: "neutral";
|
|
101
|
+
readonly Red: "red";
|
|
102
|
+
readonly Orange: "orange";
|
|
103
|
+
readonly Yellow: "yellow";
|
|
104
|
+
readonly Green: "green";
|
|
105
|
+
readonly Blue: "blue";
|
|
106
|
+
readonly Violet: "violet";
|
|
107
|
+
readonly Pink: "pink";
|
|
108
|
+
readonly Loading: "loading";
|
|
109
|
+
};
|
|
102
110
|
var getRowActionsColumnDef: typeof import("../../helperComponents").getRowActionsColumnDef;
|
|
103
|
-
var emptyStateAppearances: typeof import("@snack-uikit/icon-predefined/dist/constants").Appearance;
|
|
104
111
|
}
|
|
@@ -12,14 +12,12 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
13
13
|
import { getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable, } from '@tanstack/react-table';
|
|
14
14
|
import { useCallback, useMemo } from 'react';
|
|
15
|
-
import { IconPredefined } from '@snack-uikit/icon-predefined';
|
|
16
15
|
import { Scroll } from '@snack-uikit/scroll';
|
|
17
16
|
import { SkeletonContextProvider } from '@snack-uikit/skeleton';
|
|
18
17
|
import { Toolbar } from '@snack-uikit/toolbar';
|
|
19
18
|
import { TruncateString } from '@snack-uikit/truncate-string';
|
|
20
19
|
import { extractSupportProps } from '@snack-uikit/utils';
|
|
21
|
-
import {
|
|
22
|
-
import { BodyRow, ExportButton, getColumnId, getRowActionsColumnDef, getSelectionCellColumnDef, getStatusColumnDef, HeaderRow, StatusAppearance, TableContext, } from '../../helperComponents';
|
|
20
|
+
import { BodyRow, ExportButton, getColumnId, getRowActionsColumnDef, getSelectionCellColumnDef, getStatusColumnDef, HeaderRow, STATUS_APPEARANCE, TableContext, } from '../../helperComponents';
|
|
23
21
|
import { fuzzyFilter } from '../../utils';
|
|
24
22
|
import { TableEmptyState } from '../TableEmptyState';
|
|
25
23
|
import { TablePagination } from '../TablePagination';
|
|
@@ -115,11 +113,8 @@ export function Table(_a) {
|
|
|
115
113
|
const tableRows = table.getRowModel().rows;
|
|
116
114
|
const loadingTableRows = loadingTable.getRowModel().rows;
|
|
117
115
|
const tablePagination = table.getState().pagination;
|
|
118
|
-
return (_jsx(_Fragment, { children: _jsxs("div", Object.assign({ style: { '--page-size': !suppressPagination ? tablePagination === null || tablePagination === void 0 ? void 0 : tablePagination.pageSize : pageSize }, className: className }, extractSupportProps(rest), { children: [!suppressToolbar && (_jsxs("div",
|
|
116
|
+
return (_jsx(_Fragment, { children: _jsxs("div", Object.assign({ style: { '--page-size': !suppressPagination ? tablePagination === null || tablePagination === void 0 ? void 0 : tablePagination.pageSize : pageSize }, className: className }, extractSupportProps(rest), { children: [!suppressToolbar && (_jsxs("div", { className: styles.header, children: [_jsx(Toolbar, { value: globalFilter, onChange: onGlobalFilterChange, checked: table.getIsAllPageRowsSelected(), indeterminate: table.getIsSomePageRowsSelected(), className: styles.toolbar, onRefresh: onRefresh ? handleOnRefresh : undefined, onDelete: enableSelection && onDelete ? handleOnDelete : undefined, onCheck: enableSelection ? handleOnCheck : undefined, outline: outline, loading: search === null || search === void 0 ? void 0 : search.loading, placeholder: (search === null || search === void 0 ? void 0 : search.placeholder) || 'Search', selectionMode: (rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow) ? 'multiple' : 'single', actions: exportFileName ? (_jsx(ExportButton, { fileName: exportFileName, columnDefinitions: columnDefinitions, data: data })) : undefined, moreActions: moreActions }), columnFiltersProp && _jsxs("div", { className: styles.filtersWrapper, children: [" ", columnFiltersProp, " "] })] })), _jsx("div", { className: styles.scrollWrapper, "data-outline": outline || undefined, children: _jsx(Scroll, { size: 's', className: styles.table, children: _jsx("div", { className: styles.tableContent, 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: [tableRows.length ? _jsx(HeaderRow, {}) : null, tableRows.map(row => (_jsx(BodyRow, { row: row, onRowClick: onRowClick }, row.id))), !tableRows.length && globalFilter && _jsx(TableEmptyState, Object.assign({}, noResultsState)), !tableRows.length && !globalFilter && _jsx(TableEmptyState, Object.assign({}, noDataState))] })) }) }) }) }), !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 }))] })) }));
|
|
119
117
|
}
|
|
120
|
-
Table.columnPinPositions = ColumnPinPosition;
|
|
121
|
-
Table.columnAligns = ColumnAlign;
|
|
122
118
|
Table.getStatusColumnDef = getStatusColumnDef;
|
|
123
|
-
Table.statusAppearances =
|
|
119
|
+
Table.statusAppearances = STATUS_APPEARANCE;
|
|
124
120
|
Table.getRowActionsColumnDef = getRowActionsColumnDef;
|
|
125
|
-
Table.emptyStateAppearances = IconPredefined.appearances;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { IconPredefined } from '@snack-uikit/icon-predefined';
|
|
2
1
|
import { CrossSVG, SearchSVG } from '@snack-uikit/icons';
|
|
3
2
|
export const DEFAULT_NO_DATA_TABLE_STATE = {
|
|
4
3
|
icon: CrossSVG,
|
|
5
|
-
appearance:
|
|
4
|
+
appearance: 'red',
|
|
6
5
|
title: 'Data collection error',
|
|
7
6
|
description: 'Try refreshing the page',
|
|
8
7
|
};
|
|
9
8
|
export const DEFAULT_NO_RESULTS_TABLE_STATE = {
|
|
10
9
|
icon: SearchSVG,
|
|
11
|
-
appearance:
|
|
10
|
+
appearance: 'neutral',
|
|
12
11
|
title: 'Not found',
|
|
13
12
|
description: 'Try entering another query',
|
|
14
13
|
};
|
|
@@ -4,5 +4,5 @@ import { IconPredefined } from '@snack-uikit/icon-predefined';
|
|
|
4
4
|
import { Typography } from '@snack-uikit/typography';
|
|
5
5
|
import styles from './styles.module.css';
|
|
6
6
|
export function TableEmptyState({ title, description, className, icon, appearance }) {
|
|
7
|
-
return (_jsxs("div",
|
|
7
|
+
return (_jsxs("div", { className: cn(styles.tableEmptyStateWrapper, className), children: [_jsx(IconPredefined, { icon: icon, size: 'l', appearance: appearance }), _jsxs("div", { className: styles.textWrapper, children: [_jsx(Typography.SansTitleM, { children: title }), description && _jsx(Typography.SansBodyM, { children: description })] })] }));
|
|
8
8
|
}
|
|
@@ -15,5 +15,5 @@ export function TablePagination({ table, options: optionsProp, optionsLabel = 'R
|
|
|
15
15
|
if (table.getPageCount() <= 1 && !options) {
|
|
16
16
|
return null;
|
|
17
17
|
}
|
|
18
|
-
return (_jsxs("div",
|
|
18
|
+
return (_jsxs("div", { className: styles.footer, children: [table.getPageCount() > 1 && (_jsx(Pagination, { total: table.getPageCount(), page: tablePaginationState.pageIndex + 1, onChange: handlePaginationOnChange, className: styles.pagination })), options && table.getRowModel().rows.length >= Number(options[0].value) && (_jsx(ChipChoice.Single, { value: String(tablePaginationState.pageSize), onChange: handleRowsVolumeOnChange, placement: 'top-end', options: options, label: optionsLabel, widthStrategy: 'auto', showClearButton: false }))] }));
|
|
19
19
|
}
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export declare
|
|
2
|
-
Left
|
|
3
|
-
Right
|
|
4
|
-
}
|
|
5
|
-
export declare
|
|
6
|
-
Left
|
|
7
|
-
Right
|
|
8
|
-
}
|
|
1
|
+
export declare const COLUMN_PIN_POSITION: {
|
|
2
|
+
readonly Left: "left";
|
|
3
|
+
readonly Right: "right";
|
|
4
|
+
};
|
|
5
|
+
export declare const COLUMN_ALIGN: {
|
|
6
|
+
readonly Left: "left";
|
|
7
|
+
readonly Right: "right";
|
|
8
|
+
};
|
|
9
9
|
export declare const TEST_IDS: {
|
|
10
10
|
headerSortIndicator: string;
|
|
11
11
|
headerRow: string;
|
|
@@ -22,7 +22,7 @@ export declare const TEST_IDS: {
|
|
|
22
22
|
statusIndicator: string;
|
|
23
23
|
statusLabel: string;
|
|
24
24
|
};
|
|
25
|
-
export declare
|
|
26
|
-
DateTime
|
|
27
|
-
AlphaNumeric
|
|
28
|
-
}
|
|
25
|
+
export declare const SORT_FN: {
|
|
26
|
+
readonly DateTime: "datetime";
|
|
27
|
+
readonly AlphaNumeric: "alphanumeric";
|
|
28
|
+
};
|
package/dist/constants.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
ColumnAlign["Right"] = "right";
|
|
10
|
-
})(ColumnAlign || (ColumnAlign = {}));
|
|
1
|
+
export const COLUMN_PIN_POSITION = {
|
|
2
|
+
Left: 'left',
|
|
3
|
+
Right: 'right',
|
|
4
|
+
};
|
|
5
|
+
export const COLUMN_ALIGN = {
|
|
6
|
+
Left: 'left',
|
|
7
|
+
Right: 'right',
|
|
8
|
+
};
|
|
11
9
|
export const TEST_IDS = {
|
|
12
10
|
headerSortIndicator: 'table__header__sort-indicator',
|
|
13
11
|
headerRow: 'table__header-row',
|
|
@@ -24,8 +22,7 @@ export const TEST_IDS = {
|
|
|
24
22
|
statusIndicator: 'table__status-indicator',
|
|
25
23
|
statusLabel: 'table__status-label',
|
|
26
24
|
};
|
|
27
|
-
export
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
})(SortFn || (SortFn = {}));
|
|
25
|
+
export const SORT_FN = {
|
|
26
|
+
DateTime: 'datetime',
|
|
27
|
+
AlphaNumeric: 'alphanumeric',
|
|
28
|
+
};
|
|
@@ -20,5 +20,5 @@ export function BodyCell(_a) {
|
|
|
20
20
|
var { cell, className } = _a, props = __rest(_a, ["cell", "className"]);
|
|
21
21
|
const columnDef = cell.column.columnDef;
|
|
22
22
|
const style = useCellSizes(cell);
|
|
23
|
-
return (_jsx(Cell, Object.assign({}, props, { style: style, className: cn(styles.tableBodyCell, className, columnDef.cellClassName), "data-align": columnDef.align, "data-no-padding": columnDef.noBodyCellPadding || undefined, "data-column-id": cell.column.id, "data-test-id": TEST_IDS.bodyCell
|
|
23
|
+
return (_jsx(Cell, Object.assign({}, props, { style: style, className: cn(styles.tableBodyCell, className, columnDef.cellClassName), "data-align": columnDef.align, "data-no-padding": columnDef.noBodyCellPadding || undefined, "data-column-id": cell.column.id, "data-test-id": TEST_IDS.bodyCell, children: flexRender(columnDef.cell, cell.getContext()) })));
|
|
24
24
|
}
|
|
@@ -13,5 +13,5 @@ export function HeaderCell({ header, className }) {
|
|
|
13
13
|
const sortIcon = getSortingIcon(sortDirection);
|
|
14
14
|
const columnDef = header.column.columnDef;
|
|
15
15
|
const style = useCellSizes(header);
|
|
16
|
-
return (_jsxs(Cell,
|
|
16
|
+
return (_jsxs(Cell, { style: style, onClick: header.column.getToggleSortingHandler(), "data-sortable": isSortable || undefined, "data-no-padding": columnDef.noHeaderCellPadding || undefined, "data-no-offset": columnDef.noHeaderCellBorderOffset || undefined, "data-test-id": TEST_IDS.headerCell, className: cn(styles.tableHeaderCell, className, columnDef.headerClassName), children: [columnDef.header && (_jsx("div", { className: styles.tableHeaderCellName, children: _jsx(TruncateString, { text: flexRender(columnDef.header, header.getContext()) }) })), Boolean(sortIcon) && (_jsx("div", { className: styles.tableHeaderSortIcon, "data-sort-direction": sortDirection, "data-test-id": TEST_IDS.headerSortIndicator, children: sortIcon }))] }));
|
|
17
17
|
}
|
|
@@ -3,7 +3,7 @@ import { createElement as _createElement } from "react";
|
|
|
3
3
|
import { ButtonFunction } from '@snack-uikit/button';
|
|
4
4
|
import { Droplist } from '@snack-uikit/droplist';
|
|
5
5
|
import { MoreSVG } from '@snack-uikit/icons';
|
|
6
|
-
import {
|
|
6
|
+
import { COLUMN_PIN_POSITION, TEST_IDS } from '../../../constants';
|
|
7
7
|
import { useRowContext } from '../../contexts';
|
|
8
8
|
import styles from './styles.module.css';
|
|
9
9
|
function RowActionsCell({ row, actions }) {
|
|
@@ -18,13 +18,13 @@ function RowActionsCell({ row, actions }) {
|
|
|
18
18
|
};
|
|
19
19
|
return (
|
|
20
20
|
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
21
|
-
_jsx("div",
|
|
21
|
+
_jsx("div", { onClick: stopPropagationClick, className: styles.rowActionsCellWrap, "data-open": droplistOpened || undefined, children: !disabled && Boolean(actions.length) && (_jsx(Droplist, { open: droplistOpened, onOpenChange: setDroplistOpen, placement: 'bottom-end', firstElementRefCallback: firstElementRefCallback, onFocusLeave: handleDroplistFocusLeave, triggerElement: _jsx("span", { children: _jsx(ButtonFunction, { icon: _jsx(MoreSVG, { size: 24 }), "data-test-id": TEST_IDS.rowActions.droplistTrigger, onKeyDown: handleTriggerKeyDown, ref: triggerElementRef }) }), triggerClassName: styles.rowActionsCellTrigger, size: 's', "data-test-id": TEST_IDS.rowActions.droplist, children: actions.map(item => (_createElement(Droplist.ItemSingle, Object.assign({}, item, { key: `${row.id}-${item.id || item.option}`, onClick: e => handleDroplistItemClick(e, handleItemClick(item)), "data-test-id": TEST_IDS.rowActions.option, onKeyDown: handleDroplistItemKeyDown })))) })) }));
|
|
22
22
|
}
|
|
23
23
|
/** Вспомогательная функция для создания ячейки с дополнительными действиями у строки */
|
|
24
24
|
export function getRowActionsColumnDef({ actionsGenerator, pinned, }) {
|
|
25
25
|
return {
|
|
26
26
|
id: 'rowActions',
|
|
27
|
-
pinned: pinned ?
|
|
27
|
+
pinned: pinned ? COLUMN_PIN_POSITION.Right : undefined,
|
|
28
28
|
size: 40,
|
|
29
29
|
meta: {
|
|
30
30
|
skipOnExport: true,
|
|
@@ -11,7 +11,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
13
|
import { Checkbox, Radio } from '@snack-uikit/toggles';
|
|
14
|
-
import {
|
|
14
|
+
import { COLUMN_PIN_POSITION, TEST_IDS } from '../../../constants';
|
|
15
15
|
import styles from './styles.module.css';
|
|
16
16
|
function SelectionCell(_a) {
|
|
17
17
|
var { isMulti, onChange } = _a, props = __rest(_a, ["isMulti", "onChange"]);
|
|
@@ -21,12 +21,12 @@ function SelectionCell(_a) {
|
|
|
21
21
|
};
|
|
22
22
|
return (
|
|
23
23
|
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
24
|
-
_jsx("div",
|
|
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
26
|
export function getSelectionCellColumnDef() {
|
|
27
27
|
return {
|
|
28
28
|
id: 'selectionCell',
|
|
29
|
-
pinned:
|
|
29
|
+
pinned: COLUMN_PIN_POSITION.Left,
|
|
30
30
|
noBodyCellPadding: true,
|
|
31
31
|
size: 40,
|
|
32
32
|
headerClassName: styles.selectionCellHeader,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { ColumnDefinition } from '../../../types';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { STATUS_APPEARANCE } from './constants';
|
|
3
|
+
import { StatusAppearance } from './types';
|
|
4
|
+
export type { StatusAppearance };
|
|
5
|
+
export { STATUS_APPEARANCE };
|
|
4
6
|
type BaseStatusColumnDef = {
|
|
5
7
|
/** Имя ключа соответствующее полю в data */
|
|
6
8
|
accessorKey: string;
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { TruncateString } from '@snack-uikit/truncate-string';
|
|
3
3
|
import { Typography } from '@snack-uikit/typography';
|
|
4
|
-
import {
|
|
5
|
-
import { MIN_STATUS_CELL_SIZE,
|
|
4
|
+
import { COLUMN_PIN_POSITION, TEST_IDS } from '../../../constants';
|
|
5
|
+
import { MIN_STATUS_CELL_SIZE, STATUS_APPEARANCE } from './constants';
|
|
6
6
|
import styles from './styles.module.css';
|
|
7
|
-
export {
|
|
7
|
+
export { STATUS_APPEARANCE };
|
|
8
8
|
function StatusCell({ appearance, label }) {
|
|
9
|
-
const isLoading = appearance ===
|
|
10
|
-
return (_jsxs("div",
|
|
9
|
+
const isLoading = appearance === STATUS_APPEARANCE.Loading;
|
|
10
|
+
return (_jsxs("div", { className: styles.statusCell, "data-no-label": !label || undefined, children: [_jsx("div", { "data-appearance": isLoading ? undefined : appearance, className: styles.statusCellIndicator, "data-loading": isLoading || undefined, "data-test-id": TEST_IDS.statusIndicator }), label && (_jsx("div", { className: styles.statusCellLabel, "data-test-id": TEST_IDS.statusLabel, children: _jsx(Typography.LightLabelS, { children: _jsx(TruncateString, { text: label }) }) }))] }));
|
|
11
11
|
}
|
|
12
12
|
/** Вспомогательная функция для создания ячейки со статусом */
|
|
13
13
|
export function getStatusColumnDef({ header, accessorKey, mapStatusToAppearance, renderDescription, size, enableSorting, }) {
|
|
14
14
|
const hasDescription = Boolean(renderDescription);
|
|
15
15
|
return {
|
|
16
16
|
id: 'snack_predefined_statusColumn',
|
|
17
|
-
pinned:
|
|
17
|
+
pinned: COLUMN_PIN_POSITION.Left,
|
|
18
18
|
noBodyCellPadding: true,
|
|
19
19
|
noHeaderCellPadding: !hasDescription,
|
|
20
20
|
noHeaderCellBorderOffset: hasDescription,
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
export declare
|
|
2
|
-
Primary
|
|
3
|
-
Neutral
|
|
4
|
-
Red
|
|
5
|
-
Orange
|
|
6
|
-
Yellow
|
|
7
|
-
Green
|
|
8
|
-
Blue
|
|
9
|
-
Violet
|
|
10
|
-
Pink
|
|
11
|
-
Loading
|
|
12
|
-
}
|
|
1
|
+
export declare const STATUS_APPEARANCE: {
|
|
2
|
+
readonly Primary: "primary";
|
|
3
|
+
readonly Neutral: "neutral";
|
|
4
|
+
readonly Red: "red";
|
|
5
|
+
readonly Orange: "orange";
|
|
6
|
+
readonly Yellow: "yellow";
|
|
7
|
+
readonly Green: "green";
|
|
8
|
+
readonly Blue: "blue";
|
|
9
|
+
readonly Violet: "violet";
|
|
10
|
+
readonly Pink: "pink";
|
|
11
|
+
readonly Loading: "loading";
|
|
12
|
+
};
|
|
13
13
|
export declare const MIN_STATUS_CELL_SIZE = 16;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
})(StatusAppearance || (StatusAppearance = {}));
|
|
1
|
+
export const STATUS_APPEARANCE = {
|
|
2
|
+
Primary: 'primary',
|
|
3
|
+
Neutral: 'neutral',
|
|
4
|
+
Red: 'red',
|
|
5
|
+
Orange: 'orange',
|
|
6
|
+
Yellow: 'yellow',
|
|
7
|
+
Green: 'green',
|
|
8
|
+
Blue: 'blue',
|
|
9
|
+
Violet: 'violet',
|
|
10
|
+
Pink: 'pink',
|
|
11
|
+
Loading: 'loading',
|
|
12
|
+
};
|
|
14
13
|
export const MIN_STATUS_CELL_SIZE = 16;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -7,7 +7,7 @@ import { exportToCSV, exportToXLSX } from '../../exportTable';
|
|
|
7
7
|
export function ExportButton({ fileName, data, columnDefinitions }) {
|
|
8
8
|
const [isOpen, setIsOpen] = useState(false);
|
|
9
9
|
const { firstElementRefCallback, handleDroplistFocusLeave, handleTriggerKeyDown, handleDroplistItemKeyDown, handleDroplistItemClick, triggerElementRef, } = Droplist.useKeyboardNavigation({ setDroplistOpen: setIsOpen });
|
|
10
|
-
return (_jsx(Droplist,
|
|
10
|
+
return (_jsx(Droplist, { firstElementRefCallback: firstElementRefCallback, triggerRef: triggerElementRef, onFocusLeave: handleDroplistFocusLeave, open: isOpen, onOpenChange: setIsOpen, useScroll: true, placement: 'bottom-end', triggerElement: _jsx(ButtonFunction, { size: 'm', onKeyDown: handleTriggerKeyDown, icon: _jsx(DownloadSVG, {}) }), children: [
|
|
11
11
|
{
|
|
12
12
|
option: 'Export to CSV',
|
|
13
13
|
onClick: () => {
|
|
@@ -23,5 +23,5 @@ export function ExportButton({ fileName, data, columnDefinitions }) {
|
|
|
23
23
|
].map(({ option, onClick }) => (_jsx(Droplist.ItemSingle, { option: option, onKeyDown: handleDroplistItemKeyDown, onClick: e => {
|
|
24
24
|
handleDroplistItemClick(e);
|
|
25
25
|
onClick === null || onClick === void 0 ? void 0 : onClick();
|
|
26
|
-
} }, option))) }))
|
|
26
|
+
} }, option))) }));
|
|
27
27
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { COLUMN_PIN_POSITION, TEST_IDS } from '../../constants';
|
|
4
4
|
import { BodyCell } from '../Cells';
|
|
5
5
|
import { RowContext } from '../contexts';
|
|
6
6
|
import { useRowCells } from '../hooks';
|
|
@@ -21,5 +21,5 @@ export function BodyRow({ row, onRowClick }) {
|
|
|
21
21
|
toggleSelected: row.toggleSelected,
|
|
22
22
|
});
|
|
23
23
|
};
|
|
24
|
-
return (_jsx(RowContext.Provider,
|
|
24
|
+
return (_jsx(RowContext.Provider, { value: { droplistOpened, setDroplistOpen }, children: _jsxs(Row, { onClick: handleRowClick, "data-clickable": Boolean(onRowClick) || undefined, "data-disabled": disabled || undefined, "data-selected": row.getIsSelected() || undefined, "data-actions-opened": droplistOpened || undefined, "data-test-id": TEST_IDS.bodyRow, "data-row-id": row.id, className: styles.bodyRow, children: [pinnedLeft && (_jsx(PinnedCells, { position: COLUMN_PIN_POSITION.Left, children: pinnedLeft.map(cell => (_jsx(BodyCell, { cell: cell }, cell.id))) })), unpinned.map(cell => (_jsx(BodyCell, { cell: cell }, cell.id))), pinnedRight && (_jsx(PinnedCells, { position: COLUMN_PIN_POSITION.Right, children: pinnedRight.map(cell => (_jsx(BodyCell, { cell: cell }, cell.id))) }))] }) }));
|
|
25
25
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { COLUMN_PIN_POSITION, TEST_IDS } from '../../constants';
|
|
3
3
|
import { HeaderCell } from '../Cells';
|
|
4
4
|
import { useHeaderGroups } from '../hooks';
|
|
5
5
|
import { PinnedCells } from './PinnedCells';
|
|
@@ -7,5 +7,5 @@ import { Row } from './Row';
|
|
|
7
7
|
import styles from './styles.module.css';
|
|
8
8
|
export function HeaderRow() {
|
|
9
9
|
const { leftPinned, unpinned, rightPinned } = useHeaderGroups();
|
|
10
|
-
return (_jsxs(Row,
|
|
10
|
+
return (_jsxs(Row, { className: styles.tableHeader, "data-test-id": TEST_IDS.headerRow, role: 'rowheader', children: [leftPinned && (_jsx(PinnedCells, { position: COLUMN_PIN_POSITION.Left, children: leftPinned.map(headerGroup => headerGroup.headers.map(header => header.isPlaceholder ? null : _jsx(HeaderCell, { header: header }, header.id))) })), unpinned.map(headerGroup => headerGroup.headers.map(header => _jsx(HeaderCell, { header: header }, header.id))), rightPinned && (_jsx(PinnedCells, { position: COLUMN_PIN_POSITION.Right, children: rightPinned.map(headerGroup => headerGroup.headers.map(header => header.isPlaceholder ? null : _jsx(HeaderCell, { header: header }, header.id))) }))] }));
|
|
11
11
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { ValueOf } from '@snack-uikit/utils';
|
|
3
|
+
import { COLUMN_PIN_POSITION } from '../../constants';
|
|
3
4
|
type PinnedCellsProps = {
|
|
4
|
-
position:
|
|
5
|
+
position: ValueOf<typeof COLUMN_PIN_POSITION>;
|
|
5
6
|
children: ReactNode;
|
|
6
7
|
};
|
|
7
8
|
export declare function PinnedCells({ position, children }: PinnedCellsProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -2,5 +2,5 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { TEST_IDS } from '../../constants';
|
|
3
3
|
import styles from './styles.module.css';
|
|
4
4
|
export function PinnedCells({ position, children }) {
|
|
5
|
-
return (_jsx("div",
|
|
5
|
+
return (_jsx("div", { "data-position": position, "data-test-id": TEST_IDS.pinnedCells, className: styles.rowPinnedCells, children: children }));
|
|
6
6
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { CellContext, ColumnDef, ColumnMeta, HeaderContext, PaginationState, RowSelectionOptions, RowSelectionState, SortingState } from '@tanstack/react-table';
|
|
2
2
|
import { ToolbarProps } from '@snack-uikit/toolbar';
|
|
3
|
+
import { ValueOf } from '@snack-uikit/utils';
|
|
3
4
|
import { TableEmptyStateProps } from './components/TableEmptyState';
|
|
4
|
-
import {
|
|
5
|
-
import { Except } from './helperComponents
|
|
5
|
+
import { COLUMN_ALIGN, COLUMN_PIN_POSITION } from './constants';
|
|
6
|
+
import { Except } from './helperComponents';
|
|
7
|
+
type ColumnAlign = ValueOf<typeof COLUMN_ALIGN>;
|
|
8
|
+
type ColumnPinPosition = ValueOf<typeof COLUMN_PIN_POSITION>;
|
|
6
9
|
type BaseColumnDefinition<TData> = Except<ColumnDef<TData>, 'footer' | 'enablePinning' | 'enableGrouping' | 'enableResizing' | 'enableColumnFilter' | 'filterFn' | 'enableGlobalFilter' | 'enableMultiSort' | 'enableHiding'> & {
|
|
7
10
|
/** Заголовок колонки */
|
|
8
11
|
header?: string | ((ctx: HeaderContext<TData, unknown>) => string);
|
|
@@ -35,4 +38,4 @@ type PinnedColumnDefinition<TData> = BaseColumnDefinition<TData> & {
|
|
|
35
38
|
};
|
|
36
39
|
export type ColumnDefinition<TData> = NormalColumnDefinition<TData> | PinnedColumnDefinition<TData>;
|
|
37
40
|
export type { RowActionInfo, RowActionProps, RowActionsColumnDefProps, StatusColumnDefinitionProps, RowInfo, RowClickHandler, } from './helperComponents';
|
|
38
|
-
export {
|
|
41
|
+
export type { PaginationState, SortingState, RowSelectionState, RowSelectionOptions, TableEmptyStateProps, ToolbarProps, HeaderContext, CellContext, };
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
6
|
"title": "Table",
|
|
7
|
-
"version": "0.
|
|
7
|
+
"version": "0.8.1",
|
|
8
8
|
"sideEffects": [
|
|
9
9
|
"*.css",
|
|
10
10
|
"*.woff",
|
|
@@ -32,24 +32,24 @@
|
|
|
32
32
|
"license": "Apache-2.0",
|
|
33
33
|
"scripts": {},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@snack-uikit/button": "0.
|
|
36
|
-
"@snack-uikit/chips": "0.
|
|
37
|
-
"@snack-uikit/droplist": "0.
|
|
38
|
-
"@snack-uikit/icon-predefined": "0.
|
|
39
|
-
"@snack-uikit/icons": "0.19.
|
|
40
|
-
"@snack-uikit/pagination": "0.5.
|
|
41
|
-
"@snack-uikit/scroll": "0.
|
|
42
|
-
"@snack-uikit/skeleton": "0.3.
|
|
43
|
-
"@snack-uikit/toggles": "0.
|
|
44
|
-
"@snack-uikit/toolbar": "0.
|
|
45
|
-
"@snack-uikit/truncate-string": "0.
|
|
46
|
-
"@snack-uikit/typography": "0.
|
|
47
|
-
"@snack-uikit/utils": "3.
|
|
35
|
+
"@snack-uikit/button": "0.15.0",
|
|
36
|
+
"@snack-uikit/chips": "0.10.1",
|
|
37
|
+
"@snack-uikit/droplist": "0.12.1",
|
|
38
|
+
"@snack-uikit/icon-predefined": "0.4.0",
|
|
39
|
+
"@snack-uikit/icons": "0.19.1",
|
|
40
|
+
"@snack-uikit/pagination": "0.5.3",
|
|
41
|
+
"@snack-uikit/scroll": "0.5.0",
|
|
42
|
+
"@snack-uikit/skeleton": "0.3.2",
|
|
43
|
+
"@snack-uikit/toggles": "0.9.1",
|
|
44
|
+
"@snack-uikit/toolbar": "0.5.1",
|
|
45
|
+
"@snack-uikit/truncate-string": "0.4.1",
|
|
46
|
+
"@snack-uikit/typography": "0.6.0",
|
|
47
|
+
"@snack-uikit/utils": "3.2.0",
|
|
48
48
|
"@tanstack/match-sorter-utils": "8.8.4",
|
|
49
49
|
"@tanstack/react-table": "8.10.7",
|
|
50
50
|
"classnames": "2.3.2",
|
|
51
51
|
"uncontrollable": "8.0.0",
|
|
52
52
|
"xlsx": "0.18.5"
|
|
53
53
|
},
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "62f43bf0cbfd611d0b746117400f67096b1790f6"
|
|
55
55
|
}
|
|
@@ -13,14 +13,12 @@ import {
|
|
|
13
13
|
} from '@tanstack/react-table';
|
|
14
14
|
import { ReactNode, useCallback, useMemo } from 'react';
|
|
15
15
|
|
|
16
|
-
import { IconPredefined } from '@snack-uikit/icon-predefined';
|
|
17
16
|
import { Scroll } from '@snack-uikit/scroll';
|
|
18
17
|
import { SkeletonContextProvider } from '@snack-uikit/skeleton';
|
|
19
18
|
import { Toolbar, ToolbarProps } from '@snack-uikit/toolbar';
|
|
20
19
|
import { TruncateString } from '@snack-uikit/truncate-string';
|
|
21
20
|
import { extractSupportProps, WithSupportProps } from '@snack-uikit/utils';
|
|
22
21
|
|
|
23
|
-
import { ColumnAlign, ColumnPinPosition } from '../../constants';
|
|
24
22
|
import {
|
|
25
23
|
BodyRow,
|
|
26
24
|
ExportButton,
|
|
@@ -30,7 +28,7 @@ import {
|
|
|
30
28
|
getStatusColumnDef,
|
|
31
29
|
HeaderRow,
|
|
32
30
|
RowClickHandler,
|
|
33
|
-
|
|
31
|
+
STATUS_APPEARANCE,
|
|
34
32
|
TableContext,
|
|
35
33
|
} from '../../helperComponents';
|
|
36
34
|
import { ColumnDefinition } from '../../types';
|
|
@@ -322,9 +320,7 @@ export function Table<TData extends object>({
|
|
|
322
320
|
outline={outline}
|
|
323
321
|
loading={search?.loading}
|
|
324
322
|
placeholder={search?.placeholder || 'Search'}
|
|
325
|
-
selectionMode={
|
|
326
|
-
rowSelectionProp?.multiRow ? Toolbar.selectionModes.Multiple : Toolbar.selectionModes.Single
|
|
327
|
-
}
|
|
323
|
+
selectionMode={rowSelectionProp?.multiRow ? 'multiple' : 'single'}
|
|
328
324
|
actions={
|
|
329
325
|
exportFileName ? (
|
|
330
326
|
<ExportButton fileName={exportFileName} columnDefinitions={columnDefinitions} data={data} />
|
|
@@ -338,7 +334,7 @@ export function Table<TData extends object>({
|
|
|
338
334
|
)}
|
|
339
335
|
|
|
340
336
|
<div className={styles.scrollWrapper} data-outline={outline || undefined}>
|
|
341
|
-
<Scroll size=
|
|
337
|
+
<Scroll size='s' className={styles.table}>
|
|
342
338
|
<div className={styles.tableContent}>
|
|
343
339
|
<TableContext.Provider value={{ table }}>
|
|
344
340
|
{loading ? (
|
|
@@ -377,9 +373,6 @@ export function Table<TData extends object>({
|
|
|
377
373
|
);
|
|
378
374
|
}
|
|
379
375
|
|
|
380
|
-
Table.columnPinPositions = ColumnPinPosition;
|
|
381
|
-
Table.columnAligns = ColumnAlign;
|
|
382
376
|
Table.getStatusColumnDef = getStatusColumnDef;
|
|
383
|
-
Table.statusAppearances =
|
|
377
|
+
Table.statusAppearances = STATUS_APPEARANCE;
|
|
384
378
|
Table.getRowActionsColumnDef = getRowActionsColumnDef;
|
|
385
|
-
Table.emptyStateAppearances = IconPredefined.appearances;
|
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
import { IconPredefined } from '@snack-uikit/icon-predefined';
|
|
2
1
|
import { CrossSVG, SearchSVG } from '@snack-uikit/icons';
|
|
3
2
|
|
|
4
3
|
import { TableEmptyStateProps } from '../TableEmptyState';
|
|
5
4
|
|
|
6
5
|
export const DEFAULT_NO_DATA_TABLE_STATE: TableEmptyStateProps = {
|
|
7
6
|
icon: CrossSVG,
|
|
8
|
-
appearance:
|
|
7
|
+
appearance: 'red',
|
|
9
8
|
title: 'Data collection error',
|
|
10
9
|
description: 'Try refreshing the page',
|
|
11
10
|
} as const;
|
|
12
11
|
|
|
13
12
|
export const DEFAULT_NO_RESULTS_TABLE_STATE: TableEmptyStateProps = {
|
|
14
13
|
icon: SearchSVG,
|
|
15
|
-
appearance:
|
|
14
|
+
appearance: 'neutral',
|
|
16
15
|
title: 'Not found',
|
|
17
16
|
description: 'Try entering another query',
|
|
18
17
|
} as const;
|
|
@@ -15,7 +15,7 @@ export type TableEmptyStateProps = {
|
|
|
15
15
|
export function TableEmptyState({ title, description, className, icon, appearance }: TableEmptyStateProps) {
|
|
16
16
|
return (
|
|
17
17
|
<div className={cn(styles.tableEmptyStateWrapper, className)}>
|
|
18
|
-
<IconPredefined icon={icon} size=
|
|
18
|
+
<IconPredefined icon={icon} size='l' appearance={appearance} />
|
|
19
19
|
<div className={styles.textWrapper}>
|
|
20
20
|
<Typography.SansTitleM>{title}</Typography.SansTitleM>
|
|
21
21
|
{description && <Typography.SansBodyM>{description}</Typography.SansBodyM>}
|
|
@@ -58,10 +58,10 @@ export function TablePagination<TData>({
|
|
|
58
58
|
<ChipChoice.Single
|
|
59
59
|
value={String(tablePaginationState.pageSize)}
|
|
60
60
|
onChange={handleRowsVolumeOnChange}
|
|
61
|
-
placement=
|
|
61
|
+
placement='top-end'
|
|
62
62
|
options={options}
|
|
63
63
|
label={optionsLabel}
|
|
64
|
-
widthStrategy=
|
|
64
|
+
widthStrategy='auto'
|
|
65
65
|
showClearButton={false}
|
|
66
66
|
/>
|
|
67
67
|
)}
|
package/src/constants.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
export
|
|
2
|
-
Left
|
|
3
|
-
Right
|
|
4
|
-
}
|
|
1
|
+
export const COLUMN_PIN_POSITION = {
|
|
2
|
+
Left: 'left',
|
|
3
|
+
Right: 'right',
|
|
4
|
+
} as const;
|
|
5
5
|
|
|
6
|
-
export
|
|
7
|
-
Left
|
|
8
|
-
Right
|
|
9
|
-
}
|
|
6
|
+
export const COLUMN_ALIGN = {
|
|
7
|
+
Left: 'left',
|
|
8
|
+
Right: 'right',
|
|
9
|
+
} as const;
|
|
10
10
|
|
|
11
11
|
export const TEST_IDS = {
|
|
12
12
|
headerSortIndicator: 'table__header__sort-indicator',
|
|
@@ -25,7 +25,7 @@ export const TEST_IDS = {
|
|
|
25
25
|
statusLabel: 'table__status-label',
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
export
|
|
29
|
-
DateTime
|
|
30
|
-
AlphaNumeric
|
|
31
|
-
}
|
|
28
|
+
export const SORT_FN = {
|
|
29
|
+
DateTime: 'datetime',
|
|
30
|
+
AlphaNumeric: 'alphanumeric',
|
|
31
|
+
} as const;
|
|
@@ -5,7 +5,7 @@ import { ButtonFunction } from '@snack-uikit/button';
|
|
|
5
5
|
import { Droplist, ItemSingleProps } from '@snack-uikit/droplist';
|
|
6
6
|
import { MoreSVG } from '@snack-uikit/icons';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { COLUMN_PIN_POSITION, TEST_IDS } from '../../../constants';
|
|
9
9
|
import { ColumnDefinition } from '../../../types';
|
|
10
10
|
import { useRowContext } from '../../contexts';
|
|
11
11
|
import styles from './styles.module.scss';
|
|
@@ -58,7 +58,7 @@ function RowActionsCell<TData>({ row, actions }: RowActionsCellProps<TData>) {
|
|
|
58
58
|
<Droplist
|
|
59
59
|
open={droplistOpened}
|
|
60
60
|
onOpenChange={setDroplistOpen}
|
|
61
|
-
placement=
|
|
61
|
+
placement='bottom-end'
|
|
62
62
|
firstElementRefCallback={firstElementRefCallback}
|
|
63
63
|
onFocusLeave={handleDroplistFocusLeave}
|
|
64
64
|
triggerElement={
|
|
@@ -72,7 +72,7 @@ function RowActionsCell<TData>({ row, actions }: RowActionsCellProps<TData>) {
|
|
|
72
72
|
</span>
|
|
73
73
|
}
|
|
74
74
|
triggerClassName={styles.rowActionsCellTrigger}
|
|
75
|
-
size=
|
|
75
|
+
size='s'
|
|
76
76
|
data-test-id={TEST_IDS.rowActions.droplist}
|
|
77
77
|
>
|
|
78
78
|
{actions.map(item => (
|
|
@@ -106,7 +106,7 @@ export function getRowActionsColumnDef<TData>({
|
|
|
106
106
|
}: RowActionsColumnDefProps<TData>): ColumnDefinition<TData> {
|
|
107
107
|
return {
|
|
108
108
|
id: 'rowActions',
|
|
109
|
-
pinned: pinned ?
|
|
109
|
+
pinned: pinned ? COLUMN_PIN_POSITION.Right : (undefined as never),
|
|
110
110
|
size: 40,
|
|
111
111
|
meta: {
|
|
112
112
|
skipOnExport: true,
|
|
@@ -2,7 +2,7 @@ import { MouseEvent } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { Checkbox, Radio } from '@snack-uikit/toggles';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { COLUMN_PIN_POSITION, TEST_IDS } from '../../../constants';
|
|
6
6
|
import { ColumnDefinition } from '../../../types';
|
|
7
7
|
import styles from './styles.module.scss';
|
|
8
8
|
|
|
@@ -22,7 +22,7 @@ function SelectionCell({ isMulti, onChange, ...props }: SelectionCellProps) {
|
|
|
22
22
|
return (
|
|
23
23
|
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
24
24
|
<div onClick={handleCellClick} className={styles.selectionCell} data-test-id={TEST_IDS.rowSelect}>
|
|
25
|
-
{isMulti ? <Checkbox {...props} size=
|
|
25
|
+
{isMulti ? <Checkbox {...props} size='s' /> : <Radio {...props} size='s' />}
|
|
26
26
|
</div>
|
|
27
27
|
);
|
|
28
28
|
}
|
|
@@ -30,7 +30,7 @@ function SelectionCell({ isMulti, onChange, ...props }: SelectionCellProps) {
|
|
|
30
30
|
export function getSelectionCellColumnDef<TData>(): ColumnDefinition<TData> {
|
|
31
31
|
return {
|
|
32
32
|
id: 'selectionCell',
|
|
33
|
-
pinned:
|
|
33
|
+
pinned: COLUMN_PIN_POSITION.Left,
|
|
34
34
|
noBodyCellPadding: true,
|
|
35
35
|
size: 40,
|
|
36
36
|
headerClassName: styles.selectionCellHeader,
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { TruncateString } from '@snack-uikit/truncate-string';
|
|
2
2
|
import { Typography } from '@snack-uikit/typography';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { COLUMN_PIN_POSITION, TEST_IDS } from '../../../constants';
|
|
5
5
|
import { ColumnDefinition } from '../../../types';
|
|
6
|
-
import { MIN_STATUS_CELL_SIZE,
|
|
6
|
+
import { MIN_STATUS_CELL_SIZE, STATUS_APPEARANCE } from './constants';
|
|
7
7
|
import styles from './styles.module.scss';
|
|
8
|
+
import { StatusAppearance } from './types';
|
|
8
9
|
|
|
9
|
-
export { StatusAppearance };
|
|
10
|
+
export type { StatusAppearance };
|
|
11
|
+
|
|
12
|
+
export { STATUS_APPEARANCE };
|
|
10
13
|
|
|
11
14
|
type StatusCellProps = {
|
|
12
15
|
label?: string;
|
|
@@ -40,7 +43,7 @@ type StatusColumnDefWithDescription<TData> = BaseStatusColumnDef & {
|
|
|
40
43
|
export type StatusColumnDefinitionProps<TData> = StatusColumnDef | StatusColumnDefWithDescription<TData>;
|
|
41
44
|
|
|
42
45
|
function StatusCell({ appearance, label }: StatusCellProps) {
|
|
43
|
-
const isLoading = appearance ===
|
|
46
|
+
const isLoading = appearance === STATUS_APPEARANCE.Loading;
|
|
44
47
|
|
|
45
48
|
return (
|
|
46
49
|
<div className={styles.statusCell} data-no-label={!label || undefined}>
|
|
@@ -75,7 +78,7 @@ export function getStatusColumnDef<TData>({
|
|
|
75
78
|
|
|
76
79
|
return {
|
|
77
80
|
id: 'snack_predefined_statusColumn',
|
|
78
|
-
pinned:
|
|
81
|
+
pinned: COLUMN_PIN_POSITION.Left,
|
|
79
82
|
noBodyCellPadding: true,
|
|
80
83
|
noHeaderCellPadding: !hasDescription,
|
|
81
84
|
noHeaderCellBorderOffset: hasDescription,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
export
|
|
2
|
-
Primary
|
|
3
|
-
Neutral
|
|
4
|
-
Red
|
|
5
|
-
Orange
|
|
6
|
-
Yellow
|
|
7
|
-
Green
|
|
8
|
-
Blue
|
|
9
|
-
Violet
|
|
10
|
-
Pink
|
|
11
|
-
Loading
|
|
12
|
-
}
|
|
1
|
+
export const STATUS_APPEARANCE = {
|
|
2
|
+
Primary: 'primary',
|
|
3
|
+
Neutral: 'neutral',
|
|
4
|
+
Red: 'red',
|
|
5
|
+
Orange: 'orange',
|
|
6
|
+
Yellow: 'yellow',
|
|
7
|
+
Green: 'green',
|
|
8
|
+
Blue: 'blue',
|
|
9
|
+
Violet: 'violet',
|
|
10
|
+
Pink: 'pink',
|
|
11
|
+
Loading: 'loading',
|
|
12
|
+
} as const;
|
|
13
13
|
|
|
14
14
|
export const MIN_STATUS_CELL_SIZE = 16;
|
|
@@ -36,10 +36,8 @@ export function ExportButton<TData extends object>({ fileName, data, columnDefin
|
|
|
36
36
|
open={isOpen}
|
|
37
37
|
onOpenChange={setIsOpen}
|
|
38
38
|
useScroll
|
|
39
|
-
placement=
|
|
40
|
-
triggerElement={
|
|
41
|
-
<ButtonFunction size={ButtonFunction.sizes.M} onKeyDown={handleTriggerKeyDown} icon={<DownloadSVG />} />
|
|
42
|
-
}
|
|
39
|
+
placement='bottom-end'
|
|
40
|
+
triggerElement={<ButtonFunction size='m' onKeyDown={handleTriggerKeyDown} icon={<DownloadSVG />} />}
|
|
43
41
|
>
|
|
44
42
|
{[
|
|
45
43
|
{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Row as TableRow } from '@tanstack/react-table';
|
|
2
2
|
import { MouseEvent, useState } from 'react';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { COLUMN_PIN_POSITION, TEST_IDS } from '../../constants';
|
|
5
5
|
import { BodyCell } from '../Cells';
|
|
6
6
|
import { RowContext } from '../contexts';
|
|
7
7
|
import { useRowCells } from '../hooks';
|
|
@@ -54,7 +54,7 @@ export function BodyRow<TData>({ row, onRowClick }: BodyRowProps<TData>) {
|
|
|
54
54
|
className={styles.bodyRow}
|
|
55
55
|
>
|
|
56
56
|
{pinnedLeft && (
|
|
57
|
-
<PinnedCells position={
|
|
57
|
+
<PinnedCells position={COLUMN_PIN_POSITION.Left}>
|
|
58
58
|
{pinnedLeft.map(cell => (
|
|
59
59
|
<BodyCell key={cell.id} cell={cell} />
|
|
60
60
|
))}
|
|
@@ -66,7 +66,7 @@ export function BodyRow<TData>({ row, onRowClick }: BodyRowProps<TData>) {
|
|
|
66
66
|
))}
|
|
67
67
|
|
|
68
68
|
{pinnedRight && (
|
|
69
|
-
<PinnedCells position={
|
|
69
|
+
<PinnedCells position={COLUMN_PIN_POSITION.Right}>
|
|
70
70
|
{pinnedRight.map(cell => (
|
|
71
71
|
<BodyCell key={cell.id} cell={cell} />
|
|
72
72
|
))}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { COLUMN_PIN_POSITION, TEST_IDS } from '../../constants';
|
|
2
2
|
import { HeaderCell } from '../Cells';
|
|
3
3
|
import { useHeaderGroups } from '../hooks';
|
|
4
4
|
import { PinnedCells } from './PinnedCells';
|
|
@@ -11,7 +11,7 @@ export function HeaderRow() {
|
|
|
11
11
|
return (
|
|
12
12
|
<Row className={styles.tableHeader} data-test-id={TEST_IDS.headerRow} role='rowheader'>
|
|
13
13
|
{leftPinned && (
|
|
14
|
-
<PinnedCells position={
|
|
14
|
+
<PinnedCells position={COLUMN_PIN_POSITION.Left}>
|
|
15
15
|
{leftPinned.map(headerGroup =>
|
|
16
16
|
headerGroup.headers.map(header =>
|
|
17
17
|
header.isPlaceholder ? null : <HeaderCell key={header.id} header={header} />,
|
|
@@ -23,7 +23,7 @@ export function HeaderRow() {
|
|
|
23
23
|
{unpinned.map(headerGroup => headerGroup.headers.map(header => <HeaderCell key={header.id} header={header} />))}
|
|
24
24
|
|
|
25
25
|
{rightPinned && (
|
|
26
|
-
<PinnedCells position={
|
|
26
|
+
<PinnedCells position={COLUMN_PIN_POSITION.Right}>
|
|
27
27
|
{rightPinned.map(headerGroup =>
|
|
28
28
|
headerGroup.headers.map(header =>
|
|
29
29
|
header.isPlaceholder ? null : <HeaderCell key={header.id} header={header} />,
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { ValueOf } from '@snack-uikit/utils';
|
|
4
|
+
|
|
5
|
+
import { COLUMN_PIN_POSITION, TEST_IDS } from '../../constants';
|
|
4
6
|
import styles from './styles.module.scss';
|
|
5
7
|
|
|
6
8
|
type PinnedCellsProps = {
|
|
7
|
-
position:
|
|
9
|
+
position: ValueOf<typeof COLUMN_PIN_POSITION>;
|
|
8
10
|
children: ReactNode;
|
|
9
11
|
};
|
|
10
12
|
|
package/src/types.ts
CHANGED
|
@@ -10,10 +10,15 @@ import {
|
|
|
10
10
|
} from '@tanstack/react-table';
|
|
11
11
|
|
|
12
12
|
import { ToolbarProps } from '@snack-uikit/toolbar';
|
|
13
|
+
import { ValueOf } from '@snack-uikit/utils';
|
|
13
14
|
|
|
14
15
|
import { TableEmptyStateProps } from './components/TableEmptyState';
|
|
15
|
-
import {
|
|
16
|
-
import { Except } from './helperComponents
|
|
16
|
+
import { COLUMN_ALIGN, COLUMN_PIN_POSITION } from './constants';
|
|
17
|
+
import { Except } from './helperComponents';
|
|
18
|
+
|
|
19
|
+
type ColumnAlign = ValueOf<typeof COLUMN_ALIGN>;
|
|
20
|
+
|
|
21
|
+
type ColumnPinPosition = ValueOf<typeof COLUMN_PIN_POSITION>;
|
|
17
22
|
|
|
18
23
|
type BaseColumnDefinition<TData> = Except<
|
|
19
24
|
ColumnDef<TData>,
|
|
@@ -68,13 +73,13 @@ export type {
|
|
|
68
73
|
RowClickHandler,
|
|
69
74
|
} from './helperComponents';
|
|
70
75
|
|
|
71
|
-
export {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
export type {
|
|
77
|
+
PaginationState,
|
|
78
|
+
SortingState,
|
|
79
|
+
RowSelectionState,
|
|
80
|
+
RowSelectionOptions,
|
|
81
|
+
TableEmptyStateProps,
|
|
82
|
+
ToolbarProps,
|
|
83
|
+
HeaderContext,
|
|
84
|
+
CellContext,
|
|
80
85
|
};
|