@etsoo/react 1.5.85 → 1.5.88
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/lib/components/GridLoader.d.ts +4 -0
- package/lib/components/ScrollerGrid.js +16 -3
- package/lib/components/ScrollerList.d.ts +7 -2
- package/lib/components/ScrollerList.js +19 -6
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/uses/useSearchParamsEx.d.ts +6 -0
- package/lib/uses/useSearchParamsEx.js +16 -0
- package/lib/uses/useWindowScroll.js +4 -4
- package/package.json +14 -14
- package/src/components/GridLoader.ts +5 -0
- package/src/components/ScrollerGrid.tsx +19 -3
- package/src/components/ScrollerList.tsx +42 -7
- package/src/index.ts +1 -0
- package/src/uses/useSearchParamsEx.ts +22 -0
- package/src/uses/useWindowScroll.ts +4 -4
|
@@ -24,7 +24,8 @@ export const ScrollerGrid = (props) => {
|
|
|
24
24
|
orderByAsc: defaultOrderByAsc,
|
|
25
25
|
batchSize: 10,
|
|
26
26
|
loadedItems: 0,
|
|
27
|
-
selectedItems: []
|
|
27
|
+
selectedItems: [],
|
|
28
|
+
idCache: {}
|
|
28
29
|
});
|
|
29
30
|
const state = refs.current;
|
|
30
31
|
const ref = React.useRef(null);
|
|
@@ -60,14 +61,26 @@ export const ScrollerGrid = (props) => {
|
|
|
60
61
|
.splice(rows.length - state.lastLoadedItems, state.lastLoadedItems)
|
|
61
62
|
.concat(result)
|
|
62
63
|
: result;
|
|
64
|
+
state.idCache = {};
|
|
65
|
+
for (const row of newRows) {
|
|
66
|
+
const id = row[idField];
|
|
67
|
+
state.idCache[id] = null;
|
|
68
|
+
}
|
|
63
69
|
// Update rows
|
|
64
70
|
setRows(newRows);
|
|
65
71
|
}
|
|
66
72
|
else {
|
|
67
73
|
// Set current page
|
|
68
74
|
state.currentPage = state.currentPage + pageAdd;
|
|
69
|
-
// Update rows
|
|
70
|
-
|
|
75
|
+
// Update rows, avoid duplicate items
|
|
76
|
+
const newRows = [...rows];
|
|
77
|
+
for (const item of result) {
|
|
78
|
+
const id = item[idField];
|
|
79
|
+
if (state.idCache[id] === undefined) {
|
|
80
|
+
newRows.push(item);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
setRows(newRows);
|
|
71
84
|
}
|
|
72
85
|
});
|
|
73
86
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DataTypes, IdDefaultType } from '@etsoo/shared';
|
|
1
2
|
import React from 'react';
|
|
2
3
|
import { Align, ListChildComponentProps, ListProps } from 'react-window';
|
|
3
4
|
import { GridLoader } from './GridLoader';
|
|
@@ -5,7 +6,7 @@ import { GridMethodRef } from './GridMethodRef';
|
|
|
5
6
|
/**
|
|
6
7
|
* Scroller vertical list props
|
|
7
8
|
*/
|
|
8
|
-
export interface ScrollerListProps<T extends object
|
|
9
|
+
export interface ScrollerListProps<T extends object, D extends DataTypes.Keys<T>> extends GridLoader<T>, Omit<ListProps<T>, 'ref' | 'outerRef' | 'height' | 'width' | 'children' | 'itemCount'> {
|
|
9
10
|
/**
|
|
10
11
|
* Default order by asc/desc
|
|
11
12
|
*/
|
|
@@ -26,6 +27,10 @@ export interface ScrollerListProps<T extends object> extends GridLoader<T>, Omit
|
|
|
26
27
|
* Width of the list
|
|
27
28
|
*/
|
|
28
29
|
width?: number | string;
|
|
30
|
+
/**
|
|
31
|
+
* Id field
|
|
32
|
+
*/
|
|
33
|
+
idField?: D;
|
|
29
34
|
/**
|
|
30
35
|
* Item renderer
|
|
31
36
|
*/
|
|
@@ -59,5 +64,5 @@ export interface ScrollerListForwardRef<T> extends GridMethodRef<T>, ScrollerLis
|
|
|
59
64
|
* @param props Props
|
|
60
65
|
* @returns Component
|
|
61
66
|
*/
|
|
62
|
-
export declare const ScrollerList: <T extends object>(props: ScrollerListProps<T>) => JSX.Element;
|
|
67
|
+
export declare const ScrollerList: <T extends object, D extends DataTypes.Keys<T, string | number> = IdDefaultType<T>>(props: ScrollerListProps<T, D>) => JSX.Element;
|
|
63
68
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Utils } from '@etsoo/shared';
|
|
1
|
+
import { DataTypes, Utils } from '@etsoo/shared';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { FixedSizeList, VariableSizeList } from 'react-window';
|
|
4
4
|
import { useCombinedRefs } from '../uses/useCombinedRefs';
|
|
@@ -15,7 +15,7 @@ const calculateBatchSize = (height, itemSize) => {
|
|
|
15
15
|
*/
|
|
16
16
|
export const ScrollerList = (props) => {
|
|
17
17
|
// Destruct
|
|
18
|
-
const { autoLoad = true, defaultOrderBy, defaultOrderByAsc, height = document.documentElement.clientHeight, width = '100%', mRef, oRef, style = {}, itemRenderer, itemSize, loadBatchSize = calculateBatchSize(height, itemSize), loadData, threshold = GridSizeGet(loadBatchSize, height) / 2, onItemsRendered, ...rest } = props;
|
|
18
|
+
const { autoLoad = true, defaultOrderBy, defaultOrderByAsc, height = document.documentElement.clientHeight, width = '100%', mRef, oRef, style = {}, idField = 'id', itemRenderer, itemSize, loadBatchSize = calculateBatchSize(height, itemSize), loadData, threshold = GridSizeGet(loadBatchSize, height) / 2, onItemsRendered, ...rest } = props;
|
|
19
19
|
// Style
|
|
20
20
|
Object.assign(style, {
|
|
21
21
|
width: '100%',
|
|
@@ -42,7 +42,8 @@ export const ScrollerList = (props) => {
|
|
|
42
42
|
orderBy: defaultOrderBy,
|
|
43
43
|
orderByAsc: defaultOrderByAsc,
|
|
44
44
|
batchSize: GridSizeGet(loadBatchSize, height),
|
|
45
|
-
selectedItems: []
|
|
45
|
+
selectedItems: [],
|
|
46
|
+
idCache: {}
|
|
46
47
|
});
|
|
47
48
|
const state = stateRefs.current;
|
|
48
49
|
// Load data
|
|
@@ -77,13 +78,25 @@ export const ScrollerList = (props) => {
|
|
|
77
78
|
.splice(rows.length - state.lastLoadedItems, state.lastLoadedItems)
|
|
78
79
|
.concat(result)
|
|
79
80
|
: result;
|
|
81
|
+
state.idCache = {};
|
|
82
|
+
for (const row of newRows) {
|
|
83
|
+
const id = row[idField];
|
|
84
|
+
state.idCache[id] = null;
|
|
85
|
+
}
|
|
80
86
|
// Update rows
|
|
81
87
|
setRows(newRows);
|
|
82
88
|
}
|
|
83
89
|
else {
|
|
84
90
|
state.currentPage = state.currentPage + pageAdd;
|
|
85
|
-
// Update rows
|
|
86
|
-
|
|
91
|
+
// Update rows, avoid duplicate items
|
|
92
|
+
const newRows = [...rows];
|
|
93
|
+
for (const item of result) {
|
|
94
|
+
const id = item[idField];
|
|
95
|
+
if (state.idCache[id] === undefined) {
|
|
96
|
+
newRows.push(item);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
setRows(newRows);
|
|
87
100
|
}
|
|
88
101
|
});
|
|
89
102
|
};
|
|
@@ -180,5 +193,5 @@ export const ScrollerList = (props) => {
|
|
|
180
193
|
if (state.currentPage === 0 && state.autoLoad)
|
|
181
194
|
loadDataLocal();
|
|
182
195
|
// Layout
|
|
183
|
-
return typeof itemSize === 'function' ? (React.createElement(VariableSizeList, { height: height, width: width, itemCount: itemCount, itemSize: itemSize, outerRef: refs, ref: listRef, style: style, onItemsRendered: onItemsRenderedLocal, ...rest }, itemRendererLocal)) : (React.createElement(FixedSizeList, { height: height, width: width, itemCount: itemCount, itemSize: itemSize, outerRef: refs, ref: listRef, style: style, onItemsRendered: onItemsRenderedLocal, ...rest }, itemRendererLocal));
|
|
196
|
+
return typeof itemSize === 'function' ? (React.createElement(VariableSizeList, { height: height, width: width, itemCount: itemCount, itemKey: (index, data) => { var _a; return (_a = DataTypes.getIdValue1(data, idField)) !== null && _a !== void 0 ? _a : index; }, itemSize: itemSize, outerRef: refs, ref: listRef, style: style, onItemsRendered: onItemsRenderedLocal, ...rest }, itemRendererLocal)) : (React.createElement(FixedSizeList, { height: height, width: width, itemCount: itemCount, itemKey: (index, data) => { var _a; return (_a = DataTypes.getIdValue1(data, idField)) !== null && _a !== void 0 ? _a : index; }, itemSize: itemSize, outerRef: refs, ref: listRef, style: style, onItemsRendered: onItemsRenderedLocal, ...rest }, itemRendererLocal));
|
|
184
197
|
};
|
package/lib/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export * from './uses/useCombinedRefs';
|
|
|
21
21
|
export * from './uses/useDelayedExecutor';
|
|
22
22
|
export * from './uses/useDimensions';
|
|
23
23
|
export * from './uses/useParamsEx';
|
|
24
|
+
export * from './uses/useSearchParamsEx';
|
|
24
25
|
export * from './uses/useTimeout';
|
|
25
26
|
export * from './uses/useWindowScroll';
|
|
26
27
|
export * from './uses/useWindowSize';
|
package/lib/index.js
CHANGED
|
@@ -26,6 +26,7 @@ export * from './uses/useCombinedRefs';
|
|
|
26
26
|
export * from './uses/useDelayedExecutor';
|
|
27
27
|
export * from './uses/useDimensions';
|
|
28
28
|
export * from './uses/useParamsEx';
|
|
29
|
+
export * from './uses/useSearchParamsEx';
|
|
29
30
|
export * from './uses/useTimeout';
|
|
30
31
|
export * from './uses/useWindowScroll';
|
|
31
32
|
export * from './uses/useWindowSize';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { DomUtils } from '@etsoo/shared';
|
|
2
|
+
import { useSearchParams } from 'react-router-dom';
|
|
3
|
+
/**
|
|
4
|
+
* Extended useSearchParams of react-router-dom
|
|
5
|
+
* Provide exact type data
|
|
6
|
+
*/
|
|
7
|
+
export function useSearchParamsEx(template) {
|
|
8
|
+
// Get parameters
|
|
9
|
+
const [sp] = useSearchParams();
|
|
10
|
+
const paras = Object.fromEntries(Object.keys(template).map((key) => {
|
|
11
|
+
const type = template[key];
|
|
12
|
+
return [key, type.endsWith('[]') ? sp.getAll(key) : sp.get(key)];
|
|
13
|
+
}));
|
|
14
|
+
// Return
|
|
15
|
+
return DomUtils.dataAs(paras, template, false);
|
|
16
|
+
}
|
|
@@ -6,8 +6,8 @@ import React from 'react';
|
|
|
6
6
|
export const useWindowScroll = () => {
|
|
7
7
|
// State
|
|
8
8
|
const [pos, setPos] = React.useState({
|
|
9
|
-
x: window.
|
|
10
|
-
y: window.
|
|
9
|
+
x: window.scrollX,
|
|
10
|
+
y: window.scrollY
|
|
11
11
|
});
|
|
12
12
|
React.useEffect(() => {
|
|
13
13
|
let ticking = false;
|
|
@@ -15,8 +15,8 @@ export const useWindowScroll = () => {
|
|
|
15
15
|
let requestAnimationFrameSeed = 0;
|
|
16
16
|
const scrollHandler = () => {
|
|
17
17
|
lastPos = {
|
|
18
|
-
x: window.
|
|
19
|
-
y: window.
|
|
18
|
+
x: window.scrollX,
|
|
19
|
+
y: window.scrollY
|
|
20
20
|
};
|
|
21
21
|
if (!ticking) {
|
|
22
22
|
requestAnimationFrameSeed = window.requestAnimationFrame(() => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/react",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.88",
|
|
4
4
|
"description": "TypeScript ReactJs UI Independent Framework",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -48,12 +48,12 @@
|
|
|
48
48
|
"@dnd-kit/core": "^6.0.5",
|
|
49
49
|
"@dnd-kit/sortable": "^7.0.1",
|
|
50
50
|
"@emotion/css": "^11.10.0",
|
|
51
|
-
"@emotion/react": "^11.10.
|
|
52
|
-
"@emotion/styled": "^11.10.
|
|
53
|
-
"@etsoo/appscript": "^1.2.
|
|
51
|
+
"@emotion/react": "^11.10.4",
|
|
52
|
+
"@emotion/styled": "^11.10.4",
|
|
53
|
+
"@etsoo/appscript": "^1.2.89",
|
|
54
54
|
"@etsoo/notificationbase": "^1.1.7",
|
|
55
|
-
"@etsoo/shared": "^1.1.
|
|
56
|
-
"@types/react": "^18.0.
|
|
55
|
+
"@etsoo/shared": "^1.1.52",
|
|
56
|
+
"@types/react": "^18.0.18",
|
|
57
57
|
"@types/react-dom": "^18.0.6",
|
|
58
58
|
"@types/react-window": "^1.8.5",
|
|
59
59
|
"react": "^18.2.0",
|
|
@@ -63,19 +63,19 @@
|
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@babel/cli": "^7.18.10",
|
|
66
|
-
"@babel/core": "^7.
|
|
66
|
+
"@babel/core": "^7.19.0",
|
|
67
67
|
"@babel/plugin-transform-runtime": "^7.18.10",
|
|
68
|
-
"@babel/preset-env": "^7.
|
|
69
|
-
"@babel/runtime-corejs3": "^7.
|
|
68
|
+
"@babel/preset-env": "^7.19.0",
|
|
69
|
+
"@babel/runtime-corejs3": "^7.19.0",
|
|
70
70
|
"@testing-library/jest-dom": "^5.16.5",
|
|
71
|
-
"@testing-library/react": "^13.
|
|
72
|
-
"@types/jest": "^
|
|
73
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
74
|
-
"@typescript-eslint/parser": "^5.
|
|
71
|
+
"@testing-library/react": "^13.4.0",
|
|
72
|
+
"@types/jest": "^29.0.0",
|
|
73
|
+
"@typescript-eslint/eslint-plugin": "^5.36.2",
|
|
74
|
+
"@typescript-eslint/parser": "^5.36.2",
|
|
75
75
|
"eslint": "^8.23.0",
|
|
76
76
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
77
77
|
"eslint-plugin-import": "^2.26.0",
|
|
78
|
-
"eslint-plugin-react": "^7.31.
|
|
78
|
+
"eslint-plugin-react": "^7.31.7",
|
|
79
79
|
"jest": "^28.1.3",
|
|
80
80
|
"jest-environment-jsdom": "^28.1.3",
|
|
81
81
|
"ts-jest": "^28.0.8",
|
|
@@ -190,7 +190,8 @@ export const ScrollerGrid = <
|
|
|
190
190
|
orderByAsc: defaultOrderByAsc,
|
|
191
191
|
batchSize: 10,
|
|
192
192
|
loadedItems: 0,
|
|
193
|
-
selectedItems: []
|
|
193
|
+
selectedItems: [],
|
|
194
|
+
idCache: {}
|
|
194
195
|
});
|
|
195
196
|
const state = refs.current;
|
|
196
197
|
|
|
@@ -237,14 +238,29 @@ export const ScrollerGrid = <
|
|
|
237
238
|
.concat(result)
|
|
238
239
|
: result;
|
|
239
240
|
|
|
241
|
+
state.idCache = {};
|
|
242
|
+
for (const row of newRows) {
|
|
243
|
+
const id = row[idField] as any;
|
|
244
|
+
state.idCache[id] = null;
|
|
245
|
+
}
|
|
246
|
+
|
|
240
247
|
// Update rows
|
|
241
248
|
setRows(newRows);
|
|
242
249
|
} else {
|
|
243
250
|
// Set current page
|
|
244
251
|
state.currentPage = state.currentPage + pageAdd;
|
|
245
252
|
|
|
246
|
-
// Update rows
|
|
247
|
-
|
|
253
|
+
// Update rows, avoid duplicate items
|
|
254
|
+
const newRows = [...rows];
|
|
255
|
+
|
|
256
|
+
for (const item of result) {
|
|
257
|
+
const id = item[idField] as any;
|
|
258
|
+
if (state.idCache[id] === undefined) {
|
|
259
|
+
newRows.push(item);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
setRows(newRows);
|
|
248
264
|
}
|
|
249
265
|
});
|
|
250
266
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Utils } from '@etsoo/shared';
|
|
1
|
+
import { DataTypes, IdDefaultType, Utils } from '@etsoo/shared';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import {
|
|
4
4
|
Align,
|
|
@@ -20,8 +20,10 @@ import { GridMethodRef } from './GridMethodRef';
|
|
|
20
20
|
/**
|
|
21
21
|
* Scroller vertical list props
|
|
22
22
|
*/
|
|
23
|
-
export interface ScrollerListProps<
|
|
24
|
-
extends
|
|
23
|
+
export interface ScrollerListProps<
|
|
24
|
+
T extends object,
|
|
25
|
+
D extends DataTypes.Keys<T>
|
|
26
|
+
> extends GridLoader<T>,
|
|
25
27
|
Omit<
|
|
26
28
|
ListProps<T>,
|
|
27
29
|
'ref' | 'outerRef' | 'height' | 'width' | 'children' | 'itemCount'
|
|
@@ -51,6 +53,11 @@ export interface ScrollerListProps<T extends object>
|
|
|
51
53
|
*/
|
|
52
54
|
width?: number | string;
|
|
53
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Id field
|
|
58
|
+
*/
|
|
59
|
+
idField?: D;
|
|
60
|
+
|
|
54
61
|
/**
|
|
55
62
|
* Item renderer
|
|
56
63
|
*/
|
|
@@ -100,7 +107,12 @@ const calculateBatchSize = (
|
|
|
100
107
|
* @param props Props
|
|
101
108
|
* @returns Component
|
|
102
109
|
*/
|
|
103
|
-
export const ScrollerList = <
|
|
110
|
+
export const ScrollerList = <
|
|
111
|
+
T extends object,
|
|
112
|
+
D extends DataTypes.Keys<T> = IdDefaultType<T>
|
|
113
|
+
>(
|
|
114
|
+
props: ScrollerListProps<T, D>
|
|
115
|
+
) => {
|
|
104
116
|
// Destruct
|
|
105
117
|
const {
|
|
106
118
|
autoLoad = true,
|
|
@@ -111,6 +123,7 @@ export const ScrollerList = <T extends object>(props: ScrollerListProps<T>) => {
|
|
|
111
123
|
mRef,
|
|
112
124
|
oRef,
|
|
113
125
|
style = {},
|
|
126
|
+
idField = 'id' as D,
|
|
114
127
|
itemRenderer,
|
|
115
128
|
itemSize,
|
|
116
129
|
loadBatchSize = calculateBatchSize(height, itemSize),
|
|
@@ -150,7 +163,8 @@ export const ScrollerList = <T extends object>(props: ScrollerListProps<T>) => {
|
|
|
150
163
|
orderBy: defaultOrderBy,
|
|
151
164
|
orderByAsc: defaultOrderByAsc,
|
|
152
165
|
batchSize: GridSizeGet(loadBatchSize, height),
|
|
153
|
-
selectedItems: []
|
|
166
|
+
selectedItems: [],
|
|
167
|
+
idCache: {}
|
|
154
168
|
});
|
|
155
169
|
const state = stateRefs.current;
|
|
156
170
|
|
|
@@ -195,13 +209,28 @@ export const ScrollerList = <T extends object>(props: ScrollerListProps<T>) => {
|
|
|
195
209
|
.concat(result)
|
|
196
210
|
: result;
|
|
197
211
|
|
|
212
|
+
state.idCache = {};
|
|
213
|
+
for (const row of newRows) {
|
|
214
|
+
const id = row[idField] as any;
|
|
215
|
+
state.idCache[id] = null;
|
|
216
|
+
}
|
|
217
|
+
|
|
198
218
|
// Update rows
|
|
199
219
|
setRows(newRows);
|
|
200
220
|
} else {
|
|
201
221
|
state.currentPage = state.currentPage + pageAdd;
|
|
202
222
|
|
|
203
|
-
// Update rows
|
|
204
|
-
|
|
223
|
+
// Update rows, avoid duplicate items
|
|
224
|
+
const newRows = [...rows];
|
|
225
|
+
|
|
226
|
+
for (const item of result) {
|
|
227
|
+
const id = item[idField] as any;
|
|
228
|
+
if (state.idCache[id] === undefined) {
|
|
229
|
+
newRows.push(item);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
setRows(newRows);
|
|
205
234
|
}
|
|
206
235
|
});
|
|
207
236
|
};
|
|
@@ -327,6 +356,9 @@ export const ScrollerList = <T extends object>(props: ScrollerListProps<T>) => {
|
|
|
327
356
|
height={height}
|
|
328
357
|
width={width}
|
|
329
358
|
itemCount={itemCount}
|
|
359
|
+
itemKey={(index, data) =>
|
|
360
|
+
DataTypes.getIdValue1(data, idField) ?? index
|
|
361
|
+
}
|
|
330
362
|
itemSize={itemSize}
|
|
331
363
|
outerRef={refs}
|
|
332
364
|
ref={listRef}
|
|
@@ -341,6 +373,9 @@ export const ScrollerList = <T extends object>(props: ScrollerListProps<T>) => {
|
|
|
341
373
|
height={height}
|
|
342
374
|
width={width}
|
|
343
375
|
itemCount={itemCount}
|
|
376
|
+
itemKey={(index, data) =>
|
|
377
|
+
DataTypes.getIdValue1(data, idField) ?? index
|
|
378
|
+
}
|
|
344
379
|
itemSize={itemSize}
|
|
345
380
|
outerRef={refs}
|
|
346
381
|
ref={listRef}
|
package/src/index.ts
CHANGED
|
@@ -30,6 +30,7 @@ export * from './uses/useCombinedRefs';
|
|
|
30
30
|
export * from './uses/useDelayedExecutor';
|
|
31
31
|
export * from './uses/useDimensions';
|
|
32
32
|
export * from './uses/useParamsEx';
|
|
33
|
+
export * from './uses/useSearchParamsEx';
|
|
33
34
|
export * from './uses/useTimeout';
|
|
34
35
|
export * from './uses/useWindowScroll';
|
|
35
36
|
export * from './uses/useWindowSize';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { DataTypes, DomUtils } from '@etsoo/shared';
|
|
2
|
+
import { useSearchParams } from 'react-router-dom';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Extended useSearchParams of react-router-dom
|
|
6
|
+
* Provide exact type data
|
|
7
|
+
*/
|
|
8
|
+
export function useSearchParamsEx<T extends DataTypes.BasicTemplate>(
|
|
9
|
+
template: T
|
|
10
|
+
) {
|
|
11
|
+
// Get parameters
|
|
12
|
+
const [sp] = useSearchParams();
|
|
13
|
+
const paras = Object.fromEntries(
|
|
14
|
+
Object.keys(template).map((key) => {
|
|
15
|
+
const type = template[key];
|
|
16
|
+
return [key, type.endsWith('[]') ? sp.getAll(key) : sp.get(key)];
|
|
17
|
+
})
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
// Return
|
|
21
|
+
return DomUtils.dataAs(paras, template, false);
|
|
22
|
+
}
|
|
@@ -12,8 +12,8 @@ interface IScrollPos {
|
|
|
12
12
|
export const useWindowScroll = () => {
|
|
13
13
|
// State
|
|
14
14
|
const [pos, setPos] = React.useState<IScrollPos>({
|
|
15
|
-
x: window.
|
|
16
|
-
y: window.
|
|
15
|
+
x: window.scrollX,
|
|
16
|
+
y: window.scrollY
|
|
17
17
|
});
|
|
18
18
|
|
|
19
19
|
React.useEffect(() => {
|
|
@@ -23,8 +23,8 @@ export const useWindowScroll = () => {
|
|
|
23
23
|
|
|
24
24
|
const scrollHandler = () => {
|
|
25
25
|
lastPos = {
|
|
26
|
-
x: window.
|
|
27
|
-
y: window.
|
|
26
|
+
x: window.scrollX,
|
|
27
|
+
y: window.scrollY
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
if (!ticking) {
|