@khanacademy/wonder-blocks-timing 2.0.3 → 2.1.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.
@@ -0,0 +1,147 @@
1
+ import {Meta, Story, Source, Canvas} from "@storybook/addon-docs";
2
+
3
+ import {Body, HeadingSmall} from "@khanacademy/wonder-blocks-typography";
4
+ import {View} from "@khanacademy/wonder-blocks-core";
5
+ import Button from "@khanacademy/wonder-blocks-button";
6
+
7
+ import {ClearPolicy, SchedulePolicy} from "../util/policies.js";
8
+ import {useScheduledInterval} from "./use-scheduled-interval.js";
9
+
10
+ <Meta
11
+ title="Timing/useScheduledInterval"
12
+ parameters={{
13
+ chromatic: {
14
+ disableSnapshot: true,
15
+ },
16
+ }}
17
+ />
18
+
19
+ # `useScheduledInterval`
20
+
21
+ `useScheduledInterval` is a hook that provides a convenient API for setting and clearing
22
+ an interval. It is defined as follows:
23
+
24
+ ```ts
25
+ function useScheduledInterval(
26
+ action: () => mixed,
27
+ timeoutMs: number,
28
+ options?: {|
29
+ schedulePolicy?: "schedule-immediately" | "schedule-on-demand",
30
+ clearPolicy?: "resolve-on-clear" | "cancel-on-clear",
31
+ |},
32
+ ): ITimeout;
33
+
34
+ interface ITimeout {
35
+ get isSet(): boolean;
36
+ set(): void;
37
+ clear(policy?: ClearPolicy): void;
38
+ }
39
+ ```
40
+
41
+ By default the interval will be set immediately up creation. The `options` parameter can
42
+ be used to control when when the interval is schedule and whether or not `action` should be
43
+ called when the interval is cleared.
44
+
45
+ Notes:
46
+
47
+ - Because `clear` takes a param, it's import that you don't pass it directly to an event handler,
48
+ e.g. `<Button onClick={clear} />` will not work as expected.
49
+ - Calling `set` after the interval has been cleared will restart the interval.
50
+ - Updating the second paramter, `timeoutMs`, will also restart the interval.
51
+ - When the component using this hooks is unmounted, the interval will automatically be cleared.
52
+ - Calling `set` after the interval is already set does nothing.
53
+
54
+ export const Immediately = () => {
55
+ const [callCount, setCallCount] = React.useState(0);
56
+ const callback = React.useCallback(() => {
57
+ setCallCount((callCount) => callCount + 1);
58
+ }, []);
59
+ const interval = useScheduledInterval(callback, 1000);
60
+ return (
61
+ <View>
62
+ <View>isSet = {interval.isSet.toString()}</View>
63
+ <View>callCount = {callCount}</View>
64
+ <View style={{flexDirection: "row"}}>
65
+ <Button onClick={() => interval.set()}>Set interval</Button>
66
+ <Button onClick={() => interval.clear()}>Clear interval</Button>
67
+ </View>
68
+ </View>
69
+ );
70
+ };
71
+
72
+ <Canvas>
73
+ <Story name="Immediately">
74
+ <Immediately />
75
+ </Story>
76
+ </Canvas>
77
+
78
+ ```jsx
79
+ const Immediately = () => {
80
+ const [callCount, setCallCount] = React.useState(0);
81
+ const callback = React.useCallback(() => {
82
+ setCallCount((callCount) => callCount + 1);
83
+ }, []);
84
+ const interval = useScheduledInterval(callback, 1000);
85
+ return (
86
+ <View>
87
+ <View>isSet = {interval.isSet.toString()}</View>
88
+ <View>callCount = {callCount}</View>
89
+ <View style={{flexDirection: "row"}}>
90
+ <Button onClick={() => interval.set()}>Set interval</Button>
91
+ <Button onClick={() => interval.clear()}>Clear interval</Button>
92
+ </View>
93
+ </View>
94
+ );
95
+ };
96
+ ```
97
+
98
+ export const OnDemandAndResolveOnClear = () => {
99
+ const [callCount, setCallCount] = React.useState(0);
100
+ const callback = React.useCallback(() => {
101
+ console.log("action called");
102
+ setCallCount((callCount) => callCount + 1);
103
+ }, []);
104
+ const interval = useScheduledInterval(callback, 1000, {
105
+ clearPolicy: ClearPolicy.Resolve,
106
+ schedulePolicy: SchedulePolicy.OnDemand,
107
+ });
108
+ return (
109
+ <View>
110
+ <View>isSet = {interval.isSet.toString()}</View>
111
+ <View>callCount = {callCount}</View>
112
+ <View style={{flexDirection: "row"}}>
113
+ <Button onClick={() => interval.set()}>Set interval</Button>
114
+ <Button onClick={() => interval.clear()}>Clear interval</Button>
115
+ </View>
116
+ </View>
117
+ );
118
+ };
119
+
120
+ <Canvas>
121
+ <Story name="OnDemandAndResolveOnClear">
122
+ <OnDemandAndResolveOnClear />
123
+ </Story>
124
+ </Canvas>
125
+
126
+ ```jsx
127
+ const OnDemandAndResolveOnClear = () => {
128
+ const [callCount, setCallCount] = React.useState(0);
129
+ const callback = React.useCallback(() => {
130
+ setCallCount((callCount) => callCount + 1);
131
+ }, []);
132
+ const interval = useScheduledInterval(callback, 1000, {
133
+ clearPolicy: ClearPolicy.Resolve,
134
+ schedulePolicy: SchedulePolicy.OnDemand,
135
+ });
136
+ return (
137
+ <View>
138
+ <View>isSet = {interval.isSet.toString()}</View>
139
+ <View>callCount = {callCount}</View>
140
+ <View style={{flexDirection: "row"}}>
141
+ <Button onClick={() => interval.set()}>Set interval</Button>
142
+ <Button onClick={() => interval.clear()}>Clear interval</Button>
143
+ </View>
144
+ </View>
145
+ );
146
+ };
147
+ ```
@@ -0,0 +1,80 @@
1
+ // @flow
2
+ import {useEffect, useState, useCallback} from "react";
3
+
4
+ import {
5
+ SchedulePolicy as SchedulePolicies,
6
+ ClearPolicy as ClearPolicies,
7
+ } from "../util/policies.js";
8
+ import type {ITimeout, ClearPolicy, Options} from "../util/types.js";
9
+
10
+ import {useUpdatingRef} from "./internal/use-updating-ref.js";
11
+ import {useTimeout} from "./use-timeout.js";
12
+
13
+ export function useScheduledTimeout(
14
+ action: () => mixed,
15
+ timeoutMs: number,
16
+ options?: Options,
17
+ ): ITimeout {
18
+ if (typeof action !== "function") {
19
+ throw new Error("Action must be a function");
20
+ }
21
+
22
+ if (timeoutMs < 0) {
23
+ throw new Error("Timeout period must be >= 0");
24
+ }
25
+
26
+ const schedulePolicy =
27
+ options?.schedulePolicy ?? SchedulePolicies.Immediately;
28
+
29
+ const [isSet, setIsSet] = useState(
30
+ schedulePolicy === SchedulePolicies.Immediately,
31
+ );
32
+
33
+ const set = useCallback(() => setIsSet(true), []);
34
+
35
+ // This wrapper isn't present in useScheduledInterval because we
36
+ // don't need to update `isSet` in that situations.
37
+ const wrappedAction = useCallback(() => {
38
+ setIsSet(false);
39
+ action();
40
+ }, [action]);
41
+
42
+ const actionRef = useUpdatingRef(wrappedAction);
43
+
44
+ const clear = useCallback(
45
+ (policy?: ClearPolicy) => {
46
+ policy = policy ?? options?.clearPolicy;
47
+ if (isSet && policy === ClearPolicies.Resolve) {
48
+ actionRef.current();
49
+ }
50
+ setIsSet(false);
51
+ },
52
+ // react-hooks/exhaustive-deps doesn't require refs to be
53
+ // listed in the deps array. Unfortunately, in this situation
54
+ // it doesn't recognized actionRef as a ref.
55
+ [actionRef, isSet, options?.clearPolicy],
56
+ );
57
+
58
+ const runOnUnmountRef = useUpdatingRef(
59
+ isSet && options?.clearPolicy === ClearPolicies.Resolve,
60
+ );
61
+
62
+ useEffect(() => {
63
+ return () => {
64
+ // This code will only run with the component using this
65
+ // hook is unmounted.
66
+ // eslint-disable-next-line react-hooks/exhaustive-deps
67
+ if (runOnUnmountRef.current) {
68
+ // eslint-disable-next-line react-hooks/exhaustive-deps
69
+ actionRef.current();
70
+ }
71
+ };
72
+ // This eslint rule doesn't realize actionRef and runOnUnmountRef
73
+ // a both refs and thus do not have to be listed as deps.
74
+ // eslint-disable-next-line react-hooks/exhaustive-deps
75
+ }, []);
76
+
77
+ useTimeout(wrappedAction, timeoutMs, isSet);
78
+
79
+ return {isSet, set, clear};
80
+ }
@@ -0,0 +1,148 @@
1
+ import {Meta, Story, Source, Canvas} from "@storybook/addon-docs";
2
+
3
+ import {Body, HeadingSmall} from "@khanacademy/wonder-blocks-typography";
4
+ import {View} from "@khanacademy/wonder-blocks-core";
5
+ import Button from "@khanacademy/wonder-blocks-button";
6
+
7
+ import {ClearPolicy, SchedulePolicy} from "../util/policies.js";
8
+ import {useScheduledTimeout} from "./use-scheduled-timeout.js";
9
+
10
+ <Meta
11
+ title="Timing/useScheduledTimeout"
12
+ parameters={{
13
+ chromatic: {
14
+ disableSnapshot: true,
15
+ },
16
+ }}
17
+ />
18
+
19
+ # `useScheduledTimeout`
20
+
21
+ `useScheduledTimeout` is a hook that provides a convenient API for setting and clearing
22
+ a timeout. It is defined as follows:
23
+
24
+ ```ts
25
+ function useScheduledTimeout(
26
+ action: () => mixed,
27
+ timeoutMs: number,
28
+ options?: {|
29
+ schedulePolicy?: "schedule-immediately" | "schedule-on-demand",
30
+ clearPolicy?: "resolve-on-clear" | "cancel-on-clear",
31
+ |},
32
+ ): ITimeout;
33
+
34
+ interface ITimeout {
35
+ get isSet(): boolean;
36
+ set(): void;
37
+ clear(policy?: ClearPolicy): void;
38
+ }
39
+ ```
40
+
41
+ By default the timeout will be set immediately up creation. The `options` parameter can
42
+ be used to control when when the timeout is schedule and whether or not `action` should be
43
+ called when the timeout is cleared.
44
+
45
+ Notes:
46
+
47
+ - Because `clear` takes a param, it's import that you don't pass it directly to an event handler,
48
+ e.g. `<Button onClick={clear} />` will not work as expected.
49
+ - Calling `set` after the timeout has expired will restart the timeout.
50
+ - Updating the second paramter, `timeoutMs`, will also restart the timeout.
51
+ - When the component using this hooks is unmounted, the timeout will automatically be cleared.
52
+ - Calling `set` after the timeout is set but before it expires means that the timeout will be
53
+ reset and will call `action`, `timeoutMs` after the most recent call to `set` was made.
54
+
55
+ export const Immediately = () => {
56
+ const [callCount, setCallCount] = React.useState(0);
57
+ const callback = React.useCallback(() => {
58
+ setCallCount((callCount) => callCount + 1);
59
+ }, []);
60
+ const {isSet, set, clear} = useScheduledTimeout(callback, 1000);
61
+ return (
62
+ <View>
63
+ <View>isSet = {isSet.toString()}</View>
64
+ <View>callCount = {callCount}</View>
65
+ <View style={{flexDirection: "row"}}>
66
+ <Button onClick={set}>Set timeout</Button>
67
+ <Button onClick={clear}>Clear timeout</Button>
68
+ </View>
69
+ </View>
70
+ );
71
+ };
72
+
73
+ <Canvas>
74
+ <Story name="Immediately">
75
+ <Immediately />
76
+ </Story>
77
+ </Canvas>
78
+
79
+ ```jsx
80
+ const Immediately = () => {
81
+ const [callCount, setCallCount] = React.useState(0);
82
+ const callback = React.useCallback(() => {
83
+ setCallCount((callCount) => callCount + 1);
84
+ }, []);
85
+ const {isSet, set, clear} = useScheduledTimeout(callback, 1000);
86
+ return (
87
+ <View>
88
+ <View>isSet = {isSet.toString()}</View>
89
+ <View>callCount = {callCount}</View>
90
+ <View style={{flexDirection: "row"}}>
91
+ <Button onClick={() => set()}>Set timeout</Button>
92
+ <Button onClick={() => clear()}>Clear timeout</Button>
93
+ </View>
94
+ </View>
95
+ );
96
+ };
97
+ ```
98
+
99
+ export const OnDemandAndResolveOnClear = () => {
100
+ const [callCount, setCallCount] = React.useState(0);
101
+ const callback = React.useCallback(() => {
102
+ console.log("action called");
103
+ setCallCount((callCount) => callCount + 1);
104
+ }, []);
105
+ const {isSet, set, clear} = useScheduledTimeout(callback, 1000, {
106
+ clearPolicy: ClearPolicy.Resolve,
107
+ schedulePolicy: SchedulePolicy.OnDemand,
108
+ });
109
+ return (
110
+ <View>
111
+ <View>isSet = {isSet.toString()}</View>
112
+ <View>callCount = {callCount}</View>
113
+ <View style={{flexDirection: "row"}}>
114
+ <Button onClick={() => set()}>Set timeout</Button>
115
+ <Button onClick={() => clear()}>Clear timeout</Button>
116
+ </View>
117
+ </View>
118
+ );
119
+ };
120
+
121
+ <Canvas>
122
+ <Story name="OnDemandAndResolveOnClear">
123
+ <OnDemandAndResolveOnClear />
124
+ </Story>
125
+ </Canvas>
126
+
127
+ ```jsx
128
+ const OnDemandAndResolveOnClear = () => {
129
+ const [callCount, setCallCount] = React.useState(0);
130
+ const callback = React.useCallback(() => {
131
+ setCallCount((callCount) => callCount + 1);
132
+ }, []);
133
+ const {isSet, set, clear} = useScheduledTimeout(callback, 1000, {
134
+ clearPolicy: ClearPolicy.Resolve,
135
+ schedulePolicy: SchedulePolicy.OnDemand,
136
+ });
137
+ return (
138
+ <View>
139
+ <View>isSet = {isSet.toString()}</View>
140
+ <View>callCount = {callCount}</View>
141
+ <View style={{flexDirection: "row"}}>
142
+ <Button onClick={() => set()}>Set timeout</Button>
143
+ <Button onClick={() => clear()}>Clear timeout</Button>
144
+ </View>
145
+ </View>
146
+ );
147
+ };
148
+ ```
@@ -1,70 +1,37 @@
1
1
  // @flow
