@khanacademy/wonder-blocks-timing 4.0.2 → 5.0.1
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 +18 -0
- package/dist/es/index.js +89 -104
- package/dist/hooks/use-interval.d.ts +27 -5
- package/dist/hooks/use-timeout.d.ts +27 -5
- package/dist/index.d.ts +2 -5
- package/dist/index.js +88 -104
- package/dist/util/animation-frame.d.ts +6 -6
- package/dist/util/interval.d.ts +7 -7
- package/dist/util/policies.d.ts +12 -8
- package/dist/util/timeout.d.ts +7 -6
- package/dist/util/types.d.ts +18 -10
- package/package.json +2 -2
- package/src/hooks/__tests__/use-interval.test.ts +453 -56
- package/src/hooks/__tests__/use-timeout.test.ts +412 -58
- package/src/hooks/use-interval.ts +90 -25
- package/src/hooks/use-timeout.ts +90 -25
- package/src/index.ts +4 -14
- package/src/util/animation-frame.ts +12 -16
- package/src/util/interval.ts +12 -16
- package/src/util/policies.ts +13 -8
- package/src/util/timeout.ts +13 -16
- package/src/util/types.ts +19 -11
- package/tsconfig-build.json +2 -4
- package/tsconfig-build.tsbuildinfo +1 -1
- package/dist/hooks/internal/use-updating-ref.d.ts +0 -13
- package/dist/hooks/use-scheduled-interval.d.ts +0 -2
- package/dist/hooks/use-scheduled-timeout.d.ts +0 -2
- package/src/hooks/__tests__/use-scheduled-interval.test.ts +0 -460
- package/src/hooks/__tests__/use-scheduled-timeout.test.ts +0 -478
- package/src/hooks/internal/use-updating-ref.ts +0 -23
- package/src/hooks/use-scheduled-interval.ts +0 -72
- package/src/hooks/use-scheduled-timeout.ts +0 -79
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-timing
|
|
2
2
|
|
|
3
|
+
## 5.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 559e82d5: Update to build tooling, generating smaller output
|
|
8
|
+
|
|
9
|
+
## 5.0.0
|
|
10
|
+
|
|
11
|
+
### Major Changes
|
|
12
|
+
|
|
13
|
+
- f72f7dd4: - **[BREAKING CHANGE]** Policy types are now using enums across all APIs
|
|
14
|
+
- **[BREAKING CHANGE]** `useScheduledTimeout` has been renamed to `useTimeout` and the original `useTimeout` has been removed. To update existing uses of `useTimeout` to the new API: if `active` was `true` just delete that argument or replace it with `{schedulingPolicy: SchedulingPolicy.Immediately}`; if `active` was `false` replace it with `{schedulingPolicy: SchedulingPolicy.OnDemand}`.
|
|
15
|
+
- **[BREAKING CHANGE]** `useScheduledInterval` has been renamed to `useInterval` and the original `useInterval` has been removed. To update existing uses of `useInterval` to the new API: if `active` was `true` just delete that argument or replace it with `{schedulingPolicy: SchedulingPolicy.Immediately}`; if `active` was `false` replace it with `{schedulingPolicy: SchedulingPolicy.OnDemand}`.
|
|
16
|
+
- **[NEW]** `useTimeout` now supports an optional `ActionPolicy` in the options. The default is to not reset the timeout when the `action` callback changes. This can be changed to `ActionPolicy.Reset` to reset the timeout when the `action` callback changes (it is recommended that you use `useCallback` on your `action` callback to avoid resetting the timeout everytime a component renders when using the `Reset` policy).
|
|
17
|
+
- **[NEW]** `useInterval` now supports an optional `ActionPolicy` in the options. The default is to not reset the interval when the `action` callback changes. This can be changed to `ActionPolicy.Reset` to reset the interval when the `action` callback changes (it is recommended that you use `useCallback` on your `action` callback to avoid resetting the interval everytime a component renders when using the `Reset` policy).
|
|
18
|
+
- **[BUGFIX]** `useTimeout` will now correctly reset the timeout when the `set` method is called, as intended.
|
|
19
|
+
- **[BUGFIX]** `useInterval` will now correctly reset the interval when the `set` method is called, as intended.
|
|
20
|
+
|
|
3
21
|
## 4.0.2
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/dist/es/index.js
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { useRef, useEffect,
|
|
2
|
+
import { useRef, useEffect, useMemo } from 'react';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
Immediately
|
|
6
|
-
OnDemand
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
let SchedulePolicy = function (SchedulePolicy) {
|
|
5
|
+
SchedulePolicy["Immediately"] = "schedule-immediately";
|
|
6
|
+
SchedulePolicy["OnDemand"] = "schedule-on-demand";
|
|
7
|
+
return SchedulePolicy;
|
|
8
|
+
}({});
|
|
9
|
+
let ClearPolicy = function (ClearPolicy) {
|
|
10
|
+
ClearPolicy["Resolve"] = "resolve-on-clear";
|
|
11
|
+
ClearPolicy["Cancel"] = "cancel-on-clear";
|
|
12
|
+
return ClearPolicy;
|
|
13
|
+
}({});
|
|
14
|
+
let ActionPolicy = function (ActionPolicy) {
|
|
15
|
+
ActionPolicy["Reset"] = "reset";
|
|
16
|
+
ActionPolicy["Passive"] = "passive";
|
|
17
|
+
return ActionPolicy;
|
|
18
|
+
}({});
|
|
12
19
|
|
|
13
20
|
class Timeout {
|
|
14
21
|
constructor(action, timeoutMs, schedulePolicy = SchedulePolicy.Immediately) {
|
|
@@ -209,116 +216,94 @@ function withActionScheduler(WrappedComponent) {
|
|
|
209
216
|
return C;
|
|
210
217
|
}
|
|
211
218
|
|
|
212
|
-
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
function useInterval(action, intervalMs, active) {
|
|
221
|
-
const actionRef = useUpdatingRef(action);
|
|
222
|
-
useEffect(() => {
|
|
223
|
-
if (active) {
|
|
224
|
-
const intervalId = setInterval(() => {
|
|
225
|
-
actionRef.current();
|
|
226
|
-
}, intervalMs);
|
|
227
|
-
return () => {
|
|
228
|
-
clearInterval(intervalId);
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
}, [intervalMs, active, actionRef]);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
function useTimeout(action, timeoutMs, active) {
|
|
235
|
-
const actionRef = useUpdatingRef(action);
|
|
236
|
-
useEffect(() => {
|
|
237
|
-
if (active) {
|
|
238
|
-
const timeoutId = setTimeout(() => {
|
|
239
|
-
actionRef.current();
|
|
240
|
-
}, timeoutMs);
|
|
241
|
-
return () => {
|
|
242
|
-
clearTimeout(timeoutId);
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
}, [timeoutMs, active, actionRef]);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
function useScheduledInterval(action, intervalMs, options) {
|
|
249
|
-
var _options$schedulePoli;
|
|
219
|
+
function useInterval(action, intervalMs, options = {}) {
|
|
220
|
+
const {
|
|
221
|
+
actionPolicy,
|
|
222
|
+
clearPolicy,
|
|
223
|
+
schedulePolicy
|
|
224
|
+
} = options;
|
|
225
|
+
const actionProxyRef = useRef(action);
|
|
226
|
+
const intervalRef = useRef(null);
|
|
250
227
|
if (typeof action !== "function") {
|
|
251
228
|
throw new Error("Action must be a function");
|
|
252
229
|
}
|
|
253
|
-
if (
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
const set = useCallback(() => setIsSet(true), []);
|
|
259
|
-
const actionRef = useUpdatingRef(action);
|
|
260
|
-
const clear = useCallback(policy => {
|
|
261
|
-
var _policy;
|
|
262
|
-
policy = (_policy = policy) != null ? _policy : options == null ? void 0 : options.clearPolicy;
|
|
263
|
-
if (isSet && policy === ClearPolicy.Resolve) {
|
|
264
|
-
actionRef.current();
|
|
230
|
+
if (action !== actionProxyRef.current) {
|
|
231
|
+
actionProxyRef.current = action;
|
|
232
|
+
if (actionPolicy === ActionPolicy.Reset) {
|
|
233
|
+
var _intervalRef$current;
|
|
234
|
+
(_intervalRef$current = intervalRef.current) == null ? void 0 : _intervalRef$current.set();
|
|
265
235
|
}
|
|
266
|
-
|
|
267
|
-
}, [actionRef, isSet, options == null ? void 0 : options.clearPolicy]);
|
|
268
|
-
const runOnUnmountRef = useUpdatingRef(isSet && (options == null ? void 0 : options.clearPolicy) === ClearPolicy.Resolve);
|
|
236
|
+
}
|
|
269
237
|
useEffect(() => {
|
|
238
|
+
intervalRef.current = new Interval(() => {
|
|
239
|
+
actionProxyRef.current == null ? void 0 : actionProxyRef.current();
|
|
240
|
+
}, intervalMs, schedulePolicy);
|
|
270
241
|
return () => {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
242
|
+
var _intervalRef$current2;
|
|
243
|
+
(_intervalRef$current2 = intervalRef.current) == null ? void 0 : _intervalRef$current2.clear(clearPolicy);
|
|
244
|
+
intervalRef.current = null;
|
|
274
245
|
};
|
|
275
|
-
}, []);
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
246
|
+
}, [intervalMs, clearPolicy, schedulePolicy]);
|
|
247
|
+
const externalApi = useMemo(() => ({
|
|
248
|
+
set: () => {
|
|
249
|
+
var _intervalRef$current3;
|
|
250
|
+
(_intervalRef$current3 = intervalRef.current) == null ? void 0 : _intervalRef$current3.set();
|
|
251
|
+
},
|
|
252
|
+
clear: policy => {
|
|
253
|
+
var _intervalRef$current4;
|
|
254
|
+
(_intervalRef$current4 = intervalRef.current) == null ? void 0 : _intervalRef$current4.clear(policy);
|
|
255
|
+
},
|
|
256
|
+
get isSet() {
|
|
257
|
+
var _intervalRef$current$, _intervalRef$current5;
|
|
258
|
+
return (_intervalRef$current$ = (_intervalRef$current5 = intervalRef.current) == null ? void 0 : _intervalRef$current5.isSet) != null ? _intervalRef$current$ : false;
|
|
259
|
+
}
|
|
260
|
+
}), []);
|
|
261
|
+
return externalApi;
|
|
282
262
|
}
|
|
283
263
|
|
|
284
|
-
function
|
|
285
|
-
|
|
264
|
+
function useTimeout(action, timeoutMs, options = {}) {
|
|
265
|
+
const {
|
|
266
|
+
actionPolicy,
|
|
267
|
+
clearPolicy,
|
|
268
|
+
schedulePolicy
|
|
269
|
+
} = options;
|
|
270
|
+
const actionProxyRef = useRef(action);
|
|
271
|
+
const timeoutRef = useRef(null);
|
|
286
272
|
if (typeof action !== "function") {
|
|
287
273
|
throw new Error("Action must be a function");
|
|
288
274
|
}
|
|
289
|
-
if (
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
const set = useCallback(() => setIsSet(true), []);
|
|
295
|
-
const wrappedAction = useCallback(() => {
|
|
296
|
-
setIsSet(false);
|
|
297
|
-
action();
|
|
298
|
-
}, [action]);
|
|
299
|
-
const actionRef = useUpdatingRef(wrappedAction);
|
|
300
|
-
const clear = useCallback(policy => {
|
|
301
|
-
var _policy;
|
|
302
|
-
policy = (_policy = policy) != null ? _policy : options == null ? void 0 : options.clearPolicy;
|
|
303
|
-
if (isSet && policy === ClearPolicy.Resolve) {
|
|
304
|
-
actionRef.current();
|
|
275
|
+
if (action !== actionProxyRef.current) {
|
|
276
|
+
actionProxyRef.current = action;
|
|
277
|
+
if (actionPolicy === ActionPolicy.Reset) {
|
|
278
|
+
var _timeoutRef$current;
|
|
279
|
+
(_timeoutRef$current = timeoutRef.current) == null ? void 0 : _timeoutRef$current.set();
|
|
305
280
|
}
|
|
306
|
-
|
|
307
|
-
}, [actionRef, isSet, options == null ? void 0 : options.clearPolicy]);
|
|
308
|
-
const runOnUnmountRef = useUpdatingRef(isSet && (options == null ? void 0 : options.clearPolicy) === ClearPolicy.Resolve);
|
|
281
|
+
}
|
|
309
282
|
useEffect(() => {
|
|
283
|
+
timeoutRef.current = new Timeout(() => {
|
|
284
|
+
actionProxyRef.current == null ? void 0 : actionProxyRef.current();
|
|
285
|
+
}, timeoutMs, schedulePolicy);
|
|
310
286
|
return () => {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
287
|
+
var _timeoutRef$current2;
|
|
288
|
+
(_timeoutRef$current2 = timeoutRef.current) == null ? void 0 : _timeoutRef$current2.clear(clearPolicy);
|
|
289
|
+
timeoutRef.current = null;
|
|
314
290
|
};
|
|
315
|
-
}, []);
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
291
|
+
}, [timeoutMs, clearPolicy, schedulePolicy]);
|
|
292
|
+
const externalApi = useMemo(() => ({
|
|
293
|
+
set: () => {
|
|
294
|
+
var _timeoutRef$current3;
|
|
295
|
+
(_timeoutRef$current3 = timeoutRef.current) == null ? void 0 : _timeoutRef$current3.set();
|
|
296
|
+
},
|
|
297
|
+
clear: policy => {
|
|
298
|
+
var _timeoutRef$current4;
|
|
299
|
+
(_timeoutRef$current4 = timeoutRef.current) == null ? void 0 : _timeoutRef$current4.clear(policy);
|
|
300
|
+
},
|
|
301
|
+
get isSet() {
|
|
302
|
+
var _timeoutRef$current$i, _timeoutRef$current5;
|
|
303
|
+
return (_timeoutRef$current$i = (_timeoutRef$current5 = timeoutRef.current) == null ? void 0 : _timeoutRef$current5.isSet) != null ? _timeoutRef$current$i : false;
|
|
304
|
+
}
|
|
305
|
+
}), []);
|
|
306
|
+
return externalApi;
|
|
322
307
|
}
|
|
323
308
|
|
|
324
|
-
export { ActionSchedulerProvider, ClearPolicy, SchedulePolicy, useInterval,
|
|
309
|
+
export { ActionPolicy, ActionSchedulerProvider, ClearPolicy, SchedulePolicy, useInterval, useTimeout, withActionScheduler };
|
|
@@ -1,8 +1,30 @@
|
|
|
1
|
+
import type { IInterval, HookOptions } from "../util/types";
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
+
* Hook providing access to a scheduled interval.
|
|
3
4
|
*
|
|
4
|
-
* @param action
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* @param action The action to be invoked each time the interval period has
|
|
6
|
+
* passed. By default, this will not cause the interval to restart if it
|
|
7
|
+
* changes. This makes it easier to use with inline lambda functions rather than
|
|
8
|
+
* requiring consumers to wrap their action in a `useCallback`. To change this
|
|
9
|
+
* behavior, see the `actionPolicy` option.
|
|
10
|
+
* @param intervalMs The interval period. If this changes, the interval will
|
|
11
|
+
* be reset per the `schedulePolicy` option.
|
|
12
|
+
* @param options Options for the hook.
|
|
13
|
+
* @param options.actionPolicy Determines how the action is handled when it
|
|
14
|
+
* changes. By default, the action is replaced but the interval is not reset,
|
|
15
|
+
* and the updated action will be invoked when the interval next fires.
|
|
16
|
+
* If you want to reset the interval when the action changes, use
|
|
17
|
+
* `ActionPolicy.Reset`.
|
|
18
|
+
* @param options.clearPolicy Determines how the interval is cleared when the
|
|
19
|
+
* component is unmounted or the interval is recreated. By default, the
|
|
20
|
+
* interval is cleared immediately. If you want to let the interval run to
|
|
21
|
+
* completion, use `ClearPolicy.Resolve`. This is NOT applied if the interval
|
|
22
|
+
* is cleared manually via the `clear()` method on the returned API.
|
|
23
|
+
* @param options.schedulePolicy Determines when the interval is scheduled.
|
|
24
|
+
* By default, the interval is scheduled immediately. If you want to delay
|
|
25
|
+
* scheduling the interval, use `SchedulePolicy.OnDemand`.
|
|
26
|
+
* @returns An `IInterval` API for interacting with the given interval. This
|
|
27
|
+
* API is a no-op if called when not mounted. This means that any calls prior
|
|
28
|
+
* to mounting or after unmounting will not have any effect.
|
|
7
29
|
*/
|
|
8
|
-
export declare function useInterval(action: () => unknown, intervalMs: number,
|
|
30
|
+
export declare function useInterval(action: () => unknown, intervalMs: number, options?: HookOptions): IInterval;
|
|
@@ -1,8 +1,30 @@
|
|
|
1
|
+
import type { ITimeout, HookOptions } from "../util/types";
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
+
* Hook providing access to a scheduled timeout.
|
|
3
4
|
*
|
|
4
|
-
* @param action
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* @param action The action to be invoked when the timeout period has
|
|
6
|
+
* passed. By default, this will not cause the timeout to restart if it changes.
|
|
7
|
+
* This makes it easier to use with inline lambda functions rather than
|
|
8
|
+
* requiring consumers to wrap their action in a `useCallback`. To change
|
|
9
|
+
* this behavior, see the `actionPolicy` option.
|
|
10
|
+
* @param timeoutMs The timeout period. If this changes, the timeout will
|
|
11
|
+
* be reset per the `schedulePolicy` option.
|
|
12
|
+
* @param options Options for the hook.
|
|
13
|
+
* @param options.actionPolicy Determines how the action is handled when it
|
|
14
|
+
* changes. By default, the action is replaced but the timeout is not reset,
|
|
15
|
+
* and the updated action will be invoked when the timeout next fires.
|
|
16
|
+
* If you want to reset the timeout when the action changes, use
|
|
17
|
+
* `ActionPolicy.Reset`.
|
|
18
|
+
* @param options.clearPolicy Determines how the timeout is cleared when the
|
|
19
|
+
* component is unmounted or the timeout is recreated. By default, the
|
|
20
|
+
* timeout is cleared immediately. If you want to let the timeout run to
|
|
21
|
+
* completion, use `ClearPolicy.Resolve`. This is NOT applied if the timeout
|
|
22
|
+
* is cleared manually via the `clear()` method on the returned API.
|
|
23
|
+
* @param options.schedulePolicy Determines when the timeout is scheduled.
|
|
24
|
+
* By default, the timeout is scheduled immediately. If you want to delay
|
|
25
|
+
* scheduling the timeout, use `SchedulePolicy.OnDemand`.
|
|
26
|
+
* @returns An `ITimeout` API for interacting with the given timeout. This
|
|
27
|
+
* API is a no-op if called when not mounted. This means that any calls prior
|
|
28
|
+
* to mounting or after unmounting will not have any effect.
|
|
7
29
|
*/
|
|
8
|
-
export declare function useTimeout(action: () => unknown, timeoutMs: number,
|
|
30
|
+
export declare function useTimeout(action: () => unknown, timeoutMs: number, options?: HookOptions): ITimeout;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
export { SchedulePolicy, ClearPolicy } from "./util/policies";
|
|
1
|
+
export type { IAnimationFrame, IInterval, IScheduleActions, ITimeout, WithActionScheduler, WithActionSchedulerProps, WithoutActionScheduler, HookOptions, Options, } from "./util/types";
|
|
2
|
+
export { SchedulePolicy, ClearPolicy, ActionPolicy } from "./util/policies";
|
|
4
3
|
export { default as ActionSchedulerProvider } from "./components/action-scheduler-provider";
|
|
5
4
|
export { default as withActionScheduler } from "./components/with-action-scheduler";
|
|
6
5
|
export { useInterval } from "./hooks/use-interval";
|
|
7
6
|
export { useTimeout } from "./hooks/use-timeout";
|
|
8
|
-
export { useScheduledInterval } from "./hooks/use-scheduled-interval";
|
|
9
|
-
export { useScheduledTimeout } from "./hooks/use-scheduled-timeout";
|
package/dist/index.js
CHANGED
|
@@ -24,14 +24,21 @@ function _interopNamespace(e) {
|
|
|
24
24
|
|
|
25
25
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
Immediately
|
|
29
|
-
OnDemand
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
let SchedulePolicy = function (SchedulePolicy) {
|
|
28
|
+
SchedulePolicy["Immediately"] = "schedule-immediately";
|
|
29
|
+
SchedulePolicy["OnDemand"] = "schedule-on-demand";
|
|
30
|
+
return SchedulePolicy;
|
|
31
|
+
}({});
|
|
32
|
+
let ClearPolicy = function (ClearPolicy) {
|
|
33
|
+
ClearPolicy["Resolve"] = "resolve-on-clear";
|
|
34
|
+
ClearPolicy["Cancel"] = "cancel-on-clear";
|
|
35
|
+
return ClearPolicy;
|
|
36
|
+
}({});
|
|
37
|
+
let ActionPolicy = function (ActionPolicy) {
|
|
38
|
+
ActionPolicy["Reset"] = "reset";
|
|
39
|
+
ActionPolicy["Passive"] = "passive";
|
|
40
|
+
return ActionPolicy;
|
|
41
|
+
}({});
|
|
35
42
|
|
|
36
43
|
class Timeout {
|
|
37
44
|
constructor(action, timeoutMs, schedulePolicy = SchedulePolicy.Immediately) {
|
|
@@ -232,123 +239,100 @@ function withActionScheduler(WrappedComponent) {
|
|
|
232
239
|
return C;
|
|
233
240
|
}
|
|
234
241
|
|
|
235
|
-
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
function useInterval(action, intervalMs, active) {
|
|
244
|
-
const actionRef = useUpdatingRef(action);
|
|
245
|
-
React.useEffect(() => {
|
|
246
|
-
if (active) {
|
|
247
|
-
const intervalId = setInterval(() => {
|
|
248
|
-
actionRef.current();
|
|
249
|
-
}, intervalMs);
|
|
250
|
-
return () => {
|
|
251
|
-
clearInterval(intervalId);
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
}, [intervalMs, active, actionRef]);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
function useTimeout(action, timeoutMs, active) {
|
|
258
|
-
const actionRef = useUpdatingRef(action);
|
|
259
|
-
React.useEffect(() => {
|
|
260
|
-
if (active) {
|
|
261
|
-
const timeoutId = setTimeout(() => {
|
|
262
|
-
actionRef.current();
|
|
263
|
-
}, timeoutMs);
|
|
264
|
-
return () => {
|
|
265
|
-
clearTimeout(timeoutId);
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
}, [timeoutMs, active, actionRef]);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
function useScheduledInterval(action, intervalMs, options) {
|
|
272
|
-
var _options$schedulePoli;
|
|
242
|
+
function useInterval(action, intervalMs, options = {}) {
|
|
243
|
+
const {
|
|
244
|
+
actionPolicy,
|
|
245
|
+
clearPolicy,
|
|
246
|
+
schedulePolicy
|
|
247
|
+
} = options;
|
|
248
|
+
const actionProxyRef = React.useRef(action);
|
|
249
|
+
const intervalRef = React.useRef(null);
|
|
273
250
|
if (typeof action !== "function") {
|
|
274
251
|
throw new Error("Action must be a function");
|
|
275
252
|
}
|
|
276
|
-
if (
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
const set = React.useCallback(() => setIsSet(true), []);
|
|
282
|
-
const actionRef = useUpdatingRef(action);
|
|
283
|
-
const clear = React.useCallback(policy => {
|
|
284
|
-
var _policy;
|
|
285
|
-
policy = (_policy = policy) != null ? _policy : options == null ? void 0 : options.clearPolicy;
|
|
286
|
-
if (isSet && policy === ClearPolicy.Resolve) {
|
|
287
|
-
actionRef.current();
|
|
253
|
+
if (action !== actionProxyRef.current) {
|
|
254
|
+
actionProxyRef.current = action;
|
|
255
|
+
if (actionPolicy === ActionPolicy.Reset) {
|
|
256
|
+
var _intervalRef$current;
|
|
257
|
+
(_intervalRef$current = intervalRef.current) == null ? void 0 : _intervalRef$current.set();
|
|
288
258
|
}
|
|
289
|
-
|
|
290
|
-
}, [actionRef, isSet, options == null ? void 0 : options.clearPolicy]);
|
|
291
|
-
const runOnUnmountRef = useUpdatingRef(isSet && (options == null ? void 0 : options.clearPolicy) === ClearPolicy.Resolve);
|
|
259
|
+
}
|
|
292
260
|
React.useEffect(() => {
|
|
261
|
+
intervalRef.current = new Interval(() => {
|
|
262
|
+
actionProxyRef.current == null ? void 0 : actionProxyRef.current();
|
|
263
|
+
}, intervalMs, schedulePolicy);
|
|
293
264
|
return () => {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
265
|
+
var _intervalRef$current2;
|
|
266
|
+
(_intervalRef$current2 = intervalRef.current) == null ? void 0 : _intervalRef$current2.clear(clearPolicy);
|
|
267
|
+
intervalRef.current = null;
|
|
297
268
|
};
|
|
298
|
-
}, []);
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
269
|
+
}, [intervalMs, clearPolicy, schedulePolicy]);
|
|
270
|
+
const externalApi = React.useMemo(() => ({
|
|
271
|
+
set: () => {
|
|
272
|
+
var _intervalRef$current3;
|
|
273
|
+
(_intervalRef$current3 = intervalRef.current) == null ? void 0 : _intervalRef$current3.set();
|
|
274
|
+
},
|
|
275
|
+
clear: policy => {
|
|
276
|
+
var _intervalRef$current4;
|
|
277
|
+
(_intervalRef$current4 = intervalRef.current) == null ? void 0 : _intervalRef$current4.clear(policy);
|
|
278
|
+
},
|
|
279
|
+
get isSet() {
|
|
280
|
+
var _intervalRef$current$, _intervalRef$current5;
|
|
281
|
+
return (_intervalRef$current$ = (_intervalRef$current5 = intervalRef.current) == null ? void 0 : _intervalRef$current5.isSet) != null ? _intervalRef$current$ : false;
|
|
282
|
+
}
|
|
283
|
+
}), []);
|
|
284
|
+
return externalApi;
|
|
305
285
|
}
|
|
306
286
|
|
|
307
|
-
function
|
|
308
|
-
|
|
287
|
+
function useTimeout(action, timeoutMs, options = {}) {
|
|
288
|
+
const {
|
|
289
|
+
actionPolicy,
|
|
290
|
+
clearPolicy,
|
|
291
|
+
schedulePolicy
|
|
292
|
+
} = options;
|
|
293
|
+
const actionProxyRef = React.useRef(action);
|
|
294
|
+
const timeoutRef = React.useRef(null);
|
|
309
295
|
if (typeof action !== "function") {
|
|
310
296
|
throw new Error("Action must be a function");
|
|
311
297
|
}
|
|
312
|
-
if (
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
const set = React.useCallback(() => setIsSet(true), []);
|
|
318
|
-
const wrappedAction = React.useCallback(() => {
|
|
319
|
-
setIsSet(false);
|
|
320
|
-
action();
|
|
321
|
-
}, [action]);
|
|
322
|
-
const actionRef = useUpdatingRef(wrappedAction);
|
|
323
|
-
const clear = React.useCallback(policy => {
|
|
324
|
-
var _policy;
|
|
325
|
-
policy = (_policy = policy) != null ? _policy : options == null ? void 0 : options.clearPolicy;
|
|
326
|
-
if (isSet && policy === ClearPolicy.Resolve) {
|
|
327
|
-
actionRef.current();
|
|
298
|
+
if (action !== actionProxyRef.current) {
|
|
299
|
+
actionProxyRef.current = action;
|
|
300
|
+
if (actionPolicy === ActionPolicy.Reset) {
|
|
301
|
+
var _timeoutRef$current;
|
|
302
|
+
(_timeoutRef$current = timeoutRef.current) == null ? void 0 : _timeoutRef$current.set();
|
|
328
303
|
}
|
|
329
|
-
|
|
330
|
-
}, [actionRef, isSet, options == null ? void 0 : options.clearPolicy]);
|
|
331
|
-
const runOnUnmountRef = useUpdatingRef(isSet && (options == null ? void 0 : options.clearPolicy) === ClearPolicy.Resolve);
|
|
304
|
+
}
|
|
332
305
|
React.useEffect(() => {
|
|
306
|
+
timeoutRef.current = new Timeout(() => {
|
|
307
|
+
actionProxyRef.current == null ? void 0 : actionProxyRef.current();
|
|
308
|
+
}, timeoutMs, schedulePolicy);
|
|
333
309
|
return () => {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
310
|
+
var _timeoutRef$current2;
|
|
311
|
+
(_timeoutRef$current2 = timeoutRef.current) == null ? void 0 : _timeoutRef$current2.clear(clearPolicy);
|
|
312
|
+
timeoutRef.current = null;
|
|
337
313
|
};
|
|
338
|
-
}, []);
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
314
|
+
}, [timeoutMs, clearPolicy, schedulePolicy]);
|
|
315
|
+
const externalApi = React.useMemo(() => ({
|
|
316
|
+
set: () => {
|
|
317
|
+
var _timeoutRef$current3;
|
|
318
|
+
(_timeoutRef$current3 = timeoutRef.current) == null ? void 0 : _timeoutRef$current3.set();
|
|
319
|
+
},
|
|
320
|
+
clear: policy => {
|
|
321
|
+
var _timeoutRef$current4;
|
|
322
|
+
(_timeoutRef$current4 = timeoutRef.current) == null ? void 0 : _timeoutRef$current4.clear(policy);
|
|
323
|
+
},
|
|
324
|
+
get isSet() {
|
|
325
|
+
var _timeoutRef$current$i, _timeoutRef$current5;
|
|
326
|
+
return (_timeoutRef$current$i = (_timeoutRef$current5 = timeoutRef.current) == null ? void 0 : _timeoutRef$current5.isSet) != null ? _timeoutRef$current$i : false;
|
|
327
|
+
}
|
|
328
|
+
}), []);
|
|
329
|
+
return externalApi;
|
|
345
330
|
}
|
|
346
331
|
|
|
332
|
+
exports.ActionPolicy = ActionPolicy;
|
|
347
333
|
exports.ActionSchedulerProvider = ActionSchedulerProvider;
|
|
348
334
|
exports.ClearPolicy = ClearPolicy;
|
|
349
335
|
exports.SchedulePolicy = SchedulePolicy;
|
|
350
336
|
exports.useInterval = useInterval;
|
|
351
|
-
exports.useScheduledInterval = useScheduledInterval;
|
|
352
|
-
exports.useScheduledTimeout = useScheduledTimeout;
|
|
353
337
|
exports.useTimeout = useTimeout;
|
|
354
338
|
exports.withActionScheduler = withActionScheduler;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { SchedulePolicy, ClearPolicy } from "./policies";
|
|
2
|
+
import type { IAnimationFrame } from "./types";
|
|
2
3
|
/**
|
|
3
4
|
* Encapsulates everything associated with calling requestAnimationFrame/
|
|
4
5
|
* cancelAnimationFrame, and managing the lifecycle of that request, including
|
|
@@ -15,8 +16,8 @@ export default class AnimationFrame implements IAnimationFrame {
|
|
|
15
16
|
* Creates an animation frame request that will invoke the given action.
|
|
16
17
|
* The request is not made until set is called.
|
|
17
18
|
*
|
|
18
|
-
* @param
|
|
19
|
-
* @param
|
|
19
|
+
* @param action The action to be invoked.
|
|
20
|
+
* @param [schedulePolicy] When SchedulePolicy.Immediately,
|
|
20
21
|
* the interval is set immediately on instantiation; otherwise, `set` must be
|
|
21
22
|
* called to set the interval.
|
|
22
23
|
* Defaults to `SchedulePolicy.Immediately`.
|
|
@@ -47,15 +48,14 @@ export default class AnimationFrame implements IAnimationFrame {
|
|
|
47
48
|
* If the request is pending, this cancels that pending request without
|
|
48
49
|
* invoking the action. If no request is pending, this does nothing.
|
|
49
50
|
*
|
|
50
|
-
* @param
|
|
51
|
+
* @param [policy] When ClearPolicy.Resolve, if the request
|
|
51
52
|
* was set when called, the request action is invoked after cancelling
|
|
52
53
|
* the request; otherwise, the pending action is cancelled.
|
|
53
54
|
* Defaults to `ClearPolicy.Cancel`.
|
|
54
|
-
* @param
|
|
55
|
+
* @param [time] Timestamp to pass to the action when
|
|
55
56
|
* ClearPolicy.Resolve is specified. Ignored when ClearPolicy.Cancel is
|
|
56
57
|
* specified.
|
|
57
58
|
*
|
|
58
|
-
* @returns {void}
|
|
59
59
|
* @memberof AnimationFrame
|
|
60
60
|
*/
|
|
61
61
|
clear(policy?: ClearPolicy, time?: DOMHighResTimeStamp): void;
|
package/dist/util/interval.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { SchedulePolicy, ClearPolicy } from "./policies";
|
|
2
|
+
import type { IInterval } from "./types";
|
|
2
3
|
/**
|
|
3
4
|
* Encapsulates everything associated with calling setInterval/clearInterval,
|
|
4
5
|
* and managing the lifecycle of that interval. This includes the ability to
|
|
@@ -16,10 +17,10 @@ export default class Interval implements IInterval {
|
|
|
16
17
|
* Creates an interval that will invoke the given action after
|
|
17
18
|
* the given period. The interval does not start until set is called.
|
|
18
19
|
*
|
|
19
|
-
* @param
|
|
20
|
+
* @param action The action to be invoked each time the
|
|
20
21
|
* interval period has passed.
|
|
21
|
-
* @param
|
|
22
|
-
* @param
|
|
22
|
+
* @param intervalMs The interval period.
|
|
23
|
+
* @param [schedulePolicy] When SchedulePolicy.Immediately,
|
|
23
24
|
* the interval is set immediately on instantiation; otherwise, `set` must be
|
|
24
25
|
* called to set the interval.
|
|
25
26
|
* Defaults to `SchedulePolicy.Immediately`.
|
|
@@ -29,7 +30,7 @@ export default class Interval implements IInterval {
|
|
|
29
30
|
/**
|
|
30
31
|
* Determine if the interval is active or not.
|
|
31
32
|
*
|
|
32
|
-
* @returns
|
|
33
|
+
* @returns true if the interval is active, otherwise false.
|
|
33
34
|
* @memberof Interval
|
|
34
35
|
*/
|
|
35
36
|
get isSet(): boolean;
|
|
@@ -48,12 +49,11 @@ export default class Interval implements IInterval {
|
|
|
48
49
|
* If the interval is active, this cancels that interval. If no interval is
|
|
49
50
|
* pending, this does nothing.
|
|
50
51
|
*
|
|
51
|
-
* @param
|
|
52
|
+
* @param [policy] When ClearPolicy.Resolve, if the request
|
|
52
53
|
* was set when called, the request action is invoked after cancelling
|
|
53
54
|
* the request; otherwise, the pending action is cancelled.
|
|
54
55
|
* Defaults to `ClearPolicy.Cancel`.
|
|
55
56
|
*
|
|
56
|
-
* @returns {void}
|
|
57
57
|
* @memberof Interval
|
|
58
58
|
*/
|
|
59
59
|
clear(policy?: ClearPolicy): void;
|