@cloud-ru/uikit-product-mobile-table 0.16.2 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/dist/cjs/components/AdaptiveServerTable/AdaptiveServerTable.js +7 -6
- package/dist/{esm/components → cjs/components/AdaptiveServerTable}/constants.d.ts +0 -1
- package/dist/cjs/components/{constants.js → AdaptiveServerTable/constants.js} +1 -2
- package/dist/cjs/components/{utils.d.ts → AdaptiveServerTable/utils.d.ts} +0 -2
- package/dist/cjs/components/{utils.js → AdaptiveServerTable/utils.js} +1 -11
- package/dist/cjs/components/MobileTable/MobileTable.d.ts +7 -0
- package/dist/cjs/components/{MobileTable.js → MobileTable/MobileTable.js} +33 -10
- package/dist/cjs/components/MobileTable/hooks/index.d.ts +2 -0
- package/dist/cjs/components/MobileTable/hooks/index.js +18 -0
- package/dist/cjs/components/MobileTable/hooks/useFilters/index.d.ts +1 -0
- package/dist/cjs/components/MobileTable/hooks/useFilters/index.js +17 -0
- package/dist/cjs/components/MobileTable/hooks/useFilters/useFilters.d.ts +78 -0
- package/dist/cjs/components/MobileTable/hooks/useFilters/useFilters.js +31 -0
- package/dist/cjs/components/MobileTable/hooks/useFilters/utils/getInitialColumnsFiltersOpenValue.d.ts +2 -0
- package/dist/cjs/components/MobileTable/hooks/useFilters/utils/getInitialColumnsFiltersOpenValue.js +11 -0
- package/dist/cjs/components/MobileTable/hooks/useFilters/utils/index.d.ts +1 -0
- package/dist/cjs/components/MobileTable/hooks/useFilters/utils/index.js +17 -0
- package/dist/cjs/components/{hooks.d.ts → MobileTable/hooks/useLoadingTable.d.ts} +0 -8
- package/dist/cjs/components/{hooks.js → MobileTable/hooks/useLoadingTable.js} +1 -15
- package/dist/cjs/components/MobileTable/index.d.ts +3 -0
- package/dist/cjs/components/MobileTable/index.js +21 -0
- package/dist/cjs/components/MobileTable/types.d.ts +11 -0
- package/dist/cjs/components/MobileTable/types.js +2 -0
- package/dist/cjs/components/MobileTable/utils/fuzzyFilter.d.ts +2 -0
- package/dist/cjs/components/MobileTable/utils/fuzzyFilter.js +13 -0
- package/dist/cjs/components/MobileTable/utils/index.d.ts +2 -0
- package/dist/cjs/components/MobileTable/utils/index.js +18 -0
- package/dist/cjs/components/MobileTable/utils/saveTableState/getPersistedStateValidator.d.ts +4 -0
- package/dist/cjs/components/MobileTable/utils/saveTableState/getPersistedStateValidator.js +13 -0
- package/dist/cjs/components/MobileTable/utils/saveTableState/index.d.ts +3 -0
- package/dist/cjs/components/MobileTable/utils/saveTableState/index.js +19 -0
- package/dist/cjs/components/MobileTable/utils/saveTableState/mappers.d.ts +18 -0
- package/dist/cjs/components/MobileTable/utils/saveTableState/mappers.js +45 -0
- package/dist/cjs/components/MobileTable/utils/saveTableState/validators.d.ts +5 -0
- package/dist/cjs/components/MobileTable/utils/saveTableState/validators.js +13 -0
- package/dist/cjs/constants.d.ts +1 -0
- package/dist/cjs/constants.js +2 -1
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +1 -0
- package/dist/esm/components/AdaptiveServerTable/AdaptiveServerTable.js +5 -4
- package/dist/{cjs/components → esm/components/AdaptiveServerTable}/constants.d.ts +0 -1
- package/dist/esm/components/{constants.js → AdaptiveServerTable/constants.js} +0 -1
- package/dist/esm/components/{utils.d.ts → AdaptiveServerTable/utils.d.ts} +0 -2
- package/dist/esm/components/AdaptiveServerTable/utils.js +5 -0
- package/dist/esm/components/MobileTable/MobileTable.d.ts +7 -0
- package/dist/esm/components/{MobileTable.js → MobileTable/MobileTable.js} +33 -10
- package/dist/esm/components/MobileTable/hooks/index.d.ts +2 -0
- package/dist/esm/components/MobileTable/hooks/index.js +2 -0
- package/dist/esm/components/MobileTable/hooks/useFilters/index.d.ts +1 -0
- package/dist/esm/components/MobileTable/hooks/useFilters/index.js +1 -0
- package/dist/esm/components/MobileTable/hooks/useFilters/useFilters.d.ts +78 -0
- package/dist/esm/components/MobileTable/hooks/useFilters/useFilters.js +28 -0
- package/dist/esm/components/MobileTable/hooks/useFilters/utils/getInitialColumnsFiltersOpenValue.d.ts +2 -0
- package/dist/esm/components/MobileTable/hooks/useFilters/utils/getInitialColumnsFiltersOpenValue.js +8 -0
- package/dist/esm/components/MobileTable/hooks/useFilters/utils/index.d.ts +1 -0
- package/dist/esm/components/MobileTable/hooks/useFilters/utils/index.js +1 -0
- package/dist/esm/components/{hooks.d.ts → MobileTable/hooks/useLoadingTable.d.ts} +0 -8
- package/dist/esm/components/MobileTable/hooks/useLoadingTable.js +17 -0
- package/dist/esm/components/MobileTable/index.d.ts +3 -0
- package/dist/esm/components/MobileTable/index.js +3 -0
- package/dist/esm/components/MobileTable/types.d.ts +11 -0
- package/dist/esm/components/MobileTable/types.js +1 -0
- package/dist/esm/components/MobileTable/utils/fuzzyFilter.d.ts +2 -0
- package/dist/esm/components/{utils.js → MobileTable/utils/fuzzyFilter.js} +0 -5
- package/dist/esm/components/MobileTable/utils/index.d.ts +2 -0
- package/dist/esm/components/MobileTable/utils/index.js +2 -0
- package/dist/esm/components/MobileTable/utils/saveTableState/getPersistedStateValidator.d.ts +4 -0
- package/dist/esm/components/MobileTable/utils/saveTableState/getPersistedStateValidator.js +9 -0
- package/dist/esm/components/MobileTable/utils/saveTableState/index.d.ts +3 -0
- package/dist/esm/components/MobileTable/utils/saveTableState/index.js +3 -0
- package/dist/esm/components/MobileTable/utils/saveTableState/mappers.d.ts +18 -0
- package/dist/esm/components/MobileTable/utils/saveTableState/mappers.js +37 -0
- package/dist/esm/components/MobileTable/utils/saveTableState/validators.d.ts +5 -0
- package/dist/esm/components/MobileTable/utils/saveTableState/validators.js +7 -0
- package/dist/esm/constants.d.ts +1 -0
- package/dist/esm/constants.js +1 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/package.json +12 -9
- package/src/components/AdaptiveServerTable/AdaptiveServerTable.tsx +5 -4
- package/src/components/{constants.ts → AdaptiveServerTable/constants.ts} +0 -1
- package/src/components/AdaptiveServerTable/utils.ts +12 -0
- package/src/components/{MobileTable.tsx → MobileTable/MobileTable.tsx} +50 -55
- package/src/components/MobileTable/hooks/index.ts +2 -0
- package/src/components/MobileTable/hooks/useFilters/index.ts +1 -0
- package/src/components/MobileTable/hooks/useFilters/useFilters.ts +57 -0
- package/src/components/MobileTable/hooks/useFilters/utils/getInitialColumnsFiltersOpenValue.ts +13 -0
- package/src/components/MobileTable/hooks/useFilters/utils/index.ts +1 -0
- package/src/components/{hooks.tsx → MobileTable/hooks/useLoadingTable.tsx} +1 -22
- package/src/components/MobileTable/index.ts +3 -0
- package/src/components/MobileTable/types.ts +44 -0
- package/src/components/{utils.ts → MobileTable/utils/fuzzyFilter.ts} +0 -12
- package/src/components/MobileTable/utils/index.ts +2 -0
- package/src/components/MobileTable/utils/saveTableState/getPersistedStateValidator.ts +21 -0
- package/src/components/MobileTable/utils/saveTableState/index.ts +3 -0
- package/src/components/MobileTable/utils/saveTableState/mappers.ts +62 -0
- package/src/components/MobileTable/utils/saveTableState/validators.ts +21 -0
- package/src/constants.ts +2 -0
- package/src/helperComponents/ColumnsSettings/ColumnsSettings.tsx +1 -0
- package/src/index.ts +1 -0
- package/dist/cjs/components/MobileTable.d.ts +0 -13
- package/dist/esm/components/MobileTable.d.ts +0 -13
- package/dist/esm/components/hooks.js +0 -30
- /package/dist/cjs/components/{styles.module.css → MobileTable/styles.module.css} +0 -0
- /package/dist/esm/components/{styles.module.css → MobileTable/styles.module.css} +0 -0
- /package/src/components/{styles.module.scss → MobileTable/styles.module.scss} +0 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloud-ru/uikit-product-mobile-table",
|
|
3
3
|
"title": "Mobile Table",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.17.0",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"*.css",
|
|
7
7
|
"*.woff",
|
|
@@ -36,12 +36,14 @@
|
|
|
36
36
|
},
|
|
37
37
|
"scripts": {},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@cloud-ru/
|
|
40
|
-
"@cloud-ru/uikit-product-
|
|
41
|
-
"@cloud-ru/uikit-product-mobile-
|
|
42
|
-
"@cloud-ru/uikit-product-mobile-
|
|
43
|
-
"@cloud-ru/uikit-product-
|
|
39
|
+
"@cloud-ru/ft-request-payload-transform": "0.3.0",
|
|
40
|
+
"@cloud-ru/uikit-product-icons": "16.1.1",
|
|
41
|
+
"@cloud-ru/uikit-product-mobile-chips": "0.8.47",
|
|
42
|
+
"@cloud-ru/uikit-product-mobile-dropdown": "0.9.31",
|
|
43
|
+
"@cloud-ru/uikit-product-mobile-toolbar": "0.5.0",
|
|
44
|
+
"@cloud-ru/uikit-product-utils": "8.1.0",
|
|
44
45
|
"@snack-uikit/button": "0.19.16",
|
|
46
|
+
"@snack-uikit/chips": "0.28.12",
|
|
45
47
|
"@snack-uikit/figma-tokens": "18.0.1",
|
|
46
48
|
"@snack-uikit/icons": "0.27.4",
|
|
47
49
|
"@snack-uikit/info-block": "0.6.35",
|
|
@@ -51,11 +53,12 @@
|
|
|
51
53
|
"@snack-uikit/status": "0.10.7",
|
|
52
54
|
"@snack-uikit/table": "0.37.25",
|
|
53
55
|
"@snack-uikit/toggles": "0.13.23",
|
|
56
|
+
"@snack-uikit/toolbar": "0.14.15",
|
|
57
|
+
"@snack-uikit/utils": "4.0.1",
|
|
54
58
|
"@tanstack/match-sorter-utils": "8.19.4",
|
|
55
59
|
"@tanstack/react-table": "8.12.0",
|
|
56
60
|
"classnames": "2.5.1",
|
|
57
|
-
"lodash.debounce": "4.0.8"
|
|
58
|
-
"uncontrollable": "8.0.4"
|
|
61
|
+
"lodash.debounce": "4.0.8"
|
|
59
62
|
},
|
|
60
63
|
"peerDependencies": {
|
|
61
64
|
"@cloud-ru/uikit-product-locale": "*"
|
|
@@ -63,5 +66,5 @@
|
|
|
63
66
|
"devDependencies": {
|
|
64
67
|
"@types/lodash.debounce": "4.0.9"
|
|
65
68
|
},
|
|
66
|
-
"gitHead": "
|
|
69
|
+
"gitHead": "b8c76e1a66bd22f7c266466eb340860b06581d10"
|
|
67
70
|
}
|
|
@@ -3,11 +3,12 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
|
3
3
|
import { FiltersState } from '@cloud-ru/uikit-product-mobile-chips';
|
|
4
4
|
import { WithLayoutType } from '@cloud-ru/uikit-product-utils';
|
|
5
5
|
import { PaginationState, ServerTable as DesktopTable, ServerTableProps } from '@snack-uikit/table';
|
|
6
|
+
import { useValueControl } from '@snack-uikit/utils';
|
|
6
7
|
|
|
7
|
-
import { DEFAULT_PAGE_SIZE
|
|
8
|
-
import { useStateControl } from '../hooks';
|
|
8
|
+
import { DEFAULT_PAGE_SIZE } from '../../constants';
|
|
9
9
|
import { MobileTable, MobileTableProps } from '../MobileTable';
|
|
10
|
-
import {
|
|
10
|
+
import { DEFAULT_PAGINATION_LIMIT } from './constants';
|
|
11
|
+
import { onSearchDebounced } from './utils';
|
|
11
12
|
|
|
12
13
|
export type AdaptiveServerTableProps<TData extends object, TFilters extends FiltersState> = Omit<
|
|
13
14
|
ServerTableProps<TData, TFilters>,
|
|
@@ -34,7 +35,7 @@ export function AdaptiveServerTable<TData extends object, TFilters extends Filte
|
|
|
34
35
|
...rest
|
|
35
36
|
} = props;
|
|
36
37
|
|
|
37
|
-
const
|
|
38
|
+
const [search, setSearch] = useValueControl<string>(searchProp ?? { defaultValue: '' });
|
|
38
39
|
|
|
39
40
|
const [tempSearch, setTempSearch] = useState(search || '');
|
|
40
41
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import debounce from 'lodash.debounce';
|
|
2
|
+
|
|
3
|
+
import { SEARCH_DELAY } from './constants';
|
|
4
|
+
|
|
5
|
+
type OnSearchDebouncedType = (newValue: string, onChange: (newValue: string) => void) => void;
|
|
6
|
+
|
|
7
|
+
export const onSearchDebounced: OnSearchDebouncedType = debounce(
|
|
8
|
+
(newValue: string, onChange: (newValue: string) => void) => {
|
|
9
|
+
onChange(newValue);
|
|
10
|
+
},
|
|
11
|
+
SEARCH_DELAY,
|
|
12
|
+
);
|
|
@@ -12,20 +12,22 @@ import cn from 'classnames';
|
|
|
12
12
|
import { useCallback, useEffect, useMemo } from 'react';
|
|
13
13
|
|
|
14
14
|
import { useLocale } from '@cloud-ru/uikit-product-locale';
|
|
15
|
-
import { FiltersState
|
|
15
|
+
import { FiltersState } from '@cloud-ru/uikit-product-mobile-chips';
|
|
16
16
|
import { MobileToolbar, MobileToolbarProps } from '@cloud-ru/uikit-product-mobile-toolbar';
|
|
17
|
-
import { extractSupportProps
|
|
17
|
+
import { extractSupportProps } from '@cloud-ru/uikit-product-utils';
|
|
18
18
|
import { SkeletonContextProvider } from '@snack-uikit/skeleton';
|
|
19
19
|
import {
|
|
20
20
|
getPinnedGroups,
|
|
21
21
|
PaginationState,
|
|
22
|
-
TableProps,
|
|
23
22
|
useColumnOrderByDrag,
|
|
24
23
|
useColumnSettings,
|
|
25
24
|
usePageReset,
|
|
26
25
|
} from '@snack-uikit/table';
|
|
26
|
+
import { useValueControl } from '@snack-uikit/utils';
|
|
27
27
|
|
|
28
|
+
import { DEFAULT_PAGE_SIZE } from '../../constants';
|
|
28
29
|
import {
|
|
30
|
+
ColumnsSettings,
|
|
29
31
|
getRowActionsColumnDef,
|
|
30
32
|
getStatusColumnDef,
|
|
31
33
|
TableCard,
|
|
@@ -33,50 +35,18 @@ import {
|
|
|
33
35
|
TablePagination,
|
|
34
36
|
TableSorting,
|
|
35
37
|
useEmptyState,
|
|
36
|
-
} from '
|
|
37
|
-
import {
|
|
38
|
-
import { DEFAULT_PAGE_SIZE } from './constants';
|
|
39
|
-
import { useLoadingTable, useStateControl } from './hooks';
|
|
38
|
+
} from '../../helperComponents';
|
|
39
|
+
import { useFilters, useLoadingTable } from './hooks';
|
|
40
40
|
import styles from './styles.module.scss';
|
|
41
|
-
import {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
| 'search'
|
|
51
|
-
| 'onRefresh'
|
|
52
|
-
| 'moreActions'
|
|
53
|
-
| 'className'
|
|
54
|
-
| 'enableFuzzySearch'
|
|
55
|
-
| 'loading'
|
|
56
|
-
| 'dataError'
|
|
57
|
-
| 'dataFiltered'
|
|
58
|
-
| 'noDataState'
|
|
59
|
-
| 'noResultsState'
|
|
60
|
-
| 'errorDataState'
|
|
61
|
-
| 'sorting'
|
|
62
|
-
| 'pagination'
|
|
63
|
-
| 'pageCount'
|
|
64
|
-
| 'manualFiltering'
|
|
65
|
-
| 'manualPagination'
|
|
66
|
-
| 'manualSorting'
|
|
67
|
-
| 'getRowId'
|
|
68
|
-
| 'rowSelection'
|
|
69
|
-
| 'bulkActions'
|
|
70
|
-
| 'columnsSettings'
|
|
71
|
-
| 'savedState'
|
|
72
|
-
| 'autoResetPageIndex'
|
|
73
|
-
| 'toolbarAfter'
|
|
74
|
-
> &
|
|
75
|
-
WithSupportProps<{
|
|
76
|
-
headlineId?: string;
|
|
77
|
-
headerBackground?: 'default' | '1-level' | '2-level';
|
|
78
|
-
columnFilters?: MobileChipChoiceRowProps<FiltersState>;
|
|
79
|
-
}>;
|
|
41
|
+
import { MobileTableProps } from './types';
|
|
42
|
+
import {
|
|
43
|
+
fuzzyFilter,
|
|
44
|
+
getPersistedStateValidator,
|
|
45
|
+
mapPaginationToRequestPayload,
|
|
46
|
+
mapPaginationToTableState,
|
|
47
|
+
mapSortToRequestPayload,
|
|
48
|
+
mapSortToTableState,
|
|
49
|
+
} from './utils';
|
|
80
50
|
|
|
81
51
|
export function MobileTable<TData extends object, TFilters extends FiltersState = Record<string, unknown>>({
|
|
82
52
|
data,
|
|
@@ -115,16 +85,14 @@ export function MobileTable<TData extends object, TFilters extends FiltersState
|
|
|
115
85
|
}: MobileTableProps<TData, TFilters>) {
|
|
116
86
|
const defaultPaginationState = useMemo(() => ({ pageIndex: 0, pageSize: DEFAULT_PAGE_SIZE }), []);
|
|
117
87
|
|
|
118
|
-
const
|
|
119
|
-
const
|
|
120
|
-
const
|
|
121
|
-
paginationProp,
|
|
122
|
-
defaultPaginationState,
|
|
88
|
+
const [sorting = [], onSortingChange] = useValueControl<SortingState>(sortingProp ?? { defaultValue: [] });
|
|
89
|
+
const [globalFilter = '', onGlobalFilterChange] = useValueControl<string>(search ?? { defaultValue: '' });
|
|
90
|
+
const [pagination = defaultPaginationState, onPaginationChange] = useValueControl<PaginationState>(
|
|
91
|
+
paginationProp ?? { defaultValue: defaultPaginationState },
|
|
123
92
|
);
|
|
124
93
|
|
|
125
|
-
const
|
|
126
|
-
rowSelectionProp,
|
|
127
|
-
{},
|
|
94
|
+
const [rowSelection = {}, onRowSelectionChange] = useValueControl<RowSelectionState>(
|
|
95
|
+
rowSelectionProp ?? { defaultValue: {} },
|
|
128
96
|
);
|
|
129
97
|
|
|
130
98
|
const enableRowSelection = useCallback(
|
|
@@ -311,6 +279,9 @@ export function MobileTable<TData extends object, TFilters extends FiltersState
|
|
|
311
279
|
|
|
312
280
|
const tableFilteredRows = table.getFilteredRowModel().rows;
|
|
313
281
|
|
|
282
|
+
const { filter, patchedFilter, setFilter, setFilterVisibility } = useFilters({ columnFilters });
|
|
283
|
+
const validatePersistedState = useMemo(() => getPersistedStateValidator(columnFilters), [columnFilters]);
|
|
284
|
+
|
|
314
285
|
usePageReset({
|
|
315
286
|
manualPagination,
|
|
316
287
|
maximumAvailablePage: pageCount || tableFilteredRows.length / pagination.pageSize,
|
|
@@ -336,7 +307,7 @@ export function MobileTable<TData extends object, TFilters extends FiltersState
|
|
|
336
307
|
}
|
|
337
308
|
onRefresh={onRefresh ? handleOnRefresh : undefined}
|
|
338
309
|
outline
|
|
339
|
-
filterRow={
|
|
310
|
+
filterRow={patchedFilter}
|
|
340
311
|
after={
|
|
341
312
|
toolbarAfter || shouldShowSorting || (areColumnsSettingsEnabled && columnsSettings) ? (
|
|
342
313
|
<>
|
|
@@ -366,6 +337,30 @@ export function MobileTable<TData extends object, TFilters extends FiltersState
|
|
|
366
337
|
onCheck={enableSelection ? handleOnToolbarCheck : undefined}
|
|
367
338
|
checked={table.getIsAllPageRowsSelected()}
|
|
368
339
|
indeterminate={table.getIsSomePageRowsSelected()}
|
|
340
|
+
persist={
|
|
341
|
+
savedState?.id && savedState?.filterQueryKey
|
|
342
|
+
? {
|
|
343
|
+
id: savedState.id,
|
|
344
|
+
filterQueryKey: savedState.filterQueryKey,
|
|
345
|
+
validateData: data => validatePersistedState(data),
|
|
346
|
+
state: {
|
|
347
|
+
pagination: mapPaginationToRequestPayload(pagination),
|
|
348
|
+
ordering: mapSortToRequestPayload(sorting),
|
|
349
|
+
filter,
|
|
350
|
+
search: globalFilter || '',
|
|
351
|
+
},
|
|
352
|
+
onLoad: state => {
|
|
353
|
+
state.pagination && onPaginationChange(mapPaginationToTableState(state.pagination));
|
|
354
|
+
state.search && onGlobalFilterChange(state.search);
|
|
355
|
+
state.ordering && onSortingChange(mapSortToTableState(state.ordering));
|
|
356
|
+
if (state.filter) {
|
|
357
|
+
setFilter(state.filter as TFilters);
|
|
358
|
+
setFilterVisibility(Object.keys(state.filter));
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
}
|
|
362
|
+
: undefined
|
|
363
|
+
}
|
|
369
364
|
/>
|
|
370
365
|
</div>
|
|
371
366
|
)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useFilters';
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { useMemo, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import { FiltersState } from '@cloud-ru/uikit-product-mobile-chips';
|
|
4
|
+
import { useValueControl } from '@snack-uikit/utils';
|
|
5
|
+
|
|
6
|
+
import { MobileTableProps } from '../../types';
|
|
7
|
+
import { getInitialColumnsFiltersOpenValue } from './utils';
|
|
8
|
+
|
|
9
|
+
type useFiltersProps<TData extends object, TFilters extends FiltersState = Record<string, unknown>> = Pick<
|
|
10
|
+
MobileTableProps<TData, TFilters>,
|
|
11
|
+
'columnFilters'
|
|
12
|
+
>;
|
|
13
|
+
|
|
14
|
+
export function useFilters<TData extends object, TFilters extends FiltersState = Record<string, unknown>>({
|
|
15
|
+
columnFilters,
|
|
16
|
+
}: useFiltersProps<TData, TFilters>) {
|
|
17
|
+
const [areColumnFiltersOpen, setAreColumnFiltersOpen] = useState<boolean>(() =>
|
|
18
|
+
getInitialColumnsFiltersOpenValue(columnFilters),
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
const [filter, setFilter] = useValueControl<TFilters | undefined>({
|
|
22
|
+
value: columnFilters?.value,
|
|
23
|
+
defaultValue: columnFilters?.defaultValue as TFilters,
|
|
24
|
+
onChange: columnFilters?.onChange,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const [filterVisibility = [], setFilterVisibility] = useValueControl<string[]>({
|
|
28
|
+
value: columnFilters?.visibleFilters,
|
|
29
|
+
defaultValue: [],
|
|
30
|
+
onChange: columnFilters?.onVisibleFiltersChange,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const patchedFilter = useMemo(() => {
|
|
34
|
+
if (!columnFilters) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
open: areColumnFiltersOpen,
|
|
40
|
+
onOpenChange: setAreColumnFiltersOpen,
|
|
41
|
+
...columnFilters,
|
|
42
|
+
value: filter,
|
|
43
|
+
onChange: setFilter as (filter: TFilters) => void,
|
|
44
|
+
visibleFilters: filterVisibility,
|
|
45
|
+
onVisibleFiltersChange: setFilterVisibility,
|
|
46
|
+
};
|
|
47
|
+
}, [columnFilters, areColumnFiltersOpen, filter, setFilter, filterVisibility, setFilterVisibility]);
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
filter,
|
|
51
|
+
setFilter,
|
|
52
|
+
|
|
53
|
+
patchedFilter,
|
|
54
|
+
|
|
55
|
+
setFilterVisibility,
|
|
56
|
+
};
|
|
57
|
+
}
|
package/src/components/MobileTable/hooks/useFilters/utils/getInitialColumnsFiltersOpenValue.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { MobileTableProps } from '../../../types';
|
|
2
|
+
|
|
3
|
+
export function getInitialColumnsFiltersOpenValue<TData extends object>(
|
|
4
|
+
columnFilters: MobileTableProps<TData>['columnFilters'],
|
|
5
|
+
) {
|
|
6
|
+
if (!columnFilters) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return 'initialOpen' in columnFilters && typeof columnFilters.initialOpen === 'boolean'
|
|
11
|
+
? columnFilters.initialOpen
|
|
12
|
+
: true;
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './getInitialColumnsFiltersOpenValue';
|
|
@@ -1,32 +1,11 @@
|
|
|
1
1
|
import { getCoreRowModel, useReactTable } from '@tanstack/react-table';
|
|
2
2
|
import { useMemo } from 'react';
|
|
3
|
-
import { useUncontrolledProp } from 'uncontrollable';
|
|
4
3
|
|
|
5
4
|
import { FiltersState } from '@cloud-ru/uikit-product-mobile-chips';
|
|
6
5
|
import { SkeletonText } from '@snack-uikit/skeleton';
|
|
7
6
|
import { TableProps } from '@snack-uikit/table';
|
|
8
7
|
|
|
9
|
-
import { ROW_ACTIONS_COLUMN_ID } from '
|
|
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
|
-
}
|
|
8
|
+
import { ROW_ACTIONS_COLUMN_ID } from '../../../constants';
|
|
30
9
|
|
|
31
10
|
type UseLoadingTableProps<TData extends object, TFilters extends FiltersState> = {
|
|
32
11
|
columnDefinitions: TableProps<TData, TFilters>['columnDefinitions'];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { FiltersState, MobileChipChoiceRowProps } from '@cloud-ru/uikit-product-mobile-chips';
|
|
2
|
+
import { WithSupportProps } from '@cloud-ru/uikit-product-utils';
|
|
3
|
+
import { TableProps } from '@snack-uikit/table';
|
|
4
|
+
|
|
5
|
+
export type MobileTableProps<TData extends object, TFilters extends FiltersState = Record<string, unknown>> = Pick<
|
|
6
|
+
TableProps<TData, TFilters>,
|
|
7
|
+
| 'data'
|
|
8
|
+
| 'columnDefinitions'
|
|
9
|
+
| 'suppressPagination'
|
|
10
|
+
| 'suppressToolbar'
|
|
11
|
+
| 'suppressSearch'
|
|
12
|
+
| 'search'
|
|
13
|
+
| 'onRefresh'
|
|
14
|
+
| 'moreActions'
|
|
15
|
+
| 'className'
|
|
16
|
+
| 'enableFuzzySearch'
|
|
17
|
+
| 'loading'
|
|
18
|
+
| 'dataError'
|
|
19
|
+
| 'dataFiltered'
|
|
20
|
+
| 'noDataState'
|
|
21
|
+
| 'noResultsState'
|
|
22
|
+
| 'errorDataState'
|
|
23
|
+
| 'sorting'
|
|
24
|
+
| 'pagination'
|
|
25
|
+
| 'pageCount'
|
|
26
|
+
| 'manualFiltering'
|
|
27
|
+
| 'manualPagination'
|
|
28
|
+
| 'manualSorting'
|
|
29
|
+
| 'getRowId'
|
|
30
|
+
| 'rowSelection'
|
|
31
|
+
| 'bulkActions'
|
|
32
|
+
| 'columnsSettings'
|
|
33
|
+
| 'savedState'
|
|
34
|
+
| 'autoResetPageIndex'
|
|
35
|
+
| 'toolbarAfter'
|
|
36
|
+
> &
|
|
37
|
+
WithSupportProps<{
|
|
38
|
+
headlineId?: string;
|
|
39
|
+
headerBackground?: 'default' | '1-level' | '2-level';
|
|
40
|
+
/** Фильтры */
|
|
41
|
+
columnFilters?: MobileChipChoiceRowProps<TFilters> & {
|
|
42
|
+
initialOpen?: boolean;
|
|
43
|
+
};
|
|
44
|
+
}>;
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { RankingInfo, rankItem } from '@tanstack/match-sorter-utils';
|
|
2
2
|
import { FilterFn } from '@tanstack/react-table';
|
|
3
|
-
import debounce from 'lodash.debounce';
|
|
4
|
-
|
|
5
|
-
import { SEARCH_DELAY } from './constants';
|
|
6
3
|
|
|
7
4
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
5
|
export const fuzzyFilter: FilterFn<any> = (row, columnId, value, addMeta) => {
|
|
@@ -14,12 +11,3 @@ export const fuzzyFilter: FilterFn<any> = (row, columnId, value, addMeta) => {
|
|
|
14
11
|
|
|
15
12
|
return itemRank.passed;
|
|
16
13
|
};
|
|
17
|
-
|
|
18
|
-
type OnSearchDebouncedType = (newValue: string, onChange: (newValue: string) => void) => void;
|
|
19
|
-
|
|
20
|
-
export const onSearchDebounced: OnSearchDebouncedType = debounce(
|
|
21
|
-
(newValue: string, onChange: (newValue: string) => void) => {
|
|
22
|
-
onChange(newValue);
|
|
23
|
-
},
|
|
24
|
-
SEARCH_DELAY,
|
|
25
|
-
);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { FiltersState } from '@snack-uikit/chips';
|
|
2
|
+
import { PersistedFilterState } from '@snack-uikit/toolbar';
|
|
3
|
+
|
|
4
|
+
import { MobileTableProps } from '../../types';
|
|
5
|
+
import { validateFilter, validatePaging, validateSorting } from './validators';
|
|
6
|
+
|
|
7
|
+
export const getPersistedStateValidator =
|
|
8
|
+
<TData extends object, TFilters extends FiltersState = Record<string, unknown>>(
|
|
9
|
+
columnFilters: MobileTableProps<TData, TFilters>['columnFilters'],
|
|
10
|
+
) =>
|
|
11
|
+
(data: unknown): data is PersistedFilterState<TFilters> => {
|
|
12
|
+
const dataAsSettings = data as PersistedFilterState<TFilters>;
|
|
13
|
+
const isPaginationValid = validatePaging(dataAsSettings?.pagination);
|
|
14
|
+
const isSortingValid = validateSorting(dataAsSettings?.ordering);
|
|
15
|
+
const isSearchValid = !dataAsSettings?.search || typeof dataAsSettings?.search === 'string';
|
|
16
|
+
const isFilterValid = Boolean(
|
|
17
|
+
columnFilters?.filters && validateFilter(dataAsSettings.filter, columnFilters.filters),
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
return isPaginationValid && isSortingValid && isSearchValid && isFilterValid;
|
|
21
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { RequestPayloadParams, SortDirection } from '@cloud-ru/ft-request-payload-transform';
|
|
2
|
+
import { PaginationState, SortingState } from '@tanstack/react-table';
|
|
3
|
+
|
|
4
|
+
import { FiltersState } from '@snack-uikit/chips';
|
|
5
|
+
import { formatFilterStateToRequestPayload, PersistedFilterState } from '@snack-uikit/toolbar';
|
|
6
|
+
|
|
7
|
+
import { DEFAULT_PAGE_SIZE } from '../../../../constants';
|
|
8
|
+
|
|
9
|
+
export const mapPaginationToTableState = (value?: RequestPayloadParams['pagination']): PaginationState => {
|
|
10
|
+
if (!value || value.offset === undefined || value.limit === undefined) {
|
|
11
|
+
return { pageSize: DEFAULT_PAGE_SIZE, pageIndex: 0 };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
pageSize: value.limit || DEFAULT_PAGE_SIZE,
|
|
16
|
+
pageIndex: Math.floor(value.offset / value.limit),
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const mapSortToTableState = (value: RequestPayloadParams['ordering'] = []): SortingState =>
|
|
21
|
+
value.map(column => ({
|
|
22
|
+
id: column.field,
|
|
23
|
+
desc: column.direction === '-',
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
export const mapPaginationToRequestPayload = (
|
|
27
|
+
value?: PaginationState | RequestPayloadParams['pagination'],
|
|
28
|
+
): RequestPayloadParams['pagination'] => {
|
|
29
|
+
if (!value) return undefined;
|
|
30
|
+
|
|
31
|
+
if ('limit' in value || 'offset' in value) {
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
limit: value.pageSize,
|
|
37
|
+
offset: value.pageSize * value.pageIndex,
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const mapSortToRequestPayload = (value?: SortingState): RequestPayloadParams['ordering'] =>
|
|
42
|
+
value?.map(column => ({
|
|
43
|
+
field: column.id,
|
|
44
|
+
direction: (column.desc ? '-' : '+') as SortDirection,
|
|
45
|
+
}));
|
|
46
|
+
|
|
47
|
+
/** Вспомогательная функция для преобразования состояния таблицы к формату RequestPayloadParams */
|
|
48
|
+
export const formatTableStateToRequestPayload = <T extends FiltersState>({
|
|
49
|
+
pagination,
|
|
50
|
+
sorting,
|
|
51
|
+
search,
|
|
52
|
+
filter,
|
|
53
|
+
}: Omit<PersistedFilterState<T>, 'pagination' | 'sorting'> & {
|
|
54
|
+
pagination?: PaginationState | RequestPayloadParams['pagination'];
|
|
55
|
+
sorting?: SortingState;
|
|
56
|
+
}) =>
|
|
57
|
+
formatFilterStateToRequestPayload({
|
|
58
|
+
filter,
|
|
59
|
+
search,
|
|
60
|
+
pagination: mapPaginationToRequestPayload(pagination),
|
|
61
|
+
ordering: mapSortToRequestPayload(sorting),
|
|
62
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { RequestPayloadParams } from '@cloud-ru/ft-request-payload-transform';
|
|
2
|
+
|
|
3
|
+
import { ChipChoiceRowProps } from '@snack-uikit/chips';
|
|
4
|
+
|
|
5
|
+
export const validatePaging = (value: unknown): value is RequestPayloadParams['pagination'] =>
|
|
6
|
+
typeof (value as RequestPayloadParams['pagination'])?.limit === 'number' &&
|
|
7
|
+
typeof (value as RequestPayloadParams['pagination'])?.offset === 'number';
|
|
8
|
+
|
|
9
|
+
export const validateSorting = (value: unknown): value is RequestPayloadParams['ordering'] =>
|
|
10
|
+
!value ||
|
|
11
|
+
(value as NonNullable<RequestPayloadParams['ordering']>).every(
|
|
12
|
+
column => typeof column?.field === 'string' && typeof column?.direction === 'string',
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
export const validateFilter = <TFilters extends Record<string, unknown>>(
|
|
16
|
+
value: unknown,
|
|
17
|
+
filterSettings: ChipChoiceRowProps<TFilters>['filters'],
|
|
18
|
+
): value is TFilters =>
|
|
19
|
+
typeof value === 'object' &&
|
|
20
|
+
value !== null &&
|
|
21
|
+
Object.keys(value).every(field => Boolean(filterSettings.find(setting => setting.id === field)));
|
package/src/constants.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { FunctionSettingsSVG } from '@snack-uikit/icons';
|
|
|
4
4
|
import { GroupSelectItemProps } from '@snack-uikit/list';
|
|
5
5
|
|
|
6
6
|
import styles from './styles.module.scss';
|
|
7
|
+
|
|
7
8
|
export type ColumnsSettingsProps = {
|
|
8
9
|
enabledColumns: string[];
|
|
9
10
|
setEnabledColumns(enabledColumns: string[]): void;
|
package/src/index.ts
CHANGED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { FiltersState, MobileChipChoiceRowProps } from '@cloud-ru/uikit-product-mobile-chips';
|
|
2
|
-
import { WithSupportProps } from '@cloud-ru/uikit-product-utils';
|
|
3
|
-
import { TableProps } from '@snack-uikit/table';
|
|
4
|
-
export type MobileTableProps<TData extends object, TFilters extends FiltersState = Record<string, unknown>> = Pick<TableProps<TData, TFilters>, 'data' | 'columnDefinitions' | 'suppressPagination' | 'suppressToolbar' | 'suppressSearch' | 'search' | 'onRefresh' | 'moreActions' | 'className' | 'enableFuzzySearch' | 'loading' | 'dataError' | 'dataFiltered' | 'noDataState' | 'noResultsState' | 'errorDataState' | 'sorting' | 'pagination' | 'pageCount' | 'manualFiltering' | 'manualPagination' | 'manualSorting' | 'getRowId' | 'rowSelection' | 'bulkActions' | 'columnsSettings' | 'savedState' | 'autoResetPageIndex' | 'toolbarAfter'> & WithSupportProps<{
|
|
5
|
-
headlineId?: string;
|
|
6
|
-
headerBackground?: 'default' | '1-level' | '2-level';
|
|
7
|
-
columnFilters?: MobileChipChoiceRowProps<FiltersState>;
|
|
8
|
-
}>;
|
|
9
|
-
export declare function MobileTable<TData extends object, TFilters extends FiltersState = Record<string, unknown>>({ data, columnDefinitions, headlineId, suppressPagination, suppressToolbar, suppressSearch, enableFuzzySearch, search, onRefresh, toolbarAfter, moreActions, columnFilters, className, headerBackground, noDataState, noResultsState, errorDataState, loading, dataError, dataFiltered, pagination: paginationProp, pageCount, sorting: sortingProp, manualSorting, manualPagination, manualFiltering, autoResetPageIndex, getRowId, rowSelection: rowSelectionProp, bulkActions: bulkActionsProp, columnsSettings: columnsSettingsProp, savedState, ...rest }: MobileTableProps<TData, TFilters>): import("react/jsx-runtime").JSX.Element;
|
|
10
|
-
export declare namespace MobileTable {
|
|
11
|
-
var getRowActionsColumnDef: typeof import("../helperComponents").getRowActionsColumnDef;
|
|
12
|
-
var getStatusColumnDef: typeof import("../helperComponents").getStatusColumnDef;
|
|
13
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { FiltersState, MobileChipChoiceRowProps } from '@cloud-ru/uikit-product-mobile-chips';
|
|
2
|
-
import { WithSupportProps } from '@cloud-ru/uikit-product-utils';
|
|
3
|
-
import { TableProps } from '@snack-uikit/table';
|
|
4
|
-
export type MobileTableProps<TData extends object, TFilters extends FiltersState = Record<string, unknown>> = Pick<TableProps<TData, TFilters>, 'data' | 'columnDefinitions' | 'suppressPagination' | 'suppressToolbar' | 'suppressSearch' | 'search' | 'onRefresh' | 'moreActions' | 'className' | 'enableFuzzySearch' | 'loading' | 'dataError' | 'dataFiltered' | 'noDataState' | 'noResultsState' | 'errorDataState' | 'sorting' | 'pagination' | 'pageCount' | 'manualFiltering' | 'manualPagination' | 'manualSorting' | 'getRowId' | 'rowSelection' | 'bulkActions' | 'columnsSettings' | 'savedState' | 'autoResetPageIndex' | 'toolbarAfter'> & WithSupportProps<{
|
|
5
|
-
headlineId?: string;
|
|
6
|
-
headerBackground?: 'default' | '1-level' | '2-level';
|
|
7
|
-
columnFilters?: MobileChipChoiceRowProps<FiltersState>;
|
|
8
|
-
}>;
|
|
9
|
-
export declare function MobileTable<TData extends object, TFilters extends FiltersState = Record<string, unknown>>({ data, columnDefinitions, headlineId, suppressPagination, suppressToolbar, suppressSearch, enableFuzzySearch, search, onRefresh, toolbarAfter, moreActions, columnFilters, className, headerBackground, noDataState, noResultsState, errorDataState, loading, dataError, dataFiltered, pagination: paginationProp, pageCount, sorting: sortingProp, manualSorting, manualPagination, manualFiltering, autoResetPageIndex, getRowId, rowSelection: rowSelectionProp, bulkActions: bulkActionsProp, columnsSettings: columnsSettingsProp, savedState, ...rest }: MobileTableProps<TData, TFilters>): import("react/jsx-runtime").JSX.Element;
|
|
10
|
-
export declare namespace MobileTable {
|
|
11
|
-
var getRowActionsColumnDef: typeof import("../helperComponents").getRowActionsColumnDef;
|
|
12
|
-
var getStatusColumnDef: typeof import("../helperComponents").getStatusColumnDef;
|
|
13
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { getCoreRowModel, useReactTable } from '@tanstack/react-table';
|
|
3
|
-
import { useMemo } from 'react';
|
|
4
|
-
import { useUncontrolledProp } from 'uncontrollable';
|
|
5
|
-
import { SkeletonText } from '@snack-uikit/skeleton';
|
|
6
|
-
import { ROW_ACTIONS_COLUMN_ID } from '../constants';
|
|
7
|
-
export function useStateControl(control, defaultState) {
|
|
8
|
-
var _a, _b;
|
|
9
|
-
const [state, onStateChange] = useUncontrolledProp(control === null || control === void 0 ? void 0 : control.state, (_b = (_a = control === null || control === void 0 ? void 0 : control.state) !== null && _a !== void 0 ? _a : control === null || control === void 0 ? void 0 : control.initialState) !== null && _b !== void 0 ? _b : defaultState, (controlState) => {
|
|
10
|
-
var _a;
|
|
11
|
-
const newState = typeof controlState === 'function' ? controlState(state) : controlState;
|
|
12
|
-
(_a = control === null || control === void 0 ? void 0 : control.onChange) === null || _a === void 0 ? void 0 : _a.call(control, newState);
|
|
13
|
-
});
|
|
14
|
-
return {
|
|
15
|
-
state,
|
|
16
|
-
onStateChange,
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
export function useLoadingTable({ pageSize, columnDefinitions, }) {
|
|
20
|
-
const data = useMemo(() => (Array.from({ length: pageSize }).map(() => ({})) || []), [pageSize]);
|
|
21
|
-
const columns = useMemo(() => columnDefinitions
|
|
22
|
-
.filter(column => column.id !== ROW_ACTIONS_COLUMN_ID)
|
|
23
|
-
.map(column => (Object.assign(Object.assign({}, column), { cell: () => _jsx(SkeletonText, { lines: 1, width: '100%' }) }))), [columnDefinitions]);
|
|
24
|
-
const loadingTable = useReactTable({
|
|
25
|
-
data,
|
|
26
|
-
columns,
|
|
27
|
-
getCoreRowModel: getCoreRowModel(),
|
|
28
|
-
});
|
|
29
|
-
return { loadingTable };
|
|
30
|
-
}
|
|
File without changes
|
|
File without changes
|