@khanacademy/wonder-blocks-timing 5.0.1 → 6.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 +12 -0
- package/dist/components/with-action-scheduler.d.ts +1 -1
- package/package.json +4 -3
- package/src/components/__tests__/action-scheduler-provider.test.tsx +0 -36
- package/src/components/__tests__/with-action-scheduler.test.tsx +0 -22
- package/src/components/action-scheduler-provider.ts +0 -35
- package/src/components/with-action-scheduler.tsx +0 -36
- package/src/hooks/__tests__/use-interval.test.ts +0 -520
- package/src/hooks/__tests__/use-timeout.test.ts +0 -489
- package/src/hooks/use-interval.ts +0 -101
- package/src/hooks/use-timeout.ts +0 -101
- package/src/index.ts +0 -17
- package/src/util/__tests__/action-scheduler.test.ts +0 -271
- package/src/util/__tests__/animation-frame.test.ts +0 -225
- package/src/util/__tests__/interval.test.ts +0 -234
- package/src/util/__tests__/timeout.test.ts +0 -224
- package/src/util/action-scheduler.ts +0 -89
- package/src/util/animation-frame.ts +0 -103
- package/src/util/interval.ts +0 -102
- package/src/util/policies.ts +0 -14
- package/src/util/timeout.ts +0 -108
- package/src/util/types.ts +0 -256
- package/src/util/types.typestest.tsx +0 -72
- package/tsconfig-build.json +0 -9
- package/tsconfig-build.tsbuildinfo +0 -1
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
import Interval from "../interval";
|
|
2
|
-
import {SchedulePolicy, ClearPolicy} from "../policies";
|
|
3
|
-
|
|
4
|
-
describe("Interval", () => {
|
|
5
|
-
beforeEach(() => {
|
|
6
|
-
jest.useFakeTimers();
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
afterEach(() => {
|
|
10
|
-
jest.restoreAllMocks();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
describe("constructor", () => {
|
|
14
|
-
it("creates instance", () => {
|
|
15
|
-
// Arrange
|
|
16
|
-
|
|
17
|
-
// Act
|
|
18
|
-
const result = new Interval(() => {}, 1000);
|
|
19
|
-
|
|
20
|
-
// Assert
|
|
21
|
-
expect(result).toBeDefined();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it("throws if the action is not a function", () => {
|
|
25
|
-
// Arrange
|
|
26
|
-
|
|
27
|
-
// Act
|
|
28
|
-
const underTest = () => new Interval(null as any, 1);
|
|
29
|
-
|
|
30
|
-
// Assert
|
|
31
|
-
expect(underTest).toThrowErrorMatchingInlineSnapshot(
|
|
32
|
-
`"Action must be a function"`,
|
|
33
|
-
);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it("throws if the period is less than 1", () => {
|
|
37
|
-
// Arrange
|
|
38
|
-
|
|
39
|
-
// Act
|
|
40
|
-
const underTest = () => new Interval(() => {}, 0);
|
|
41
|
-
|
|
42
|
-
// Assert
|
|
43
|
-
expect(underTest).toThrowErrorMatchingInlineSnapshot(
|
|
44
|
-
`"Interval period must be >= 1"`,
|
|
45
|
-
);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it("sets an interval when schedule policy is SchedulePolicy.Immediately", () => {
|
|
49
|
-
// Arrange
|
|
50
|
-
const intervalSpy = jest.spyOn(global, "setInterval");
|
|
51
|
-
|
|
52
|
-
// Act
|
|
53
|
-
// eslint-disable-next-line no-new
|
|
54
|
-
new Interval(() => {}, 1000, SchedulePolicy.Immediately);
|
|
55
|
-
|
|
56
|
-
// Assert
|
|
57
|
-
expect(intervalSpy).toHaveBeenCalledTimes(1);
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe("isSet", () => {
|
|
62
|
-
it("is false when the interval has not been set", () => {
|
|
63
|
-
// Arrange
|
|
64
|
-
const interval = new Interval(
|
|
65
|
-
() => {},
|
|
66
|
-
1000,
|
|
67
|
-
SchedulePolicy.OnDemand,
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
// Act
|
|
71
|
-
const result = interval.isSet;
|
|
72
|
-
|
|
73
|
-
// Assert
|
|
74
|
-
expect(result).toBeFalsy();
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it("is true when the interval is active", () => {
|
|
78
|
-
// Arrange
|
|
79
|
-
const interval = new Interval(() => {}, 1000);
|
|
80
|
-
interval.set();
|
|
81
|
-
|
|
82
|
-
// Act
|
|
83
|
-
const result = interval.isSet;
|
|
84
|
-
|
|
85
|
-
// Assert
|
|
86
|
-
expect(result).toBeTruthy();
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it("is false when the interval is cleared", () => {
|
|
90
|
-
// Arrange
|
|
91
|
-
const interval = new Interval(() => {}, 1000);
|
|
92
|
-
interval.set();
|
|
93
|
-
interval.clear();
|
|
94
|
-
|
|
95
|
-
// Act
|
|
96
|
-
const result = interval.isSet;
|
|
97
|
-
|
|
98
|
-
// Assert
|
|
99
|
-
expect(result).toBeFalsy();
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
describe("#set", () => {
|
|
104
|
-
it("should call setInterval", () => {
|
|
105
|
-
// Arrange
|
|
106
|
-
const intervalSpy = jest.spyOn(global, "setInterval");
|
|
107
|
-
const interval = new Interval(
|
|
108
|
-
() => {},
|
|
109
|
-
500,
|
|
110
|
-
SchedulePolicy.OnDemand,
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
// Act
|
|
114
|
-
interval.set();
|
|
115
|
-
|
|
116
|
-
// Assert
|
|
117
|
-
expect(intervalSpy).toHaveBeenNthCalledWith(
|
|
118
|
-
1,
|
|
119
|
-
expect.any(Function),
|
|
120
|
-
500,
|
|
121
|
-
);
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it("should invoke setInterval to call the given action", () => {
|
|
125
|
-
// Arrange
|
|
126
|
-
const intervalSpy = jest.spyOn(global, "setInterval");
|
|
127
|
-
const action = jest.fn();
|
|
128
|
-
const interval = new Interval(
|
|
129
|
-
() => action(),
|
|
130
|
-
500,
|
|
131
|
-
SchedulePolicy.OnDemand,
|
|
132
|
-
);
|
|
133
|
-
interval.set();
|
|
134
|
-
const scheduledAction = intervalSpy.mock.calls[0][0];
|
|
135
|
-
|
|
136
|
-
// Act
|
|
137
|
-
scheduledAction();
|
|
138
|
-
|
|
139
|
-
// Assert
|
|
140
|
-
expect(action).toHaveBeenCalledTimes(1);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it("should clear the active interval", () => {
|
|
144
|
-
// Arrange
|
|
145
|
-
const action = jest.fn();
|
|
146
|
-
const interval = new Interval(
|
|
147
|
-
() => action(),
|
|
148
|
-
500,
|
|
149
|
-
SchedulePolicy.OnDemand,
|
|
150
|
-
);
|
|
151
|
-
interval.set();
|
|
152
|
-
|
|
153
|
-
// Act
|
|
154
|
-
interval.set();
|
|
155
|
-
jest.advanceTimersByTime(501);
|
|
156
|
-
|
|
157
|
-
// Assert
|
|
158
|
-
expect(action).toHaveBeenCalledTimes(1);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it("should set an interval that stays active while not cleared", () => {
|
|
162
|
-
// Arrange
|
|
163
|
-
const action = jest.fn();
|
|
164
|
-
const interval = new Interval(() => action(), 500);
|
|
165
|
-
interval.set();
|
|
166
|
-
|
|
167
|
-
// Act
|
|
168
|
-
jest.advanceTimersByTime(1501);
|
|
169
|
-
|
|
170
|
-
// Assert
|
|
171
|
-
expect(action).toHaveBeenCalledTimes(3);
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
describe("#clear", () => {
|
|
176
|
-
it("should clear an active interval", () => {
|
|
177
|
-
// Arrange
|
|
178
|
-
const action = jest.fn();
|
|
179
|
-
const interval = new Interval(action, 500);
|
|
180
|
-
interval.set();
|
|
181
|
-
|
|
182
|
-
// Act
|
|
183
|
-
interval.clear();
|
|
184
|
-
jest.advanceTimersByTime(501);
|
|
185
|
-
|
|
186
|
-
// Assert
|
|
187
|
-
expect(action).not.toHaveBeenCalled();
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
it("should invoke the action if clear policy is ClearPolicy.Resolve", () => {
|
|
191
|
-
// Arrange
|
|
192
|
-
const action = jest.fn();
|
|
193
|
-
const interval = new Interval(action, 500);
|
|
194
|
-
interval.set();
|
|
195
|
-
|
|
196
|
-
// Act
|
|
197
|
-
interval.clear(ClearPolicy.Resolve);
|
|
198
|
-
jest.advanceTimersByTime(501);
|
|
199
|
-
|
|
200
|
-
// Assert
|
|
201
|
-
expect(action).toHaveBeenCalledTimes(1);
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
it("should not invoke the action if clear policy is ClearPolicy.Cancel", () => {
|
|
205
|
-
// Arrange
|
|
206
|
-
const action = jest.fn();
|
|
207
|
-
const interval = new Interval(
|
|
208
|
-
action,
|
|
209
|
-
500,
|
|
210
|
-
SchedulePolicy.Immediately,
|
|
211
|
-
);
|
|
212
|
-
|
|
213
|
-
// Act
|
|
214
|
-
interval.clear(ClearPolicy.Cancel);
|
|
215
|
-
jest.advanceTimersByTime(501);
|
|
216
|
-
|
|
217
|
-
// Assert
|
|
218
|
-
expect(action).not.toHaveBeenCalled();
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
it("should not invoke the action if interval is inactive and clear policy is ClearPolicy.Resolve", () => {
|
|
222
|
-
// Arrange
|
|
223
|
-
const action = jest.fn();
|
|
224
|
-
const interval = new Interval(action, 500, SchedulePolicy.OnDemand);
|
|
225
|
-
|
|
226
|
-
// Act
|
|
227
|
-
interval.clear(ClearPolicy.Resolve);
|
|
228
|
-
jest.advanceTimersByTime(501);
|
|
229
|
-
|
|
230
|
-
// Assert
|
|
231
|
-
expect(action).not.toHaveBeenCalled();
|
|
232
|
-
});
|
|
233
|
-
});
|
|
234
|
-
});
|
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
import Timeout from "../timeout";
|
|
2
|
-
import {SchedulePolicy, ClearPolicy} from "../policies";
|
|
3
|
-
|
|
4
|
-
describe("Timeout", () => {
|
|
5
|
-
beforeEach(() => {
|
|
6
|
-
jest.useFakeTimers();
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
afterEach(() => {
|
|
10
|
-
jest.restoreAllMocks();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
describe("constructor", () => {
|
|
14
|
-
it("creates instance", () => {
|
|
15
|
-
// Arrange
|
|
16
|
-
|
|
17
|
-
// Act
|
|
18
|
-
const result = new Timeout(() => {}, 0);
|
|
19
|
-
|
|
20
|
-
// Assert
|
|
21
|
-
expect(result).toBeDefined();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it("throws if the action is not a function", () => {
|
|
25
|
-
// Arrange
|
|
26
|
-
|
|
27
|
-
// Act
|
|
28
|
-
const underTest = () => new Timeout(null as any, 0);
|
|
29
|
-
|
|
30
|
-
// Assert
|
|
31
|
-
expect(underTest).toThrowErrorMatchingInlineSnapshot(
|
|
32
|
-
`"Action must be a function"`,
|
|
33
|
-
);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it("throws if the period is less than 0", () => {
|
|
37
|
-
// Arrange
|
|
38
|
-
|
|
39
|
-
// Act
|
|
40
|
-
const underTest = () => new Timeout(() => {}, -1);
|
|
41
|
-
|
|
42
|
-
// Assert
|
|
43
|
-
expect(underTest).toThrowErrorMatchingInlineSnapshot(
|
|
44
|
-
`"Timeout period must be >= 0"`,
|
|
45
|
-
);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it("sets a timeout when schedule policy is SchedulePolicy.Immediately", () => {
|
|
49
|
-
// Arrange
|
|
50
|
-
const timeoutSpy = jest.spyOn(global, "setTimeout");
|
|
51
|
-
|
|
52
|
-
// Act
|
|
53
|
-
// eslint-disable-next-line no-new
|
|
54
|
-
new Timeout(() => {}, 0, SchedulePolicy.Immediately);
|
|
55
|
-
|
|
56
|
-
// Assert
|
|
57
|
-
expect(timeoutSpy).toHaveBeenCalledTimes(1);
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe("isSet", () => {
|
|
62
|
-
it("is false when the timeout has not been set", () => {
|
|
63
|
-
// Arrange
|
|
64
|
-
const timeout = new Timeout(() => {}, 0, SchedulePolicy.OnDemand);
|
|
65
|
-
|
|
66
|
-
// Act
|
|
67
|
-
const result = timeout.isSet;
|
|
68
|
-
|
|
69
|
-
// Assert
|
|
70
|
-
expect(result).toBeFalsy();
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it("is true when the timeout is pending", () => {
|
|
74
|
-
// Arrange
|
|
75
|
-
const timeout = new Timeout(() => {}, 0);
|
|
76
|
-
timeout.set();
|
|
77
|
-
|
|
78
|
-
// Act
|
|
79
|
-
const result = timeout.isSet;
|
|
80
|
-
|
|
81
|
-
// Assert
|
|
82
|
-
expect(result).toBeTruthy();
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it("is false when the timeout has executed", () => {
|
|
86
|
-
// Arrange
|
|
87
|
-
const timeout = new Timeout(() => {}, 0);
|
|
88
|
-
timeout.set();
|
|
89
|
-
jest.runOnlyPendingTimers();
|
|
90
|
-
|
|
91
|
-
// Act
|
|
92
|
-
const result = timeout.isSet;
|
|
93
|
-
|
|
94
|
-
// Assert
|
|
95
|
-
expect(result).toBeFalsy();
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
describe("#set", () => {
|
|
100
|
-
it("should call setTimeout", () => {
|
|
101
|
-
// Arrange
|
|
102
|
-
const timeoutSpy = jest.spyOn(global, "setTimeout");
|
|
103
|
-
const timeout = new Timeout(() => {}, 500, SchedulePolicy.OnDemand);
|
|
104
|
-
|
|
105
|
-
// Act
|
|
106
|
-
timeout.set();
|
|
107
|
-
|
|
108
|
-
// Assert
|
|
109
|
-
expect(timeoutSpy).toHaveBeenNthCalledWith(
|
|
110
|
-
1,
|
|
111
|
-
expect.any(Function),
|
|
112
|
-
500,
|
|
113
|
-
);
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it("should invoke setTimeout to call the given action", () => {
|
|
117
|
-
// Arrange
|
|
118
|
-
const timeoutSpy = jest.spyOn(global, "setTimeout");
|
|
119
|
-
const action = jest.fn();
|
|
120
|
-
const timeout = new Timeout(
|
|
121
|
-
() => action(),
|
|
122
|
-
500,
|
|
123
|
-
SchedulePolicy.OnDemand,
|
|
124
|
-
);
|
|
125
|
-
timeout.set();
|
|
126
|
-
const scheduledAction = timeoutSpy.mock.calls[0][0];
|
|
127
|
-
|
|
128
|
-
// Act
|
|
129
|
-
scheduledAction();
|
|
130
|
-
|
|
131
|
-
// Assert
|
|
132
|
-
expect(action).toHaveBeenCalledTimes(1);
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it("should clear any pending timeout", () => {
|
|
136
|
-
// Arrange
|
|
137
|
-
const action = jest.fn();
|
|
138
|
-
const timeout = new Timeout(() => action(), 500);
|
|
139
|
-
timeout.set();
|
|
140
|
-
|
|
141
|
-
// Act
|
|
142
|
-
timeout.set();
|
|
143
|
-
jest.runOnlyPendingTimers();
|
|
144
|
-
|
|
145
|
-
// Assert
|
|
146
|
-
expect(action).toHaveBeenCalledTimes(1);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it("should set the timeout again if it has already executed", () => {
|
|
150
|
-
// Arrange
|
|
151
|
-
const timeoutSpy = jest.spyOn(global, "setTimeout");
|
|
152
|
-
const action = jest.fn();
|
|
153
|
-
const timeout = new Timeout(action, 500, SchedulePolicy.OnDemand);
|
|
154
|
-
timeout.set();
|
|
155
|
-
jest.runAllTimers();
|
|
156
|
-
|
|
157
|
-
// Act
|
|
158
|
-
timeout.set();
|
|
159
|
-
|
|
160
|
-
// Assert
|
|
161
|
-
expect(timeoutSpy).toHaveBeenCalledTimes(2);
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
describe("#clear", () => {
|
|
166
|
-
it("should clear a pending timout", () => {
|
|
167
|
-
// Arrange
|
|
168
|
-
const action = jest.fn();
|
|
169
|
-
const timeout = new Timeout(action, 500);
|
|
170
|
-
timeout.set();
|
|
171
|
-
|
|
172
|
-
// Act
|
|
173
|
-
timeout.clear();
|
|
174
|
-
jest.runOnlyPendingTimers();
|
|
175
|
-
|
|
176
|
-
// Assert
|
|
177
|
-
expect(action).not.toHaveBeenCalled();
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it("should invoke the action if clear policy is ClearPolicy.Resolve", () => {
|
|
181
|
-
// Arrange
|
|
182
|
-
const action = jest.fn();
|
|
183
|
-
const timeout = new Timeout(action, 500);
|
|
184
|
-
timeout.set();
|
|
185
|
-
|
|
186
|
-
// Act
|
|
187
|
-
timeout.clear(ClearPolicy.Resolve);
|
|
188
|
-
jest.runOnlyPendingTimers();
|
|
189
|
-
|
|
190
|
-
// Assert
|
|
191
|
-
expect(action).toHaveBeenCalledTimes(1);
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
it("should not invoke the action if clear policy is ClearPolicy.Cancel", () => {
|
|
195
|
-
// Arrange
|
|
196
|
-
const action = jest.fn();
|
|
197
|
-
const timeout = new Timeout(
|
|
198
|
-
action,
|
|
199
|
-
500,
|
|
200
|
-
SchedulePolicy.Immediately,
|
|
201
|
-
);
|
|
202
|
-
|
|
203
|
-
// Act
|
|
204
|
-
timeout.clear(ClearPolicy.Cancel);
|
|
205
|
-
jest.runOnlyPendingTimers();
|
|
206
|
-
|
|
207
|
-
// Assert
|
|
208
|
-
expect(action).not.toHaveBeenCalled();
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
it("should not invoke the action if timeout is not pending", () => {
|
|
212
|
-
// Arrange
|
|
213
|
-
const action = jest.fn();
|
|
214
|
-
const timeout = new Timeout(action, 500, SchedulePolicy.OnDemand);
|
|
215
|
-
|
|
216
|
-
// Act
|
|
217
|
-
timeout.clear(ClearPolicy.Resolve);
|
|
218
|
-
jest.runOnlyPendingTimers();
|
|
219
|
-
|
|
220
|
-
// Assert
|
|
221
|
-
expect(action).not.toHaveBeenCalled();
|
|
222
|
-
});
|
|
223
|
-
});
|
|
224
|
-
});
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import Timeout from "./timeout";
|
|
2
|
-
import Interval from "./interval";
|
|
3
|
-
import AnimationFrame from "./animation-frame";
|
|
4
|
-
|
|
5
|
-
import type {
|
|
6
|
-
IAnimationFrame,
|
|
7
|
-
IInterval,
|
|
8
|
-
ITimeout,
|
|
9
|
-
IScheduleActions,
|
|
10
|
-
Options,
|
|
11
|
-
} from "./types";
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Implements the `IScheduleActions` API to provide timeout, interval, and
|
|
15
|
-
* animation frame support. This is not intended for direct use, but instead
|
|
16
|
-
* is to be used solely by the `ActionSchedulerProvider` to provide an
|
|
17
|
-
* `IScheduleActions` instance.
|
|
18
|
-
*/
|
|
19
|
-
export default class ActionScheduler implements IScheduleActions {
|
|
20
|
-
_disabled = false;
|
|
21
|
-
_registeredActions: Array<() => void> = [];
|
|
22
|
-
static readonly NoopAction: ITimeout & IAnimationFrame & IInterval = {
|
|
23
|
-
set: () => {},
|
|
24
|
-
get isSet() {
|
|
25
|
-
return false;
|
|
26
|
-
},
|
|
27
|
-
clear: () => {},
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
timeout(
|
|
31
|
-
action: () => unknown,
|
|
32
|
-
period: number,
|
|
33
|
-
options?: Options,
|
|
34
|
-
): ITimeout {
|
|
35
|
-
if (this._disabled) {
|
|
36
|
-
return ActionScheduler.NoopAction;
|
|
37
|
-
}
|
|
38
|
-
const timeout = new Timeout(action, period, options?.schedulePolicy);
|
|
39
|
-
this._registeredActions.push(() => timeout.clear(options?.clearPolicy));
|
|
40
|
-
return timeout;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
interval(
|
|
44
|
-
action: () => unknown,
|
|
45
|
-
period: number,
|
|
46
|
-
options?: Options,
|
|
47
|
-
): IInterval {
|
|
48
|
-
if (this._disabled) {
|
|
49
|
-
return ActionScheduler.NoopAction;
|
|
50
|
-
}
|
|
51
|
-
const interval = new Interval(action, period, options?.schedulePolicy);
|
|
52
|
-
this._registeredActions.push(() =>
|
|
53
|
-
interval.clear(options?.clearPolicy),
|
|
54
|
-
);
|
|
55
|
-
return interval;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
animationFrame(
|
|
59
|
-
action: (arg1: DOMHighResTimeStamp) => void,
|
|
60
|
-
options?: Options,
|
|
61
|
-
): IAnimationFrame {
|
|
62
|
-
if (this._disabled) {
|
|
63
|
-
return ActionScheduler.NoopAction;
|
|
64
|
-
}
|
|
65
|
-
const animationFrame = new AnimationFrame(
|
|
66
|
-
action,
|
|
67
|
-
options?.schedulePolicy,
|
|
68
|
-
);
|
|
69
|
-
this._registeredActions.push(() =>
|
|
70
|
-
animationFrame.clear(options?.clearPolicy),
|
|
71
|
-
);
|
|
72
|
-
return animationFrame;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
clearAll(): void {
|
|
76
|
-
const registered = [...this._registeredActions];
|
|
77
|
-
this._registeredActions = [];
|
|
78
|
-
registered.forEach((clearFn) => clearFn());
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Prevents this scheduler from creating any additional actions.
|
|
83
|
-
* This also clears any pending actions.
|
|
84
|
-
*/
|
|
85
|
-
disable(): void {
|
|
86
|
-
this._disabled = true;
|
|
87
|
-
this.clearAll();
|
|
88
|
-
}
|
|
89
|
-
}
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import {SchedulePolicy, ClearPolicy} from "./policies";
|
|
2
|
-
|
|
3
|
-
import type {IAnimationFrame} from "./types";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Encapsulates everything associated with calling requestAnimationFrame/
|
|
7
|
-
* cancelAnimationFrame, and managing the lifecycle of that request, including
|
|
8
|
-
* the ability to resolve or cancel a pending request action.
|
|
9
|
-
*
|
|
10
|
-
* @export
|
|
11
|
-
* @class AnimationFrame
|
|
12
|
-
* @implements {IAnimationFrame}
|
|
13
|
-
*/
|
|
14
|
-
export default class AnimationFrame implements IAnimationFrame {
|
|
15
|
-
_animationFrameId: number | null | undefined;
|
|
16
|
-
_action: (time: DOMHighResTimeStamp) => unknown;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Creates an animation frame request that will invoke the given action.
|
|
20
|
-
* The request is not made until set is called.
|
|
21
|
-
*
|
|
22
|
-
* @param action The action to be invoked.
|
|
23
|
-
* @param [schedulePolicy] When SchedulePolicy.Immediately,
|
|
24
|
-
* the interval is set immediately on instantiation; otherwise, `set` must be
|
|
25
|
-
* called to set the interval.
|
|
26
|
-
* Defaults to `SchedulePolicy.Immediately`.
|
|
27
|
-
* @memberof AnimationFrame
|
|
28
|
-
*/
|
|
29
|
-
constructor(
|
|
30
|
-
action: (time: DOMHighResTimeStamp) => unknown,
|
|
31
|
-
schedulePolicy: SchedulePolicy = SchedulePolicy.Immediately,
|
|
32
|
-
) {
|
|
33
|
-
if (typeof action !== "function") {
|
|
34
|
-
throw new Error("Action must be a function");
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
this._action = action;
|
|
38
|
-
|
|
39
|
-
if (schedulePolicy === SchedulePolicy.Immediately) {
|
|
40
|
-
this.set();
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Determine if the request is pending or not.
|
|
46
|
-
*
|
|
47
|
-
* @returns {boolean} true if the request is pending, otherwise
|
|
48
|
-
* false.
|
|
49
|
-
* @memberof AnimationFrame
|
|
50
|
-
*/
|
|
51
|
-
get isSet(): boolean {
|
|
52
|
-
return this._animationFrameId != null;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Make the animation frame request.
|
|
57
|
-
*
|
|
58
|
-
* If the request is pending, this cancels that pending request and
|
|
59
|
-
* makes the request afresh. If the request is not pending, this
|
|
60
|
-
* makes a new request.
|
|
61
|
-
*
|
|
62
|
-
* @memberof AnimationFrame
|
|
63
|
-
*/
|
|
64
|
-
set(): void {
|
|
65
|
-
if (this.isSet) {
|
|
66
|
-
this.clear(ClearPolicy.Cancel);
|
|
67
|
-
}
|
|
68
|
-
this._animationFrameId = requestAnimationFrame((time) =>
|
|
69
|
-
this.clear(ClearPolicy.Resolve, time),
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Clear the pending request.
|
|
75
|
-
*
|
|
76
|
-
* If the request is pending, this cancels that pending request without
|
|
77
|
-
* invoking the action. If no request is pending, this does nothing.
|
|
78
|
-
*
|
|
79
|
-
* @param [policy] When ClearPolicy.Resolve, if the request
|
|
80
|
-
* was set when called, the request action is invoked after cancelling
|
|
81
|
-
* the request; otherwise, the pending action is cancelled.
|
|
82
|
-
* Defaults to `ClearPolicy.Cancel`.
|
|
83
|
-
* @param [time] Timestamp to pass to the action when
|
|
84
|
-
* ClearPolicy.Resolve is specified. Ignored when ClearPolicy.Cancel is
|
|
85
|
-
* specified.
|
|
86
|
-
*
|
|
87
|
-
* @memberof AnimationFrame
|
|
88
|
-
*/
|
|
89
|
-
clear(
|
|
90
|
-
policy: ClearPolicy = ClearPolicy.Cancel,
|
|
91
|
-
time?: DOMHighResTimeStamp,
|
|
92
|
-
): void {
|
|
93
|
-
const animationFrameId = this._animationFrameId;
|
|
94
|
-
this._animationFrameId = null;
|
|
95
|
-
if (animationFrameId == null) {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
cancelAnimationFrame(animationFrameId);
|
|
99
|
-
if (policy === ClearPolicy.Resolve) {
|
|
100
|
-
this._action(time || performance.now());
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|