@promoboxx/use-filter 1.11.2 → 2.0.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/.github/workflows/main.yml +38 -0
- package/.vscode/settings.json +3 -0
- package/CHANGELOG.md +185 -0
- package/Makefile +25 -0
- package/eslint.config.js +30 -0
- package/mise.toml +3 -0
- package/package.json +33 -43
- package/prettier.config.js +3 -0
- package/src/lib/buildDefaultFilterInfo.ts +36 -0
- package/src/lib/getOffsetFromPage.ts +5 -0
- package/src/lib/getPageFromOffset.ts +5 -0
- package/src/lib/shallowEqual.test.ts +71 -0
- package/src/lib/shallowEqual.ts +26 -0
- package/src/store/index.ts +30 -0
- package/src/store/localStorageStore.ts +36 -0
- package/src/store/memoryStore.ts +27 -0
- package/src/store/reduxHelpers/createActions.test.ts +32 -0
- package/src/store/reduxHelpers/createActions.ts +56 -0
- package/src/store/reduxHelpers/createReducer.test.ts +65 -0
- package/src/store/reduxHelpers/createReducer.ts +47 -0
- package/src/store/reduxStore.ts +78 -0
- package/src/store/urlParamStore.test.ts +131 -0
- package/src/store/urlParamStore.ts +85 -0
- package/src/useFilter.test.tsx +822 -0
- package/src/useFilter.ts +524 -0
- package/src/useSimpleFilter.test.tsx +676 -0
- package/src/useSimpleFilter.ts +397 -0
- package/src/vitest-env.d.ts +1 -0
- package/tsconfig.json +76 -0
- package/tsdown.config.ts +30 -0
- package/vite.config.ts +9 -0
- package/dist/lib/buildDefaultFilterInfo.d.ts +0 -3
- package/dist/lib/buildDefaultFilterInfo.js +0 -35
- package/dist/lib/getOffsetFromPage.d.ts +0 -2
- package/dist/lib/getOffsetFromPage.js +0 -6
- package/dist/lib/getPageFromOffset.d.ts +0 -2
- package/dist/lib/getPageFromOffset.js +0 -6
- package/dist/lib/shallowEqual.d.ts +0 -2
- package/dist/lib/shallowEqual.js +0 -23
- package/dist/store/index.d.ts +0 -10
- package/dist/store/index.js +0 -16
- package/dist/store/localStorageStore.d.ts +0 -3
- package/dist/store/localStorageStore.js +0 -31
- package/dist/store/memoryStore.d.ts +0 -3
- package/dist/store/memoryStore.js +0 -23
- package/dist/store/reduxHelpers/createActions.d.ts +0 -16
- package/dist/store/reduxHelpers/createActions.js +0 -27
- package/dist/store/reduxHelpers/createReducer.d.ts +0 -8
- package/dist/store/reduxHelpers/createReducer.js +0 -26
- package/dist/store/reduxStore.d.ts +0 -15
- package/dist/store/reduxStore.js +0 -67
- package/dist/store/urlParamStore.d.ts +0 -4
- package/dist/store/urlParamStore.js +0 -91
- package/dist/useFilter.d.ts +0 -103
- package/dist/useFilter.js +0 -254
- package/dist/useSimpleFilter.d.ts +0 -86
- package/dist/useSimpleFilter.js +0 -173
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { FilterStore } from './store';
|
|
2
|
-
import { UseFilterUpdateReason } from './useFilter';
|
|
3
|
-
interface UseSimpleFilterOptions<TFilter> {
|
|
4
|
-
/**
|
|
5
|
-
* Default values for your filter. When calling `.reset` your filter will be
|
|
6
|
-
* set to this.
|
|
7
|
-
* Changing these values does not cause a call to happen.
|
|
8
|
-
*/
|
|
9
|
-
defaultFilterInfo?: Partial<SimpleFilterInfo<TFilter>>;
|
|
10
|
-
/**
|
|
11
|
-
* In case you want to change the default debounce duration.
|
|
12
|
-
*/
|
|
13
|
-
debounceDuration?: number;
|
|
14
|
-
onBeforeSaveFilter?: (filterInfo: SimpleFilterInfo<TFilter>) => SimpleFilterInfo<TFilter>;
|
|
15
|
-
store?: FilterStore;
|
|
16
|
-
}
|
|
17
|
-
export interface SimpleFilterApi<TFilter> {
|
|
18
|
-
/**
|
|
19
|
-
* Really more "is debouncing", since simple mode doesn't know when your code
|
|
20
|
-
* is doing anything.
|
|
21
|
-
*/
|
|
22
|
-
isLoading: boolean;
|
|
23
|
-
/**
|
|
24
|
-
* Access to the filter and its metadata.
|
|
25
|
-
*/
|
|
26
|
-
filterInfo: SimpleFilterInfo<TFilter>;
|
|
27
|
-
/**
|
|
28
|
-
* Same as the regular `filterInfo`, but updates in a debounced fashion.
|
|
29
|
-
*/
|
|
30
|
-
debouncedFilterInfo: SimpleFilterInfo<TFilter>;
|
|
31
|
-
/**
|
|
32
|
-
* Why the last update happened.
|
|
33
|
-
*/
|
|
34
|
-
updateReason: UseFilterUpdateReason;
|
|
35
|
-
/**
|
|
36
|
-
* Update one or more values in your filter.
|
|
37
|
-
*/
|
|
38
|
-
updateFilter: (filter: Partial<TFilter>, shouldRunImmediately?: boolean) => void;
|
|
39
|
-
/**
|
|
40
|
-
* Does the boring math for you based on your `pageSize` and `totalResults`.
|
|
41
|
-
*/
|
|
42
|
-
pagingInfo: (total: string | number | null | undefined) => {
|
|
43
|
-
totalResults: number;
|
|
44
|
-
totalPages: number;
|
|
45
|
-
};
|
|
46
|
-
/**
|
|
47
|
-
* Resets the filter back to `defaultFilterInfo`.
|
|
48
|
-
*/
|
|
49
|
-
resetFilter: (shouldRunImmediately?: boolean) => void;
|
|
50
|
-
/**
|
|
51
|
-
* Changes the offset. Will update `page`.
|
|
52
|
-
*/
|
|
53
|
-
setOffset: (offset: number | string, shouldRunImmediately?: boolean) => void;
|
|
54
|
-
/**
|
|
55
|
-
* Changes the page. Will update `offset`.
|
|
56
|
-
*/
|
|
57
|
-
setPage: (page: number | string, shouldRunImmediately?: boolean) => void;
|
|
58
|
-
/**
|
|
59
|
-
* Changes the page size.
|
|
60
|
-
*/
|
|
61
|
-
setPageSize: (pageSize: number | string, shouldRunImmediately?: boolean) => void;
|
|
62
|
-
/**
|
|
63
|
-
* Change the sort method.
|
|
64
|
-
*/
|
|
65
|
-
setSort: (sort: string, shouldRunImmediately?: boolean) => void;
|
|
66
|
-
/**
|
|
67
|
-
* Changes the cursor.
|
|
68
|
-
*/
|
|
69
|
-
setCursor: (cursor: string | null | undefined, shouldRunImmediately?: boolean) => void;
|
|
70
|
-
/**
|
|
71
|
-
* Forces a refresh of the filter.
|
|
72
|
-
*/
|
|
73
|
-
forceRefresh: (shouldRunImmediately?: boolean) => void;
|
|
74
|
-
}
|
|
75
|
-
export interface SimpleFilterInfo<TFilter> {
|
|
76
|
-
filter: TFilter;
|
|
77
|
-
sort?: string;
|
|
78
|
-
offset: number;
|
|
79
|
-
page: number;
|
|
80
|
-
pageSize: number;
|
|
81
|
-
lastRefreshAt: number;
|
|
82
|
-
cursor?: string | null;
|
|
83
|
-
shouldRunImmediately: boolean;
|
|
84
|
-
}
|
|
85
|
-
declare function useSimpleFilter<TFilter>(namespace: string, options: UseSimpleFilterOptions<TFilter>): SimpleFilterApi<TFilter>;
|
|
86
|
-
export default useSimpleFilter;
|
package/dist/useSimpleFilter.js
DELETED
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __assign = (this && this.__assign) || function () {
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
var react_1 = require("react");
|
|
18
|
-
var getOffsetFromPage_1 = __importDefault(require("./lib/getOffsetFromPage"));
|
|
19
|
-
var getPageFromOffset_1 = __importDefault(require("./lib/getPageFromOffset"));
|
|
20
|
-
var shallowEqual_1 = __importDefault(require("./lib/shallowEqual"));
|
|
21
|
-
var store_1 = require("./store");
|
|
22
|
-
function useSimpleFilter(namespace, options) {
|
|
23
|
-
// Having these types of refs helps get around rules of hooks, and they need
|
|
24
|
-
// to be updated each render.
|
|
25
|
-
var ctxRefValue = {
|
|
26
|
-
namespace: namespace,
|
|
27
|
-
debounceDuration: options.debounceDuration,
|
|
28
|
-
defaultFilterInfo: options.defaultFilterInfo,
|
|
29
|
-
onBeforeSaveFilter: options.onBeforeSaveFilter,
|
|
30
|
-
store: options.store,
|
|
31
|
-
};
|
|
32
|
-
var ctxRef = react_1.useRef(ctxRefValue);
|
|
33
|
-
react_1.useEffect(function () {
|
|
34
|
-
ctxRef.current = ctxRefValue;
|
|
35
|
-
});
|
|
36
|
-
var _a = react_1.useState(false), isLoading = _a[0], setIsLoading = _a[1];
|
|
37
|
-
var _b = react_1.useState(function () {
|
|
38
|
-
var _a;
|
|
39
|
-
var fromStore = store_1.getFilterStore(ctxRef.current.store).getFilter(namespace);
|
|
40
|
-
// If the filter is already in the store, we have to make sure it ...
|
|
41
|
-
// - has both the filter and filterInfo
|
|
42
|
-
// - has all the fields the user passed to the hook
|
|
43
|
-
if (fromStore) {
|
|
44
|
-
var filterInfo_1 = buildDefaultFilterInfo(__assign(__assign({}, fromStore), { shouldRunImmediately: true, filter: __assign(__assign({}, (_a = options.defaultFilterInfo) === null || _a === void 0 ? void 0 : _a.filter), fromStore.filter) }));
|
|
45
|
-
return filterInfo_1;
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
return buildDefaultFilterInfo(__assign(__assign({}, options.defaultFilterInfo), { shouldRunImmediately: true }));
|
|
49
|
-
}
|
|
50
|
-
}), filterInfo = _b[0], setFilterInfoState = _b[1];
|
|
51
|
-
var _c = react_1.useState(filterInfo), debouncedFilterInfo = _c[0], setDebouncedFilterInfo = _c[1];
|
|
52
|
-
// Not sure this is needed in simple mode?
|
|
53
|
-
var lastRefreshAtRef = react_1.useRef(-1);
|
|
54
|
-
var updateReasonRef = react_1.useRef('initial');
|
|
55
|
-
react_1.useEffect(function () {
|
|
56
|
-
var _a;
|
|
57
|
-
setIsLoading(true);
|
|
58
|
-
// If the lastRefreshAt hasn't changed, don't do anything.
|
|
59
|
-
if (lastRefreshAtRef.current === filterInfo.lastRefreshAt) {
|
|
60
|
-
setIsLoading(false);
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
var timeout = undefined;
|
|
64
|
-
function makeRequest() {
|
|
65
|
-
lastRefreshAtRef.current = filterInfo.lastRefreshAt;
|
|
66
|
-
store_1.getFilterStore(ctxRef.current.store).saveFilter(ctxRef.current.namespace, (ctxRef.current.onBeforeSaveFilter
|
|
67
|
-
? ctxRef.current.onBeforeSaveFilter(filterInfo)
|
|
68
|
-
: filterInfo));
|
|
69
|
-
setDebouncedFilterInfo(filterInfo);
|
|
70
|
-
setIsLoading(false);
|
|
71
|
-
}
|
|
72
|
-
if (filterInfo.shouldRunImmediately) {
|
|
73
|
-
makeRequest();
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
timeout = setTimeout(makeRequest, (_a = ctxRef.current.debounceDuration) !== null && _a !== void 0 ? _a : 500);
|
|
77
|
-
}
|
|
78
|
-
return function () {
|
|
79
|
-
if (timeout) {
|
|
80
|
-
clearTimeout(timeout);
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
}, [filterInfo]);
|
|
84
|
-
var previousTotalRef = react_1.useRef(0);
|
|
85
|
-
var api = {
|
|
86
|
-
isLoading: isLoading,
|
|
87
|
-
filterInfo: filterInfo,
|
|
88
|
-
debouncedFilterInfo: debouncedFilterInfo,
|
|
89
|
-
updateReason: updateReasonRef.current,
|
|
90
|
-
updateFilter: react_1.useCallback(function (filter, shouldRunImmediately) {
|
|
91
|
-
if (shouldRunImmediately === void 0) { shouldRunImmediately = false; }
|
|
92
|
-
updateReasonRef.current = 'filter';
|
|
93
|
-
setFilterInfoState(function (previous) {
|
|
94
|
-
var nextFilter = __assign(__assign({}, previous.filter), filter);
|
|
95
|
-
if (shallowEqual_1.default(previous.filter, nextFilter)) {
|
|
96
|
-
return previous;
|
|
97
|
-
}
|
|
98
|
-
return __assign(__assign({}, previous), { shouldRunImmediately: shouldRunImmediately, offset: 0, page: 1, totalResults: 1, totalPages: 1, filter: nextFilter, cursor: undefined, lastRefreshAt: new Date().getTime() });
|
|
99
|
-
});
|
|
100
|
-
}, []),
|
|
101
|
-
pagingInfo: react_1.useCallback(function (total) {
|
|
102
|
-
var normalized = Number(
|
|
103
|
-
// Because we accept `null` as an argument, we can't do something as
|
|
104
|
-
// simple as `total ?? ...`
|
|
105
|
-
total == null ? previousTotalRef.current : total);
|
|
106
|
-
previousTotalRef.current = normalized;
|
|
107
|
-
return {
|
|
108
|
-
totalResults: normalized,
|
|
109
|
-
totalPages: Math.ceil(normalized / filterInfo.pageSize),
|
|
110
|
-
};
|
|
111
|
-
}, [filterInfo.pageSize]),
|
|
112
|
-
resetFilter: react_1.useCallback(function (shouldRunImmediately) {
|
|
113
|
-
if (shouldRunImmediately === void 0) { shouldRunImmediately = false; }
|
|
114
|
-
updateReasonRef.current = 'filter';
|
|
115
|
-
setFilterInfoState(__assign(__assign({}, buildDefaultFilterInfo(ctxRef.current.defaultFilterInfo)), { shouldRunImmediately: shouldRunImmediately }));
|
|
116
|
-
}, []),
|
|
117
|
-
setOffset: react_1.useCallback(function (offset, shouldRunImmediately) {
|
|
118
|
-
if (shouldRunImmediately === void 0) { shouldRunImmediately = false; }
|
|
119
|
-
updateReasonRef.current = 'pagination';
|
|
120
|
-
var offsetNumber = Number(offset);
|
|
121
|
-
setFilterInfoState(function (previous) { return (__assign(__assign({}, previous), { offset: offsetNumber, page: getPageFromOffset_1.default(offsetNumber, previous.pageSize), lastRefreshAt: new Date().getTime(), shouldRunImmediately: shouldRunImmediately })); });
|
|
122
|
-
}, []),
|
|
123
|
-
setPage: react_1.useCallback(function (page, shouldRunImmediately) {
|
|
124
|
-
if (shouldRunImmediately === void 0) { shouldRunImmediately = false; }
|
|
125
|
-
updateReasonRef.current = 'pagination';
|
|
126
|
-
var pageNumber = Number(page);
|
|
127
|
-
setFilterInfoState(function (previous) { return (__assign(__assign({}, previous), { offset: getOffsetFromPage_1.default(pageNumber, previous.pageSize), page: pageNumber, lastRefreshAt: new Date().getTime(), shouldRunImmediately: shouldRunImmediately })); });
|
|
128
|
-
}, []),
|
|
129
|
-
setPageSize: react_1.useCallback(function (pageSize, shouldRunImmediately) {
|
|
130
|
-
if (shouldRunImmediately === void 0) { shouldRunImmediately = false; }
|
|
131
|
-
updateReasonRef.current = 'pagination';
|
|
132
|
-
setFilterInfoState(function (previous) {
|
|
133
|
-
var pageSizeNumber = Number(pageSize);
|
|
134
|
-
var page = getPageFromOffset_1.default(previous.offset, pageSizeNumber);
|
|
135
|
-
var offset = getOffsetFromPage_1.default(page, pageSizeNumber);
|
|
136
|
-
return __assign(__assign({}, previous), { pageSize: pageSizeNumber, offset: offset, page: page, lastRefreshAt: new Date().getTime(), shouldRunImmediately: shouldRunImmediately });
|
|
137
|
-
});
|
|
138
|
-
}, []),
|
|
139
|
-
setSort: react_1.useCallback(function (sort, shouldRunImmediately) {
|
|
140
|
-
if (shouldRunImmediately === void 0) { shouldRunImmediately = false; }
|
|
141
|
-
updateReasonRef.current = 'filter';
|
|
142
|
-
setFilterInfoState(function (previous) { return (__assign(__assign({}, previous), { sort: sort, lastRefreshAt: new Date().getTime(), shouldRunImmediately: shouldRunImmediately })); });
|
|
143
|
-
}, []),
|
|
144
|
-
setCursor: react_1.useCallback(function (cursor, shouldRunImmediately) {
|
|
145
|
-
if (shouldRunImmediately === void 0) { shouldRunImmediately = false; }
|
|
146
|
-
updateReasonRef.current = 'pagination';
|
|
147
|
-
setFilterInfoState(function (previous) { return (__assign(__assign({}, previous), { cursor: cursor, lastRefreshAt: new Date().getTime(), shouldRunImmediately: shouldRunImmediately })); });
|
|
148
|
-
}, []),
|
|
149
|
-
forceRefresh: react_1.useCallback(function (shouldRunImmediately) {
|
|
150
|
-
if (shouldRunImmediately === void 0) { shouldRunImmediately = false; }
|
|
151
|
-
updateReasonRef.current = 'filter';
|
|
152
|
-
setFilterInfoState(function (previous) { return (__assign(__assign({}, previous), { lastRefreshAt: new Date().getTime(), shouldRunImmediately: shouldRunImmediately })); });
|
|
153
|
-
}, []),
|
|
154
|
-
};
|
|
155
|
-
return api;
|
|
156
|
-
}
|
|
157
|
-
function buildDefaultFilterInfo(filterInfo) {
|
|
158
|
-
if (filterInfo === void 0) { filterInfo = {}; }
|
|
159
|
-
var merged = __assign({
|
|
160
|
-
// Cast here to work around "'T' could be instantiated with an arbitrary
|
|
161
|
-
// type which could be unrelated to '{}'"
|
|
162
|
-
filter: {}, sort: undefined, pageSize: 20, lastRefreshAt: new Date().getTime(), offset: 0, page: 1, shouldRunImmediately: false }, filterInfo);
|
|
163
|
-
// If there's a page but no offset, set the offset.
|
|
164
|
-
if (filterInfo.page != null && filterInfo.offset == null) {
|
|
165
|
-
merged.offset = getOffsetFromPage_1.default(filterInfo.page, merged.pageSize);
|
|
166
|
-
// If there's an offset but no page, set the page.
|
|
167
|
-
}
|
|
168
|
-
else if (filterInfo.page == null && filterInfo.offset != null) {
|
|
169
|
-
merged.page = getPageFromOffset_1.default(filterInfo.offset, merged.pageSize);
|
|
170
|
-
}
|
|
171
|
-
return merged;
|
|
172
|
-
}
|
|
173
|
-
exports.default = useSimpleFilter;
|