@cloud-ru/uikit-product-mobile-table 0.11.3

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.
Files changed (31) hide show
  1. package/CHANGELOG.md +1312 -0
  2. package/LICENSE +201 -0
  3. package/README.md +8 -0
  4. package/package.json +64 -0
  5. package/src/components/AdaptiveServerTable/AdaptiveServerTable.tsx +95 -0
  6. package/src/components/AdaptiveServerTable/index.ts +1 -0
  7. package/src/components/AdaptiveTable/AdaptiveTable.tsx +26 -0
  8. package/src/components/AdaptiveTable/index.ts +1 -0
  9. package/src/components/MobileTable.tsx +272 -0
  10. package/src/components/constants.ts +3 -0
  11. package/src/components/hooks.tsx +60 -0
  12. package/src/components/index.ts +3 -0
  13. package/src/components/styles.module.scss +50 -0
  14. package/src/components/utils.ts +20 -0
  15. package/src/constants.ts +18 -0
  16. package/src/helperComponents/RowActionsCell/RowActionsCell.tsx +86 -0
  17. package/src/helperComponents/RowActionsCell/index.ts +1 -0
  18. package/src/helperComponents/RowActionsCell/styles.module.scss +38 -0
  19. package/src/helperComponents/TableCard/TableCard.tsx +75 -0
  20. package/src/helperComponents/TableCard/index.ts +1 -0
  21. package/src/helperComponents/TableCard/styles.module.scss +79 -0
  22. package/src/helperComponents/TableEmptyState/TableEmptyState.tsx +29 -0
  23. package/src/helperComponents/TableEmptyState/hooks.ts +46 -0
  24. package/src/helperComponents/TableEmptyState/index.ts +2 -0
  25. package/src/helperComponents/TableEmptyState/styles.module.scss +12 -0
  26. package/src/helperComponents/TableEmptyState/types.ts +11 -0
  27. package/src/helperComponents/TablePagination/TablePagination.tsx +39 -0
  28. package/src/helperComponents/TablePagination/index.ts +1 -0
  29. package/src/helperComponents/TablePagination/styles.module.scss +8 -0
  30. package/src/helperComponents/index.ts +4 -0
  31. package/src/index.ts +1 -0