2
- import {useEffect, useState, useCallback, useRef} from "react";
2
+ import {useEffect} from "react";
3
3
 
4
- import {
5
- SchedulePolicy as SchedulePolicies,
6
- ClearPolicy as ClearPolicies,
7
- } from "../util/policies.js";
8
- import type {ITimeout, ClearPolicy, Options} from "../util/types.js";
4
+ import {useUpdatingRef} from "./internal/use-updating-ref.js";
9
5
 
6
+ /**
7
+ * A simple hook for using `setTimeout`.
8
+ *
9
+ * @param action called after `timeoutMs` when `active` is true
10
+ * @param timeoutMs the duration after which `action` is called
11
+ * @param active whether or not the interval is active
12
+ */
10
13
  export function useTimeout(
11
14
  action: () => mixed,
12
15
  timeoutMs: number,
13
- options?: Options,
14
- ): ITimeout {
15
- const schedulePolicy =
16
- options?.schedulePolicy ?? SchedulePolicies.Immediately;
17
- const [isSet, setIsSet] = useState(
18
- schedulePolicy === SchedulePolicies.Immediately,
19
- );
20
- const actionRef = useRef(action);
21
- const mountedRef = useRef(false);
16
+ active: boolean,
17
+ ) {
18
+ // We using a ref instead of a callback for `action` to avoid resetting
19
+ // the interval whenever the `action` changes.
20
+ const actionRef = useUpdatingRef(action);
22
21
 
23
22
  useEffect(() => {
24
- mountedRef.current = true;
25
- return () => {
26
- mountedRef.current = false;
27
- };
28
- }, []);
29
-
30
- useEffect(() => {
31
- actionRef.current = action;
32
- }, [action]);
33
-
34
- const clear = useCallback(
35
- (policy?: ClearPolicy) => {
36
- if ((policy ?? options?.clearPolicy) === ClearPolicies.Resolve) {
23
+ if (active) {
24
+ const timeoutId = setTimeout(() => {
37
25
  actionRef.current();
38
- }
39
- // This will cause the useEffect below to re-run
40
- setIsSet(false);
41
- },
42
- [options?.clearPolicy],
43
- );
44
-
45
- const set = useCallback(() => {
46
- if (isSet) {
47
- clear();
48
- }
49
- // This will cause the useEffect below to re-run
50
- setIsSet(true);
51
- }, [clear, isSet]);
52
-
53
- useEffect(() => {
54
- if (isSet && mountedRef.current) {
55
- const timeout = window.setTimeout(() => {
56
- actionRef.current();
57
- setIsSet(false);
58
26
  }, timeoutMs);
59
27
 
60
28
  return () => {
61
- window.clearTimeout(timeout);
62
- if (!mountedRef.current) {
63
- clear();
64
- }
29
+ clearTimeout(timeoutId);
65
30
  };
66
31
  }
67
- }, [clear, isSet, timeoutMs]);
68
-
69
- return {isSet, set, clear};
32
+ // actionRef isn't actually required, but react-hooks/exhaustive-deps
33
+ // doesn't recognize it as a ref and thus complains if it isn't in the
34
+ // deps list. It isn't a big deal though since the value ofactionRef
35
+ // never changes (only its contents do).
36
+ }, [timeoutMs, active, actionRef]);
70
37
  }
@@ -4,7 +4,6 @@ import {Body, HeadingSmall} from "@khanacademy/wonder-blocks-typography";
4
4
  import {View} from "@khanacademy/wonder-blocks-core";
5
5
  import Button from "@khanacademy/wonder-blocks-button";
6
6
 
7
- import {ClearPolicy, SchedulePolicy} from "../util/policies.js";
8
7
  import {useTimeout} from "./use-timeout.js";
9
8
 
10
9
  <Meta
@@ -18,134 +17,63 @@ import {useTimeout} from "./use-timeout.js";
18
17
 
19
18
  # `useTimeout`
20
19
 
21
- `useTimeout` is a hook that provides a convenient API for setting and clearing
22
- a timeout. It is defined as follows:
20
+ `useTimeout` is a hook that provides a simple API for using timers safely.
21
+ It is defined as follows:
23
22
 
24
23
  ```ts
25
24
  function useTimeout(
26
25
  action: () => mixed,
27
26
  timeoutMs: number,
28
- options?: {|
29
- schedulePolicy?: "schedule-immediately" | "schedule-on-demand",
30
- clearPolicy?: "resolve-on-clear" | "cancel-on-clear",
31
- |},
32
- ): ITimeout;
33
-
34
- interface ITimeout {
35
- get isSet(): boolean;
36
- set(): void;
37
- clear(policy?: ClearPolicy): void;
38
- }
27
+ active: boolean,
28
+ ): void;
39
29
  ```
40
30
 
41
- By default the timeout will be set immediately up creation. The `options` parameter can
42
- be used to control when when the timeout is schedule and whether or not `action` should be
43
- called when the timeout is cleared.
44
-
45
31
  Notes:
46
32
 
47
- - Because `clear` takes a param, it's import that you don't pass it directly to an event handler,
48
- e.g. `<Button onClick={clear} />` will not work as expected.
49
- - Calling `set` after the timeout has expired will restart the timeout.
50
- - Updating the second paramter, `timeoutMs`, will also restart the timeout.
51
- - When the component using this hooks is unmounted, the timeout will automatically be cleared.
52
- - Calling `set` after the timeout is set but before it expires means that the timeout will be
53
- reset and will call `action`, `timeoutMs` after the most recent call to `set` was made.
54
-
55
- export const Immediately = () => {
56
- const [callCount, setCallCount] = React.useState(0);
57
- const callback = React.useCallback(() => {
58
- setCallCount((callCount) => callCount + 1);
59
- }, []);
60
- const {isSet, set, clear} = useTimeout(callback, 1000);
61
- return (
62
- <View>
63
- <View>isSet = {isSet.toString()}</View>
64
- <View>callCount = {callCount}</View>
65
- <View style={{flexDirection: "row"}}>
66
- <Button onClick={set}>Set timeout</Button>
67
- <Button onClick={clear}>Clear timeout</Button>
68
- </View>
69
- </View>
70
- );
71
- };
72
-
73
- <Canvas>
74
- <Story name="Immediately">
75
- <Immediately />
76
- </Story>
77
- </Canvas>
78
-
79
- ```jsx
80
- const Immediately = () => {
81
- const [callCount, setCallCount] = React.useState(0);
82
- const callback = React.useCallback(() => {
83
- setCallCount((callCount) => callCount + 1);
84
- }, []);
85
- const {isSet, set, clear} = useTimeout(callback, 1000);
86
- return (
87
- <View>
88
- <View>isSet = {isSet.toString()}</View>
89
- <View>callCount = {callCount}</View>
90
- <View style={{flexDirection: "row"}}>
91
- <Button onClick={() => set()}>Set timeout</Button>
92
- <Button onClick={() => clear()}>Clear timeout</Button>
93
- </View>
94
- </View>
95
- );
96
- };
97
- ```
33
+ - Setting `active` to `true` will start the timeout and setting it to `false`
34
+ will stop it
35
+ - Changing the value of `timeoutMs` will reset the timeout, changing `action`
36
+ will not.
98
37
 
99
- export const OnDemandAndResolveOnClear = () => {
38
+ export const BasicUsage = () => {
100
39
  const [callCount, setCallCount] = React.useState(0);
40
+ const [active, setActive] = React.useState(false);
101
41
  const callback = React.useCallback(() => {
102
- console.log("action called");
103
42
  setCallCount((callCount) => callCount + 1);
104
43
  }, []);
105
- const {isSet, set, clear} = useTimeout(callback, 1000, {
106
- clearPolicy: ClearPolicy.Resolve,
107
- schedulePolicy: SchedulePolicy.OnDemand,
108
- });
44
+ useTimeout(callback, 1000, active);
109
45
  return (
110
46
  <View>
111
- <View>isSet = {isSet.toString()}</View>
112
47
  <View>callCount = {callCount}</View>
113
- <View style={{flexDirection: "row"}}>
114
- <Button onClick={() => set()}>Set timeout</Button>
115
- <Button onClick={() => clear()}>Clear timeout</Button>
116
- </View>
48
+ <View>active = {active.toString()}</View>
49
+ <Button onClick={() => setActive(!active)} style={{width: 200}}>
50
+ Toggle active
51
+ </Button>
117
52
  </View>
118
53
  );
119
54
  };
120
55
 
121
56
  <Canvas>
122
- <Story name="OnDemandAndResolveOnClear">
123
- <OnDemandAndResolveOnClear />
57
+ <Story name="BasicUsage">
58
+ <BasicUsage />
124
59
  </Story>
125
60
  </Canvas>
126
61
 
127
62
  ```jsx
128
- const OnDemandAndResolveOnClear = () => {
63
+ export const BasicUsage = () => {
129
64
  const [callCount, setCallCount] = React.useState(0);
65
+ const [active, setActive] = React.useState(false);
130
66
  const callback = React.useCallback(() => {
131
67
  setCallCount((callCount) => callCount + 1);
132
68
  }, []);
133
- const {isSet, set, clear} = useTimeout(
134
- callback,
135
- 1000,
136
- {
137
- clearPolicy: ClearPolicy.Resolve,
138
- schedulePolicy: SchedulePolicy.OnDemand,
139
- },
140
- );
69
+ useTimeout(callback, 1000, active);
141
70
  return (
142
71
  <View>
143
- <View>isSet = {isSet.toString()}</View>
144
72
  <View>callCount = {callCount}</View>
145
- <View style={{flexDirection: "row"}}>
146
- <Button onClick={() => set()}>Set timeout</Button>
147
- <Button onClick={() => clear()}>Clear timeout</Button>
148
- </View>
73
+ <View>active = {active.toString()}</View>
74
+ <Button onClick={() => setActive(!active)} style={{width: 200}}>
75
+ Toggle active
76
+ </Button>
149
77
  </View>
150
78
  );
151
79
  };
package/src/index.js CHANGED
@@ -21,4 +21,7 @@ export type {
21
21
 
22
22
  export {SchedulePolicy, ClearPolicy} from "./util/policies.js";
23
23
  export {default as withActionScheduler} from "./components/with-action-scheduler.js";
24
+ export {useInterval} from "./hooks/use-interval.js";
24
25
  export {useTimeout} from "./hooks/use-timeout.js";
26
+ export {useScheduledInterval} from "./hooks/use-scheduled-interval.js";
27
+ export {useScheduledTimeout} from "./hooks/use-scheduled-timeout.js";
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2018 Khan Academy
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.