@khanacademy/wonder-blocks-timing 4.0.1 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/components/with-action-scheduler.d.ts +4 -1
- package/dist/es/index.js +93 -105
- 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 +92 -105
- package/dist/util/animation-frame.d.ts +6 -6
- package/dist/util/interval.d.ts +8 -8
- package/dist/util/policies.d.ts +12 -8
- package/dist/util/timeout.d.ts +8 -7
- package/dist/util/types.d.ts +18 -10
- package/package.json +3 -3
- package/src/components/with-action-scheduler.tsx +9 -1
- 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/__tests__/animation-frame.test.ts +9 -10
- package/src/util/animation-frame.ts +12 -16
- package/src/util/interval.ts +13 -18
- package/src/util/policies.ts +13 -8
- package/src/util/timeout.ts +14 -18
- package/src/util/types.ts +19 -11
- package/tsconfig-build.json +2 -4
- package/tsconfig-build.tsbuildinfo +1 -1
- package/dist/components/action-scheduler-provider.js.flow +0 -33
- package/dist/components/with-action-scheduler.js.flow +0 -22
- package/dist/hooks/internal/use-updating-ref.d.ts +0 -13
- package/dist/hooks/internal/use-updating-ref.js.flow +0 -20
- package/dist/hooks/use-interval.js.flow +0 -17
- package/dist/hooks/use-scheduled-interval.d.ts +0 -2
- package/dist/hooks/use-scheduled-interval.js.flow +0 -12
- package/dist/hooks/use-scheduled-timeout.d.ts +0 -2
- package/dist/hooks/use-scheduled-timeout.js.flow +0 -12
- package/dist/hooks/use-timeout.js.flow +0 -17
- package/dist/index.js.flow +0 -31
- package/dist/util/action-scheduler.js.flow +0 -38
- package/dist/util/animation-frame.js.flow +0 -70
- package/dist/util/interval.js.flow +0 -69
- package/dist/util/policies.js.flow +0 -14
- package/dist/util/timeout.js.flow +0 -71
- package/dist/util/types.js.flow +0 -232
- package/dist/util/types.typestest.js.flow +0 -6
- 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.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- f72f7dd4: - **[BREAKING CHANGE]** Policy types are now using enums across all APIs
|
|
8
|
+
- **[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}`.
|
|
9
|
+
- **[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}`.
|
|
10
|
+
- **[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).
|
|
11
|
+
- **[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).
|
|
12
|
+
- **[BUGFIX]** `useTimeout` will now correctly reset the timeout when the `set` method is called, as intended.
|
|
13
|
+
- **[BUGFIX]** `useInterval` will now correctly reset the interval when the `set` method is called, as intended.
|
|
14
|
+
|
|
15
|
+
## 4.0.2
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- 695f2567: Provide a friendly name (for dev tools) for withActionScheduler
|
|
20
|
+
|
|
3
21
|
## 4.0.1
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
|
@@ -10,5 +10,8 @@ type WithoutActionScheduler<T> = Omit<T, "schedule">;
|
|
|
10
10
|
* the additional action scheduler prop. To attach the additional prop to
|
|
11
11
|
* these props use the `WithActionScheduler` type.
|
|
12
12
|
*/
|
|
13
|
-
export default function withActionScheduler<Props extends WithActionSchedulerProps>(WrappedComponent: React.ComponentType<Props>):
|
|
13
|
+
export default function withActionScheduler<Props extends WithActionSchedulerProps>(WrappedComponent: React.ComponentType<Props>): {
|
|
14
|
+
(props: WithoutActionScheduler<Props>): JSX.Element;
|
|
15
|
+
displayName: string;
|
|
16
|
+
};
|
|
14
17
|
export {};
|
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) {
|
|
@@ -201,121 +208,102 @@ function _extends() {
|
|
|
201
208
|
}
|
|
202
209
|
|
|
203
210
|
function withActionScheduler(WrappedComponent) {
|
|
204
|
-
|
|
211
|
+
const displayName = `withActionScheduler(${WrappedComponent.displayName || WrappedComponent.name})`;
|
|
212
|
+
const C = props => React.createElement(ActionSchedulerProvider, null, schedule => React.createElement(WrappedComponent, _extends({}, props, {
|
|
205
213
|
schedule: schedule
|
|
206
214
|
})));
|
|
215
|
+
C.displayName = displayName;
|
|
216
|
+
return C;
|
|
207
217
|
}
|
|
208
218
|
|
|
209
|
-
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
function useInterval(action, intervalMs, active) {
|
|
218
|
-
const actionRef = useUpdatingRef(action);
|
|
219
|
-
useEffect(() => {
|
|
220
|
-
if (active) {
|
|
221
|
-
const intervalId = setInterval(() => {
|
|
222
|
-
actionRef.current();
|
|
223
|
-
}, intervalMs);
|
|
224
|
-
return () => {
|
|
225
|
-
clearInterval(intervalId);
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
}, [intervalMs, active, actionRef]);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
function useTimeout(action, timeoutMs, active) {
|
|
232
|
-
const actionRef = useUpdatingRef(action);
|
|
233
|
-
useEffect(() => {
|
|
234
|
-
if (active) {
|
|
235
|
-
const timeoutId = setTimeout(() => {
|
|
236
|
-
actionRef.current();
|
|
237
|
-
}, timeoutMs);
|
|
238
|
-
return () => {
|
|
239
|
-
clearTimeout(timeoutId);
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
}, [timeoutMs, active, actionRef]);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
function useScheduledInterval(action, intervalMs, options) {
|
|
246
|
-
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);
|
|
247
227
|
if (typeof action !== "function") {
|
|
248
228
|
throw new Error("Action must be a function");
|
|
249
229
|
}
|
|
250
|
-
if (
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const set = useCallback(() => setIsSet(true), []);
|
|
256
|
-
const actionRef = useUpdatingRef(action);
|
|
257
|
-
const clear = useCallback(policy => {
|
|
258
|
-
var _policy;
|
|
259
|
-
policy = (_policy = policy) != null ? _policy : options == null ? void 0 : options.clearPolicy;
|
|
260
|
-
if (isSet && policy === ClearPolicy.Resolve) {
|
|
261
|
-
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();
|
|
262
235
|
}
|
|
263
|
-
|
|
264
|
-
}, [actionRef, isSet, options == null ? void 0 : options.clearPolicy]);
|
|
265
|
-
const runOnUnmountRef = useUpdatingRef(isSet && (options == null ? void 0 : options.clearPolicy) === ClearPolicy.Resolve);
|
|
236
|
+
}
|
|
266
237
|
useEffect(() => {
|
|
238
|
+
intervalRef.current = new Interval(() => {
|
|
239
|
+
actionProxyRef.current == null ? void 0 : actionProxyRef.current();
|
|
240
|
+
}, intervalMs, schedulePolicy);
|
|
267
241
|
return () => {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
242
|
+
var _intervalRef$current2;
|
|
243
|
+
(_intervalRef$current2 = intervalRef.current) == null ? void 0 : _intervalRef$current2.clear(clearPolicy);
|
|
244
|
+
intervalRef.current = null;
|
|
271
245
|
};
|
|
272
|
-
}, []);
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
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;
|
|
279
262
|
}
|
|
280
263
|
|
|
281
|
-
function
|
|
282
|
-
|
|
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);
|
|
283
272
|
if (typeof action !== "function") {
|
|
284
273
|
throw new Error("Action must be a function");
|
|
285
274
|
}
|
|
286
|
-
if (
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
const set = useCallback(() => setIsSet(true), []);
|
|
292
|
-
const wrappedAction = useCallback(() => {
|
|
293
|
-
setIsSet(false);
|
|
294
|
-
action();
|
|
295
|
-
}, [action]);
|
|
296
|
-
const actionRef = useUpdatingRef(wrappedAction);
|
|
297
|
-
const clear = useCallback(policy => {
|
|
298
|
-
var _policy;
|
|
299
|
-
policy = (_policy = policy) != null ? _policy : options == null ? void 0 : options.clearPolicy;
|
|
300
|
-
if (isSet && policy === ClearPolicy.Resolve) {
|
|
301
|
-
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();
|
|
302
280
|
}
|
|
303
|
-
|
|
304
|
-
}, [actionRef, isSet, options == null ? void 0 : options.clearPolicy]);
|
|
305
|
-
const runOnUnmountRef = useUpdatingRef(isSet && (options == null ? void 0 : options.clearPolicy) === ClearPolicy.Resolve);
|
|
281
|
+
}
|
|
306
282
|
useEffect(() => {
|
|
283
|
+
timeoutRef.current = new Timeout(() => {
|
|
284
|
+
actionProxyRef.current == null ? void 0 : actionProxyRef.current();
|
|
285
|
+
}, timeoutMs, schedulePolicy);
|
|
307
286
|
return () => {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
287
|
+
var _timeoutRef$current2;
|
|
288
|
+
(_timeoutRef$current2 = timeoutRef.current) == null ? void 0 : _timeoutRef$current2.clear(clearPolicy);
|
|
289
|
+
timeoutRef.current = null;
|
|
311
290
|
};
|
|
312
|
-
}, []);
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
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;
|
|
319
307
|
}
|
|
320
308
|
|
|
321
|
-
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) {
|
|
@@ -224,128 +231,108 @@ function _extends() {
|
|
|
224
231
|
}
|
|
225
232
|
|
|
226
233
|
function withActionScheduler(WrappedComponent) {
|
|
227
|
-
|
|
234
|
+
const displayName = `withActionScheduler(${WrappedComponent.displayName || WrappedComponent.name})`;
|
|
235
|
+
const C = props => React__namespace.createElement(ActionSchedulerProvider, null, schedule => React__namespace.createElement(WrappedComponent, _extends({}, props, {
|
|
228
236
|
schedule: schedule
|
|
229
237
|
})));
|
|
238
|
+
C.displayName = displayName;
|
|
239
|
+
return C;
|
|
230
240
|
}
|
|
231
241
|
|
|
232
|
-
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
function useInterval(action, intervalMs, active) {
|
|
241
|
-
const actionRef = useUpdatingRef(action);
|
|
242
|
-
React.useEffect(() => {
|
|
243
|
-
if (active) {
|
|
244
|
-
const intervalId = setInterval(() => {
|
|
245
|
-
actionRef.current();
|
|
246
|
-
}, intervalMs);
|
|
247
|
-
return () => {
|
|
248
|
-
clearInterval(intervalId);
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
}, [intervalMs, active, actionRef]);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
function useTimeout(action, timeoutMs, active) {
|
|
255
|
-
const actionRef = useUpdatingRef(action);
|
|
256
|
-
React.useEffect(() => {
|
|
257
|
-
if (active) {
|
|
258
|
-
const timeoutId = setTimeout(() => {
|
|
259
|
-
actionRef.current();
|
|
260
|
-
}, timeoutMs);
|
|
261
|
-
return () => {
|
|
262
|
-
clearTimeout(timeoutId);
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
}, [timeoutMs, active, actionRef]);
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
function useScheduledInterval(action, intervalMs, options) {
|
|
269
|
-
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);
|
|
270
250
|
if (typeof action !== "function") {
|
|
271
251
|
throw new Error("Action must be a function");
|
|
272
252
|
}
|
|
273
|
-
if (
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
const set = React.useCallback(() => setIsSet(true), []);
|
|
279
|
-
const actionRef = useUpdatingRef(action);
|
|
280
|
-
const clear = React.useCallback(policy => {
|
|
281
|
-
var _policy;
|
|
282
|
-
policy = (_policy = policy) != null ? _policy : options == null ? void 0 : options.clearPolicy;
|
|
283
|
-
if (isSet && policy === ClearPolicy.Resolve) {
|
|
284
|
-
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();
|
|
285
258
|
}
|
|
286
|
-
|
|
287
|
-
}, [actionRef, isSet, options == null ? void 0 : options.clearPolicy]);
|
|
288
|
-
const runOnUnmountRef = useUpdatingRef(isSet && (options == null ? void 0 : options.clearPolicy) === ClearPolicy.Resolve);
|
|
259
|
+
}
|
|
289
260
|
React.useEffect(() => {
|
|
261
|
+
intervalRef.current = new Interval(() => {
|
|
262
|
+
actionProxyRef.current == null ? void 0 : actionProxyRef.current();
|
|
263
|
+
}, intervalMs, schedulePolicy);
|
|
290
264
|
return () => {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
265
|
+
var _intervalRef$current2;
|
|
266
|
+
(_intervalRef$current2 = intervalRef.current) == null ? void 0 : _intervalRef$current2.clear(clearPolicy);
|
|
267
|
+
intervalRef.current = null;
|
|
294
268
|
};
|
|
295
|
-
}, []);
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
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;
|
|
302
285
|
}
|
|
303
286
|
|
|
304
|
-
function
|
|
305
|
-
|
|
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);
|
|
306
295
|
if (typeof action !== "function") {
|
|
307
296
|
throw new Error("Action must be a function");
|
|
308
297
|
}
|
|
309
|
-
if (
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
const set = React.useCallback(() => setIsSet(true), []);
|
|
315
|
-
const wrappedAction = React.useCallback(() => {
|
|
316
|
-
setIsSet(false);
|
|
317
|
-
action();
|
|
318
|
-
}, [action]);
|
|
319
|
-
const actionRef = useUpdatingRef(wrappedAction);
|
|
320
|
-
const clear = React.useCallback(policy => {
|
|
321
|
-
var _policy;
|
|
322
|
-
policy = (_policy = policy) != null ? _policy : options == null ? void 0 : options.clearPolicy;
|
|
323
|
-
if (isSet && policy === ClearPolicy.Resolve) {
|
|
324
|
-
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();
|
|
325
303
|
}
|
|
326
|
-
|
|
327
|
-
}, [actionRef, isSet, options == null ? void 0 : options.clearPolicy]);
|
|
328
|
-
const runOnUnmountRef = useUpdatingRef(isSet && (options == null ? void 0 : options.clearPolicy) === ClearPolicy.Resolve);
|
|
304
|
+
}
|
|
329
305
|
React.useEffect(() => {
|
|
306
|
+
timeoutRef.current = new Timeout(() => {
|
|
307
|
+
actionProxyRef.current == null ? void 0 : actionProxyRef.current();
|
|
308
|
+
}, timeoutMs, schedulePolicy);
|
|
330
309
|
return () => {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
310
|
+
var _timeoutRef$current2;
|
|
311
|
+
(_timeoutRef$current2 = timeoutRef.current) == null ? void 0 : _timeoutRef$current2.clear(clearPolicy);
|
|
312
|
+
timeoutRef.current = null;
|
|
334
313
|
};
|
|
335
|
-
}, []);
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
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;
|
|
342
330
|
}
|
|
343
331
|
|
|
332
|
+
exports.ActionPolicy = ActionPolicy;
|
|
344
333
|
exports.ActionSchedulerProvider = ActionSchedulerProvider;
|
|
345
334
|
exports.ClearPolicy = ClearPolicy;
|
|
346
335
|
exports.SchedulePolicy = SchedulePolicy;
|
|
347
336
|
exports.useInterval = useInterval;
|
|
348
|
-
exports.useScheduledInterval = useScheduledInterval;
|
|
349
|
-
exports.useScheduledTimeout = useScheduledTimeout;
|
|
350
337
|
exports.useTimeout = useTimeout;
|
|
351
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;
|