-
Notifications
You must be signed in to change notification settings - Fork 0
/
with-filters.add-on.ts
95 lines (80 loc) · 2.73 KB
/
with-filters.add-on.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import { useCallback, useMemo, useState } from 'react';
import {
Column, Filters,
useFilters,
UseFiltersColumnOptions,
UseFiltersInstanceProps,
UseFiltersOptions,
UseFiltersState,
} from 'react-table';
import { filter, includes, map, values } from 'lodash-es';
import {
FILTER_ACTIONS,
FilterSetter,
IRelatableStateInstance,
TableAddOnReturn,
} from '../relatable.types';
import { IFilterFieldProps, TextFilter } from '../components/renderers';
export interface IWithFiltersOptions<Data extends object = any> extends UseFiltersOptions<Data> {
defaultFilterCell?: React.FC<IFilterFieldProps>;
onFilterChange?: FilterSetter<Data>;
// react-table state override https://react-table.js.org/api/useFilters
// with custom filter value array
filters?: Filters<Data>[];
}
export interface IWithFiltersState<Data extends object = any> extends UseFiltersState<Data> {
}
export interface IWithFiltersInstance<Data extends object = any> extends UseFiltersInstanceProps<Data>, IRelatableStateInstance<Data, IWithFiltersState<Data>> {
onCustomFilterChange: FilterSetter<Data>;
defaultColumn: Partial<Column<Data> & UseFiltersColumnOptions<Data>>;
}
export default function withFilters<Data extends object = any>(options: IWithFiltersOptions<Data> = {}): TableAddOnReturn {
const {
defaultFilterCell,
filters: theirFilters,
onFilterChange,
...rest
} = options;
const [ourFilters, setOurFilters] = useState<Filters<Data>>([]);
const filters = theirFilters || ourFilters;
const stateParams = { filters };
const onCustomFilterChange: FilterSetter = useCallback((column, action, values) => {
if (onFilterChange) {
onFilterChange(column, action, values);
return;
}
if (action === FILTER_ACTIONS.FILTER_CLEAR) {
setOurFilters(filter(ourFilters, ({ id }) => id === column.id));
return;
}
if (action === FILTER_ACTIONS.FILTER_ADD) {
setOurFilters([
...ourFilters,
...map(values, (value) => ({id: column.id, value}))
]);
return;
}
setOurFilters(filter(ourFilters, ({ id, value }) => !(id === column.id && includes(values, value))));
}, [onFilterChange, ourFilters, setOurFilters]);
const tableParams = {
...rest,
onCustomFilterChange,
defaultColumn: {
Filter: defaultFilterCell || TextFilter,
},
};
return [
withFilters.name,
null,
({ canFilter }) => canFilter,
({ defaultColumn }) => useMemo((): Partial<IWithFiltersInstance> => ({
...tableParams,
defaultColumn: {
...defaultColumn,
...tableParams.defaultColumn,
},
}), [defaultColumn, defaultFilterCell, onCustomFilterChange, ...values(rest)]),
() => useMemo(() => stateParams, [filters]),
useFilters,
];
}