@etsoo/react 1.7.94 → 1.7.95
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/README.md +2 -1
- package/__tests__/EventWatcher.tsx +21 -21
- package/__tests__/ReactUtils.ts +4 -4
- package/__tests__/tsconfig.json +17 -17
- package/babel.config.json +8 -8
- package/lib/app/CoreConstants.js +2 -2
- package/lib/app/EventWatcher.d.ts +1 -1
- package/lib/app/EventWatcher.js +3 -5
- package/lib/app/InputDialogProps.d.ts +2 -2
- package/lib/app/ReactUtils.d.ts +2 -2
- package/lib/app/ReactUtils.js +20 -19
- package/lib/components/DnDList.d.ts +3 -3
- package/lib/components/DnDList.js +4 -4
- package/lib/components/DynamicRouter.d.ts +2 -2
- package/lib/components/DynamicRouter.js +2 -2
- package/lib/components/GridColumn.d.ts +6 -6
- package/lib/components/GridColumn.js +7 -7
- package/lib/components/GridLoader.d.ts +4 -4
- package/lib/components/GridLoader.js +2 -2
- package/lib/components/GridMethodRef.d.ts +2 -2
- package/lib/components/ListItemReact.d.ts +2 -2
- package/lib/components/ScrollRestoration.js +3 -3
- package/lib/components/ScrollerGrid.d.ts +7 -12
- package/lib/components/ScrollerGrid.js +13 -17
- package/lib/components/ScrollerList.d.ts +6 -10
- package/lib/components/ScrollerList.js +15 -14
- package/lib/custom/CustomFieldReact.d.ts +1 -1
- package/lib/index.d.ts +32 -32
- package/lib/index.js +31 -31
- package/lib/notifier/Notifier.d.ts +5 -5
- package/lib/notifier/Notifier.js +7 -7
- package/lib/states/CultureState.d.ts +3 -3
- package/lib/states/CultureState.js +3 -3
- package/lib/states/IState.d.ts +2 -2
- package/lib/states/PageState.d.ts +2 -2
- package/lib/states/PageState.js +2 -3
- package/lib/states/State.d.ts +3 -3
- package/lib/states/State.js +2 -2
- package/lib/states/UserState.d.ts +2 -2
- package/lib/states/UserState.js +5 -5
- package/lib/uses/useAsyncState.d.ts +1 -1
- package/lib/uses/useAsyncState.js +1 -1
- package/lib/uses/useCombinedRefs.js +2 -2
- package/lib/uses/useDelayedExecutor.d.ts +1 -1
- package/lib/uses/useDelayedExecutor.js +2 -2
- package/lib/uses/useDimensions.d.ts +1 -1
- package/lib/uses/useDimensions.js +3 -3
- package/lib/uses/useParamsEx.d.ts +1 -1
- package/lib/uses/useParamsEx.js +2 -2
- package/lib/uses/useRefs.d.ts +2 -2
- package/lib/uses/useRefs.js +1 -1
- package/lib/uses/useSearchParamsEx.d.ts +1 -1
- package/lib/uses/useSearchParamsEx.js +3 -3
- package/lib/uses/useTimeout.js +2 -2
- package/lib/uses/useWindowScroll.js +3 -3
- package/lib/uses/useWindowSize.js +4 -5
- package/package.json +72 -74
- package/src/app/CoreConstants.ts +8 -8
- package/src/app/EventWatcher.ts +50 -52
- package/src/app/InputDialogProps.ts +16 -16
- package/src/app/ReactUtils.ts +206 -208
- package/src/components/DnDList.tsx +268 -283
- package/src/components/DynamicRouter.tsx +35 -35
- package/src/components/GridColumn.ts +201 -201
- package/src/components/GridLoader.ts +121 -121
- package/src/components/GridMethodRef.ts +26 -26
- package/src/components/ListItemReact.ts +2 -2
- package/src/components/ScrollRestoration.tsx +24 -24
- package/src/components/ScrollerGrid.tsx +428 -448
- package/src/components/ScrollerList.tsx +320 -332
- package/src/custom/CustomFieldReact.ts +12 -12
- package/src/index.ts +35 -35
- package/src/notifier/Notifier.ts +229 -240
- package/src/states/CultureState.ts +51 -52
- package/src/states/IState.ts +19 -19
- package/src/states/PageState.ts +63 -66
- package/src/states/State.tsx +47 -51
- package/src/states/UserState.ts +98 -98
- package/src/uses/useAsyncState.ts +37 -39
- package/src/uses/useCombinedRefs.ts +16 -16
- package/src/uses/useDelayedExecutor.ts +8 -8
- package/src/uses/useDimensions.ts +102 -103
- package/src/uses/useParamsEx.ts +6 -6
- package/src/uses/useRefs.ts +6 -6
- package/src/uses/useSearchParamsEx.ts +13 -13
- package/src/uses/useTimeout.ts +17 -17
- package/src/uses/useWindowScroll.ts +43 -43
- package/src/uses/useWindowSize.ts +46 -49
- package/tsconfig.json +17 -17
- package/.eslintignore +0 -3
- package/.eslintrc.json +0 -38
- package/.prettierignore +0 -5
- package/.prettierrc +0 -6
package/src/states/UserState.ts
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
import { IAction, IUser, IUserData, UserKey } from
|
|
2
|
-
import { Utils } from
|
|
3
|
-
import { IProviderProps, IUpdate } from
|
|
4
|
-
import { State } from
|
|
1
|
+
import { IAction, IUser, IUserData, UserKey } from "@etsoo/appscript";
|
|
2
|
+
import { Utils } from "@etsoo/shared";
|
|
3
|
+
import { IProviderProps, IUpdate } from "./IState";
|
|
4
|
+
import { State } from "./State";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* User action type
|
|
8
8
|
* Style like 'const enum' will remove definition of the enum and cause module errors
|
|
9
9
|
*/
|
|
10
10
|
export enum UserActionType {
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
// Login
|
|
12
|
+
Login = "LOGIN",
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
// Logout
|
|
15
|
+
Logout = "LOGOUT",
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
// Update
|
|
18
|
+
Update = "UPDATE",
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
// Unauthorized
|
|
21
|
+
Unauthorized = "UNAUTHORIZED"
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* User action to manage the user
|
|
26
26
|
*/
|
|
27
27
|
export interface UserAction<D extends IUser> extends IAction {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Action type
|
|
30
|
+
*/
|
|
31
|
+
type: UserActionType;
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
/**
|
|
34
|
+
* User data
|
|
35
|
+
*/
|
|
36
|
+
user?: IUserData;
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
/**
|
|
39
|
+
* User update callback
|
|
40
|
+
*/
|
|
41
|
+
update?: (state: D) => void;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
/**
|
|
@@ -55,83 +55,83 @@ export interface UserCalls<D extends IUser> extends IUpdate<D, UserAction<D>> {}
|
|
|
55
55
|
* User state
|
|
56
56
|
*/
|
|
57
57
|
export class UserState<D extends IUser> {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Context
|
|
60
|
+
*/
|
|
61
|
+
readonly context;
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
/**
|
|
64
|
+
* Provider
|
|
65
|
+
*/
|
|
66
|
+
readonly provider;
|
|
67
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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
68
|
+
/**
|
|
69
|
+
* Constructor
|
|
70
|
+
*/
|
|
71
|
+
constructor() {
|
|
72
|
+
const { context, provider } = State.create<
|
|
73
|
+
D,
|
|
74
|
+
UserAction<D>,
|
|
75
|
+
UserCalls<D>,
|
|
76
|
+
UserProviderProps<D>
|
|
77
|
+
>(
|
|
78
|
+
(state, action) => {
|
|
79
|
+
// User reducer
|
|
80
|
+
switch (action.type) {
|
|
81
|
+
case UserActionType.Login:
|
|
82
|
+
const lastChangedFields =
|
|
83
|
+
state.authorized && action.user
|
|
84
|
+
? this.getChangedFields(action.user, state)
|
|
85
|
+
: undefined;
|
|
86
|
+
return {
|
|
87
|
+
...action.user!,
|
|
88
|
+
authorized: true,
|
|
89
|
+
lastChangedFields
|
|
90
|
+
} as D;
|
|
91
|
+
case UserActionType.Logout:
|
|
92
|
+
return {
|
|
93
|
+
...state, // Keep other user data
|
|
94
|
+
lastChangedFields: undefined,
|
|
95
|
+
token: undefined, // Remove token
|
|
96
|
+
authorized: false // Flag as unauthorized
|
|
97
|
+
};
|
|
98
|
+
case UserActionType.Update:
|
|
99
|
+
if (action.update) {
|
|
100
|
+
var newState = { ...state };
|
|
101
|
+
action.update(newState);
|
|
102
|
+
newState.lastChangedFields = this.getChangedFields(
|
|
103
|
+
newState,
|
|
104
|
+
state
|
|
105
|
+
);
|
|
106
|
+
return newState;
|
|
107
|
+
}
|
|
108
|
+
return state;
|
|
109
|
+
case UserActionType.Unauthorized:
|
|
110
|
+
// Avoid multiple updates (For example, multiple API calls failed with 405)
|
|
111
|
+
if (state.authorized === false) return state;
|
|
112
112
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
113
|
+
return {
|
|
114
|
+
...state, // Keep other user data and token for refresh
|
|
115
|
+
lastChangedFields: undefined,
|
|
116
|
+
authorized: false // Flag as unauthorized
|
|
117
|
+
};
|
|
118
|
+
default:
|
|
119
|
+
return state;
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
{} as D,
|
|
123
|
+
{} as UserCalls<D>
|
|
124
|
+
);
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
126
|
+
this.context = context;
|
|
127
|
+
this.provider = provider;
|
|
128
|
+
}
|
|
129
129
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
130
|
+
private getChangedFields(input: object, init: object) {
|
|
131
|
+
return Utils.objectUpdated(input, init, [
|
|
132
|
+
"authorized",
|
|
133
|
+
"seconds",
|
|
134
|
+
"lastChangedFields"
|
|
135
|
+
]) as UserKey[];
|
|
136
|
+
}
|
|
137
137
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import React from
|
|
1
|
+
import React from "react";
|
|
2
2
|
|
|
3
3
|
export function useAsyncState<S = undefined>(): [
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
S | undefined,
|
|
5
|
+
(newState: React.SetStateAction<S | undefined>) => Promise<S | undefined>
|
|
6
6
|
];
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -11,7 +11,7 @@ export function useAsyncState<S = undefined>(): [
|
|
|
11
11
|
* @returns Current state and update action
|
|
12
12
|
*/
|
|
13
13
|
export function useAsyncState<S>(
|
|
14
|
-
|
|
14
|
+
initialState: S | (() => S)
|
|
15
15
|
): [S, (newState: React.SetStateAction<S>) => Promise<S>];
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -20,47 +20,45 @@ export function useAsyncState<S>(
|
|
|
20
20
|
* @returns Current state and update action
|
|
21
21
|
*/
|
|
22
22
|
export function useAsyncState<S>(
|
|
23
|
-
|
|
23
|
+
initialState?: S | (() => S)
|
|
24
24
|
): [
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
S | undefined,
|
|
26
|
+
(newState: React.SetStateAction<S | undefined>) => Promise<S | undefined>
|
|
27
27
|
] {
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
// State
|
|
29
|
+
const [state, setState] = React.useState(initialState);
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
(value: S | undefined | PromiseLike<S | undefined>) => void
|
|
35
|
-
>();
|
|
31
|
+
// Resolve sate
|
|
32
|
+
const resolveState =
|
|
33
|
+
React.useRef<(value: S | undefined | PromiseLike<S | undefined>) => void>();
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
// Is mounted or not
|
|
36
|
+
const isMounted = React.useRef(false);
|
|
37
|
+
React.useEffect(() => {
|
|
38
|
+
isMounted.current = true;
|
|
41
39
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
return () => {
|
|
41
|
+
isMounted.current = false;
|
|
42
|
+
};
|
|
43
|
+
}, []);
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
45
|
+
// When state update
|
|
46
|
+
React.useEffect(() => {
|
|
47
|
+
if (resolveState.current) {
|
|
48
|
+
resolveState.current(state);
|
|
49
|
+
}
|
|
50
|
+
}, [state]);
|
|
53
51
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
52
|
+
const setAsyncState = React.useCallback(
|
|
53
|
+
(newState: React.SetStateAction<S | undefined>) =>
|
|
54
|
+
new Promise<S | undefined>((resolve) => {
|
|
55
|
+
if (isMounted.current) {
|
|
56
|
+
resolveState.current = resolve;
|
|
57
|
+
setState(newState);
|
|
58
|
+
}
|
|
59
|
+
}),
|
|
60
|
+
[]
|
|
61
|
+
);
|
|
64
62
|
|
|
65
|
-
|
|
63
|
+
return [state, setAsyncState];
|
|
66
64
|
}
|
|
@@ -4,22 +4,22 @@
|
|
|
4
4
|
* @returns Callback
|
|
5
5
|
*/
|
|
6
6
|
export function useCombinedRefs<T>(...refs: (React.Ref<T> | undefined)[]) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
return (target: T | null) => {
|
|
8
|
+
// Ignore null reference
|
|
9
|
+
if (target == null) return;
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
// Update all refs
|
|
12
|
+
refs.forEach((ref) => {
|
|
13
|
+
// Null ref
|
|
14
|
+
if (!ref) return;
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
// Callback function
|
|
17
|
+
if (typeof ref === "function") {
|
|
18
|
+
ref(target);
|
|
19
|
+
} else {
|
|
20
|
+
// as any to update readonly property
|
|
21
|
+
Reflect.set(ref, "current", target);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
25
|
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { DelayedExecutorType, ExtendUtils } from
|
|
2
|
-
import React from
|
|
1
|
+
import { DelayedExecutorType, ExtendUtils } from "@etsoo/shared";
|
|
2
|
+
import React from "react";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Create delayed executor
|
|
6
6
|
*/
|
|
7
7
|
export function useDelayedExecutor<P extends any[]>(
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
func: (...args: P) => void,
|
|
9
|
+
delayMiliseconcs: number
|
|
10
10
|
) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
const ref = React.useRef<DelayedExecutorType<P>>();
|
|
12
|
+
if (ref.current == null)
|
|
13
|
+
ref.current = ExtendUtils.delayedExecutor(func, delayMiliseconcs);
|
|
14
|
+
return ref.current;
|
|
15
15
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { DomUtils } from
|
|
2
|
-
import React from
|
|
3
|
-
import { useDelayedExecutor } from
|
|
1
|
+
import { DomUtils } from "@etsoo/shared";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { useDelayedExecutor } from "./useDelayedExecutor";
|
|
4
4
|
|
|
5
5
|
interface states {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
count: number;
|
|
7
|
+
indices: number[];
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -15,109 +15,108 @@ interface states {
|
|
|
15
15
|
* @param equalCallback Equall callback
|
|
16
16
|
*/
|
|
17
17
|
export function useDimensions(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
elements: number,
|
|
19
|
+
updateCallback?: (target: Element, rect: DOMRect) => boolean | void,
|
|
20
|
+
miliseconds: number = 50,
|
|
21
|
+
equalCallback: (
|
|
22
|
+
d1?: DOMRect,
|
|
23
|
+
d2?: DOMRect
|
|
24
|
+
) => boolean = DomUtils.dimensionEqual
|
|
25
25
|
) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
// State
|
|
27
|
+
const [state, setState] = React.useState<states>({
|
|
28
|
+
count: 0,
|
|
29
|
+
indices: []
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Dimentions
|
|
33
|
+
const dimensions =
|
|
34
|
+
React.useRef<[React.RefCallback<Element>, Element?, DOMRect?][]>();
|
|
35
|
+
if (dimensions.current == null) {
|
|
36
|
+
// Init
|
|
37
|
+
const init: [React.RefCallback<Element>, Element?, DOMRect?][] = [];
|
|
38
|
+
for (let e = 0; e < elements; e++) {
|
|
39
|
+
init.push(
|
|
40
|
+
((index): [React.RefCallback<Element>] => {
|
|
41
|
+
return [
|
|
42
|
+
(instance) => {
|
|
43
|
+
if (instance != null) {
|
|
44
|
+
// Current element
|
|
45
|
+
const currentElement = init[index][1];
|
|
46
|
+
|
|
47
|
+
if (currentElement != null) {
|
|
48
|
+
// Same target, return
|
|
49
|
+
if (currentElement == instance) return;
|
|
50
|
+
|
|
51
|
+
// Cancel observation
|
|
52
|
+
resizeObserver.unobserve(currentElement);
|
|
53
|
+
}
|
|
31
54
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
React.useRef<[React.RefCallback<Element>, Element?, DOMRect?][]>();
|
|
35
|
-
if (dimensions.current == null) {
|
|
36
|
-
// Init
|
|
37
|
-
const init: [React.RefCallback<Element>, Element?, DOMRect?][] = [];
|
|
38
|
-
for (let e = 0; e < elements; e++) {
|
|
39
|
-
init.push(
|
|
40
|
-
((index): [React.RefCallback<Element>] => {
|
|
41
|
-
return [
|
|
42
|
-
(instance) => {
|
|
43
|
-
if (instance != null) {
|
|
44
|
-
// Current element
|
|
45
|
-
const currentElement = init[index][1];
|
|
46
|
-
|
|
47
|
-
if (currentElement != null) {
|
|
48
|
-
// Same target, return
|
|
49
|
-
if (currentElement == instance) return;
|
|
50
|
-
|
|
51
|
-
// Cancel observation
|
|
52
|
-
resizeObserver.unobserve(currentElement);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Update element
|
|
56
|
-
init[index][1] = instance;
|
|
57
|
-
|
|
58
|
-
// Start observe
|
|
59
|
-
resizeObserver.observe(instance);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
];
|
|
63
|
-
})(e)
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
dimensions.current = init;
|
|
67
|
-
}
|
|
55
|
+
// Update element
|
|
56
|
+
init[index][1] = instance;
|
|
68
57
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const resizeObserver = new ResizeObserver((entries) => {
|
|
73
|
-
// Update Rect
|
|
74
|
-
const indices: number[] = [];
|
|
75
|
-
const init = dimensions.current!;
|
|
76
|
-
|
|
77
|
-
entries.forEach((entry) => {
|
|
78
|
-
const index = init.findIndex((item) => item[1] === entry.target);
|
|
79
|
-
if (index !== -1) {
|
|
80
|
-
// Previous rect
|
|
81
|
-
const pre = init[index][2];
|
|
82
|
-
|
|
83
|
-
// New rect
|
|
84
|
-
const rect = entry.target.getBoundingClientRect();
|
|
85
|
-
|
|
86
|
-
// Check equal
|
|
87
|
-
if (!equalCallback(pre, rect)) {
|
|
88
|
-
// Update callback
|
|
89
|
-
if (updateCallback) {
|
|
90
|
-
// Return false means no further push
|
|
91
|
-
if (updateCallback(entry.target, rect) === false)
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Update rect
|
|
96
|
-
init[index][2] = rect;
|
|
97
|
-
|
|
98
|
-
// Push for update
|
|
99
|
-
indices.push(index);
|
|
100
|
-
}
|
|
58
|
+
// Start observe
|
|
59
|
+
resizeObserver.observe(instance);
|
|
60
|
+
}
|
|
101
61
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
62
|
+
];
|
|
63
|
+
})(e)
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
dimensions.current = init;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const delayed = useDelayedExecutor(setState, miliseconds);
|
|
70
|
+
|
|
71
|
+
// Observer
|
|
72
|
+
const resizeObserver = new ResizeObserver((entries) => {
|
|
73
|
+
// Update Rect
|
|
74
|
+
const indices: number[] = [];
|
|
75
|
+
const init = dimensions.current!;
|
|
76
|
+
|
|
77
|
+
entries.forEach((entry) => {
|
|
78
|
+
const index = init.findIndex((item) => item[1] === entry.target);
|
|
79
|
+
if (index !== -1) {
|
|
80
|
+
// Previous rect
|
|
81
|
+
const pre = init[index][2];
|
|
82
|
+
|
|
83
|
+
// New rect
|
|
84
|
+
const rect = entry.target.getBoundingClientRect();
|
|
85
|
+
|
|
86
|
+
// Check equal
|
|
87
|
+
if (!equalCallback(pre, rect)) {
|
|
88
|
+
// Update callback
|
|
89
|
+
if (updateCallback) {
|
|
90
|
+
// Return false means no further push
|
|
91
|
+
if (updateCallback(entry.target, rect) === false) return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Update rect
|
|
95
|
+
init[index][2] = rect;
|
|
96
|
+
|
|
97
|
+
// Push for update
|
|
98
|
+
indices.push(index);
|
|
109
99
|
}
|
|
100
|
+
}
|
|
110
101
|
});
|
|
111
102
|
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
return
|
|
103
|
+
// Update state
|
|
104
|
+
if (indices.length > 0) {
|
|
105
|
+
// Count only for unique update
|
|
106
|
+
const update = { count: state.count + 1, indices };
|
|
107
|
+
delayed.call(undefined, update);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// Layout ready
|
|
112
|
+
React.useEffect(() => {
|
|
113
|
+
return () => {
|
|
114
|
+
// Clear the observer
|
|
115
|
+
resizeObserver.disconnect();
|
|
116
|
+
delayed.clear();
|
|
117
|
+
};
|
|
118
|
+
}, []);
|
|
119
|
+
|
|
120
|
+
// Return
|
|
121
|
+
return { dimensions: dimensions.current, state };
|
|
123
122
|
}
|
package/src/uses/useParamsEx.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { DataTypes, DomUtils } from
|
|
2
|
-
import { useParams } from
|
|
1
|
+
import { DataTypes, DomUtils } from "@etsoo/shared";
|
|
2
|
+
import { useParams } from "react-router-dom";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Extended useParams of react-router-dom
|
|
6
6
|
* Provide exact type data
|
|
7
7
|
*/
|
|
8
8
|
export function useParamsEx<T extends DataTypes.BasicTemplate>(template: T) {
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
// Get parameters
|
|
10
|
+
const params = useParams<{ [K in keyof T]: string }>();
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
// Return
|
|
13
|
+
return DomUtils.dataAs(params, template, false);
|
|
14
14
|
}
|
package/src/uses/useRefs.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DataTypes } from
|
|
2
|
-
import React from
|
|
1
|
+
import { DataTypes } from "@etsoo/shared";
|
|
2
|
+
import React from "react";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Create multiple refs
|
|
@@ -7,9 +7,9 @@ import React from 'react';
|
|
|
7
7
|
* @returns Result
|
|
8
8
|
*/
|
|
9
9
|
export function useRefs<F extends ReadonlyArray<string>, T = HTMLInputElement>(
|
|
10
|
-
|
|
10
|
+
fields: F
|
|
11
11
|
): DataTypes.DI<F, React.MutableRefObject<T | null>> {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
const refs: Record<string, React.MutableRefObject<T | null>> = {};
|
|
13
|
+
fields.forEach((field) => (refs[field] = React.useRef<T>(null)));
|
|
14
|
+
return refs as any;
|
|
15
15
|
}
|