@snack-uikit/table 0.37.10 → 0.37.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,22 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## <small>0.37.12 (2025-10-24)</small>
7
+
8
+ * feat(FF-7464): add getRowBackgroundColor into table ([1854275](https://github.com/cloud-ru-tech/snack-uikit/commit/1854275))
9
+
10
+
11
+
12
+
13
+
14
+ ## <small>0.37.11 (2025-09-25)</small>
15
+
16
+ * fix(FF-7134): update ft-request-payload-transform ([4f95098](https://github.com/cloud-ru-tech/snack-uikit/commit/4f95098))
17
+
18
+
19
+
20
+
21
+
6
22
  ## <small>0.37.10 (2025-09-25)</small>
7
23
 
8
24
  * fix(FF-7134): table requestPayload offset calculation ([d36ad78](https://github.com/cloud-ru-tech/snack-uikit/commit/d36ad78))
package/README.md CHANGED
@@ -155,6 +155,7 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
155
155
  | scrollContainerRef | `RefObject<HTMLElement>` | - | Ссылка на контейнер, который скроллится |
156
156
  | rowPinning | `Pick<RowPinningState, "top">` | { top: [], } | Определение какие строки должны быть закреплены в таблице |
157
157
  | savedState | `{ id: string; filterQueryKey?: string; resize?: boolean; columnSettings?: boolean; }` | - | Конфиг для сохранения состояния в localStorage и queryParams. <br> Поле id должно быть уникальным для разных таблиц в рамках приложения. <br> Для корректной работы необходимо наличие id в конфиге columnDefinitions |
158
+ | getRowBackgroundColor | `(data: TData) => TableRowColor` | - | Функция для определения цвета фона строки на основе данных строки @param data - данные строки таблицы @returns цвет фона строки или undefined, если цвет не должен применяться |
158
159
  | 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>: Текст для селектора кол-ва строк на страницу |
159
160
  | autoResetPageIndex | `boolean` | - | Автоматический сброс пагинации к первой странице при изменении данных или состояния (e.g фильтры, сортировки, и т.д) |
160
161
  | pageCount | `number` | - | Кол-во страниц (используется для внешнего управления) |
@@ -221,6 +222,7 @@ const columnDefinitions: ColumnDefinition<TableData>[] = [
221
222
  | scrollContainerRef | `RefObject<HTMLElement>` | - | Ссылка на контейнер, который скроллится |
222
223
  | rowPinning | `Pick<RowPinningState, "top">` | - | Определение какие строки должны быть закреплены в таблице |
223
224
  | savedState | `{ id: string; filterQueryKey?: string; resize?: boolean; columnSettings?: boolean; }` | - | Конфиг для сохранения состояния в localStorage и queryParams. <br> Поле id должно быть уникальным для разных таблиц в рамках приложения. <br> Для корректной работы необходимо наличие id в конфиге columnDefinitions |
225
+ | getRowBackgroundColor | `(data: TData) => TableRowColor` | - | Функция для определения цвета фона строки на основе данных строки @param data - данные строки таблицы @returns цвет фона строки или undefined, если цвет не должен применяться |
224
226
  | autoResetPageIndex | `boolean` | - | Автоматический сброс пагинации к первой странице при изменении данных или состояния (e.g фильтры, сортировки, и т.д) |
225
227
  | suppressPagination | `boolean` | - | Отключение пагинации |
226
228
  | manualPagination | `boolean` | true | |
@@ -1,7 +1,7 @@
1
1
  import { FiltersState } from '@snack-uikit/chips';
2
2
  import { TableProps } from '../types';
3
3
  /** Компонент таблицы */
4
- export declare function Table<TData extends object, TFilters extends FiltersState = Record<string, unknown>>({ data, rowPinning, columnDefinitions, keepPinnedRows, copyPinnedRows, enableSelectPinned, rowSelection: rowSelectionProp, search, sorting: sortingProp, columnFilters, pagination: paginationProp, className, onRowClick, onRefresh, pageSize, pageCount, loading, infiniteLoading, outline, moreActions, exportSettings, dataFiltered, dataError, noDataState, noResultsState, errorDataState, suppressToolbar, suppressSearch, toolbarAfter, suppressPagination, manualSorting, manualPagination: manualPaginationProp, manualFiltering, autoResetPageIndex, scrollRef, scrollContainerRef, getRowId, enableFuzzySearch, savedState, expanding, bulkActions: bulkActionsProp, rowAutoHeight, columnsSettings: columnsSettingsProp, ...rest }: TableProps<TData, TFilters>): import("react/jsx-runtime").JSX.Element;
4
+ export declare function Table<TData extends object, TFilters extends FiltersState = Record<string, unknown>>({ data, rowPinning, columnDefinitions, keepPinnedRows, copyPinnedRows, enableSelectPinned, rowSelection: rowSelectionProp, search, sorting: sortingProp, columnFilters, pagination: paginationProp, className, onRowClick, onRefresh, pageSize, pageCount, loading, infiniteLoading, outline, moreActions, exportSettings, dataFiltered, dataError, noDataState, noResultsState, errorDataState, suppressToolbar, suppressSearch, toolbarAfter, suppressPagination, manualSorting, manualPagination: manualPaginationProp, manualFiltering, autoResetPageIndex, scrollRef, scrollContainerRef, getRowId, enableFuzzySearch, savedState, expanding, bulkActions: bulkActionsProp, rowAutoHeight, columnsSettings: columnsSettingsProp, getRowBackgroundColor, ...rest }: TableProps<TData, TFilters>): import("react/jsx-runtime").JSX.Element;
5
5
  export declare namespace Table {
6
6
  var getStatusColumnDef: typeof import("../../helperComponents").getStatusColumnDef;
7
7
  var statusAppearances: {
@@ -84,9 +84,10 @@ function Table(_a) {
84
84
  expanding,
85
85
  bulkActions: bulkActionsProp,
86
86
  rowAutoHeight,
87
- columnsSettings: columnsSettingsProp
87
+ columnsSettings: columnsSettingsProp,
88
+ getRowBackgroundColor
88
89
  } = _a,
89
- rest = __rest(_a, ["data", "rowPinning", "columnDefinitions", "keepPinnedRows", "copyPinnedRows", "enableSelectPinned", "rowSelection", "search", "sorting", "columnFilters", "pagination", "className", "onRowClick", "onRefresh", "pageSize", "pageCount", "loading", "infiniteLoading", "outline", "moreActions", "exportSettings", "dataFiltered", "dataError", "noDataState", "noResultsState", "errorDataState", "suppressToolbar", "suppressSearch", "toolbarAfter", "suppressPagination", "manualSorting", "manualPagination", "manualFiltering", "autoResetPageIndex", "scrollRef", "scrollContainerRef", "getRowId", "enableFuzzySearch", "savedState", "expanding", "bulkActions", "rowAutoHeight", "columnsSettings"]);
90
+ rest = __rest(_a, ["data", "rowPinning", "columnDefinitions", "keepPinnedRows", "copyPinnedRows", "enableSelectPinned", "rowSelection", "search", "sorting", "columnFilters", "pagination", "className", "onRowClick", "onRefresh", "pageSize", "pageCount", "loading", "infiniteLoading", "outline", "moreActions", "exportSettings", "dataFiltered", "dataError", "noDataState", "noResultsState", "errorDataState", "suppressToolbar", "suppressSearch", "toolbarAfter", "suppressPagination", "manualSorting", "manualPagination", "manualFiltering", "autoResetPageIndex", "scrollRef", "scrollContainerRef", "getRowId", "enableFuzzySearch", "savedState", "expanding", "bulkActions", "rowAutoHeight", "columnsSettings", "getRowBackgroundColor"]);
90
91
  const [globalFilter, onGlobalFilterChange] = (0, hooks_1.useStateControl)(search, '');
91
92
  const [rowSelection, onRowSelectionChange] = (0, hooks_1.useStateControl)(rowSelectionProp, constants_1.DEFAULT_ROW_SELECTION);
92
93
  const defaultPaginationState = (0, react_1.useMemo)(() => ({
@@ -445,7 +446,8 @@ function Table(_a) {
445
446
  children: (0, jsx_runtime_1.jsx)(core_1.DndContext, Object.assign({}, dndContextProps, {
446
447
  children: (0, jsx_runtime_1.jsx)(helperComponents_1.TableContext.Provider, {
447
448
  value: {
448
- table
449
+ table,
450
+ getRowBackgroundColor
449
451
  },
450
452
  children: (!infiniteLoading || !data.length) && loading ? (0, jsx_runtime_1.jsxs)(skeleton_1.SkeletonContextProvider, {
451
453
  loading: true,
@@ -2,9 +2,11 @@ import { PaginationState, Row, RowPinningState, RowSelectionOptions, RowSelectio
2
2
  import { ReactNode, RefObject } from 'react';
3
3
  import { FiltersState } from '@snack-uikit/chips';
4
4
  import { FilterRow, ToolbarProps } from '@snack-uikit/toolbar';
5
- import { WithSupportProps } from '@snack-uikit/utils';
5
+ import { ValueOf, WithSupportProps } from '@snack-uikit/utils';
6
+ import { TABLE_ROW_COLOR } from '../constants';
6
7
  import { EmptyStateProps, ExportButtonProps, RowClickHandler, TreeColumnDefinitionProps } from '../helperComponents';
7
8
  import { ColumnDefinition, ExpandedState } from '../types';
9
+ export type TableRowColor = ValueOf<typeof TABLE_ROW_COLOR>;
8
10
  type BulkAction = Omit<NonNullable<ToolbarProps<Record<string, string>>['bulkActions']>[number], 'onClick'> & {
9
11
  onClick?(selectionState: RowSelectionState, resetRowSelection: (defaultState?: boolean) => void): void;
10
12
  };
@@ -138,6 +140,12 @@ type BaseTableProps<TData extends object, TFilters extends FiltersState = Record
138
140
  resize?: boolean;
139
141
  columnSettings?: boolean;
140
142
  };
143
+ /**
144
+ * Функция для определения цвета фона строки на основе данных строки
145
+ * @param data - данные строки таблицы
146
+ * @returns цвет фона строки или undefined, если цвет не должен применяться
147
+ */
148
+ getRowBackgroundColor?: (data: TData) => TableRowColor | undefined;
141
149
  }>;
142
150
  export type InfiniteTableProps<TData extends object, TFilters extends FiltersState = Record<string, unknown>> = BaseTableProps<TData, TFilters> & {
143
151
  pagination?: never;
@@ -50,3 +50,13 @@ export declare enum DefaultColumns {
50
50
  RowActions = "rowActions"
51
51
  }
52
52
  export declare const DEFAULT_COLUMNS: DefaultColumns[];
53
+ export declare const TABLE_ROW_COLOR: {
54
+ readonly Red: "red";
55
+ readonly Orange: "orange";
56
+ readonly Yellow: "yellow";
57
+ readonly Green: "green";
58
+ readonly Blue: "blue";
59
+ readonly Violet: "violet";
60
+ readonly Pink: "pink";
61
+ readonly Neutral: "neutral";
62
+ };
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.DEFAULT_COLUMNS = exports.DefaultColumns = exports.DEFAULT_EXPANDED = exports.DEFAULT_ROW_SELECTION = exports.DEFAULT_FILTER_VISIBILITY = exports.DEFAULT_SORTING = exports.DEFAULT_PAGE_SIZE = exports.SORT_FN = exports.TEST_IDS = exports.COLUMN_SETTINGS_MODE = exports.COLUMN_ALIGN = exports.COLUMN_PIN_POSITION = void 0;
6
+ exports.TABLE_ROW_COLOR = exports.DEFAULT_COLUMNS = exports.DefaultColumns = exports.DEFAULT_EXPANDED = exports.DEFAULT_ROW_SELECTION = exports.DEFAULT_FILTER_VISIBILITY = exports.DEFAULT_SORTING = exports.DEFAULT_PAGE_SIZE = exports.SORT_FN = exports.TEST_IDS = exports.COLUMN_SETTINGS_MODE = exports.COLUMN_ALIGN = exports.COLUMN_PIN_POSITION = void 0;
7
7
  exports.COLUMN_PIN_POSITION = {
8
8
  Left: 'left',
9
9
  Right: 'right'
@@ -57,4 +57,14 @@ var DefaultColumns;
57
57
  DefaultColumns["Selection"] = "selectionCell";
58
58
  DefaultColumns["RowActions"] = "rowActions";
59
59
  })(DefaultColumns || (exports.DefaultColumns = DefaultColumns = {}));
60
- exports.DEFAULT_COLUMNS = [DefaultColumns.Status, DefaultColumns.Selection, DefaultColumns.RowActions];
60
+ exports.DEFAULT_COLUMNS = [DefaultColumns.Status, DefaultColumns.Selection, DefaultColumns.RowActions];
61
+ exports.TABLE_ROW_COLOR = {
62
+ Red: 'red',
63
+ Orange: 'orange',
64
+ Yellow: 'yellow',
65
+ Green: 'green',
66
+ Blue: 'blue',
67
+ Violet: 'violet',
68
+ Pink: 'pink',
69
+ Neutral: 'neutral'
70
+ };
@@ -34,6 +34,9 @@ function BodyRow(_ref) {
34
34
  } = (0, hooks_1.useRowCells)(row);
35
35
  const [dropListOpened, setDropListOpen] = (0, react_1.useState)(false);
36
36
  const disabled = !row.getCanSelect();
37
+ const {
38
+ getRowBackgroundColor
39
+ } = (0, contexts_1.useTableContext)();
37
40
  const handleRowClick = e => {
38
41
  if (disabled) return;
39
42
  onRowClick === null || onRowClick === void 0 ? void 0 : onRowClick(e, {
@@ -43,6 +46,8 @@ function BodyRow(_ref) {
43
46
  toggleSelected: row.toggleSelected
44
47
  });
45
48
  };
49
+ const isSelected = row.getIsSelected() || row.getIsSomeSelected() && !row.getCanMultiSelect() && !row.getIsExpanded();
50
+ const rowBackgroundColor = getRowBackgroundColor === null || getRowBackgroundColor === void 0 ? void 0 : getRowBackgroundColor(row.original);
46
51
  return (0, jsx_runtime_1.jsx)(contexts_1.RowContext.Provider, {
47
52
  value: {
48
53
  dropListOpened,
@@ -52,10 +57,11 @@ function BodyRow(_ref) {
52
57
  onClick: handleRowClick,
53
58
  "data-clickable": Boolean(onRowClick) || undefined,
54
59
  "data-disabled": disabled || undefined,
55
- "data-selected": row.getIsSelected() || row.getIsSomeSelected() && !row.getCanMultiSelect() && !row.getIsExpanded() || undefined,
60
+ "data-selected": isSelected || undefined,
56
61
  "data-actions-opened": dropListOpened || undefined,
57
62
  "data-test-id": constants_1.TEST_IDS.bodyRow,
58
63
  "data-row-id": row.id,
64
+ "data-row-bg-appearance": rowBackgroundColor && !disabled && !isSelected ? rowBackgroundColor : undefined,
59
65
  className: styles_module_scss_1.default.bodyRow,
60
66
  rowAutoHeight: rowAutoHeight,
61
67
  children: [leftPinned && (0, jsx_runtime_1.jsx)(PinnedCells_1.PinnedCells, {
@@ -1,9 +1,10 @@
1
- import { MouseEvent, ReactNode } from 'react';
1
+ import { CSSProperties, MouseEvent, ReactNode } from 'react';
2
2
  import { DataAttributes } from '../types';
3
3
  export type RowProps = {
4
4
  children: ReactNode;
5
5
  onClick?(e: MouseEvent<HTMLDivElement>): void;
6
6
  className?: string;
7
7
  rowAutoHeight?: boolean;
8
+ style?: CSSProperties;
8
9
  } & DataAttributes;
9
- export declare function Row({ onClick, children, className, rowAutoHeight, ...attributes }: RowProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function Row({ onClick, children, className, rowAutoHeight, style, ...attributes }: RowProps): import("react/jsx-runtime").JSX.Element;
@@ -25,16 +25,18 @@ function Row(_a) {
25
25
  onClick,
26
26
  children,
27
27
  className,
28
- rowAutoHeight
28
+ rowAutoHeight,
29
+ style
29
30
  } = _a,
30
- attributes = __rest(_a, ["onClick", "children", "className", "rowAutoHeight"]);
31
+ attributes = __rest(_a, ["onClick", "children", "className", "rowAutoHeight", "style"]);
31
32
  return (
32
33
  // eslint-disable-next-line jsx-a11y/interactive-supports-focus
33
34
  (0, jsx_runtime_1.jsx)("div", Object.assign({
34
35
  onClick: onClick,
35
36
  className: (0, classnames_1.default)(styles_module_scss_1.default.tableRow, className),
36
37
  "data-auto-height": rowAutoHeight || undefined,
37
- role: 'row'
38
+ role: 'row',
39
+ style: style
38
40
  }, attributes, {
39
41
  children: children
40
42
  }))
@@ -61,6 +61,27 @@
61
61
  height:var(--border-width-table-line, 0.5px);
62
62
  background-color:var(--sys-neutral-decor-disabled, #e6e8ef);
63
63
  }
64
+ .bodyRow[data-row-bg-appearance=red]{
65
+ --snack-ui-table-row-background:color-mix(in srgb, var(--sys-red-accent-default, #cb3f3e), var(--sys-neutral-background1-level, #fdfdfd) calc((1 - var(--opacity-a008, 0.08)) * 100%));
66
+ }
67
+ .bodyRow[data-row-bg-appearance=orange]{
68
+ --snack-ui-table-row-background:color-mix(in srgb, var(--sys-orange-accent-default, #fb8e42), var(--sys-neutral-background1-level, #fdfdfd) calc((1 - var(--opacity-a008, 0.08)) * 100%));
69
+ }
70
+ .bodyRow[data-row-bg-appearance=yellow]{
71
+ --snack-ui-table-row-background:color-mix(in srgb, var(--sys-yellow-accent-default, #e2b134), var(--sys-neutral-background1-level, #fdfdfd) calc((1 - var(--opacity-a008, 0.08)) * 100%));
72
+ }
73
+ .bodyRow[data-row-bg-appearance=green]{
74
+ --snack-ui-table-row-background:color-mix(in srgb, var(--sys-green-accent-default, #57b762), var(--sys-neutral-background1-level, #fdfdfd) calc((1 - var(--opacity-a008, 0.08)) * 100%));
75
+ }
76
+ .bodyRow[data-row-bg-appearance=blue]{
77
+ --snack-ui-table-row-background:color-mix(in srgb, var(--sys-blue-accent-default, #5388d1), var(--sys-neutral-background1-level, #fdfdfd) calc((1 - var(--opacity-a008, 0.08)) * 100%));
78
+ }
79
+ .bodyRow[data-row-bg-appearance=violet]{
80
+ --snack-ui-table-row-background:color-mix(in srgb, var(--sys-violet-accent-default, #aa6cc1), var(--sys-neutral-background1-level, #fdfdfd) calc((1 - var(--opacity-a008, 0.08)) * 100%));
81
+ }
82
+ .bodyRow[data-row-bg-appearance=pink]{
83
+ --snack-ui-table-row-background:color-mix(in srgb, var(--sys-pink-accent-default, #d1668e), var(--sys-neutral-background1-level, #fdfdfd) calc((1 - var(--opacity-a008, 0.08)) * 100%));
84
+ }
64
85
  .bodyRow[data-disabled]{
65
86
  cursor:not-allowed;
66
87
  background-color:var(--sys-neutral-background, #eeeff3);
@@ -1,5 +1,7 @@
1
1
  import { Table } from '@tanstack/react-table';
2
2
  import { Dispatch, SetStateAction } from 'react';
3
+ import { ValueOf } from '@snack-uikit/utils';
4
+ import { TABLE_ROW_COLOR } from '../constants';
3
5
  type RowContext = {
4
6
  dropListOpened: boolean;
5
7
  setDropListOpen: Dispatch<SetStateAction<boolean>>;
@@ -8,6 +10,7 @@ export declare const RowContext: import("react").Context<RowContext>;
8
10
  export declare const useRowContext: () => RowContext;
9
11
  type TableContext<TData> = {
10
12
  table: Table<TData>;
13
+ getRowBackgroundColor?: (data: TData) => ValueOf<typeof TABLE_ROW_COLOR> | undefined;
11
14
  };
12
15
  export declare const TableContext: import("react").Context<TableContext<any>>;
13
16
  export declare const useTableContext: () => TableContext<any>;
@@ -1,7 +1,7 @@
1
1
  import { FiltersState } from '@snack-uikit/chips';
2
2
  import { TableProps } from '../types';
3
3
  /** Компонент таблицы */
4
- export declare function Table<TData extends object, TFilters extends FiltersState = Record<string, unknown>>({ data, rowPinning, columnDefinitions, keepPinnedRows, copyPinnedRows, enableSelectPinned, rowSelection: rowSelectionProp, search, sorting: sortingProp, columnFilters, pagination: paginationProp, className, onRowClick, onRefresh, pageSize, pageCount, loading, infiniteLoading, outline, moreActions, exportSettings, dataFiltered, dataError, noDataState, noResultsState, errorDataState, suppressToolbar, suppressSearch, toolbarAfter, suppressPagination, manualSorting, manualPagination: manualPaginationProp, manualFiltering, autoResetPageIndex, scrollRef, scrollContainerRef, getRowId, enableFuzzySearch, savedState, expanding, bulkActions: bulkActionsProp, rowAutoHeight, columnsSettings: columnsSettingsProp, ...rest }: TableProps<TData, TFilters>): import("react/jsx-runtime").JSX.Element;
4
+ export declare function Table<TData extends object, TFilters extends FiltersState = Record<string, unknown>>({ data, rowPinning, columnDefinitions, keepPinnedRows, copyPinnedRows, enableSelectPinned, rowSelection: rowSelectionProp, search, sorting: sortingProp, columnFilters, pagination: paginationProp, className, onRowClick, onRefresh, pageSize, pageCount, loading, infiniteLoading, outline, moreActions, exportSettings, dataFiltered, dataError, noDataState, noResultsState, errorDataState, suppressToolbar, suppressSearch, toolbarAfter, suppressPagination, manualSorting, manualPagination: manualPaginationProp, manualFiltering, autoResetPageIndex, scrollRef, scrollContainerRef, getRowId, enableFuzzySearch, savedState, expanding, bulkActions: bulkActionsProp, rowAutoHeight, columnsSettings: columnsSettingsProp, getRowBackgroundColor, ...rest }: TableProps<TData, TFilters>): import("react/jsx-runtime").JSX.Element;
5
5
  export declare namespace Table {
6
6
  var getStatusColumnDef: typeof import("../../helperComponents").getStatusColumnDef;
7
7
  var statusAppearances: {
@@ -33,7 +33,7 @@ import { validateFilter, validatePaging, validateSorting } from './utils/saveTab
33
33
  export function Table(_a) {
34
34
  var { data, rowPinning = {
35
35
  top: [],
36
- }, 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, infiniteLoading = false, outline = false, moreActions, exportSettings, dataFiltered, dataError, noDataState, noResultsState, errorDataState, suppressToolbar = false, suppressSearch = false, toolbarAfter, suppressPagination = false, manualSorting = false, manualPagination: manualPaginationProp = false, manualFiltering = false, autoResetPageIndex = false, scrollRef, scrollContainerRef, getRowId, enableFuzzySearch, savedState, expanding, bulkActions: bulkActionsProp, rowAutoHeight, columnsSettings: columnsSettingsProp } = _a, rest = __rest(_a, ["data", "rowPinning", "columnDefinitions", "keepPinnedRows", "copyPinnedRows", "enableSelectPinned", "rowSelection", "search", "sorting", "columnFilters", "pagination", "className", "onRowClick", "onRefresh", "pageSize", "pageCount", "loading", "infiniteLoading", "outline", "moreActions", "exportSettings", "dataFiltered", "dataError", "noDataState", "noResultsState", "errorDataState", "suppressToolbar", "suppressSearch", "toolbarAfter", "suppressPagination", "manualSorting", "manualPagination", "manualFiltering", "autoResetPageIndex", "scrollRef", "scrollContainerRef", "getRowId", "enableFuzzySearch", "savedState", "expanding", "bulkActions", "rowAutoHeight", "columnsSettings"]);
36
+ }, 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, infiniteLoading = false, outline = false, moreActions, exportSettings, dataFiltered, dataError, noDataState, noResultsState, errorDataState, suppressToolbar = false, suppressSearch = false, toolbarAfter, suppressPagination = false, manualSorting = false, manualPagination: manualPaginationProp = false, manualFiltering = false, autoResetPageIndex = false, scrollRef, scrollContainerRef, getRowId, enableFuzzySearch, savedState, expanding, bulkActions: bulkActionsProp, rowAutoHeight, columnsSettings: columnsSettingsProp, getRowBackgroundColor } = _a, rest = __rest(_a, ["data", "rowPinning", "columnDefinitions", "keepPinnedRows", "copyPinnedRows", "enableSelectPinned", "rowSelection", "search", "sorting", "columnFilters", "pagination", "className", "onRowClick", "onRefresh", "pageSize", "pageCount", "loading", "infiniteLoading", "outline", "moreActions", "exportSettings", "dataFiltered", "dataError", "noDataState", "noResultsState", "errorDataState", "suppressToolbar", "suppressSearch", "toolbarAfter", "suppressPagination", "manualSorting", "manualPagination", "manualFiltering", "autoResetPageIndex", "scrollRef", "scrollContainerRef", "getRowId", "enableFuzzySearch", "savedState", "expanding", "bulkActions", "rowAutoHeight", "columnsSettings", "getRowBackgroundColor"]);
37
37
  const [globalFilter, onGlobalFilterChange] = useStateControl(search, '');
38
38
  const [rowSelection, onRowSelectionChange] = useStateControl(rowSelectionProp, DEFAULT_ROW_SELECTION);
39
39
  const defaultPaginationState = useMemo(() => ({
@@ -299,7 +299,7 @@ export function Table(_a) {
299
299
  }
300
300
  },
301
301
  }
302
- : undefined, bulkActions: bulkActions, selectionMode: (rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow) ? 'multiple' : 'single', checked: table.getIsAllPageRowsSelected(), indeterminate: table.getIsSomePageRowsSelected(), onCheck: enableSelection ? handleOnToolbarCheck : undefined, outline: outline, after: toolbarAfter || exportSettings || areColumnsSettingsEnabled ? (_jsxs(_Fragment, { children: [toolbarAfter, exportSettings && (_jsx(ExportButton, { settings: exportSettings, columnDefinitions: columnDefinitions, data: data, topRows: filteredTopRows, centerRows: centerRows })), areColumnsSettingsEnabled && (_jsx(ColumnsSettings, { columnsSettings: columnsSettings, enabledColumns: enabledColumns, setEnabledColumns: setEnabledColumns }))] })) : undefined, moreActions: moreActions, filterRow: patchedFilter, "data-test-id": TEST_IDS.toolbar }) })), _jsxs(Scroll, { size: 's', className: styles.table, ref: scrollContainerRef, "data-outline": outline || undefined, children: [_jsx("div", { className: styles.tableContent, style: columnSizes.vars, children: _jsx(CellAutoResizeContext.Provider, { value: { updateCellMap }, children: _jsx(DndContext, Object.assign({}, dndContextProps, { children: _jsx(TableContext.Provider, { value: { table }, children: (!infiniteLoading || !data.length) && loading ? (_jsxs(SkeletonContextProvider, { loading: true, children: [_jsx(HeaderRow, { rowAutoHeight: rowAutoHeight, columnOrder: columnOrder }), loadingTableRows.map(row => (_jsx(BodyRow, { row: row, rowAutoHeight: rowAutoHeight, columnOrder: columnOrder }, row.id)))] })) : (_jsxs(_Fragment, { children: [centerRows.length || filteredTopRows.length ? (_jsx(HeaderRow, { rowAutoHeight: rowAutoHeight, columnOrder: columnOrder, enableColumnsOrderSortByDrag: enableColumnsOrderSortByDrag })) : null, filteredTopRows.length ? (_jsx("div", { className: styles.topRowWrapper, children: filteredTopRows.map(row => (_jsx(BodyRow, { row: row, onRowClick: onRowClick, rowAutoHeight: rowAutoHeight, columnOrder: columnOrder, enableColumnsOrderSortByDrag: enableColumnsOrderSortByDrag }, row.id))) })) : null, centerRows.map(row => (_jsx(BodyRow, { row: row, onRowClick: onRowClick, rowAutoHeight: rowAutoHeight, columnOrder: columnOrder, enableColumnsOrderSortByDrag: enableColumnsOrderSortByDrag }, row.id))), data.length > 0 && infiniteLoading && loading && !dataError && (_jsx(SkeletonContextProvider, { loading: true, children: loadingTableRows.slice(0, 3).map(row => (_jsx(BodyRow, { row: row, columnOrder: columnOrder, enableColumnsOrderSortByDrag: enableColumnsOrderSortByDrag }, 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 })] }), !infiniteLoading && !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 }))] })));
302
+ : undefined, bulkActions: bulkActions, selectionMode: (rowSelectionProp === null || rowSelectionProp === void 0 ? void 0 : rowSelectionProp.multiRow) ? 'multiple' : 'single', checked: table.getIsAllPageRowsSelected(), indeterminate: table.getIsSomePageRowsSelected(), onCheck: enableSelection ? handleOnToolbarCheck : undefined, outline: outline, after: toolbarAfter || exportSettings || areColumnsSettingsEnabled ? (_jsxs(_Fragment, { children: [toolbarAfter, exportSettings && (_jsx(ExportButton, { settings: exportSettings, columnDefinitions: columnDefinitions, data: data, topRows: filteredTopRows, centerRows: centerRows })), areColumnsSettingsEnabled && (_jsx(ColumnsSettings, { columnsSettings: columnsSettings, enabledColumns: enabledColumns, setEnabledColumns: setEnabledColumns }))] })) : undefined, moreActions: moreActions, filterRow: patchedFilter, "data-test-id": TEST_IDS.toolbar }) })), _jsxs(Scroll, { size: 's', className: styles.table, ref: scrollContainerRef, "data-outline": outline || undefined, children: [_jsx("div", { className: styles.tableContent, style: columnSizes.vars, children: _jsx(CellAutoResizeContext.Provider, { value: { updateCellMap }, children: _jsx(DndContext, Object.assign({}, dndContextProps, { children: _jsx(TableContext.Provider, { value: { table, getRowBackgroundColor }, children: (!infiniteLoading || !data.length) && loading ? (_jsxs(SkeletonContextProvider, { loading: true, children: [_jsx(HeaderRow, { rowAutoHeight: rowAutoHeight, columnOrder: columnOrder }), loadingTableRows.map(row => (_jsx(BodyRow, { row: row, rowAutoHeight: rowAutoHeight, columnOrder: columnOrder }, row.id)))] })) : (_jsxs(_Fragment, { children: [centerRows.length || filteredTopRows.length ? (_jsx(HeaderRow, { rowAutoHeight: rowAutoHeight, columnOrder: columnOrder, enableColumnsOrderSortByDrag: enableColumnsOrderSortByDrag })) : null, filteredTopRows.length ? (_jsx("div", { className: styles.topRowWrapper, children: filteredTopRows.map(row => (_jsx(BodyRow, { row: row, onRowClick: onRowClick, rowAutoHeight: rowAutoHeight, columnOrder: columnOrder, enableColumnsOrderSortByDrag: enableColumnsOrderSortByDrag }, row.id))) })) : null, centerRows.map(row => (_jsx(BodyRow, { row: row, onRowClick: onRowClick, rowAutoHeight: rowAutoHeight, columnOrder: columnOrder, enableColumnsOrderSortByDrag: enableColumnsOrderSortByDrag }, row.id))), data.length > 0 && infiniteLoading && loading && !dataError && (_jsx(SkeletonContextProvider, { loading: true, children: loadingTableRows.slice(0, 3).map(row => (_jsx(BodyRow, { row: row, columnOrder: columnOrder, enableColumnsOrderSortByDrag: enableColumnsOrderSortByDrag }, 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 })] }), !infiniteLoading && !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 }))] })));
303
303
  }
304
304
  Table.getStatusColumnDef = getStatusColumnDef;
305
305
  Table.statusAppearances = STATUS_APPEARANCE;
@@ -2,9 +2,11 @@ import { PaginationState, Row, RowPinningState, RowSelectionOptions, RowSelectio
2
2
  import { ReactNode, RefObject } from 'react';
3
3
  import { FiltersState } from '@snack-uikit/chips';
4
4
  import { FilterRow, ToolbarProps } from '@snack-uikit/toolbar';
5
- import { WithSupportProps } from '@snack-uikit/utils';
5
+ import { ValueOf, WithSupportProps } from '@snack-uikit/utils';
6
+ import { TABLE_ROW_COLOR } from '../constants';
6
7
  import { EmptyStateProps, ExportButtonProps, RowClickHandler, TreeColumnDefinitionProps } from '../helperComponents';
7
8
  import { ColumnDefinition, ExpandedState } from '../types';
9
+ export type TableRowColor = ValueOf<typeof TABLE_ROW_COLOR>;
8
10
  type BulkAction = Omit<NonNullable<ToolbarProps<Record<string, string>>['bulkActions']>[number], 'onClick'> & {
9
11
  onClick?(selectionState: RowSelectionState, resetRowSelection: (defaultState?: boolean) => void): void;
10
12
  };
@@ -138,6 +140,12 @@ type BaseTableProps<TData extends object, TFilters extends FiltersState = Record
138
140
  resize?: boolean;
139
141
  columnSettings?: boolean;
140
142
  };
143
+ /**
144
+ * Функция для определения цвета фона строки на основе данных строки
145
+ * @param data - данные строки таблицы
146
+ * @returns цвет фона строки или undefined, если цвет не должен применяться
147
+ */
148
+ getRowBackgroundColor?: (data: TData) => TableRowColor | undefined;
141
149
  }>;
142
150
  export type InfiniteTableProps<TData extends object, TFilters extends FiltersState = Record<string, unknown>> = BaseTableProps<TData, TFilters> & {
143
151
  pagination?: never;
@@ -50,3 +50,13 @@ export declare enum DefaultColumns {
50
50
  RowActions = "rowActions"
51
51
  }
52
52
  export declare const DEFAULT_COLUMNS: DefaultColumns[];
53
+ export declare const TABLE_ROW_COLOR: {
54
+ readonly Red: "red";
55
+ readonly Orange: "orange";
56
+ readonly Yellow: "yellow";
57
+ readonly Green: "green";
58
+ readonly Blue: "blue";
59
+ readonly Violet: "violet";
60
+ readonly Pink: "pink";
61
+ readonly Neutral: "neutral";
62
+ };
@@ -52,3 +52,13 @@ export var DefaultColumns;
52
52
  DefaultColumns["RowActions"] = "rowActions";
53
53
  })(DefaultColumns || (DefaultColumns = {}));
54
54
  export const DEFAULT_COLUMNS = [DefaultColumns.Status, DefaultColumns.Selection, DefaultColumns.RowActions];
55
+ export const TABLE_ROW_COLOR = {
56
+ Red: 'red',
57
+ Orange: 'orange',
58
+ Yellow: 'yellow',
59
+ Green: 'green',
60
+ Blue: 'blue',
61
+ Violet: 'violet',
62
+ Pink: 'pink',
63
+ Neutral: 'neutral',
64
+ };
@@ -3,7 +3,7 @@ import { horizontalListSortingStrategy, SortableContext } from '@dnd-kit/sortabl
3
3
  import { useState } from 'react';
4
4
  import { COLUMN_PIN_POSITION, TEST_IDS } from '../../constants';
5
5
  import { BodyCell } from '../Cells';
6
- import { RowContext } from '../contexts';
6
+ import { RowContext, useTableContext } from '../contexts';
7
7
  import { useRowCells } from '../hooks';
8
8
  import { PinnedCells } from './PinnedCells';
9
9
  import { Row } from './Row';
@@ -12,6 +12,7 @@ export function BodyRow({ row, onRowClick, rowAutoHeight, columnOrder, enableCol
12
12
  const { leftPinned, rightPinned, unpinned } = useRowCells(row);
13
13
  const [dropListOpened, setDropListOpen] = useState(false);
14
14
  const disabled = !row.getCanSelect();
15
+ const { getRowBackgroundColor } = useTableContext();
15
16
  const handleRowClick = (e) => {
16
17
  if (disabled)
17
18
  return;
@@ -22,7 +23,7 @@ export function BodyRow({ row, onRowClick, rowAutoHeight, columnOrder, enableCol
22
23
  toggleSelected: row.toggleSelected,
23
24
  });
24
25
  };
25
- 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() ||
26
- (row.getIsSomeSelected() && !row.getCanMultiSelect() && !row.getIsExpanded()) ||
27
- undefined, "data-actions-opened": dropListOpened || undefined, "data-test-id": TEST_IDS.bodyRow, "data-row-id": row.id, className: styles.bodyRow, rowAutoHeight: rowAutoHeight, children: [leftPinned && (_jsx(PinnedCells, { position: COLUMN_PIN_POSITION.Left, children: leftPinned.map(cell => (_jsx(BodyCell, { cell: cell, rowAutoHeight: rowAutoHeight }, cell.id))) })), unpinned.map(cell => (_jsx(SortableContext, { items: columnOrder, strategy: horizontalListSortingStrategy, children: _jsx(BodyCell, { cell: cell, rowAutoHeight: rowAutoHeight, isDraggable: enableColumnsOrderSortByDrag }, cell.id) }, cell.id))), rightPinned && (_jsx(PinnedCells, { position: COLUMN_PIN_POSITION.Right, children: rightPinned.map(cell => (_jsx(BodyCell, { cell: cell, rowAutoHeight: rowAutoHeight, isDraggable: enableColumnsOrderSortByDrag }, cell.id))) }))] }) }));
26
+ const isSelected = row.getIsSelected() || (row.getIsSomeSelected() && !row.getCanMultiSelect() && !row.getIsExpanded());
27
+ const rowBackgroundColor = getRowBackgroundColor === null || getRowBackgroundColor === void 0 ? void 0 : getRowBackgroundColor(row.original);
28
+ return (_jsx(RowContext.Provider, { value: { dropListOpened, setDropListOpen }, children: _jsxs(Row, { onClick: handleRowClick, "data-clickable": Boolean(onRowClick) || undefined, "data-disabled": disabled || undefined, "data-selected": isSelected || undefined, "data-actions-opened": dropListOpened || undefined, "data-test-id": TEST_IDS.bodyRow, "data-row-id": row.id, "data-row-bg-appearance": rowBackgroundColor && !disabled && !isSelected ? rowBackgroundColor : undefined, className: styles.bodyRow, rowAutoHeight: rowAutoHeight, children: [leftPinned && (_jsx(PinnedCells, { position: COLUMN_PIN_POSITION.Left, children: leftPinned.map(cell => (_jsx(BodyCell, { cell: cell, rowAutoHeight: rowAutoHeight }, cell.id))) })), unpinned.map(cell => (_jsx(SortableContext, { items: columnOrder, strategy: horizontalListSortingStrategy, children: _jsx(BodyCell, { cell: cell, rowAutoHeight: rowAutoHeight, isDraggable: enableColumnsOrderSortByDrag }, cell.id) }, cell.id))), rightPinned && (_jsx(PinnedCells, { position: COLUMN_PIN_POSITION.Right, children: rightPinned.map(cell => (_jsx(BodyCell, { cell: cell, rowAutoHeight: rowAutoHeight, isDraggable: enableColumnsOrderSortByDrag }, cell.id))) }))] }) }));
28
29
  }
@@ -1,9 +1,10 @@
1
- import { MouseEvent, ReactNode } from 'react';
1
+ import { CSSProperties, MouseEvent, ReactNode } from 'react';
2
2
  import { DataAttributes } from '../types';
3
3
  export type RowProps = {
4
4
  children: ReactNode;
5
5
  onClick?(e: MouseEvent<HTMLDivElement>): void;
6
6
  className?: string;
7
7
  rowAutoHeight?: boolean;
8
+ style?: CSSProperties;
8
9
  } & DataAttributes;
9
- export declare function Row({ onClick, children, className, rowAutoHeight, ...attributes }: RowProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function Row({ onClick, children, className, rowAutoHeight, style, ...attributes }: RowProps): import("react/jsx-runtime").JSX.Element;
@@ -13,8 +13,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
13
13
  import cn from 'classnames';
14
14
  import styles from './styles.module.css';
15
15
  export function Row(_a) {
16
- var { onClick, children, className, rowAutoHeight } = _a, attributes = __rest(_a, ["onClick", "children", "className", "rowAutoHeight"]);
16
+ var { onClick, children, className, rowAutoHeight, style } = _a, attributes = __rest(_a, ["onClick", "children", "className", "rowAutoHeight", "style"]);
17
17
  return (
18
18
  // eslint-disable-next-line jsx-a11y/interactive-supports-focus
19
- _jsx("div", Object.assign({ onClick: onClick, className: cn(styles.tableRow, className), "data-auto-height": rowAutoHeight || undefined, role: 'row' }, attributes, { children: children })));
19
+ _jsx("div", Object.assign({ onClick: onClick, className: cn(styles.tableRow, className), "data-auto-height": rowAutoHeight || undefined, role: 'row', style: style }, attributes, { children: children })));
20
20
  }
@@ -61,6 +61,27 @@
61
61
  height:var(--border-width-table-line, 0.5px);
62
62
  background-color:var(--sys-neutral-decor-disabled, #e6e8ef);
63
63
  }
64
+ .bodyRow[data-row-bg-appearance=red]{
65
+ --snack-ui-table-row-background:color-mix(in srgb, var(--sys-red-accent-default, #cb3f3e), var(--sys-neutral-background1-level, #fdfdfd) calc((1 - var(--opacity-a008, 0.08)) * 100%));
66
+ }
67
+ .bodyRow[data-row-bg-appearance=orange]{
68
+ --snack-ui-table-row-background:color-mix(in srgb, var(--sys-orange-accent-default, #fb8e42), var(--sys-neutral-background1-level, #fdfdfd) calc((1 - var(--opacity-a008, 0.08)) * 100%));
69
+ }
70
+ .bodyRow[data-row-bg-appearance=yellow]{
71
+ --snack-ui-table-row-background:color-mix(in srgb, var(--sys-yellow-accent-default, #e2b134), var(--sys-neutral-background1-level, #fdfdfd) calc((1 - var(--opacity-a008, 0.08)) * 100%));
72
+ }
73
+ .bodyRow[data-row-bg-appearance=green]{
74
+ --snack-ui-table-row-background:color-mix(in srgb, var(--sys-green-accent-default, #57b762), var(--sys-neutral-background1-level, #fdfdfd) calc((1 - var(--opacity-a008, 0.08)) * 100%));
75
+ }
76
+ .bodyRow[data-row-bg-appearance=blue]{
77
+ --snack-ui-table-row-background:color-mix(in srgb, var(--sys-blue-accent-default, #5388d1), var(--sys-neutral-background1-level, #fdfdfd) calc((1 - var(--opacity-a008, 0.08)) * 100%));
78
+ }
79
+ .bodyRow[data-row-bg-appearance=violet]{
80
+ --snack-ui-table-row-background:color-mix(in srgb, var(--sys-violet-accent-default, #aa6cc1), var(--sys-neutral-background1-level, #fdfdfd) calc((1 - var(--opacity-a008, 0.08)) * 100%));
81
+ }
82
+ .bodyRow[data-row-bg-appearance=pink]{
83
+ --snack-ui-table-row-background:color-mix(in srgb, var(--sys-pink-accent-default, #d1668e), var(--sys-neutral-background1-level, #fdfdfd) calc((1 - var(--opacity-a008, 0.08)) * 100%));
84
+ }
64
85
  .bodyRow[data-disabled]{
65
86
  cursor:not-allowed;
66
87
  background-color:var(--sys-neutral-background, #eeeff3);
@@ -1,5 +1,7 @@
1
1
  import { Table } from '@tanstack/react-table';
2
2
  import { Dispatch, SetStateAction } from 'react';
3
+ import { ValueOf } from '@snack-uikit/utils';
4
+ import { TABLE_ROW_COLOR } from '../constants';
3
5
  type RowContext = {
4
6
  dropListOpened: boolean;
5
7
  setDropListOpen: Dispatch<SetStateAction<boolean>>;
@@ -8,6 +10,7 @@ export declare const RowContext: import("react").Context<RowContext>;
8
10
  export declare const useRowContext: () => RowContext;
9
11
  type TableContext<TData> = {
10
12
  table: Table<TData>;
13
+ getRowBackgroundColor?: (data: TData) => ValueOf<typeof TABLE_ROW_COLOR> | undefined;
11
14
  };
12
15
  export declare const TableContext: import("react").Context<TableContext<any>>;
13
16
  export declare const useTableContext: () => TableContext<any>;
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public"
5
5
  },
6
6
  "title": "Table",
7
- "version": "0.37.10",
7
+ "version": "0.37.12",
8
8
  "sideEffects": [
9
9
  "*.css",
10
10
  "*.woff",
@@ -36,7 +36,7 @@
36
36
  "license": "Apache-2.0",
37
37
  "scripts": {},
38
38
  "dependencies": {
39
- "@cloud-ru/ft-request-payload-transform": "0.2.1",
39
+ "@cloud-ru/ft-request-payload-transform": "0.2.2",
40
40
  "@dnd-kit/core": "6.3.1",
41
41
  "@dnd-kit/modifiers": "9.0.0",
42
42
  "@dnd-kit/sortable": "10.0.0",
@@ -51,7 +51,7 @@
51
51
  "@snack-uikit/scroll": "0.10.5",
52
52
  "@snack-uikit/skeleton": "0.6.9",
53
53
  "@snack-uikit/toggles": "0.13.22",
54
- "@snack-uikit/toolbar": "0.14.6",
54
+ "@snack-uikit/toolbar": "0.14.7",
55
55
  "@snack-uikit/truncate-string": "0.7.2",
56
56
  "@snack-uikit/typography": "0.8.11",
57
57
  "@snack-uikit/utils": "4.0.0",
@@ -66,5 +66,5 @@
66
66
  "peerDependencies": {
67
67
  "@snack-uikit/locale": "*"
68
68
  },
69
- "gitHead": "bb8ad6098f57ca731f128b2ea9d03504127ad12c"
69
+ "gitHead": "38414de2cd0a54526b6202a8bfe3ed10b3cd85a8"
70
70
  }
@@ -123,6 +123,7 @@ export function Table<TData extends object, TFilters extends FiltersState = Reco
123
123
  bulkActions: bulkActionsProp,
124
124
  rowAutoHeight,
125
125
  columnsSettings: columnsSettingsProp,
126
+ getRowBackgroundColor,
126
127
  ...rest
127
128
  }: TableProps<TData, TFilters>) {
128
129
  const [globalFilter, onGlobalFilterChange] = useStateControl<string>(search, '');
@@ -524,7 +525,7 @@ export function Table<TData extends object, TFilters extends FiltersState = Reco
524
525
  <div className={styles.tableContent} style={columnSizes.vars}>
525
526
  <CellAutoResizeContext.Provider value={{ updateCellMap }}>
526
527
  <DndContext {...dndContextProps}>
527
- <TableContext.Provider value={{ table }}>
528
+ <TableContext.Provider value={{ table, getRowBackgroundColor }}>
528
529
  {(!infiniteLoading || !data.length) && loading ? (
529
530
  <SkeletonContextProvider loading>
530
531
  <HeaderRow rowAutoHeight={rowAutoHeight} columnOrder={columnOrder} />
@@ -10,11 +10,14 @@ import { ReactNode, RefObject } from 'react';
10
10
 
11
11
  import { FiltersState } from '@snack-uikit/chips';
12
12
  import { FilterRow, ToolbarProps } from '@snack-uikit/toolbar';
13
- import { WithSupportProps } from '@snack-uikit/utils';
13
+ import { ValueOf, WithSupportProps } from '@snack-uikit/utils';
14
14
 
15
+ import { TABLE_ROW_COLOR } from '../constants';
15
16
  import { EmptyStateProps, ExportButtonProps, RowClickHandler, TreeColumnDefinitionProps } from '../helperComponents';
16
17
  import { ColumnDefinition, ExpandedState } from '../types';
17
18
 
19
+ export type TableRowColor = ValueOf<typeof TABLE_ROW_COLOR>;
20
+
18
21
  type BulkAction = Omit<NonNullable<ToolbarProps<Record<string, string>>['bulkActions']>[number], 'onClick'> & {
19
22
  onClick?(selectionState: RowSelectionState, resetRowSelection: (defaultState?: boolean) => void): void;
20
23
  };
@@ -168,6 +171,13 @@ type BaseTableProps<TData extends object, TFilters extends FiltersState = Record
168
171
  resize?: boolean;
169
172
  columnSettings?: boolean;
170
173
  };
174
+
175
+ /**
176
+ * Функция для определения цвета фона строки на основе данных строки
177
+ * @param data - данные строки таблицы
178
+ * @returns цвет фона строки или undefined, если цвет не должен применяться
179
+ */
180
+ getRowBackgroundColor?: (data: TData) => TableRowColor | undefined;
171
181
  }>;
172
182
 
173
183
  export type InfiniteTableProps<
package/src/constants.ts CHANGED
@@ -57,3 +57,14 @@ export enum DefaultColumns {
57
57
  RowActions = 'rowActions',
58
58
  }
59
59
  export const DEFAULT_COLUMNS = [DefaultColumns.Status, DefaultColumns.Selection, DefaultColumns.RowActions];
60
+
61
+ export const TABLE_ROW_COLOR = {
62
+ Red: 'red',
63
+ Orange: 'orange',
64
+ Yellow: 'yellow',
65
+ Green: 'green',
66
+ Blue: 'blue',
67
+ Violet: 'violet',
68
+ Pink: 'pink',
69
+ Neutral: 'neutral',
70
+ } as const;
@@ -5,7 +5,7 @@ import { MouseEvent, useState } from 'react';
5
5
  import { COLUMN_PIN_POSITION, TEST_IDS } from '../../constants';
6
6
  import { ColumnOrder } from '../../types';
7
7
  import { BodyCell } from '../Cells';
8
- import { RowContext } from '../contexts';
8
+ import { RowContext, useTableContext } from '../contexts';
9
9
  import { useRowCells } from '../hooks';
10
10
  import { PinnedCells } from './PinnedCells';
11
11
  import { Row, RowProps } from './Row';
@@ -40,6 +40,8 @@ export function BodyRow<TData>({
40
40
 
41
41
  const disabled = !row.getCanSelect();
42
42
 
43
+ const { getRowBackgroundColor } = useTableContext();
44
+
43
45
  const handleRowClick = (e: MouseEvent<HTMLDivElement>) => {
44
46
  if (disabled) return;
45
47
 
@@ -51,20 +53,22 @@ export function BodyRow<TData>({
51
53
  });
52
54
  };
53
55
 
56
+ const isSelected =
57
+ row.getIsSelected() || (row.getIsSomeSelected() && !row.getCanMultiSelect() && !row.getIsExpanded());
58
+
59
+ const rowBackgroundColor = getRowBackgroundColor?.(row.original);
60
+
54
61
  return (
55
62
  <RowContext.Provider value={{ dropListOpened, setDropListOpen }}>
56
63
  <Row
57
64
  onClick={handleRowClick}
58
65
  data-clickable={Boolean(onRowClick) || undefined}
59
66
  data-disabled={disabled || undefined}
60
- data-selected={
61
- row.getIsSelected() ||
62
- (row.getIsSomeSelected() && !row.getCanMultiSelect() && !row.getIsExpanded()) ||
63
- undefined
64
- }
67
+ data-selected={isSelected || undefined}
65
68
  data-actions-opened={dropListOpened || undefined}
66
69
  data-test-id={TEST_IDS.bodyRow}
67
70
  data-row-id={row.id}
71
+ data-row-bg-appearance={rowBackgroundColor && !disabled && !isSelected ? rowBackgroundColor : undefined}
68
72
  className={styles.bodyRow}
69
73
  rowAutoHeight={rowAutoHeight}
70
74
  >
@@ -1,5 +1,5 @@
1
1
  import cn from 'classnames';
2
- import { MouseEvent, ReactNode } from 'react';
2
+ import { CSSProperties, MouseEvent, ReactNode } from 'react';
3
3
 
4
4
  import { DataAttributes } from '../types';
5
5
  import styles from './styles.module.scss';
@@ -9,9 +9,10 @@ export type RowProps = {
9
9
  onClick?(e: MouseEvent<HTMLDivElement>): void;
10
10
  className?: string;
11
11
  rowAutoHeight?: boolean;
12
+ style?: CSSProperties;
12
13
  } & DataAttributes;
13
14
 
14
- export function Row({ onClick, children, className, rowAutoHeight, ...attributes }: RowProps) {
15
+ export function Row({ onClick, children, className, rowAutoHeight, style, ...attributes }: RowProps) {
15
16
  return (
16
17
  // eslint-disable-next-line jsx-a11y/interactive-supports-focus
17
18
  <div
@@ -19,6 +20,7 @@ export function Row({ onClick, children, className, rowAutoHeight, ...attributes
19
20
  className={cn(styles.tableRow, className)}
20
21
  data-auto-height={rowAutoHeight || undefined}
21
22
  role='row'
23
+ style={style}
22
24
  {...attributes}
23
25
  >
24
26
  {children}
@@ -1,6 +1,8 @@
1
1
  @use '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-table';
2
2
  @use '@snack-uikit/figma-tokens/build/scss/styles-theme-variables';
3
3
 
4
+ $appearances: 'red', 'orange', 'yellow', 'green', 'blue', 'violet', 'pink';
5
+
4
6
  $snack-ui-table-row-background: var(--snack-ui-table-row-background);
5
7
 
6
8
  @function color-with-opacity-local($color, $opacity) {
@@ -53,7 +55,6 @@ $snack-ui-table-row-background: var(--snack-ui-table-row-background);
53
55
  width: styles-tokens-table.$border-width-table;
54
56
  }
55
57
 
56
-
57
58
  &[data-position='left'] {
58
59
  left: 0;
59
60
 
@@ -83,7 +84,6 @@ $snack-ui-table-row-background: var(--snack-ui-table-row-background);
83
84
  }
84
85
 
85
86
  .bodyRow {
86
-
87
87
  & ~ &:before {
88
88
  content: '';
89
89
 
@@ -99,6 +99,16 @@ $snack-ui-table-row-background: var(--snack-ui-table-row-background);
99
99
  background-color: styles-tokens-table.$sys-neutral-decor-disabled;
100
100
  }
101
101
 
102
+ @each $appearance in $appearances {
103
+ &[data-row-bg-appearance='#{$appearance}'] {
104
+ --snack-ui-table-row-background: #{styles-tokens-table.color-on-background-with-opacity(
105
+ styles-tokens-table.simple-var(styles-tokens-table.$theme-variables, 'sys', $appearance, 'accent-default'),
106
+ styles-tokens-table.$sys-neutral-background1-level,
107
+ styles-tokens-table.$opacity-a008
108
+ )};
109
+ }
110
+ }
111
+
102
112
  &[data-disabled] {
103
113
  cursor: not-allowed;
104
114
  background-color: styles-tokens-table.$sys-neutral-background;
@@ -109,19 +119,32 @@ $snack-ui-table-row-background: var(--snack-ui-table-row-background);
109
119
  }
110
120
 
111
121
  &[data-selected] {
112
- background-color: color-with-opacity-local(styles-tokens-table.$sys-primary-accent-default, styles-tokens-table.$opacity-a008);
122
+ background-color: color-with-opacity-local(
123
+ styles-tokens-table.$sys-primary-accent-default,
124
+ styles-tokens-table.$opacity-a008
125
+ );
113
126
 
114
127
  .rowPinnedCells {
115
- background-color: color-with-opacity-local(styles-tokens-table.$sys-primary-accent-default, styles-tokens-table.$opacity-a008);
128
+ background-color: color-with-opacity-local(
129
+ styles-tokens-table.$sys-primary-accent-default,
130
+ styles-tokens-table.$opacity-a008
131
+ );
116
132
  border-color: styles-tokens-table.$sys-primary-decor-activated;
117
133
  }
118
134
 
119
- &:hover, &[data-actions-opened] {
120
- background-color: color-with-opacity-local(styles-tokens-table.$sys-primary-accent-default, styles-tokens-table.$opacity-a016);
135
+ &:hover,
136
+ &[data-actions-opened] {
137
+ background-color: color-with-opacity-local(
138
+ styles-tokens-table.$sys-primary-accent-default,
139
+ styles-tokens-table.$opacity-a016
140
+ );
121
141
  border-color: styles-tokens-table.$sys-primary-decor-hovered;
122
142
 
123
143
  .rowPinnedCells {
124
- background-color: color-with-opacity-local(styles-tokens-table.$sys-primary-accent-default, styles-tokens-table.$opacity-a016);
144
+ background-color: color-with-opacity-local(
145
+ styles-tokens-table.$sys-primary-accent-default,
146
+ styles-tokens-table.$opacity-a016
147
+ );
125
148
  border-color: styles-tokens-table.$sys-primary-decor-activated;
126
149
  }
127
150
  }
@@ -139,12 +162,19 @@ $snack-ui-table-row-background: var(--snack-ui-table-row-background);
139
162
  }
140
163
 
141
164
  &:not([data-selected]) {
142
- &:hover, &[data-actions-opened] {
143
- background-color: color-with-opacity-local(styles-tokens-table.$sys-neutral-accent-default, styles-tokens-table.$opacity-a008);
165
+ &:hover,
166
+ &[data-actions-opened] {
167
+ background-color: color-with-opacity-local(
168
+ styles-tokens-table.$sys-neutral-accent-default,
169
+ styles-tokens-table.$opacity-a008
170
+ );
144
171
  border-color: styles-tokens-table.$sys-neutral-decor-hovered;
145
172
 
146
173
  .rowPinnedCells {
147
- background-color: color-with-opacity-local(styles-tokens-table.$sys-neutral-accent-default, styles-tokens-table.$opacity-a008);
174
+ background-color: color-with-opacity-local(
175
+ styles-tokens-table.$sys-neutral-accent-default,
176
+ styles-tokens-table.$opacity-a008
177
+ );
148
178
  border-color: inherit;
149
179
  }
150
180
  }
@@ -1,6 +1,10 @@
1
1
  import { Table } from '@tanstack/react-table';
2
2
  import { createContext, Dispatch, SetStateAction, useContext } from 'react';
3
3
 
4
+ import { ValueOf } from '@snack-uikit/utils';
5
+
6
+ import { TABLE_ROW_COLOR } from '../constants';
7
+
4
8
  type RowContext = {
5
9
  dropListOpened: boolean;
6
10
  setDropListOpen: Dispatch<SetStateAction<boolean>>;
@@ -15,6 +19,7 @@ export const useRowContext = () => useContext(RowContext);
15
19
 
16
20
  type TableContext<TData> = {
17
21
  table: Table<TData>;
22
+ getRowBackgroundColor?: (data: TData) => ValueOf<typeof TABLE_ROW_COLOR> | undefined;
18
23
  };
19
24
 
20
25
  // eslint-disable-next-line @typescript-eslint/no-explicit-any