@@ -0,0 +1,60 @@
1
+ import { getCoreRowModel, useReactTable } from '@tanstack/react-table';
2
+ import { useMemo } from 'react';
3
+ import { useUncontrolledProp } from 'uncontrollable';
4
+
5
+ import { FiltersState } from '@cloud-ru/uikit-product-mobile-chips';
6
+ import { SkeletonText } from '@snack-uikit/skeleton';
7
+ import { TableProps } from '@snack-uikit/table';
8
+
9
+ import { ROW_ACTIONS_COLUMN_ID } from '../constants';
10
+
11
+ export function useStateControl<TState>(
12
+ control: { initialState?: TState; state?: TState; onChange?(state: TState): void } | undefined,
13
+ defaultState: TState,
14
+ ) {
15
+ const [state, onStateChange] = useUncontrolledProp<TState>(
16
+ control?.state,
17
+ control?.state ?? control?.initialState ?? defaultState,
18
+ (controlState: TState) => {
19
+ const newState = typeof controlState === 'function' ? controlState(state) : controlState;
20
+
21
+ control?.onChange?.(newState);
22
+ },
23
+ );
24
+
25
+ return {
26
+ state,
27
+ onStateChange,
28
+ };
29
+ }
30
+
31
+ type UseLoadingTableProps<TData extends object, TFilters extends FiltersState> = {
32
+ columnDefinitions: TableProps<TData, TFilters>['columnDefinitions'];
33
+ pageSize: number;
34
+ };
35
+
36
+ export function useLoadingTable<TData extends object, TFilters extends FiltersState>({
37
+ pageSize,
38
+ columnDefinitions,
39
+ }: UseLoadingTableProps<TData, TFilters>) {
40
+ const data = useMemo(() => (Array.from({ length: pageSize }).map(() => ({})) || []) as TData[], [pageSize]);
41
+ const columns = useMemo(
42
+ () =>
43
+ columnDefinitions
44
+ .filter(column => column.id !== ROW_ACTIONS_COLUMN_ID)
45
+ .map(column => ({
46
+ ...column,
47
+ cell: () => <SkeletonText lines={1} width={'100%'} />,
48
+ })),
49
+ [columnDefinitions],
50
+ );
51
+
52
+ const loadingTable = useReactTable<TData>({
53
+ data,
54
+ columns,
55
+
56
+ getCoreRowModel: getCoreRowModel(),
57
+ });
58
+
59
+ return { loadingTable };
60
+ }
@@ -0,0 +1,3 @@
1
+ export * from './AdaptiveTable';
2
+ export * from './AdaptiveServerTable';
3
+ export * from './MobileTable';
@@ -0,0 +1,50 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as ds;
2
+
3
+ .tableWrapper {
4
+ position: relative;
5
+ /* stylelint-disable-next-line declaration-property-value-allowed-list */
6
+ z-index: 0;
7
+ margin-top: calc(-1 * #{ds.$dimension-1m});
8
+ }
9
+
10
+ .header {
11
+ display: flex;
12
+ flex-direction: column;
13
+ gap: ds.$dimension-1m;
14
+ position: sticky;
15
+ /* stylelint-disable-next-line declaration-property-value-allowed-list */
16
+ z-index: 1;
17
+ top: 0;
18
+ padding-top: ds.$dimension-1m;
19
+ padding-bottom: ds.$dimension-1m;
20
+ margin-bottom: calc(-1 * #{ds.$dimension-1m});
21
+
22
+ &[data-background='default'] {
23
+ background-color: ds.$sys-neutral-background;
24
+ }
25
+
26
+ &[data-background='1-level'] {
27
+ background-color: ds.$sys-neutral-background1-level;
28
+ }
29
+
30
+ &[data-background='2-level'] {
31
+ background-color: ds.$sys-neutral-background2-level;
32
+ }
33
+ }
34
+
35
+ .table {
36
+ box-sizing: border-box;
37
+ border: ds.$border-width-012m solid ds.$sys-neutral-decor-default;
38
+ border-radius: ds.$dimension-050m;
39
+ background: ds.$sys-neutral-background1-level;
40
+ margin-top: ds.$dimension-1m;
41
+ }
42
+
43
+ .filtersWrapper {
44
+ display: flex;
45
+ flex-wrap: wrap;
46
+ gap: ds.$dimension-050m;
47
+ align-items: center;
48
+ justify-content: flex-start;
49
+ }
50
+
@@ -0,0 +1,20 @@
1
+ import { RankingInfo, rankItem } from '@tanstack/match-sorter-utils';
2
+ import { FilterFn } from '@tanstack/react-table';
3
+ import debounce from 'lodash.debounce';
4
+
5
+ import { SEARCH_DELAY } from './constants';
6
+
7
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
+ export const fuzzyFilter: FilterFn<any> = (row, columnId, value, addMeta) => {
9
+ const itemRank: RankingInfo = rankItem(row.getValue(columnId), value);
10
+
11
+ addMeta({
12
+ itemRank,
13
+ });
14
+
15
+ return itemRank.passed;
16
+ };
17
+
18
+ export const onSearchDebounced = debounce((newValue: string, onChange: (newValue: string) => void) => {
19
+ onChange(newValue);
20
+ }, SEARCH_DELAY);
@@ -0,0 +1,18 @@
1
+ export const TEST_IDS = {
2
+ headerSortIndicator: 'table__header__sort-indicator',
3
+ headerRow: 'table__header-row',
4
+ headerCell: 'table__header-cell',
5
+ bodyRow: 'table__body-row',
6
+ bodyCell: 'table__body-cell',
7
+ pinnedCells: 'table__pinned-cells',
8
+ rowSelect: 'table__row-select',
9
+ rowActions: {
10
+ droplistTrigger: 'table__body-row__droplistTrigger',
11
+ droplist: 'table__body-row__actions-droplist',
12
+ option: 'list__base-item-option',
13
+ },
14
+ statusIndicator: 'table__status-indicator',
15
+ statusLabel: 'table__status-label',
16
+ };
17
+
18
+ export const ROW_ACTIONS_COLUMN_ID = 'rowActions';
@@ -0,0 +1,86 @@
1
+ import { CellContext, Row } from '@tanstack/react-table';
2
+ import { MouseEvent, MouseEventHandler, useCallback, useMemo, useState } from 'react';
3
+
4
+ import { MoreSVG } from '@cloud-ru/uikit-product-icons';
5
+ import { FiltersState } from '@cloud-ru/uikit-product-mobile-chips';
6
+ import { isBaseItemProps, MobileDroplist, MobileDroplistProps } from '@cloud-ru/uikit-product-mobile-dropdown';
7
+ import { ButtonFunction } from '@snack-uikit/button';
8
+
9
+ import { MobileTableProps } from '../../components';
10
+ import { ROW_ACTIONS_COLUMN_ID, TEST_IDS } from '../../constants';
11
+ import styles from './styles.module.scss';
12
+
13
+ type RowActionsCellProps<TData> = {
14
+ actions: MobileDroplistProps['items'];
15
+ row: Row<TData>;
16
+ };
17
+
18
+ function RowActionsCell<TData>({ row, actions }: RowActionsCellProps<TData>) {
19
+ const [dropListOpened, setDropListOpen] = useState(false);
20
+
21
+ const patchItem = useCallback(
22
+ (item: MobileDroplistProps['items'][0], cb: MouseEventHandler): MobileDroplistProps['items'][0] => {
23
+ if (isBaseItemProps(item)) {
24
+ return {
25
+ ...item,
26
+ onClick(e) {
27
+ item.onClick?.(e);
28
+ cb(e);
29
+ },
30
+ };
31
+ }
32
+
33
+ return { ...item, items: item.items.map(i => patchItem(i, cb)) };
34
+ },
35
+ [],
36
+ );
37
+
38
+ const disabled = !row.getCanSelect();
39
+
40
+ const stopPropagationClick = (e: MouseEvent<HTMLDivElement>) => {
41
+ e.stopPropagation();
42
+ };
43
+
44
+ const patchedItems = useMemo(
45
+ () => actions.map(item => patchItem(item, () => setDropListOpen(false))),
46
+ [actions, patchItem, setDropListOpen],
47
+ );
48
+
49
+ return (
50
+ // eslint-disable-next-line jsx-a11y/no-static-element-interactions
51
+ <div onClick={stopPropagationClick} className={styles.rowActionsCellWrap} data-open={dropListOpened || undefined}>
52
+ {!disabled && Boolean(actions.length) && (
53
+ <MobileDroplist
54
+ open={dropListOpened}
55
+ onOpenChange={setDropListOpen}
56
+ data-test-id={TEST_IDS.rowActions.droplist}
57
+ items={patchedItems}
58
+ >
59
+ <ButtonFunction icon={<MoreSVG size={24} />} data-test-id={TEST_IDS.rowActions.droplistTrigger} />
60
+ </MobileDroplist>
61
+ )}
62
+ </div>
63
+ );
64
+ }
65
+
66
+ export type ActionsGenerator<TData> = (cell: CellContext<TData, unknown>) => MobileDroplistProps['items'];
67
+
68
+ export type RowActionsColumnDefProps<TData> = {
69
+ /** Действия для строки */
70
+ actionsGenerator: ActionsGenerator<TData>;
71
+ /** Закрепление колонки справа в таблице */
72
+ pinned?: boolean;
73
+ };
74
+
75
+ /** Вспомогательная функция для создания ячейки с дополнительными действиями у строки */
76
+ export function getRowActionsColumnDef<TData extends object, TFilters extends FiltersState>({
77
+ actionsGenerator,
78
+ }: RowActionsColumnDefProps<TData>): MobileTableProps<TData, TFilters>['columnDefinitions'][0] {
79
+ return {
80
+ id: ROW_ACTIONS_COLUMN_ID,
81
+ meta: {
82
+ skipOnExport: true,
83
+ },
84
+ cell: cell => <RowActionsCell row={cell.row} actions={actionsGenerator(cell)} />,
85
+ };
86
+ }
@@ -0,0 +1 @@
1
+ export * from './RowActionsCell';
@@ -0,0 +1,38 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/components/styles-tokens-table';
2
+
3
+ .rowActionsCell {
4
+ position: relative;
5
+ border-color: inherit;
6
+
7
+ &::after {
8
+ pointer-events: none;
9
+ content: '';
10
+
11
+ position: absolute;
12
+ top: calc(0px - styles-tokens-table.$border-width-table);
13
+ bottom: calc(0px - styles-tokens-table.$border-width-table);
14
+ left: 0;
15
+
16
+ box-sizing: border-box;
17
+ width: 100%;
18
+
19
+ /* stylelint-disable */
20
+ border-left: styles-tokens-table.$border-width-table solid;
21
+ border-color: inherit;
22
+ /* stylelint-enable */
23
+ }
24
+ }
25
+
26
+ .rowActionsCellWrap {
27
+ --offset: 0px;
28
+ cursor: pointer;
29
+ box-sizing: border-box;
30
+ width: 100%;
31
+ height: 100%;
32
+
33
+ @include styles-tokens-table.composite-var(styles-tokens-table.$table-cells-action);
34
+
35
+ display: flex;
36
+ align-items: center;
37
+ justify-content: center;
38
+ }
@@ -0,0 +1,75 @@
1
+ import { flexRender, Row, Table } from '@tanstack/react-table';
2
+ import { useCallback } from 'react';
3
+
4
+ import { Checkbox, Radio } from '@snack-uikit/toggles';
5
+
6
+ import { ROW_ACTIONS_COLUMN_ID } from '../../constants';
7
+ import styles from './styles.module.scss';
8
+
9
+ type TableCardProps<TData extends object> = {
10
+ headlineId?: string;
11
+ row: Row<TData>;
12
+ table: Table<TData>;
13
+ selection: 'multiple' | 'single' | 'none';
14
+ };
15
+
16
+ export function TableCard<TData extends object>({ headlineId, table, row, selection }: TableCardProps<TData>) {
17
+ const headerGroups = table.getHeaderGroups();
18
+
19
+ const headerCell = row._getAllCellsByColumnId()[headlineId ?? ''];
20
+ const headerColumn = table.getFlatHeaders().find(header => header.id === headlineId);
21
+
22
+ const actionsCell = row._getAllCellsByColumnId()[ROW_ACTIONS_COLUMN_ID];
23
+ const actionsColumn = table.getFlatHeaders().find(header => header.id === ROW_ACTIONS_COLUMN_ID);
24
+
25
+ const isSelected = row.getIsSelected();
26
+
27
+ const handleSelection = useCallback(() => {
28
+ if (selection === 'single') row.toggleSelected(true);
29
+ if (selection === 'multiple') row.toggleSelected(!isSelected);
30
+ }, [isSelected, row, selection]);
31
+
32
+ return (
33
+ // eslint-disable-next-line jsx-a11y/no-static-element-interactions
34
+ <div
35
+ className={styles.card}
36
+ data-is-selected={isSelected ?? undefined}
37
+ data-selection-mode={selection}
38
+ onClick={handleSelection}
39
+ >
40
+ <div className={styles.content}>
41
+ {headerCell && headerColumn && (
42
+ <div className={styles.headline}>
43
+ {flexRender(headerColumn.column.columnDef.cell, headerCell.getContext())}
44
+ </div>
45
+ )}
46
+
47
+ <div className={styles.body}>
48
+ {headerGroups.map(group =>
49
+ group.headers.map((header, index) => {
50
+ if ([headlineId, ROW_ACTIONS_COLUMN_ID].includes(header.id)) {
51
+ return null;
52
+ }
53
+
54
+ const column = header.column.columnDef;
55
+ const cell = row._getAllCellsByColumnId()[header.column.id];
56
+
57
+ return (
58
+ <div className={styles.cardRow} key={header.id || index}>
59
+ <div className={styles.cardRowHeader}>{flexRender(column.header, header.getContext())}</div>
60
+ <div className={styles.cardRowContent}>{flexRender(column.cell, cell.getContext())}</div>
61
+ </div>
62
+ );
63
+ }),
64
+ )}
65
+ </div>
66
+ </div>
67
+
68
+ {selection === 'single' && <Radio size='m' className={styles.selectionController} checked={isSelected} />}
69
+ {selection === 'multiple' && <Checkbox size='m' className={styles.selectionController} checked={isSelected} />}
70
+ {actionsCell && actionsColumn && (
71
+ <div className={styles.button}>{flexRender(actionsColumn.column.columnDef.cell, actionsCell.getContext())}</div>
72
+ )}
73
+ </div>
74
+ );
75
+ }
@@ -0,0 +1 @@
1
+ export * from './TableCard';
@@ -0,0 +1,79 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables';
2
+
3
+ .selectionController {
4
+ position: absolute;
5
+ bottom: styles-theme-variables.$dimension-2m;
6
+ right: styles-theme-variables.$dimension-2m;
7
+ }
8
+
9
+ .content {
10
+ position: relative;
11
+ }
12
+
13
+ .card {
14
+ position: relative;
15
+ box-sizing: border-box;
16
+ padding: styles-theme-variables.$dimension-2m;
17
+ display: flex;
18
+ flex-direction: column;
19
+ gap: styles-theme-variables.$dimension-2m;
20
+
21
+ &:not(:last-child) {
22
+ border-bottom: styles-theme-variables.$border-width-general-xs solid styles-theme-variables.$sys-neutral-decor-default;
23
+ }
24
+
25
+ &::before {
26
+ content: '';
27
+ position: absolute;
28
+ top: 0;
29
+ right: 0;
30
+ bottom: 0;
31
+ left: 0;
32
+
33
+ opacity: 0;
34
+ background-color: styles-theme-variables.$sys-primary-background1-level;
35
+ }
36
+
37
+ &[data-selection-mode='multiple'],
38
+ &[data-selection-mode='single'] {
39
+ &[data-is-selected=true]::before {
40
+ opacity: 1;
41
+ }
42
+ }
43
+ }
44
+
45
+ .button {
46
+ position: absolute;
47
+ top: styles-theme-variables.$dimension-1m;
48
+ right: styles-theme-variables.$dimension-1m;
49
+ }
50
+
51
+ .headline {
52
+ @include styles-theme-variables.composite-var(styles-theme-variables.$sans-title-m);
53
+
54
+ color: styles-theme-variables.$sys-neutral-text-main;
55
+ padding-right: styles-theme-variables.$dimension-4m;
56
+ }
57
+
58
+ .body {
59
+ display: flex;
60
+ flex-direction: column;
61
+ gap: styles-theme-variables.$dimension-2m;
62
+ }
63
+
64
+ .cardRow {
65
+ @include styles-theme-variables.composite-var(styles-theme-variables.$sans-body-m);
66
+ display: flex;
67
+ flex-direction: column;
68
+ gap: styles-theme-variables.$dimension-050m;
69
+ }
70
+
71
+ .cardRowHeader {
72
+ color: styles-theme-variables.$sys-neutral-text-light;
73
+ word-break: break-word;
74
+ }
75
+
76
+ .cardRowContent {
77
+ color: styles-theme-variables.$sys-neutral-text-main;
78
+ word-break: break-word;
79
+ }
@@ -0,0 +1,29 @@
1
+ import { InfoBlock } from '@snack-uikit/info-block';
2
+
3
+ import styles from './styles.module.scss';
4
+ import { EmptyStateProps } from './types';
5
+
6
+ export type TableEmptyState = {
7
+ emptyStates: {
8
+ noDataState: EmptyStateProps;
9
+ noResultsState: EmptyStateProps;
10
+ errorDataState: EmptyStateProps;
11
+ };
12
+ dataError?: boolean;
13
+ dataFiltered?: boolean;
14
+ tableRowsLength: number;
15
+ };
16
+
17
+ export function TableEmptyState({ dataError, dataFiltered, tableRowsLength, emptyStates }: TableEmptyState) {
18
+ if (tableRowsLength) {
19
+ return null;
20
+ }
21
+
22
+ return (
23
+ <div className={styles.tableEmptyStateWrapper}>
24
+ {dataError && <InfoBlock {...emptyStates.errorDataState} size='m' align='vertical' />}
25
+ {!dataError && dataFiltered && <InfoBlock {...emptyStates.noResultsState} size='m' align='vertical' />}
26
+ {!dataError && !dataFiltered && <InfoBlock {...emptyStates.noDataState} size='m' align='vertical' />}
27
+ </div>
28
+ );
29
+ }
@@ -0,0 +1,46 @@
1
+ import { useMemo } from 'react';
2
+
3
+ import { CrossSVG, SearchSVG } from '@cloud-ru/uikit-product-icons';
4
+ import { useLocale } from '@cloud-ru/uikit-product-locale';
5
+
6
+ import { EmptyStateProps } from './types';
7
+
8
+ export function useEmptyState({
9
+ noDataState: noDataStateProp,
10
+ noResultsState: noResultsStateProp,
11
+ errorDataState: errorDataStateProp,
12
+ }: {
13
+ noDataState?: EmptyStateProps;
14
+ noResultsState?: EmptyStateProps;
15
+ errorDataState?: EmptyStateProps;
16
+ }) {
17
+ const { t } = useLocale('Table');
18
+
19
+ return useMemo(() => {
20
+ const noDataState: EmptyStateProps = {
21
+ icon: { icon: SearchSVG, appearance: 'neutral', decor: true },
22
+ title: t('noData.title'),
23
+ ...noDataStateProp,
24
+ };
25
+
26
+ const noResultsState: EmptyStateProps = {
27
+ icon: { icon: SearchSVG, appearance: 'neutral', decor: true },
28
+ title: t('noResults.title'),
29
+ description: t('noResults.description'),
30
+ ...noResultsStateProp,
31
+ };
32
+
33
+ const errorDataState: EmptyStateProps = {
34
+ icon: { icon: CrossSVG, appearance: 'red', decor: true },
35
+ title: t('errorData.title'),
36
+ description: t('errorData.description'),
37
+ ...errorDataStateProp,
38
+ };
39
+
40
+ return {
41
+ noDataState,
42
+ noResultsState,
43
+ errorDataState,
44
+ };
45
+ }, [errorDataStateProp, noDataStateProp, noResultsStateProp, t]);
46
+ }
@@ -0,0 +1,2 @@
1
+ export * from './TableEmptyState';
2
+ export * from './hooks';
@@ -0,0 +1,12 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/components/styles-tokens-table';
2
+
3
+ .tableEmptyStateWrapper {
4
+ display: flex;
5
+ flex-direction: column;
6
+ align-items: center;
7
+ justify-content: center;
8
+
9
+ box-sizing: border-box;
10
+ height: calc((var(--page-size, 10) * styles-tokens-table.$size-table-line-height) + styles-tokens-table.$size-table-line-height);
11
+ padding: styles-tokens-table.$dimension-3m;
12
+ }
@@ -0,0 +1,11 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ import { IconPredefinedProps } from '@snack-uikit/icon-predefined';
4
+
5
+ export type EmptyStateProps = {
6
+ title?: string;
7
+ description?: string;
8
+ icon?: Pick<IconPredefinedProps, 'icon' | 'decor' | 'appearance'>;
9
+ footer?: ReactNode;
10
+ className?: string;
11
+ };
@@ -0,0 +1,39 @@
1
+ import { Table } from '@tanstack/react-table';
2
+ import { useCallback } from 'react';
3
+
4
+ import { Pagination } from '@snack-uikit/pagination';
5
+
6
+ import styles from './styles.module.scss';
7
+
8
+ export type TablePaginationProps<TData> = {
9
+ table: Table<TData>;
10
+ };
11
+
12
+ export function TablePagination<TData>({ table }: TablePaginationProps<TData>) {
13
+ const handlePaginationOnChange = useCallback(
14
+ (pageIndex: number) => {
15
+ table.setPageIndex(pageIndex - 1);
16
+ },
17
+ [table],
18
+ );
19
+
20
+ const tablePaginationState = table.getState().pagination;
21
+
22
+ if (table.getPageCount() <= 1) {
23
+ return null;
24
+ }
25
+
26
+ return (
27
+ <div className={styles.pagination}>
28
+ {table.getPageCount() > 1 && (
29
+ <Pagination
30
+ maxLength={6}
31
+ total={table.getPageCount()}
32
+ page={tablePaginationState.pageIndex + 1}
33
+ onChange={handlePaginationOnChange}
34
+ size='s'
35
+ />
36
+ )}
37
+ </div>
38
+ );
39
+ }
@@ -0,0 +1 @@
1
+ export * from './TablePagination';
@@ -0,0 +1,8 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables';
2
+
3
+ .pagination {
4
+ display: flex;
5
+ align-items: center;
6
+ justify-content: center;
7
+ padding-top: styles-theme-variables.$dimension-1m;
8
+ }
@@ -0,0 +1,4 @@
1
+ export * from './RowActionsCell';
2
+ export * from './TableCard';
3
+ export * from './TablePagination';
4
+ export * from './TableEmptyState';
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './components';