Skip to content

Commit 6774acf

Browse files
committed
added requestReversibleAnimationFrame
1 parent 86e23d3 commit 6774acf

File tree

6 files changed

+80
-3
lines changed

6 files changed

+80
-3
lines changed

README.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212

1313
This package includes reversible implementations of:
1414

15-
- [addEventListener](#addreversibleeventlistener)
1615
- [setTimeout](#setreversibletimeout)
1716
- [setInterval](#setreversibleinterval)
17+
- [addEventListener](#addreversibleeventlistener)
18+
- [requestAnimationFrame](#requestreversibleanimationframe)
1819

1920
<hr />
2021

@@ -64,6 +65,7 @@ Let's find out [how](#documentation) or [why](#motivation).
6465
- [`addReversibleEventListener`](#addreversibleeventlistener)
6566
- [`setReversibleTimeout`](#setreversibletimeout)
6667
- [`setReversibleInterval`](#setreversibleinterval)
68+
- [`requestReversibleAnimationFrame`](#requestreversibleanimationframe)
6769
- [Contributing](#contributing)
6870
- [Support](#support)
6971
<!-- codegen:end -->
@@ -248,13 +250,22 @@ function setReversibleInterval(
248250
): () => void;
249251
```
250252

253+
#### `requestReversibleAnimationFrame`
254+
255+
Reversible version of `window.requestReversibleAnimationFrame`. [→ docs for original](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame)
256+
257+
```ts
258+
function requestReversibleAnimationFrame(
259+
callback: (time: DOMHighResTimeStamp): void;, // function to be executed on next repaint
260+
): () => void;
261+
```
262+
251263
## Contributing
252264

253265
Improvements or additions are most welcome!
254266

255267
Current list of planned support:
256268

257-
- [requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame)
258269
- [requestIdleCallback](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback)
259270
- [setImmediate](https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate)
260271

src/addReversibleEventListener.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,5 @@ export default addReversibleEventListener;
7373
// TODO: inference of generics function properties seems to break
7474
// below example cannot resolve TouchEvent for `event` param in callback
7575
// const test = <T extends HTMLElement>(x: T) => {
76-
// registerEvent(x, 'touchcancel', event => {});
76+
// addReversibleEventListener(x, 'touchcancel', event => {});
7777
// };

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export { default as setReversibleTimeout } from './setReversibleTimeout';
22
export { default as setReversibleInterval } from './setReversibleInterval';
33
export { default as addReversibleEventListener } from './addReversibleEventListener';
4+
export { default as requestReversibleAnimationFrame } from './requestReversibleAnimationFrame';
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* Registers an action to be performed on the next repaint and returns a function to cancel it.
3+
* @param {*} cb callback
4+
* @returns callback to cancel action
5+
*/
6+
function requestReversibleAnimationFrame(...args: Parameters<typeof requestAnimationFrame>): () => void {
7+
const ref = window.requestAnimationFrame(...args);
8+
return window.cancelAnimationFrame.bind(window, ref);
9+
}
10+
11+
export default requestReversibleAnimationFrame;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { expectType } from 'tsd';
2+
3+
/**
4+
* type tests
5+
*/
6+
import { requestReversibleAnimationFrame } from '..';
7+
8+
expectType<() => void>(requestReversibleAnimationFrame(() => void null));
9+
10+
const inferParam = <T>(fun: (cb: T) => () => void) => void fun as unknown as T;
11+
expectType<(time: DOMHighResTimeStamp) => void>(inferParam(requestReversibleAnimationFrame));
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* @jest-environment jsdom
3+
*/
4+
5+
import { requestReversibleAnimationFrame } from '..';
6+
7+
beforeAll(() => {
8+
jest.useFakeTimers();
9+
});
10+
afterAll(() => {
11+
jest.useRealTimers();
12+
});
13+
afterEach(() => {
14+
jest.resetAllMocks();
15+
});
16+
17+
describe('requestReversibleAnimationFrame', () => {
18+
test('triggers', () => {
19+
const callback = jest.fn();
20+
jest.spyOn(window, 'requestAnimationFrame');
21+
requestReversibleAnimationFrame(callback);
22+
expect(requestAnimationFrame).toHaveBeenCalledTimes(1);
23+
expect(requestAnimationFrame).toHaveBeenLastCalledWith(callback);
24+
expect(callback).not.toHaveBeenCalled();
25+
jest.runOnlyPendingTimers();
26+
expect(callback).toHaveBeenCalled();
27+
jest.runOnlyPendingTimers();
28+
jest.runOnlyPendingTimers();
29+
jest.runOnlyPendingTimers();
30+
expect(callback).toHaveBeenCalledTimes(1); // runs only once
31+
});
32+
test('cancels', () => {
33+
const callback = jest.fn();
34+
jest.spyOn(window, 'cancelAnimationFrame');
35+
const cancel = requestReversibleAnimationFrame(callback);
36+
expect(callback).not.toHaveBeenCalled();
37+
expect(cancelAnimationFrame).not.toHaveBeenCalled();
38+
cancel();
39+
expect(cancelAnimationFrame).toHaveBeenCalledTimes(1);
40+
jest.runOnlyPendingTimers();
41+
expect(callback).not.toHaveBeenCalled();
42+
});
43+
});

0 commit comments

Comments
 (0)