@workos-inc/widgets 1.20.2-next.1792700156145 → 1.20.2
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 +4 -10
- package/dist/cjs/admin-portal-audit-log-streaming.client.cjs +2 -1
- package/dist/cjs/admin-portal-audit-log-streaming.client.cjs.map +1 -1
- package/dist/cjs/admin-portal-domain-verification.client.cjs +3 -2
- package/dist/cjs/admin-portal-domain-verification.client.cjs.map +1 -1
- package/dist/cjs/admin-portal-sso-connection.client.cjs +2 -1
- package/dist/cjs/admin-portal-sso-connection.client.cjs.map +1 -1
- package/dist/cjs/api/api-provider.cjs +23 -1
- package/dist/cjs/api/api-provider.cjs.map +1 -1
- package/dist/cjs/api/api-provider.d.cts.map +1 -1
- package/dist/cjs/api/claims.cjs.map +1 -1
- package/dist/cjs/api/claims.d.cts +2 -1
- package/dist/cjs/api/claims.d.cts.map +1 -1
- package/dist/cjs/api/client-graphql/client.cjs +3 -2
- package/dist/cjs/api/client-graphql/client.cjs.map +1 -1
- package/dist/cjs/api/client-graphql/hooks.cjs +3 -20
- package/dist/cjs/api/client-graphql/hooks.cjs.map +1 -1
- package/dist/cjs/api/client-graphql/hooks.d.cts +3 -12
- package/dist/cjs/api/client-graphql/hooks.d.cts.map +1 -1
- package/dist/cjs/api/client-graphql/query-keys.cjs +25 -0
- package/dist/cjs/api/client-graphql/query-keys.cjs.map +1 -0
- package/dist/cjs/api/client-graphql/query-keys.d.cts +16 -0
- package/dist/cjs/api/client-graphql/query-keys.d.cts.map +1 -0
- package/dist/cjs/components/copy-text.cjs +1 -1
- package/dist/cjs/components/copy-text.cjs.map +1 -1
- package/dist/cjs/components/form.cjs +9 -13
- package/dist/cjs/components/form.cjs.map +1 -1
- package/dist/cjs/components/form.d.cts.map +1 -1
- package/dist/cjs/components/otp-input.cjs +1 -0
- package/dist/cjs/components/otp-input.cjs.map +1 -1
- package/dist/cjs/directory-sync.client.cjs +2 -1
- package/dist/cjs/directory-sync.client.cjs.map +1 -1
- package/dist/cjs/lib/api/api-key.cjs +4 -3
- package/dist/cjs/lib/api/api-key.cjs.map +1 -1
- package/dist/cjs/lib/api/me.cjs +2 -1
- package/dist/cjs/lib/api/me.cjs.map +1 -1
- package/dist/cjs/lib/api/pipes.cjs +7 -6
- package/dist/cjs/lib/api/pipes.cjs.map +1 -1
- package/dist/cjs/lib/api/user-api-key.cjs +3 -2
- package/dist/cjs/lib/api/user-api-key.cjs.map +1 -1
- package/dist/cjs/lib/i18n/intl-context.cjs.map +1 -1
- package/dist/cjs/lib/i18n/intl-context.d.cts +1 -0
- package/dist/cjs/lib/i18n/intl-context.d.cts.map +1 -1
- package/dist/cjs/lib/i18n/use-translation.cjs +2 -2
- package/dist/cjs/lib/i18n/use-translation.cjs.map +1 -1
- package/dist/cjs/lib/use-composed-event-handlers.cjs +15 -0
- package/dist/cjs/lib/use-composed-event-handlers.cjs.map +1 -0
- package/dist/cjs/lib/use-composed-event-handlers.d.cts +6 -0
- package/dist/cjs/lib/use-composed-event-handlers.d.cts.map +1 -0
- package/dist/cjs/lib/use-debounce.cjs +124 -116
- package/dist/cjs/lib/use-debounce.cjs.map +1 -1
- package/dist/cjs/lib/use-debounce.d.cts +53 -48
- package/dist/cjs/lib/use-debounce.d.cts.map +1 -1
- package/dist/cjs/lib/use-widgets-invalidator.cjs +3 -3
- package/dist/cjs/lib/use-widgets-invalidator.cjs.map +1 -1
- package/dist/cjs/lib/use-widgets-invalidator.d.cts.map +1 -1
- package/dist/cjs/lib/utils.cjs +0 -7
- package/dist/cjs/lib/utils.cjs.map +1 -1
- package/dist/cjs/lib/utils.d.cts +0 -3
- package/dist/cjs/lib/utils.d.cts.map +1 -1
- package/dist/cjs/organization-switcher.client.cjs +2 -1
- package/dist/cjs/organization-switcher.client.cjs.map +1 -1
- package/dist/cjs/pipes-admin.client.cjs +2 -1
- package/dist/cjs/pipes-admin.client.cjs.map +1 -1
- package/dist/cjs/pipes.client.cjs +2 -1
- package/dist/cjs/pipes.client.cjs.map +1 -1
- package/dist/cjs/user-security.client.cjs +2 -1
- package/dist/cjs/user-security.client.cjs.map +1 -1
- package/dist/cjs/user-sessions.client.cjs +2 -1
- package/dist/cjs/user-sessions.client.cjs.map +1 -1
- package/dist/cjs/widgets/api-keys/api-keys-search.cjs +1 -1
- package/dist/cjs/widgets/api-keys/api-keys-search.cjs.map +1 -1
- package/dist/cjs/widgets/api-keys/user-api-keys-search.cjs +1 -1
- package/dist/cjs/widgets/api-keys/user-api-keys-search.cjs.map +1 -1
- package/dist/cjs/widgets/organization-switcher/organization-switcher.cjs +19 -5
- package/dist/cjs/widgets/organization-switcher/organization-switcher.cjs.map +1 -1
- package/dist/cjs/widgets/organization-switcher/organization-switcher.d.cts +2 -1
- package/dist/cjs/widgets/organization-switcher/organization-switcher.d.cts.map +1 -1
- package/dist/cjs/widgets/pipes/pipes.cjs +3 -2
- package/dist/cjs/widgets/pipes/pipes.cjs.map +1 -1
- package/dist/cjs/widgets/user-sessions/logout-all-sessions-dialog.cjs +2 -1
- package/dist/cjs/widgets/user-sessions/logout-all-sessions-dialog.cjs.map +1 -1
- package/dist/cjs/widgets/user-sessions/logout-dialog.cjs +2 -1
- package/dist/cjs/widgets/user-sessions/logout-dialog.cjs.map +1 -1
- package/dist/cjs/widgets/users-management/invite-user-dialog.cjs +5 -6
- package/dist/cjs/widgets/users-management/invite-user-dialog.cjs.map +1 -1
- package/dist/cjs/widgets/users-management/users-management-utils.cjs +4 -3
- package/dist/cjs/widgets/users-management/users-management-utils.cjs.map +1 -1
- package/dist/cjs/widgets/users-management/users-management.cjs.map +1 -1
- package/dist/cjs/widgets/users-management/users-search.cjs +1 -1
- package/dist/cjs/widgets/users-management/users-search.cjs.map +1 -1
- package/dist/esm/admin-portal-audit-log-streaming.client.js +2 -1
- package/dist/esm/admin-portal-audit-log-streaming.client.js.map +1 -1
- package/dist/esm/admin-portal-domain-verification.client.js +2 -1
- package/dist/esm/admin-portal-domain-verification.client.js.map +1 -1
- package/dist/esm/admin-portal-sso-connection.client.js +2 -1
- package/dist/esm/admin-portal-sso-connection.client.js.map +1 -1
- package/dist/esm/api/api-provider.d.ts.map +1 -1
- package/dist/esm/api/api-provider.js +23 -1
- package/dist/esm/api/api-provider.js.map +1 -1
- package/dist/esm/api/claims.d.ts +2 -1
- package/dist/esm/api/claims.d.ts.map +1 -1
- package/dist/esm/api/claims.js.map +1 -1
- package/dist/esm/api/client-graphql/client.js +3 -2
- package/dist/esm/api/client-graphql/client.js.map +1 -1
- package/dist/esm/api/client-graphql/hooks.d.ts +3 -12
- package/dist/esm/api/client-graphql/hooks.d.ts.map +1 -1
- package/dist/esm/api/client-graphql/hooks.js +1 -18
- package/dist/esm/api/client-graphql/hooks.js.map +1 -1
- package/dist/esm/api/client-graphql/query-keys.d.ts +16 -0
- package/dist/esm/api/client-graphql/query-keys.d.ts.map +1 -0
- package/dist/esm/api/client-graphql/query-keys.js +23 -0
- package/dist/esm/api/client-graphql/query-keys.js.map +1 -0
- package/dist/esm/components/copy-text.js +1 -1
- package/dist/esm/components/copy-text.js.map +1 -1
- package/dist/esm/components/form.d.ts.map +1 -1
- package/dist/esm/components/form.js +9 -13
- package/dist/esm/components/form.js.map +1 -1
- package/dist/esm/components/otp-input.js +1 -0
- package/dist/esm/components/otp-input.js.map +1 -1
- package/dist/esm/directory-sync.client.js +2 -1
- package/dist/esm/directory-sync.client.js.map +1 -1
- package/dist/esm/lib/api/api-key.js +2 -1
- package/dist/esm/lib/api/api-key.js.map +1 -1
- package/dist/esm/lib/api/me.js +2 -1
- package/dist/esm/lib/api/me.js.map +1 -1
- package/dist/esm/lib/api/pipes.js +2 -1
- package/dist/esm/lib/api/pipes.js.map +1 -1
- package/dist/esm/lib/api/user-api-key.js +2 -1
- package/dist/esm/lib/api/user-api-key.js.map +1 -1
- package/dist/esm/lib/i18n/intl-context.d.ts +1 -0
- package/dist/esm/lib/i18n/intl-context.d.ts.map +1 -1
- package/dist/esm/lib/i18n/intl-context.js.map +1 -1
- package/dist/esm/lib/i18n/use-translation.js +2 -2
- package/dist/esm/lib/i18n/use-translation.js.map +1 -1
- package/dist/esm/lib/use-composed-event-handlers.d.ts +6 -0
- package/dist/esm/lib/use-composed-event-handlers.d.ts.map +1 -0
- package/dist/esm/lib/use-composed-event-handlers.js +12 -0
- package/dist/esm/lib/use-composed-event-handlers.js.map +1 -0
- package/dist/esm/lib/use-debounce.d.ts +53 -48
- package/dist/esm/lib/use-debounce.d.ts.map +1 -1
- package/dist/esm/lib/use-debounce.js +124 -116
- package/dist/esm/lib/use-debounce.js.map +1 -1
- package/dist/esm/lib/use-widgets-invalidator.d.ts.map +1 -1
- package/dist/esm/lib/use-widgets-invalidator.js +2 -2
- package/dist/esm/lib/use-widgets-invalidator.js.map +1 -1
- package/dist/esm/lib/utils.d.ts +0 -3
- package/dist/esm/lib/utils.d.ts.map +1 -1
- package/dist/esm/lib/utils.js +1 -7
- package/dist/esm/lib/utils.js.map +1 -1
- package/dist/esm/organization-switcher.client.js +2 -1
- package/dist/esm/organization-switcher.client.js.map +1 -1
- package/dist/esm/pipes-admin.client.js +2 -1
- package/dist/esm/pipes-admin.client.js.map +1 -1
- package/dist/esm/pipes.client.js +2 -1
- package/dist/esm/pipes.client.js.map +1 -1
- package/dist/esm/user-security.client.js +2 -1
- package/dist/esm/user-security.client.js.map +1 -1
- package/dist/esm/user-sessions.client.js +2 -1
- package/dist/esm/user-sessions.client.js.map +1 -1
- package/dist/esm/widgets/api-keys/api-keys-search.js +1 -1
- package/dist/esm/widgets/api-keys/api-keys-search.js.map +1 -1
- package/dist/esm/widgets/api-keys/user-api-keys-search.js +1 -1
- package/dist/esm/widgets/api-keys/user-api-keys-search.js.map +1 -1
- package/dist/esm/widgets/organization-switcher/organization-switcher.d.ts +2 -1
- package/dist/esm/widgets/organization-switcher/organization-switcher.d.ts.map +1 -1
- package/dist/esm/widgets/organization-switcher/organization-switcher.js +19 -5
- package/dist/esm/widgets/organization-switcher/organization-switcher.js.map +1 -1
- package/dist/esm/widgets/pipes/pipes.js +2 -1
- package/dist/esm/widgets/pipes/pipes.js.map +1 -1
- package/dist/esm/widgets/user-sessions/logout-all-sessions-dialog.js +2 -1
- package/dist/esm/widgets/user-sessions/logout-all-sessions-dialog.js.map +1 -1
- package/dist/esm/widgets/user-sessions/logout-dialog.js +2 -1
- package/dist/esm/widgets/user-sessions/logout-dialog.js.map +1 -1
- package/dist/esm/widgets/users-management/invite-user-dialog.js +5 -6
- package/dist/esm/widgets/users-management/invite-user-dialog.js.map +1 -1
- package/dist/esm/widgets/users-management/users-management-utils.js +2 -1
- package/dist/esm/widgets/users-management/users-management-utils.js.map +1 -1
- package/dist/esm/widgets/users-management/users-management.js.map +1 -1
- package/dist/esm/widgets/users-management/users-search.js +1 -1
- package/dist/esm/widgets/users-management/users-search.js.map +1 -1
- package/package.json +1 -1
- package/src/api/api-provider.tsx +39 -1
- package/src/api/claims.ts +2 -1
- package/src/api/client-graphql/client.ts +8 -2
- package/src/api/client-graphql/hooks.ts +8 -27
- package/src/api/client-graphql/query-keys.ts +29 -0
- package/src/components/copy-text.tsx +1 -1
- package/src/components/form.tsx +33 -29
- package/src/components/otp-input.tsx +2 -0
- package/src/lib/i18n/intl-context.tsx +4 -0
- package/src/lib/i18n/use-translation.ts +1 -4
- package/src/lib/use-composed-event-handlers.ts +25 -0
- package/src/lib/use-debounce.ts +289 -237
- package/src/lib/use-widgets-invalidator.ts +0 -4
- package/src/lib/utils.ts +0 -12
- package/src/widgets/api-keys/api-keys-search.tsx +6 -3
- package/src/widgets/api-keys/user-api-keys-search.tsx +6 -3
- package/src/widgets/organization-switcher/organization-switcher.tsx +32 -8
- package/src/widgets/users-management/invite-user-dialog.tsx +9 -11
- package/src/widgets/users-management/users-management.tsx +1 -1
- package/src/widgets/users-management/users-search.tsx +6 -3
package/src/lib/use-debounce.ts
CHANGED
|
@@ -1,8 +1,55 @@
|
|
|
1
1
|
// Fork of https://github.com/xnimorz/use-debounce
|
|
2
2
|
// MIT License, Copyright (c) 2018 Nikita Mostovoy
|
|
3
3
|
import * as React from "react";
|
|
4
|
+
import { useLayoutEffect } from "./use-layout-effect.js";
|
|
4
5
|
import { canUseDOM } from "./utils.js";
|
|
5
6
|
|
|
7
|
+
interface Options {
|
|
8
|
+
/**
|
|
9
|
+
* The number of milliseconds to delay. if omitted, invocation is deferred to
|
|
10
|
+
* the next animation frame (or the next tick where that's unavailable).
|
|
11
|
+
*/
|
|
12
|
+
wait?: number;
|
|
13
|
+
/**
|
|
14
|
+
* Controls if the function should be invoked on the leading edge of the
|
|
15
|
+
* timeout.
|
|
16
|
+
* @default false
|
|
17
|
+
*/
|
|
18
|
+
leading?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Controls if the function should be invoked on the trailing edge of the
|
|
21
|
+
* timeout.
|
|
22
|
+
* @default true
|
|
23
|
+
*/
|
|
24
|
+
trailing?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Controls if the function should be invoked when the React component
|
|
27
|
+
* unmounts or the page is closed. This is usually desirable whenever `func`
|
|
28
|
+
* has persistent side-effects such as persists data.
|
|
29
|
+
*
|
|
30
|
+
* NOTE: If the callback calls `fetch()`, you usually also want to specify the
|
|
31
|
+
* `keepalive=true` option for `fetch()` so it can finish in the background
|
|
32
|
+
* after the page is closed.
|
|
33
|
+
*
|
|
34
|
+
* This option has no effect if `trailing == false`.
|
|
35
|
+
*
|
|
36
|
+
* @default false
|
|
37
|
+
*/
|
|
38
|
+
flushOnExit?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* The maximum time the given function is allowed to be delayed before it's
|
|
41
|
+
* invoked. Pass `null` and the maximum wait time is equal to the `wait` time.
|
|
42
|
+
*/
|
|
43
|
+
maxWait?: number | null;
|
|
44
|
+
/**
|
|
45
|
+
* If the setting is set to true, all debouncing and timers will happen on the
|
|
46
|
+
* server side as well.
|
|
47
|
+
*
|
|
48
|
+
* @default false
|
|
49
|
+
*/
|
|
50
|
+
debounceOnServer?: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
6
53
|
/**
|
|
7
54
|
* Creates a debounced function that delays invoking `func` until after `wait`
|
|
8
55
|
* milliseconds have elapsed since the last time the debounced function was
|
|
@@ -33,34 +80,25 @@ import { canUseDOM } from "./utils.js";
|
|
|
33
80
|
* article](https://css-tricks.com/debouncing-throttling-explained-examples/)
|
|
34
81
|
* for details over the differences between `debounce` and `throttle`.
|
|
35
82
|
*
|
|
36
|
-
* @
|
|
37
|
-
* @param
|
|
38
|
-
* @
|
|
39
|
-
* `requestAnimationFrame` is used (if available, otherwise it will be
|
|
40
|
-
* setTimeout(...,0)).
|
|
41
|
-
* @param {Object} [options={}] The options object. Controls if `func` should be
|
|
42
|
-
* invoked on the leading edge of the timeout.
|
|
43
|
-
* @param {boolean} [options.leading=false] The maximum time `func` is allowed
|
|
44
|
-
* to be delayed before it's invoked.
|
|
45
|
-
* @param {number} [options.maxWait] Controls if `func` should be invoked the
|
|
46
|
-
* trailing edge of the timeout.
|
|
47
|
-
* @param {boolean} [options.trailing=true]
|
|
48
|
-
* @returns {Function} Returns the new debounced function.
|
|
83
|
+
* @param func The function to debounce
|
|
84
|
+
* @param options The options object
|
|
85
|
+
* @returns Returns the new debounced function.
|
|
49
86
|
* @example
|
|
50
87
|
* ```tsx
|
|
51
88
|
* // Avoid costly calculations while the window size is in flux.
|
|
52
|
-
* const resizeHandler = useDebouncedCallback(calculateLayout, 150);
|
|
89
|
+
* const resizeHandler = useDebouncedCallback(calculateLayout, { wait: 150 });
|
|
53
90
|
* window.addEventListener('resize', resizeHandler)
|
|
54
91
|
*
|
|
55
92
|
* // Invoke `sendMail` when clicked, debouncing subsequent calls.
|
|
56
|
-
* const clickHandler = useDebouncedCallback(sendMail,
|
|
93
|
+
* const clickHandler = useDebouncedCallback(sendMail, {
|
|
94
|
+
* wait: 300,
|
|
57
95
|
* leading: true,
|
|
58
96
|
* trailing: false,
|
|
59
97
|
* })
|
|
60
98
|
* <button onClick={clickHandler}>click me</button>
|
|
61
99
|
*
|
|
62
100
|
* // Ensure `batchLog` is invoked once after 1 second of debounced calls.
|
|
63
|
-
* const debounced = useDebouncedCallback(batchLog, 250,
|
|
101
|
+
* const debounced = useDebouncedCallback(batchLog, { wait: 250, maxWait: 1000 })
|
|
64
102
|
* const source = new EventSource('/stream')
|
|
65
103
|
* source.addEventListener('message', debounced)
|
|
66
104
|
*
|
|
@@ -72,258 +110,272 @@ import { canUseDOM } from "./utils.js";
|
|
|
72
110
|
* ```
|
|
73
111
|
*/
|
|
74
112
|
function useDebouncedCallback<T extends (...args: any) => ReturnType<T>>(
|
|
75
|
-
this: unknown,
|
|
76
113
|
func: T,
|
|
77
|
-
|
|
78
|
-
options?: Options,
|
|
114
|
+
options: Options = {},
|
|
79
115
|
): DebouncedState<T> {
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
const debouncedRef = React.useRef<DebouncedState<T>>(undefined);
|
|
90
|
-
// Always keep the latest version of debounce callback, with no wait time.
|
|
91
|
-
// TODO: Fix this!
|
|
92
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
93
|
-
funcRef.current = func;
|
|
94
|
-
|
|
95
|
-
// Bypass `requestAnimationFrame` by explicitly setting `wait=0`.
|
|
96
|
-
const useRAF = !wait && wait !== 0 && canUseDOM;
|
|
97
|
-
|
|
98
|
-
if (typeof func !== "function") {
|
|
99
|
-
throw new TypeError("Expected a function");
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
wait = +(wait || 0);
|
|
103
|
-
options = options || {};
|
|
104
|
-
|
|
105
|
-
const leading = !!options.leading;
|
|
106
|
-
const trailing = "trailing" in options ? !!options.trailing : true; // `true` by default
|
|
116
|
+
const {
|
|
117
|
+
wait = 0,
|
|
118
|
+
leading = false,
|
|
119
|
+
trailing = true,
|
|
120
|
+
maxWait: maxWaitOption,
|
|
121
|
+
debounceOnServer = false,
|
|
122
|
+
} = options;
|
|
123
|
+
// Bypass `requestAnimationFrame` by explicitly setting `wait: 0`.
|
|
124
|
+
const useRAF = options.wait === undefined && canUseDOM;
|
|
107
125
|
const flushOnExit = !!options.flushOnExit && trailing;
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const
|
|
126
|
+
const maxWait =
|
|
127
|
+
maxWaitOption === undefined ? null : Math.max(maxWaitOption ?? 0, wait);
|
|
128
|
+
|
|
129
|
+
const stateRef = React.useRef<DebounceState<T>>({
|
|
130
|
+
func,
|
|
131
|
+
lastCallTime: null,
|
|
132
|
+
lastInvokeTime: 0,
|
|
133
|
+
timerId: null,
|
|
134
|
+
lastArgs: null,
|
|
135
|
+
lastThis: undefined,
|
|
136
|
+
result: undefined,
|
|
137
|
+
mounted: true,
|
|
138
|
+
visibilityListener: null,
|
|
139
|
+
debounced: undefined,
|
|
140
|
+
});
|
|
112
141
|
|
|
113
|
-
// You may have a question, why we have so many code under the useMemo definition.
|
|
114
|
-
//
|
|
115
|
-
// This was made as we want to escape from useCallback hell and
|
|
116
|
-
// not to initialize a number of functions each time useDebouncedCallback is called.
|
|
117
|
-
//
|
|
118
|
-
// It means that we have less garbage for our GC calls which improves performance.
|
|
119
|
-
// Also, it makes this library smaller.
|
|
120
|
-
//
|
|
121
|
-
// And the last reason, that the code without lots of useCallback with deps is easier to read.
|
|
122
|
-
// You have only one place for that.
|
|
123
142
|
const debounced = React.useMemo(() => {
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
143
|
+
const config: DebounceConfig = {
|
|
144
|
+
wait,
|
|
145
|
+
maxWait,
|
|
146
|
+
leading,
|
|
147
|
+
trailing,
|
|
148
|
+
flushOnExit,
|
|
149
|
+
useRAF,
|
|
150
|
+
debounceOnServer,
|
|
131
151
|
};
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
timerId.current = useRAF
|
|
138
|
-
? requestAnimationFrame(pendingFunc)
|
|
139
|
-
: (setTimeout(pendingFunc, wait) as unknown as number);
|
|
152
|
+
const debounced: DebouncedState<T> = function (
|
|
153
|
+
this: unknown,
|
|
154
|
+
...args: Parameters<T>
|
|
155
|
+
) {
|
|
156
|
+
return debounce(stateRef.current, config, this, args);
|
|
140
157
|
};
|
|
158
|
+
debounced.cancel = () => cancel(stateRef.current, config);
|
|
159
|
+
debounced.isPending = () => !!stateRef.current.timerId;
|
|
160
|
+
debounced.flush = () => flush(stateRef.current, config);
|
|
161
|
+
return debounced;
|
|
162
|
+
}, [wait, maxWait, leading, trailing, flushOnExit, useRAF, debounceOnServer]);
|
|
141
163
|
|
|
142
|
-
|
|
143
|
-
|
|
164
|
+
useLayoutEffect(() => {
|
|
165
|
+
stateRef.current.func = func;
|
|
166
|
+
stateRef.current.debounced = debounced;
|
|
167
|
+
});
|
|
144
168
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
169
|
+
React.useEffect(() => {
|
|
170
|
+
const state = stateRef.current;
|
|
171
|
+
state.mounted = true;
|
|
172
|
+
return () => {
|
|
173
|
+
if (flushOnExit) {
|
|
174
|
+
state.debounced?.flush();
|
|
175
|
+
}
|
|
176
|
+
if (state.visibilityListener) {
|
|
177
|
+
globalThis.document?.removeEventListener?.(
|
|
178
|
+
"visibilitychange",
|
|
179
|
+
state.visibilityListener,
|
|
180
|
+
);
|
|
181
|
+
state.visibilityListener = null;
|
|
182
|
+
}
|
|
183
|
+
state.mounted = false;
|
|
157
184
|
};
|
|
185
|
+
}, [flushOnExit]);
|
|
158
186
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
// Only invoke if we have `lastArgs` which means `func` has been
|
|
163
|
-
// debounced at least once.
|
|
164
|
-
if (trailing && lastArgs.current) {
|
|
165
|
-
return invokeFunc(time);
|
|
166
|
-
}
|
|
187
|
+
return debounced;
|
|
188
|
+
}
|
|
167
189
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
190
|
+
/**
|
|
191
|
+
* Mutable timer state for a hook instance. It outlives any single debounced
|
|
192
|
+
* function, so changing options doesn't drop pending invocations.
|
|
193
|
+
*/
|
|
194
|
+
interface DebounceState<T extends (...args: any) => ReturnType<T>> {
|
|
195
|
+
func: T;
|
|
196
|
+
lastCallTime: number | null;
|
|
197
|
+
lastInvokeTime: number;
|
|
198
|
+
timerId: number | null;
|
|
199
|
+
lastArgs: Parameters<T> | null;
|
|
200
|
+
lastThis: unknown;
|
|
201
|
+
result: ReturnType<T> | undefined;
|
|
202
|
+
mounted: boolean;
|
|
203
|
+
visibilityListener: VoidFunction | null;
|
|
204
|
+
debounced: DebouncedState<T> | undefined;
|
|
205
|
+
}
|
|
171
206
|
|
|
172
|
-
|
|
173
|
-
|
|
207
|
+
interface DebounceConfig {
|
|
208
|
+
wait: number;
|
|
209
|
+
maxWait: number | null;
|
|
210
|
+
leading: boolean;
|
|
211
|
+
trailing: boolean;
|
|
212
|
+
flushOnExit: boolean;
|
|
213
|
+
useRAF: boolean;
|
|
214
|
+
debounceOnServer: boolean;
|
|
215
|
+
}
|
|
174
216
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const timeSinceLastCall = time - (lastCallTime.current || 0);
|
|
184
|
-
const timeSinceLastInvoke = time - lastInvokeTime.current;
|
|
185
|
-
const timeWaiting = wait - timeSinceLastCall;
|
|
186
|
-
const remainingWait = maxing
|
|
187
|
-
? Math.min(timeWaiting, (maxWait || 0) - timeSinceLastInvoke)
|
|
188
|
-
: timeWaiting;
|
|
217
|
+
function invokeFunc<T extends (...args: any) => ReturnType<T>>(
|
|
218
|
+
state: DebounceState<T>,
|
|
219
|
+
time: number,
|
|
220
|
+
) {
|
|
221
|
+
const args = state.lastArgs;
|
|
222
|
+
const thisArg = state.lastThis;
|
|
223
|
+
state.lastArgs = state.lastThis = null;
|
|
224
|
+
state.lastInvokeTime = time;
|
|
189
225
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
};
|
|
226
|
+
return (state.result = state.func.apply(thisArg, args || []));
|
|
227
|
+
}
|
|
193
228
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
229
|
+
function startTimer<T extends (...args: any) => ReturnType<T>>(
|
|
230
|
+
state: DebounceState<T>,
|
|
231
|
+
config: DebounceConfig,
|
|
232
|
+
wait: number,
|
|
233
|
+
) {
|
|
234
|
+
const onTimer = () => timerExpired(state, config);
|
|
235
|
+
if (config.useRAF) {
|
|
236
|
+
cancelAnimationFrame(state.timerId!);
|
|
237
|
+
}
|
|
238
|
+
state.timerId = config.useRAF
|
|
239
|
+
? requestAnimationFrame(onTimer)
|
|
240
|
+
: (setTimeout(onTimer, wait) as unknown as number);
|
|
241
|
+
}
|
|
199
242
|
|
|
200
|
-
|
|
201
|
-
|
|
243
|
+
function shouldInvoke<T extends (...args: any) => ReturnType<T>>(
|
|
244
|
+
state: DebounceState<T>,
|
|
245
|
+
{ wait, maxWait }: DebounceConfig,
|
|
246
|
+
time: number,
|
|
247
|
+
) {
|
|
248
|
+
if (!state.mounted) return false;
|
|
249
|
+
|
|
250
|
+
const timeSinceLastCall = time - (state.lastCallTime || 0);
|
|
251
|
+
const timeSinceLastInvoke = time - state.lastInvokeTime;
|
|
252
|
+
|
|
253
|
+
// Either this is the first call, activity has stopped and we're at the
|
|
254
|
+
// trailing edge, the system time has gone backwards and we're treating
|
|
255
|
+
// it as the trailing edge, or we've hit the `maxWait` limit.
|
|
256
|
+
return (
|
|
257
|
+
!state.lastCallTime ||
|
|
258
|
+
timeSinceLastCall >= wait ||
|
|
259
|
+
timeSinceLastCall < 0 ||
|
|
260
|
+
(maxWait !== null && timeSinceLastInvoke >= maxWait)
|
|
261
|
+
);
|
|
262
|
+
}
|
|
202
263
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
264
|
+
function trailingEdge<T extends (...args: any) => ReturnType<T>>(
|
|
265
|
+
state: DebounceState<T>,
|
|
266
|
+
config: DebounceConfig,
|
|
267
|
+
time: number,
|
|
268
|
+
) {
|
|
269
|
+
state.timerId = null;
|
|
270
|
+
|
|
271
|
+
// Only invoke if we have `lastArgs` which means `func` has been
|
|
272
|
+
// debounced at least once.
|
|
273
|
+
if (config.trailing && state.lastArgs) {
|
|
274
|
+
return invokeFunc(state, time);
|
|
275
|
+
}
|
|
206
276
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
debouncedRef.current?.flush();
|
|
211
|
-
}
|
|
212
|
-
};
|
|
213
|
-
globalThis.document?.addEventListener?.(
|
|
214
|
-
"visibilitychange",
|
|
215
|
-
visibilityListener.current,
|
|
216
|
-
);
|
|
217
|
-
}
|
|
218
|
-
if (isInvoking) {
|
|
219
|
-
if (!timerId.current && mounted.current) {
|
|
220
|
-
// Reset any `maxWait` timer.
|
|
221
|
-
lastInvokeTime.current = lastCallTime.current;
|
|
222
|
-
// Start the timer for the trailing edge.
|
|
223
|
-
startTimer(timerExpired, wait);
|
|
224
|
-
// Invoke the leading edge.
|
|
225
|
-
return leading ? invokeFunc(lastCallTime.current) : result.current!;
|
|
226
|
-
}
|
|
227
|
-
if (maxing) {
|
|
228
|
-
// Handle invocations in a tight loop.
|
|
229
|
-
startTimer(timerExpired, wait);
|
|
230
|
-
return invokeFunc(lastCallTime.current);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
if (!timerId.current) {
|
|
234
|
-
startTimer(timerExpired, wait);
|
|
235
|
-
}
|
|
236
|
-
return result.current!;
|
|
237
|
-
};
|
|
277
|
+
state.lastArgs = state.lastThis = null;
|
|
278
|
+
return state.result;
|
|
279
|
+
}
|
|
238
280
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
lastInvokeTime.current = 0;
|
|
246
|
-
lastArgs.current =
|
|
247
|
-
lastCallTime.current =
|
|
248
|
-
lastThis.current =
|
|
249
|
-
timerId.current =
|
|
250
|
-
null;
|
|
251
|
-
};
|
|
281
|
+
function timerExpired<T extends (...args: any) => ReturnType<T>>(
|
|
282
|
+
state: DebounceState<T>,
|
|
283
|
+
config: DebounceConfig,
|
|
284
|
+
) {
|
|
285
|
+
const time = Date.now();
|
|
252
286
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
287
|
+
if (shouldInvoke(state, config, time)) {
|
|
288
|
+
trailingEdge(state, config, time);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
// https://github.com/xnimorz/use-debounce/issues/97
|
|
292
|
+
if (!state.mounted) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
// Remaining wait calculation
|
|
296
|
+
const timeSinceLastCall = time - (state.lastCallTime || 0);
|
|
297
|
+
const timeSinceLastInvoke = time - state.lastInvokeTime;
|
|
298
|
+
const timeWaiting = config.wait - timeSinceLastCall;
|
|
299
|
+
const remainingWait =
|
|
300
|
+
config.maxWait !== null
|
|
301
|
+
? Math.min(timeWaiting, config.maxWait - timeSinceLastInvoke)
|
|
302
|
+
: timeWaiting;
|
|
303
|
+
|
|
304
|
+
// Restart the timer
|
|
305
|
+
startTimer(state, config, remainingWait);
|
|
306
|
+
}
|
|
256
307
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
308
|
+
function debounce<T extends (...args: any) => ReturnType<T>>(
|
|
309
|
+
state: DebounceState<T>,
|
|
310
|
+
config: DebounceConfig,
|
|
311
|
+
thisArg: unknown,
|
|
312
|
+
args: Parameters<T>,
|
|
313
|
+
): ReturnType<T> | undefined {
|
|
314
|
+
if (!canUseDOM && !config.debounceOnServer) {
|
|
315
|
+
return undefined;
|
|
316
|
+
}
|
|
260
317
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
leading,
|
|
264
|
-
maxing,
|
|
265
|
-
wait,
|
|
266
|
-
maxWait,
|
|
267
|
-
trailing,
|
|
268
|
-
flushOnExit,
|
|
269
|
-
useRAF,
|
|
270
|
-
debounceOnServer,
|
|
271
|
-
]);
|
|
318
|
+
const time = Date.now();
|
|
319
|
+
const isInvoking = shouldInvoke(state, config, time);
|
|
272
320
|
|
|
273
|
-
|
|
274
|
-
|
|
321
|
+
state.lastArgs = args;
|
|
322
|
+
state.lastThis = thisArg;
|
|
323
|
+
state.lastCallTime = time;
|
|
275
324
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
debouncedRef.current?.flush();
|
|
281
|
-
}
|
|
282
|
-
if (visibilityListener.current) {
|
|
283
|
-
globalThis.document?.removeEventListener?.(
|
|
284
|
-
"visibilitychange",
|
|
285
|
-
visibilityListener.current,
|
|
286
|
-
);
|
|
287
|
-
visibilityListener.current = null;
|
|
325
|
+
if (config.flushOnExit && !state.visibilityListener) {
|
|
326
|
+
state.visibilityListener = () => {
|
|
327
|
+
if (globalThis.document?.visibilityState === "hidden") {
|
|
328
|
+
state.debounced?.flush();
|
|
288
329
|
}
|
|
289
|
-
mounted.current = false;
|
|
290
330
|
};
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
331
|
+
globalThis.document?.addEventListener?.(
|
|
332
|
+
"visibilitychange",
|
|
333
|
+
state.visibilityListener,
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
if (isInvoking) {
|
|
337
|
+
if (!state.timerId && state.mounted) {
|
|
338
|
+
// Reset any `maxWait` timer.
|
|
339
|
+
state.lastInvokeTime = time;
|
|
340
|
+
// Start the timer for the trailing edge.
|
|
341
|
+
startTimer(state, config, config.wait);
|
|
342
|
+
// Invoke the leading edge.
|
|
343
|
+
return config.leading ? invokeFunc(state, time) : state.result;
|
|
344
|
+
}
|
|
345
|
+
if (config.maxWait !== null) {
|
|
346
|
+
// Handle invocations in a tight loop.
|
|
347
|
+
startTimer(state, config, config.wait);
|
|
348
|
+
return invokeFunc(state, time);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
if (!state.timerId) {
|
|
352
|
+
startTimer(state, config, config.wait);
|
|
353
|
+
}
|
|
354
|
+
return state.result;
|
|
294
355
|
}
|
|
295
356
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
*
|
|
310
|
-
* NOTE: If the callback calls `fetch()`, you usually also want to specify the `keepalive=true`
|
|
311
|
-
* option for `fetch()` so it can finish in the background after the page is closed.
|
|
312
|
-
*
|
|
313
|
-
* This option has no effect if `trailing == false`.
|
|
314
|
-
*/
|
|
315
|
-
flushOnExit?: boolean;
|
|
357
|
+
function cancel<T extends (...args: any) => ReturnType<T>>(
|
|
358
|
+
state: DebounceState<T>,
|
|
359
|
+
config: DebounceConfig,
|
|
360
|
+
) {
|
|
361
|
+
if (state.timerId) {
|
|
362
|
+
if (config.useRAF) {
|
|
363
|
+
cancelAnimationFrame(state.timerId);
|
|
364
|
+
} else {
|
|
365
|
+
clearTimeout(state.timerId);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
state.lastInvokeTime = 0;
|
|
369
|
+
state.lastArgs = state.lastCallTime = state.lastThis = state.timerId = null;
|
|
316
370
|
}
|
|
317
371
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
*/
|
|
326
|
-
debounceOnServer?: boolean;
|
|
372
|
+
function flush<T extends (...args: any) => ReturnType<T>>(
|
|
373
|
+
state: DebounceState<T>,
|
|
374
|
+
config: DebounceConfig,
|
|
375
|
+
) {
|
|
376
|
+
return !state.timerId
|
|
377
|
+
? state.result
|
|
378
|
+
: trailingEdge(state, config, Date.now());
|
|
327
379
|
}
|
|
328
380
|
|
|
329
381
|
interface ControlFunctions<ReturnT> {
|
|
@@ -7,10 +7,6 @@ function useWidgetsInvalidatorImpl() {
|
|
|
7
7
|
|
|
8
8
|
return React.useCallback(async () => {
|
|
9
9
|
await queryClient.invalidateQueries({ queryKey: ["authToken"] });
|
|
10
|
-
// TODO: Unclear why, but invalidating other widgets' queries immediately
|
|
11
|
-
// after the authToken invalidation (even though it's async?) doesn't work,
|
|
12
|
-
// and We end up with stale data. Waiting for the next tick fixes this.
|
|
13
|
-
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
14
10
|
return queryClient.invalidateQueries({
|
|
15
11
|
predicate: (query) => isClientGraphqlQueryKey(query.queryKey),
|
|
16
12
|
});
|
package/src/lib/utils.ts
CHANGED
|
@@ -4,18 +4,6 @@ export const canUseDOM = !!(
|
|
|
4
4
|
window.document.createElement
|
|
5
5
|
);
|
|
6
6
|
|
|
7
|
-
export function composeEventHandlers<E extends { defaultPrevented: boolean }>(
|
|
8
|
-
originalEventHandler?: (event: E) => void,
|
|
9
|
-
ourEventHandler?: (event: E) => void,
|
|
10
|
-
) {
|
|
11
|
-
return function handleEvent(event: E) {
|
|
12
|
-
originalEventHandler?.(event);
|
|
13
|
-
if (!event || !event.defaultPrevented) {
|
|
14
|
-
return ourEventHandler?.(event);
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
|
|
19
7
|
export function getBestName({
|
|
20
8
|
firstName,
|
|
21
9
|
lastName,
|
|
@@ -20,9 +20,12 @@ const ApiKeysSearch = React.forwardRef<HTMLInputElement, ApiKeysSearchProps>(
|
|
|
20
20
|
const { dispatch } = useApiKeysContext();
|
|
21
21
|
const translate = useTranslation();
|
|
22
22
|
|
|
23
|
-
const filter = useDebouncedCallback(
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
const filter = useDebouncedCallback(
|
|
24
|
+
(value) => {
|
|
25
|
+
dispatch({ type: "FILTER_BY_SEARCH", searchQuery: value });
|
|
26
|
+
},
|
|
27
|
+
{ wait: 200 },
|
|
28
|
+
);
|
|
26
29
|
|
|
27
30
|
const resetSearch = () => {
|
|
28
31
|
clearSearch();
|
|
@@ -22,9 +22,12 @@ const UserApiKeysSearch = React.forwardRef<
|
|
|
22
22
|
const { dispatch } = useUserApiKeysContext();
|
|
23
23
|
const translate = useTranslation();
|
|
24
24
|
|
|
25
|
-
const filter = useDebouncedCallback(
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
const filter = useDebouncedCallback(
|
|
26
|
+
(value) => {
|
|
27
|
+
dispatch({ type: "FILTER_BY_SEARCH", searchQuery: value });
|
|
28
|
+
},
|
|
29
|
+
{ wait: 200 },
|
|
30
|
+
);
|
|
28
31
|
|
|
29
32
|
const resetSearch = () => {
|
|
30
33
|
clearSearch();
|