Compare commits

...

88 Commits

Author SHA1 Message Date
zplata
f19295f9a5 chore: release 3.0.55 2023-07-19 14:04:30 +00:00
Zach Plata
70546308b4 feature: add onAdvance callback through wasm bump too 1.2.2 2023-07-19 09:01:24 -05:00
zplata
62a425f30e chore: release 3.0.54 2023-06-26 20:26:51 +00:00
Zach Plata
4a554dd1ad patch: Bump WASM runtimes for interpolation on states 2023-06-26 15:23:29 -05:00
zplata
3e6262f21f chore: release 3.0.53 2023-06-09 15:12:24 +00:00
Zach Plata
e57a99b2d1 Bump wasm to 1.2.0 2023-06-09 10:09:09 -05:00
zplata
8a968ec266 chore: release 3.0.52 2023-06-07 19:44:53 +00:00
Zach Plata
b5f00e5c97 fix: bump WASM to fix iterator over animatables 2023-06-07 14:41:46 -05:00
zplata
22e6dd3494 chore: release 3.0.51 2023-06-02 18:56:31 +00:00
Zach Plata
08b9f9a2aa Also export the container ref current element 2023-06-02 13:53:30 -05:00
Zach Plata
a24b910096 Update prop docs 2023-06-02 13:53:30 -05:00
Zach Plata
33760042d1 fix recursive useEffect call 2023-06-02 13:53:30 -05:00
Zach Plata
2c82fa04e7 Feature: Move canvas sizing logic into useResizeCanvas hook and clean up util hooks 2023-06-02 13:53:30 -05:00
zplata
2b249494d5 chore: release 3.0.50 2023-05-26 19:26:23 +00:00
Zach Plata
b56c17d48c feat: allow for children to be set inside the canvas for fallback content when canvas cannot be shown 2023-05-26 14:22:47 -05:00
zplata
a6fe08ced9 chore: release 3.0.49 2023-05-24 19:36:23 +00:00
Zach Plata
cd1e1410f4 add joystick support 2023-05-24 14:33:00 -05:00
zplata
353fbf8e9d chore: release 3.0.48 2023-05-18 21:37:38 +00:00
Zach Plata
ae05ad4375 feature: bump web runtime to support joysticks 2023-05-18 16:34:36 -05:00
zplata
ff8bbb084c chore: release 3.0.47 2023-05-12 21:16:59 +00:00
Zach Plata
89a6802fa0 patch: bump wasm to 1.1.6 for flicker fix 2023-05-12 16:14:04 -05:00
zplata
91025e6772 chore: release 3.0.46 2023-05-02 18:30:36 +00:00
Zach Plata
d3bc913bcf Add prop to the standalone Rive component 2023-05-02 13:27:38 -05:00
Zach Plata
ce56321e1d patch: bump rive-wasm to allow new parameter for disabling Rive listeners 2023-05-02 13:27:38 -05:00
caudetgit
4b6f5410fd chore: release 3.0.45 2023-04-19 20:21:31 +00:00
Chad Audet
6544874d3d Update add_to_project.yml
apply "triage" label, too
2023-04-19 13:18:24 -07:00
caudetgit
ed90c7f7c9 chore: release 3.0.44 2023-04-19 20:10:23 +00:00
Chad Audet
e06fdd1c8b Create add_to_project.yml
workflow that adds each new issue to the Runtime Issue Board
2023-04-19 13:07:28 -07:00
zplata
b8ffb6b53c chore: release 3.0.43 2023-04-14 15:52:47 +00:00
Zach Plata
2dc925ef70 patch: bump rive-wasm to take path fix 2023-04-14 10:49:40 -05:00
zplata
639de79c9e chore: release 3.0.42 2023-04-13 02:19:19 +00:00
Zach Plata
a9961c821a chore: bump rive-wasm to get solo patch 2023-04-12 21:16:29 -05:00
zplata
fc082d1a03 chore: release 3.0.41 2023-04-06 21:50:50 +00:00
Zach Plata
87fa1ae2a5 patch: bump wasm dependency for blend state enhancements 2023-04-06 16:48:11 -05:00
zplata
62490a50f9 chore: release 3.0.40 2023-04-05 20:47:45 +00:00
Zach Plata
fcc1a16df4 feature: Add support for touch and drag interactions on canvas 2023-04-05 15:44:36 -05:00
zplata
29e0ceb797 chore: release 3.0.39 2023-03-30 18:08:35 +00:00
Zach Plata
3e6a951ca1 fix: bump wasm dependency for clipping issue fix 2023-03-30 13:05:41 -05:00
zplata
04910f78f1 chore: release 3.0.38 2023-03-03 20:43:32 +00:00
Zach Plata
c2977c705c maint: bump wasm dependency for more speed on state updates 2023-03-03 14:40:24 -06:00
zplata
4e2137422b chore: release 3.0.37 2023-03-01 15:54:14 +00:00
Zach Plata
0696417926 maint: bump wasm dependency for more speed on state updates 2023-03-01 09:51:04 -06:00
zplata
f11a433365 chore: release 3.0.36 2023-02-22 19:03:57 +00:00
Zach Plata
48a4726d1f maint: bump wasm to support speed on states feature 2023-02-22 13:01:16 -06:00
Dillon Pentz
c927f24b5a Fix link to blog article 2023-01-18 14:44:57 -06:00
elVengador
3cbbf99fec Fix: matchMedia add event listener for safari 13 and older versions 2023-01-18 10:12:34 -06:00
zplata
03f05f57b7 chore: release 3.0.35 2023-01-17 20:15:23 +00:00
Zach Plata
8b483b807b fix: update rive-wasm to try patching slow burn memory leak 2023-01-17 14:12:39 -06:00
luigi-rosso
816fcfcdbc chore: release 3.0.34 2022-12-16 19:29:15 +00:00
Luigi Rosso
6c28a8795e Bumping rive-app/canvas & webgl versions. 2022-12-16 11:25:51 -08:00
zplata
6a57630ae6 chore: release 3.0.33 2022-11-08 20:15:00 +00:00
Zach Plata
acba24c4ed maint: bump wasm runtime and replace old skills rive file example 2022-11-08 14:10:33 -06:00
luigi-rosso
1e6eb5ec92 chore: release 3.0.32 2022-10-21 20:38:27 +00:00
Luigi Rosso
6871a81ebd Bumping to latest Rive WASM to fix https://2dimensions.slack.com/archives/CLLCU09T6/p1666370141425879 2022-10-21 13:35:28 -07:00
mjtalbot
33053b3b7f chore: release 3.0.31 2022-10-21 13:20:16 +00:00
Maxwell Talbot
4040083d5a bump runtimes to incorporate speed fix for state machines 2022-10-21 14:17:25 +01:00
avivian
2153b81e6b chore: release 3.0.30 2022-10-20 18:34:05 +00:00
Arthur Vivian
6b1500e681 Bump dependencies to fix call to runtime cleanup 2022-10-20 19:31:16 +01:00
avivian
503702cf1f chore: release 3.0.29 2022-10-20 17:06:43 +00:00
Arthur Vivian
7be20b0a87 Call cleanup on unmount 2022-10-20 18:03:30 +01:00
avivian
78491f5819 chore: release 3.0.28 2022-10-20 09:44:48 +00:00
Arthur Vivian
39edb88a19 Bump canvas and webgl dependencies to fix alignment memory leaks 2022-10-20 10:42:06 +01:00
zplata
fd1a1653b1 chore: release 3.0.27 2022-10-04 17:56:49 +00:00
Zach Plata
8d7f0ab28c Fix: Bump wasm to accomodate clipping bug on nested artboards 2022-10-04 12:53:17 -05:00
zplata
2a2e532564 chore: release 3.0.26 2022-09-22 17:15:22 +00:00
Zach Plata
2b1aa01a87 fix: Adjust canvas size if devicePixelRatio changes for any reaason 2022-09-22 12:12:32 -05:00
zplata
06c4e2aea3 chore: release 3.0.25 2022-09-21 14:23:55 +00:00
Zach Plata
819bd51ea9 patch: bump js runtime dependency to address content security policy issue in WASM build 2022-09-21 09:20:55 -05:00
zplata
6b7f113296 chore: release 3.0.24 2022-09-15 15:56:54 +00:00
Zach Plata
a62e9b3a9a add tests 2022-09-15 10:53:36 -05:00
Zach Plata
04685c0bcd fix: make a canvas of size 0 until we calculate the bounds appropriately 2022-09-15 10:53:36 -05:00
avivian
48fd9f9d80 chore: release 3.0.23 2022-08-31 10:27:17 +00:00
Arthur Vivian
3c578b730f Bump runtime version to fix broken version 2022-08-31 11:24:05 +01:00
avivian
7a46886133 chore: release 3.0.22 2022-08-30 17:09:24 +00:00
Arthur Vivian
092049d20f Update @rive-app/canvas and @rive-app/webgl dependencies to support non node builds 2022-08-30 18:06:18 +01:00
mjtalbot
f7aced03cd chore: release 3.0.21 2022-07-22 13:34:00 +00:00
Maxwell Talbot
eb07281415 rev rive-wasm dependencies & update render delay to be 0ms 2022-07-22 14:30:04 +01:00
mjtalbot
156b3bdfb5 chore: release 3.0.20 2022-07-22 12:56:26 +00:00
Maxwell Talbot
24d8e0a907 update tests 2022-07-22 13:52:42 +01:00
Maxwell Talbot
a1a155849a use window.settimeout and clear out some consts 2022-07-22 13:52:42 +01:00
Maxwell Talbot
59e67cec3d update name 2022-07-22 13:52:42 +01:00
Maxwell Talbot
84b18cc3dd ensure we re evaluate state machine inputs when we play is triggered, looks like there maybe additional situations where we are going to need this. 2022-07-22 13:52:42 +01:00
Maxwell Talbot
1092b44947 update resize behaviour to throttle, add parameters to enable switching modes 2022-07-22 13:52:42 +01:00
zplata
efe28aa5f3 chore: release 3.0.19 2022-07-19 23:48:34 +00:00
Zach Plata
16d836c959 fix tests that were automatically calling the rive load callback to be more controlled 2022-07-19 18:44:20 -05:00
Zach Plata
838ed1abf8 Fix: Add check before setting Rive as state variable on Rive instance load 2022-07-19 18:44:20 -05:00
mjtalbot
d010a55cc0 chore: release 3.0.18 2022-07-14 12:26:10 +00:00
Maxwell Talbot
fd1c00a995 update canvas dimensions to use clientWidth and Height as opposed to BoundingClient, to avoid getting scaled information 2022-07-14 13:22:12 +01:00
19 changed files with 1058 additions and 281 deletions

26
.github/workflows/add_to_project.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
name: Adds all new issues to project board
on:
issues:
types:
- opened
jobs:
add-to-project:
name: Add issue to project
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@v0.5.0
with:
project-url: https://github.com/orgs/rive-app/projects/12/views/1
github-token: ${{ secrets.ADD_TO_PROJECT_ACTION }}
- uses: actions/github-script@v6
with:
script: |
github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ["triage"]
})

View File

@@ -4,9 +4,371 @@ All notable changes to this project will be documented in this file. Dates are d
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
#### [v3.0.17](https://github.com/rive-app/rive-react/compare/v3.0.1...v3.0.17)
#### [v3.0.55](https://github.com/rive-app/rive-react/compare/v3.0.53...v3.0.55)
- removed polyfill in favour of DIY appraoch to reduce package size [`62b3a1d`](https://github.com/rive-app/rive-react/commit/62b3a1d8dc93c0dd29bfe814fcd870e73b33abd2)
- feature: add onAdvance callback through wasm bump too 1.2.2 [`7054630`](https://github.com/rive-app/rive-react/commit/70546308b44718e04f5295f60b99f0fc7bbe8172)
#### [v3.0.53](https://github.com/rive-app/rive-react/compare/v3.0.52...v3.0.53)
> 9 June 2023
- chore: release 3.0.53 [`3e6262f`](https://github.com/rive-app/rive-react/commit/3e6262f21f6cc3195030f6072edde904469bf4a6)
- Bump wasm to 1.2.0 [`e57a99b`](https://github.com/rive-app/rive-react/commit/e57a99b2d193aa713770dbb34f2a66ecd7bad155)
#### [v3.0.52](https://github.com/rive-app/rive-react/compare/v3.0.51...v3.0.52)
> 7 June 2023
- chore: release 3.0.52 [`8a968ec`](https://github.com/rive-app/rive-react/commit/8a968ec266f1ed78bb614551d36ef7145d1db0ae)
- fix: bump WASM to fix iterator over animatables [`b5f00e5`](https://github.com/rive-app/rive-react/commit/b5f00e5c97146573474ab73773fe189b1bcc5d43)
#### [v3.0.51](https://github.com/rive-app/rive-react/compare/v3.0.50...v3.0.51)
> 2 June 2023
- Feature: Move canvas sizing logic into useResizeCanvas hook and clean up util hooks [`2c82fa0`](https://github.com/rive-app/rive-react/commit/2c82fa04e771550c058fae97c38a61e34a6499fc)
- Update prop docs [`a24b910`](https://github.com/rive-app/rive-react/commit/a24b910096e3e73b964fb42dd37bdacd8a791995)
- chore: release 3.0.51 [`22e6dd3`](https://github.com/rive-app/rive-react/commit/22e6dd34941edf32e71d01c483fd603fd1d1b95c)
#### [v3.0.50](https://github.com/rive-app/rive-react/compare/v3.0.49...v3.0.50)
> 26 May 2023
- chore: release 3.0.50 [`2b24949`](https://github.com/rive-app/rive-react/commit/2b249494d5c75fbe317c2e4069bf16a8333c609e)
- feat: allow for children to be set inside the canvas for fallback content when canvas cannot be shown [`b56c17d`](https://github.com/rive-app/rive-react/commit/b56c17d48c51176d7c7b0e10d465548be2538eac)
#### [v3.0.49](https://github.com/rive-app/rive-react/compare/v3.0.48...v3.0.49)
> 24 May 2023
- chore: release 3.0.49 [`a6fe08c`](https://github.com/rive-app/rive-react/commit/a6fe08ced98cd939c5b1e1288db900bcc05aeb61)
- add joystick support [`cd1e141`](https://github.com/rive-app/rive-react/commit/cd1e1410f48df008474ba0c4a1fd6a74fa67445e)
#### [v3.0.48](https://github.com/rive-app/rive-react/compare/v3.0.47...v3.0.48)
> 18 May 2023
- chore: release 3.0.48 [`353fbf8`](https://github.com/rive-app/rive-react/commit/353fbf8e9d7bad154164f2068ea967c755ac64a1)
- feature: bump web runtime to support joysticks [`ae05ad4`](https://github.com/rive-app/rive-react/commit/ae05ad4375375f43b1f4493c76bcc18cd6c40676)
#### [v3.0.47](https://github.com/rive-app/rive-react/compare/v3.0.46...v3.0.47)
> 12 May 2023
- chore: release 3.0.47 [`ff8bbb0`](https://github.com/rive-app/rive-react/commit/ff8bbb084cebf1f6f37b4432440c4c3df00b3c66)
- patch: bump wasm to 1.1.6 for flicker fix [`89a6802`](https://github.com/rive-app/rive-react/commit/89a6802fa05bb809dc30d740aaff11f4e83eb21a)
#### [v3.0.46](https://github.com/rive-app/rive-react/compare/v3.0.45...v3.0.46)
> 2 May 2023
- Add prop to the standalone Rive component [`d3bc913`](https://github.com/rive-app/rive-react/commit/d3bc913bcf70e62df6cea5b5a08d0135c965f9ff)
- chore: release 3.0.46 [`91025e6`](https://github.com/rive-app/rive-react/commit/91025e6772403fe688ae9eb6992971d2ab47b933)
- patch: bump rive-wasm to allow new parameter for disabling Rive listeners [`ce56321`](https://github.com/rive-app/rive-react/commit/ce56321e1d1b565a152220bf415e3adced63c20d)
#### [v3.0.45](https://github.com/rive-app/rive-react/compare/v3.0.44...v3.0.45)
> 19 April 2023
- Update add_to_project.yml [`6544874`](https://github.com/rive-app/rive-react/commit/6544874d3d94fbe93f9a8d0cdbb047189aced1ce)
- chore: release 3.0.45 [`4b6f541`](https://github.com/rive-app/rive-react/commit/4b6f5410fde11f69cc757cda51682cab53b3c2fc)
#### [v3.0.44](https://github.com/rive-app/rive-react/compare/v3.0.43...v3.0.44)
> 19 April 2023
- Create add_to_project.yml [`e06fdd1`](https://github.com/rive-app/rive-react/commit/e06fdd1c8be9c6fe224d6ec83547965d773f633c)
- chore: release 3.0.44 [`ed90c7f`](https://github.com/rive-app/rive-react/commit/ed90c7f7c9851f66578ad5d270b68b5e44c1592e)
#### [v3.0.43](https://github.com/rive-app/rive-react/compare/v3.0.42...v3.0.43)
> 14 April 2023
- chore: release 3.0.43 [`b8ffb6b`](https://github.com/rive-app/rive-react/commit/b8ffb6b53cda2a0ae4143b26dbc0b75bf669a7c7)
- patch: bump rive-wasm to take path fix [`2dc925e`](https://github.com/rive-app/rive-react/commit/2dc925ef70777caf65b7f7785c21d03cbe9cff5a)
#### [v3.0.42](https://github.com/rive-app/rive-react/compare/v3.0.41...v3.0.42)
> 13 April 2023
- chore: release 3.0.42 [`639de79`](https://github.com/rive-app/rive-react/commit/639de79c9edba584439afba46d9390b0dd76a704)
- chore: bump rive-wasm to get solo patch [`a9961c8`](https://github.com/rive-app/rive-react/commit/a9961c821aa7f5c512f92e77cc50e88ba5e69ecb)
#### [v3.0.41](https://github.com/rive-app/rive-react/compare/v3.0.40...v3.0.41)
> 6 April 2023
- chore: release 3.0.41 [`fc082d1`](https://github.com/rive-app/rive-react/commit/fc082d1a03ca6d88439f6be4bb5a3bcb77ed7ddb)
- patch: bump wasm dependency for blend state enhancements [`87fa1ae`](https://github.com/rive-app/rive-react/commit/87fa1ae2a56a5d71fe137fa33a0a3eb0cb3e9c1c)
#### [v3.0.40](https://github.com/rive-app/rive-react/compare/v3.0.39...v3.0.40)
> 5 April 2023
- chore: release 3.0.40 [`62490a5`](https://github.com/rive-app/rive-react/commit/62490a50f9523a146d3040547f73c6068090daf0)
- feature: Add support for touch and drag interactions on canvas [`fcc1a16`](https://github.com/rive-app/rive-react/commit/fcc1a16df494f0f791ff84551ea4db140bffbc50)
#### [v3.0.39](https://github.com/rive-app/rive-react/compare/v3.0.38...v3.0.39)
> 30 March 2023
- chore: release 3.0.39 [`29e0ceb`](https://github.com/rive-app/rive-react/commit/29e0ceb797183b2b6eb6aa9728acb433bb689df3)
- fix: bump wasm dependency for clipping issue fix [`3e6a951`](https://github.com/rive-app/rive-react/commit/3e6a951ca1b3566a7f93def6c17fe87436d2f1bd)
#### [v3.0.38](https://github.com/rive-app/rive-react/compare/v3.0.37...v3.0.38)
> 3 March 2023
- chore: release 3.0.38 [`04910f7`](https://github.com/rive-app/rive-react/commit/04910f78f1779242626db0dfb74ab27ae95c75fa)
- maint: bump wasm dependency for more speed on state updates [`c2977c7`](https://github.com/rive-app/rive-react/commit/c2977c705c5572480be3f253b7237bdc2d3eea35)
#### [v3.0.37](https://github.com/rive-app/rive-react/compare/v3.0.36...v3.0.37)
> 1 March 2023
- chore: release 3.0.37 [`4e21374`](https://github.com/rive-app/rive-react/commit/4e2137422b8c1d135a6501add3f2cc68140f1817)
- maint: bump wasm dependency for more speed on state updates [`0696417`](https://github.com/rive-app/rive-react/commit/06964179262d4b79114f3609d79cc6560c30ef94)
#### [v3.0.36](https://github.com/rive-app/rive-react/compare/v3.0.35...v3.0.36)
> 22 February 2023
- chore: release 3.0.36 [`f11a433`](https://github.com/rive-app/rive-react/commit/f11a433365c34818976798106fc03a264e6ceaea)
- Fix: matchMedia add event listener for safari 13 and older versions [`3cbbf99`](https://github.com/rive-app/rive-react/commit/3cbbf99fec90f58cdf410df861f272115a7704e6)
- maint: bump wasm to support speed on states feature [`48a4726`](https://github.com/rive-app/rive-react/commit/48a4726d1f7a01088959d47580082e5ddfed1492)
#### [v3.0.35](https://github.com/rive-app/rive-react/compare/v3.0.34...v3.0.35)
> 17 January 2023
- chore: release 3.0.35 [`03f05f5`](https://github.com/rive-app/rive-react/commit/03f05f57b7f277d7d90701954b5ca09842bcaab6)
- fix: update rive-wasm to try patching slow burn memory leak [`8b483b8`](https://github.com/rive-app/rive-react/commit/8b483b807b8207fe12c864e19f64592c0bedac46)
#### [v3.0.34](https://github.com/rive-app/rive-react/compare/v3.0.33...v3.0.34)
> 16 December 2022
- chore: release 3.0.34 [`816fcfc`](https://github.com/rive-app/rive-react/commit/816fcfcdbcb9f2d8f83cc7887f43aae011dee3be)
- Bumping rive-app/canvas & webgl versions. [`6c28a87`](https://github.com/rive-app/rive-react/commit/6c28a8795eeabc10aa8bdcee99ee9754d924d0ae)
#### [v3.0.33](https://github.com/rive-app/rive-react/compare/v3.0.32...v3.0.33)
> 8 November 2022
- maint: bump wasm runtime and replace old skills rive file example [`acba24c`](https://github.com/rive-app/rive-react/commit/acba24c4ed4f703303615819678c7273c385286f)
- chore: release 3.0.33 [`6a57630`](https://github.com/rive-app/rive-react/commit/6a57630ae67df057472a6d40f354fcfe53cb5521)
#### [v3.0.32](https://github.com/rive-app/rive-react/compare/v3.0.31...v3.0.32)
> 21 October 2022
- chore: release 3.0.32 [`1e6eb5e`](https://github.com/rive-app/rive-react/commit/1e6eb5ec927aa0bb10ee1e7659c4824c64702f58)
- Bumping to latest Rive WASM to fix https://2dimensions.slack.com/archives/CLLCU09T6/p1666370141425879 [`6871a81`](https://github.com/rive-app/rive-react/commit/6871a81ebd17038426e7089ed836379d02a9c5fd)
#### [v3.0.31](https://github.com/rive-app/rive-react/compare/v3.0.30...v3.0.31)
> 21 October 2022
- chore: release 3.0.31 [`33053b3`](https://github.com/rive-app/rive-react/commit/33053b3b7f0ff6d99ce4383ecea1f031ccb587e0)
- bump runtimes to incorporate speed fix for state machines [`4040083`](https://github.com/rive-app/rive-react/commit/4040083d5a89510356e45433e5026664baf92a49)
#### [v3.0.30](https://github.com/rive-app/rive-react/compare/v3.0.29...v3.0.30)
> 20 October 2022
- chore: release 3.0.30 [`2153b81`](https://github.com/rive-app/rive-react/commit/2153b81e6b74d33d1e2f709291fad338dcbb85da)
- Bump dependencies to fix call to runtime cleanup [`6b1500e`](https://github.com/rive-app/rive-react/commit/6b1500e681ba8984d786eec4d414c4c8ad4b0268)
#### [v3.0.29](https://github.com/rive-app/rive-react/compare/v3.0.28...v3.0.29)
> 20 October 2022
- chore: release 3.0.29 [`503702c`](https://github.com/rive-app/rive-react/commit/503702cf1f963204e3519b9b3dbfea1bfa271d0a)
- Call cleanup on unmount [`7be20b0`](https://github.com/rive-app/rive-react/commit/7be20b0a874afab7f6a29122521f42c71a22aa51)
#### [v3.0.28](https://github.com/rive-app/rive-react/compare/v3.0.27...v3.0.28)
> 20 October 2022
- chore: release 3.0.28 [`78491f5`](https://github.com/rive-app/rive-react/commit/78491f5819b78b2e7435a2509e89fd3c672f3126)
- Bump canvas and webgl dependencies to fix alignment memory leaks [`39edb88`](https://github.com/rive-app/rive-react/commit/39edb88a19aaff478e4e9cbeeef58414f28fdb60)
#### [v3.0.27](https://github.com/rive-app/rive-react/compare/v3.0.26...v3.0.27)
> 4 October 2022
- chore: release 3.0.27 [`fd1a165`](https://github.com/rive-app/rive-react/commit/fd1a1653b13c2fd15f2862e6c372a27fd49acd00)
- Fix: Bump wasm to accomodate clipping bug on nested artboards [`8d7f0ab`](https://github.com/rive-app/rive-react/commit/8d7f0ab28c8aa6af3abe5269e7b8980cc1a8dbe7)
#### [v3.0.26](https://github.com/rive-app/rive-react/compare/v3.0.25...v3.0.26)
> 22 September 2022
- fix: Adjust canvas size if devicePixelRatio changes for any reaason [`2b1aa01`](https://github.com/rive-app/rive-react/commit/2b1aa01a87c14f71b980d160f6607edc12d3eed6)
- chore: release 3.0.26 [`2a2e532`](https://github.com/rive-app/rive-react/commit/2a2e53256401b6d7137db4b73c5901d587a888af)
#### [v3.0.25](https://github.com/rive-app/rive-react/compare/v3.0.24...v3.0.25)
> 21 September 2022
- chore: release 3.0.25 [`06c4e2a`](https://github.com/rive-app/rive-react/commit/06c4e2aea39d8e08ee12760663bd612ca77f3e9c)
- patch: bump js runtime dependency to address content security policy issue in WASM build [`819bd51`](https://github.com/rive-app/rive-react/commit/819bd51ea976bbea0c218379cd88304bd1738323)
#### [v3.0.24](https://github.com/rive-app/rive-react/compare/v3.0.23...v3.0.24)
> 15 September 2022
- add tests [`a62e9b3`](https://github.com/rive-app/rive-react/commit/a62e9b3a9aeb51b71c441ea1560eea6431704ee7)
- chore: release 3.0.24 [`6b7f113`](https://github.com/rive-app/rive-react/commit/6b7f1132964dafe9783f0a79782a2ba20638c7ce)
- fix: make a canvas of size 0 until we calculate the bounds appropriately [`04685c0`](https://github.com/rive-app/rive-react/commit/04685c0bcda26ee0451ab8cc9fc09436e94d04f6)
#### [v3.0.23](https://github.com/rive-app/rive-react/compare/v3.0.22...v3.0.23)
> 31 August 2022
- chore: release 3.0.23 [`48fd9f9`](https://github.com/rive-app/rive-react/commit/48fd9f9d8048ef098ed7550e6da0d3a4eb69148e)
- Bump runtime version to fix broken version [`3c578b7`](https://github.com/rive-app/rive-react/commit/3c578b730f82059469393522722316f2ad3a61d3)
#### [v3.0.22](https://github.com/rive-app/rive-react/compare/v3.0.21...v3.0.22)
> 30 August 2022
- chore: release 3.0.22 [`7a46886`](https://github.com/rive-app/rive-react/commit/7a468861336861361f4fceae45616f001bf4b448)
- Update @rive-app/canvas and @rive-app/webgl dependencies to support non node builds [`092049d`](https://github.com/rive-app/rive-react/commit/092049d20f6f955a0528831d2b5e15087328bc75)
#### [v3.0.21](https://github.com/rive-app/rive-react/compare/v3.0.20...v3.0.21)
> 22 July 2022
- chore: release 3.0.21 [`f7aced0`](https://github.com/rive-app/rive-react/commit/f7aced03cd3c39d039cc53af54947e328fe18e83)
- rev rive-wasm dependencies & update render delay to be 0ms [`eb07281`](https://github.com/rive-app/rive-react/commit/eb072814155bb803f6faa831caa0e0292b8f6f28)
#### [v3.0.20](https://github.com/rive-app/rive-react/compare/v3.0.19...v3.0.20)
> 22 July 2022
- update tests [`24d8e0a`](https://github.com/rive-app/rive-react/commit/24d8e0a90795f650806064d53ae1b362e3fd332f)
- update resize behaviour to throttle, add parameters to enable switching modes [`1092b44`](https://github.com/rive-app/rive-react/commit/1092b44947e2ac07dd38d21e8b45445256c0a59d)
- ensure we re evaluate state machine inputs when we play is triggered, looks like there maybe additional situations where we are going to need this. [`84b18cc`](https://github.com/rive-app/rive-react/commit/84b18cc3ddf86e55b6741956ea8f86d6d21f4078)
#### [v3.0.19](https://github.com/rive-app/rive-react/compare/v3.0.18...v3.0.19)
> 19 July 2022
- chore: release 3.0.19 [`efe28aa`](https://github.com/rive-app/rive-react/commit/efe28aa5f35f5ddde3e89085c34016ce87bb5cbb)
- fix tests that were automatically calling the rive load callback to be more controlled [`16d836c`](https://github.com/rive-app/rive-react/commit/16d836c95928e4294b565ecb444d517653c4988b)
- Fix: Add check before setting Rive as state variable on Rive instance load [`838ed1a`](https://github.com/rive-app/rive-react/commit/838ed1abf8aeec86ca63bfef07953424ba9cce90)
#### [v3.0.18](https://github.com/rive-app/rive-react/compare/v3.0.17...v3.0.18)
> 14 July 2022
- update canvas dimensions to use clientWidth and Height as opposed to BoundingClient, to avoid getting scaled information [`fd1c00a`](https://github.com/rive-app/rive-react/commit/fd1c00a995374634ec8552d20a0f7094fcb04e25)
- chore: release 3.0.18 [`d010a55`](https://github.com/rive-app/rive-react/commit/d010a55cc0c065c353dd5424a6fef8a58f416c61)
#### [v3.0.17](https://github.com/rive-app/rive-react/compare/v3.0.16...v3.0.17)
> 14 July 2022
- add resizeObserver to replace window listeners for all but IE [`e966316`](https://github.com/rive-app/rive-react/commit/e966316971d88a7242651a0b1fa3a1eaff48d276)
- refactored the IE check into `useSize` [`5be9d2f`](https://github.com/rive-app/rive-react/commit/5be9d2f8741224ed7cd291898b1abe88668b3fed)
- Fix useEffects so they're not in conditional statements [`ec61a68`](https://github.com/rive-app/rive-react/commit/ec61a6835d9ca6158538f5d1ac5b6b861c58ac57)
#### [v3.0.16](https://github.com/rive-app/rive-react/compare/v3.0.15...v3.0.16)
> 12 July 2022
- Docs: Condense down README and add CONTRIBUTING guide [`0863835`](https://github.com/rive-app/rive-react/commit/08638359bb817213fb861950a20cae7e7b27111f)
- staged work [`7dbade4`](https://github.com/rive-app/rive-react/commit/7dbade4589ca0524b58f9abbdcc38afa3e3b1866)
- chore: release 3.0.16 [`ae6efc1`](https://github.com/rive-app/rive-react/commit/ae6efc14d46c33b90fe89ee067347296daf865e7)
#### [v3.0.15](https://github.com/rive-app/rive-react/compare/v3.0.14...v3.0.15)
> 28 June 2022
- chore: release 3.0.15 [`8175c4a`](https://github.com/rive-app/rive-react/commit/8175c4a4d406ac80703a6df346f3b5562d2e9311)
- Patch: Bump js runtime dependencies for nested artboard display patch [`795ee53`](https://github.com/rive-app/rive-react/commit/795ee533405ec98457db074d11730849e1be5c88)
#### [v3.0.14](https://github.com/rive-app/rive-react/compare/v3.0.12...v3.0.14)
> 28 June 2022
- Deploying to main from @ 3477afdef166251f35f1778a3143ff6c6efecc58 🚀 [`7aee5cf`](https://github.com/rive-app/rive-react/commit/7aee5cfab4eaca1fc9369742639507a770c4f756)
- Fix: Intake JS runtime patches for starting animation frames [`3477afd`](https://github.com/rive-app/rive-react/commit/3477afdef166251f35f1778a3143ff6c6efecc58)
- chore: release 3.0.14 [`04353db`](https://github.com/rive-app/rive-react/commit/04353db43266f6dcf40f4ef7f3be23afa13c2e0d)
#### [v3.0.12](https://github.com/rive-app/rive-react/compare/v3.0.11...v3.0.12)
> 22 June 2022
- chore: release 3.0.12 [`8b43a82`](https://github.com/rive-app/rive-react/commit/8b43a82c5f56cbb5b1fe7dacfa7ca8457fc6d413)
- Fix: Bump cpp to get nested artboard opacity fix and fill rule patch [`bd49e6a`](https://github.com/rive-app/rive-react/commit/bd49e6a4ee66c68005b60a670700ef69b5322656)
- Bump @rive-app/canvas to take the fillRule bug fix [`1dbb9cd`](https://github.com/rive-app/rive-react/commit/1dbb9cd38d41393b9f354cdf81e88c702aa3ae64)
#### [v3.0.11](https://github.com/rive-app/rive-react/compare/v3.0.10...v3.0.11)
> 22 June 2022
- chore: release 3.0.11 [`aee7407`](https://github.com/rive-app/rive-react/commit/aee7407f7921c515f3c1d9aabf87387baddb4064)
- Docs: Code snippets update to use new React package structure [`b48de9d`](https://github.com/rive-app/rive-react/commit/b48de9db8496be35f29bea87273a7a9fceefdafc)
#### [v3.0.10](https://github.com/rive-app/rive-react/compare/v3.0.8...v3.0.10)
> 20 June 2022
- Deploying to main from @ 5ad5a957a6e8f10abedc23f46033d4792e29dfe5 🚀 [`802648e`](https://github.com/rive-app/rive-react/commit/802648eda8fa0e5a0a35c66af06e476eac59fe9e)
- chore: release 3.0.10 [`6772f16`](https://github.com/rive-app/rive-react/commit/6772f166b7f3e4747ae508a54e2533bb3ea49878)
- Maint: Update docs for storybook link [`5ad5a95`](https://github.com/rive-app/rive-react/commit/5ad5a957a6e8f10abedc23f46033d4792e29dfe5)
#### [v3.0.8](https://github.com/rive-app/rive-react/compare/v3.0.7...v3.0.8)
> 9 June 2022
- Maint: Add GH workflow for deploying storybook to Github Pages [`38625a0`](https://github.com/rive-app/rive-react/commit/38625a00c313192d0edbe1c3a855bea1ec56bd2b)
- chore: release 3.0.8 [`414d6f8`](https://github.com/rive-app/rive-react/commit/414d6f895ac2184876dec90959c17c2b22f6843f)
#### [v3.0.7](https://github.com/rive-app/rive-react/compare/v3.0.6...v3.0.7)
> 8 June 2022
- Feat: Move existing examples into Storybook and add documentation [`ec230fa`](https://github.com/rive-app/rive-react/commit/ec230faa738202cedad14cc866e30c4c03efffd7)
- chore: release 3.0.7 [`bad688d`](https://github.com/rive-app/rive-react/commit/bad688dfa3841ec07e30fa07609a6cb7bb7c1688)
#### [v3.0.6](https://github.com/rive-app/rive-react/compare/v3.0.5...v3.0.6)
> 6 June 2022
- chore: release 3.0.6 [`90c6d1e`](https://github.com/rive-app/rive-react/commit/90c6d1edb1d4bef6250dd4a5101a7cfe04ff9ce9)
- Maint: Roll canvas and webgl dependencies forward to support nested state machines [`0480dc9`](https://github.com/rive-app/rive-react/commit/0480dc92c842265d601d08b60fb49392969cfd9e)
#### [v3.0.5](https://github.com/rive-app/rive-react/compare/v3.0.4...v3.0.5)
> 26 May 2022
- chore: release 3.0.5 [`de24fa5`](https://github.com/rive-app/rive-react/commit/de24fa564117d4acbe60b4cf734abd9e951b30f1)
- Feat: Add stateMachines param to the default Rive component [`84d9730`](https://github.com/rive-app/rive-react/commit/84d9730767a62c63e743d5a04bba5b3d480ea38d)
- Maint: Bump wasm for another listener patch [`805afd5`](https://github.com/rive-app/rive-react/commit/805afd5dff2888294926c32ec07f5e24db804d09)
#### [v3.0.4](https://github.com/rive-app/rive-react/compare/v3.0.3...v3.0.4)
> 23 May 2022
- chore: release 3.0.4 [`9abee34`](https://github.com/rive-app/rive-react/commit/9abee34d12641f845b93febf438df0f77f72153f)
- Maint: Bump rive-wasm dependency for listener patches [`12801b1`](https://github.com/rive-app/rive-react/commit/12801b10cc8980339e5856d71d96da3c612cb291)
#### [v3.0.3](https://github.com/rive-app/rive-react/compare/v3.0.2...v3.0.3)
> 17 May 2022
- Feat: Bump wasm and add examples to support touch feature [`3902948`](https://github.com/rive-app/rive-react/commit/3902948a2ef8af6955ef12124207edee29eb0be8)
- chore: release 3.0.3 [`da11387`](https://github.com/rive-app/rive-react/commit/da1138755861aadb9e7c6cb0028f2120d610a6c5)
#### [v3.0.2](https://github.com/rive-app/rive-react/compare/v3.0.1...v3.0.2)
> 17 May 2022
- chore: release 3.0.2 [`21a17ed`](https://github.com/rive-app/rive-react/commit/21a17ed40ee51263c666dde48b6c55e958eceeb8)
- Maint: Bump wasm dependencies [`f0e7092`](https://github.com/rive-app/rive-react/commit/f0e70924ec9849f45ecddda801ad63e1d87b1bdb)
#### [v3.0.1](https://github.com/rive-app/rive-react/compare/v3.0.0...v3.0.1)

View File

@@ -50,7 +50,7 @@ Check out our Storybook instance that shows how to use the library in small exam
- [Example page](https://rive-app.github.io/rive-react)
- [Login screen w/ input tracking](https://rive-app.github.io/rive-use-cases/?path=/story/example-loginformcomponent--primary)
- [Mouse tracking](https://codesandbox.io/s/rive-mouse-track-test-t0y965?file=/src/App.js)
- [Accessibility concerns](https://blog.rive.app/accessible-web-animations-aria-live-regions/)
- [Accessibility concerns](https://rive.app/blog/accesible-web-animations-aria-live-regions)
## Migration Guides

View File

@@ -4,8 +4,8 @@ import { useState } from 'react';
import { Canvas, Meta, Story, ArgsTable } from '@storybook/addon-docs';
import RiveComponent, {useRive, useStateMachineInput} from '../../src';
import {Button} from './components/Button';
import RiveComponent, { useRive, useStateMachineInput } from '../../src';
import { Button } from './components/Button';
import './rive-overview.css';
<Meta title="React Runtime/Overview" />
@@ -31,6 +31,7 @@ There's multiple ways to render Rive using the React runtime. See the associated
```tsx
import RiveComponent from '@rive-app/react-canvas';
```
The React runtime exports a default React component you can insert as JSX. Under the hood, it renders a `<canvas>` element that runs the animation, and a wrapping `<div>` element that handles sizing of the canvas based on the parent that wraps the component.
**When to use this**: Use this for simple rendering cases where you don't need to control playback or setup state machine inputs to advance state machines. It will simply autoplay the first animation it finds in the `.riv`, the animation name you provide it, or the state machine name if you provide one.
@@ -56,12 +57,13 @@ In addition to the props laid out below, the component accepts other props that
### useRive Hook
```tsx
import {useRive} from '@rive-app/react-canvas';
import { useRive } from '@rive-app/react-canvas';
```
The runtime also exports a named `useRive` hook that allows for more control at Rive instantiation, since it passes back a `rive` object you can use to manipulate state machines, control playback, and more.
**When to use this:** When you need to control your Rive animation in any aspect, such as controlling playback, using state machine inputs to advance state machines, add adding callbacks on certain Rive-specific events such as `onStateChange`, `onPause`, etc.
<Canvas withSource="open">
<Story name="useRive Hook">
{() => {
@@ -69,7 +71,7 @@ The runtime also exports a named `useRive` hook that allows for more control at
const [animationText, setAnimationText] = useState('');
const { rive, RiveComponent: RiveComponentPlayback } = useRive({
src: 'truck.riv',
stateMachines: "drive",
stateMachines: 'drive',
artboard: 'Truck',
autoplay: true,
onPause: () => {
@@ -88,15 +90,19 @@ The runtime also exports a named `useRive` hook that allows for more control at
setIsPlaying(true);
}
};
return ((
return (
<>
<div className="center">
<RiveComponentPlayback className="base-canvas-size" />
<RiveComponentPlayback className="base-canvas-size">
<p>Animation that can be paused and played by clicking on it</p>
</RiveComponentPlayback>
<p>{animationText}</p>
<Button onClick={togglePlaying}>{isPlaying ? 'Pause' : 'Play'}</Button>
<Button onClick={togglePlaying}>
{isPlaying ? 'Pause' : 'Play'}
</Button>
</div>
</>
));
);
}}
</Story>
</Canvas>

View File

@@ -4,8 +4,8 @@ import { useState } from 'react';
import { Canvas, Meta, Story, ArgsTable } from '@storybook/addon-docs';
import RiveComponent, {useRive, useStateMachineInput} from '../../src';
import {Button} from './components/Button';
import RiveComponent, { useRive, useStateMachineInput } from '../../src';
import { Button } from './components/Button';
import './rive-overview.css';
<Meta title="React Runtime/State Machines" />
@@ -15,6 +15,7 @@ import './rive-overview.css';
Not familiar with Rive State Machines? Check out our [help docs](https://help.rive.app/editor/state-machine) on what these are first!
The `useStateMachineInput` hook is a helper that makes grabbing references to state machine inputs easier to setup. This hook should be used along with the `useRive` hook, as you need to pass in the `rive` instance returned from `useRive`. See each of the examples below to see usage of the hook creating instance of three types of inputs:
- Booleans
- Numbers
- Triggers
@@ -90,8 +91,8 @@ Once you grab a reference to the state machine input, you can get/set the value
<Canvas withSource="open">
<Story name="Number input">
{() => {
const STATE_MACHINE_NAME = 'State Machine ';
const INPUT_NAME = 'Level';
const STATE_MACHINE_NAME = 'skill-controller';
const INPUT_NAME = 'level';
const { rive, RiveComponent: RiveComponentTouch } = useRive({
src: 'skills.riv',
stateMachines: STATE_MACHINE_NAME,
@@ -101,7 +102,11 @@ Once you grab a reference to the state machine input, you can get/set the value
// levelInput is a number state machine input. To transition the state machine,
// we need to set the value to a number. For this state machine input, we need
// to set to 0, 1 or 2 for a state transition to occur.
const levelInput = useStateMachineInput(rive, STATE_MACHINE_NAME, INPUT_NAME);
const levelInput = useStateMachineInput(
rive,
STATE_MACHINE_NAME,
INPUT_NAME
);
return (
// The animation will fit to the parent element, so we set a large height
// and width for this example.

View File

Binary file not shown.

View File

@@ -1,6 +1,6 @@
{
"name": "rive-react",
"version": "3.0.17",
"version": "3.0.55",
"description": "React wrapper around the rive-js library",
"main": "dist/index.js",
"typings": "dist/types/index.d.ts",
@@ -29,8 +29,8 @@
},
"homepage": "https://github.com/rive-app/rive-react#readme",
"dependencies": {
"@rive-app/canvas": "1.0.71",
"@rive-app/webgl": "1.0.68"
"@rive-app/canvas": "1.2.2",
"@rive-app/webgl": "1.2.2"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"

View File

@@ -28,7 +28,15 @@ export interface RiveProps {
* For `@rive-app/react-webgl`, sets this property to maintain a single WebGL context for multiple canvases. **We recommend to keep the default value** when rendering multiple Rive instances on a page.
*/
useOffscreenRenderer?: boolean;
};
/**
* Specify whether to disable Rive listeners on the canvas, thus preventing any event listeners to be attached to the canvas element
*/
shouldDisableRiveListeners?: boolean;
/**
* Specify whether to resize the canvas to its container automatically
*/
shouldResizeCanvasToContainer?: boolean;
}
const Rive = ({
src,
@@ -37,6 +45,9 @@ const Rive = ({
stateMachines,
layout,
useOffscreenRenderer = true,
shouldDisableRiveListeners = false,
shouldResizeCanvasToContainer = true,
children,
...rest
}: RiveProps & ComponentProps<'canvas'>) => {
const params = {
@@ -46,14 +57,16 @@ const Rive = ({
layout,
stateMachines,
autoplay: true,
shouldDisableRiveListeners,
};
const options = {
useOffscreenRenderer,
shouldResizeCanvasToContainer,
};
const { RiveComponent } = useRive(params, options);
return <RiveComponent {...rest} />;
return <RiveComponent {...rest}>{children}</RiveComponent>;
};
export default Rive;

View File

@@ -0,0 +1,94 @@
import { useEffect, useRef, useState } from 'react';
import { Dimensions } from '../types';
// There are polyfills for this, but they add hundreds of lines of code
class FakeResizeObserver {
observe() {}
unobserve() {}
disconnect() {}
}
function throttle(f: Function, delay: number) {
let timer = 0;
return function (this: Function, ...args: any) {
clearTimeout(timer);
timer = window.setTimeout(() => f.apply(this, args), delay);
};
}
const MyResizeObserver = globalThis.ResizeObserver || FakeResizeObserver;
const hasResizeObserver = globalThis.ResizeObserver !== undefined;
const useResizeObserver = hasResizeObserver;
const useWindowListener = !useResizeObserver;
/**
* Hook to listen for a ref element's resize events being triggered. When resized,
* it sets state to an object of {width: number, height: number} indicating the contentRect
* size of the element at the new resize.
*
* @param containerRef - Ref element to listen for resize events on
* @returns - Size object with width and height attributes
*/
export default function useSize(
containerRef: React.MutableRefObject<HTMLElement | null>,
shouldResizeCanvasToContainer = true
) {
const [size, setSize] = useState<Dimensions>({
width: 0,
height: 0,
});
// internet explorer does not support ResizeObservers.
useEffect(() => {
if (typeof window !== 'undefined' && shouldResizeCanvasToContainer) {
const handleResize = () => {
setSize({
width: window.innerWidth,
height: window.innerHeight,
});
};
if (useWindowListener) {
// only pay attention to window size changes when we do not have the resizeObserver (IE only)
handleResize();
window.addEventListener('resize', handleResize);
}
return () => window.removeEventListener('resize', handleResize);
}
}, []);
const observer = useRef(
new MyResizeObserver(
throttle((entries: any) => {
if (useResizeObserver) {
setSize({
width: entries[entries.length - 1].contentRect.width,
height: entries[entries.length - 1].contentRect.height,
});
}
}, 0)
)
);
useEffect(() => {
const currentObserver = observer.current;
if (!shouldResizeCanvasToContainer) {
currentObserver.disconnect();
return;
}
const containerEl = containerRef.current;
if (containerRef.current && useResizeObserver) {
currentObserver.observe(containerRef.current);
}
return () => {
currentObserver.disconnect();
if (containerEl && useResizeObserver) {
currentObserver.unobserve(containerEl);
}
};
}, [containerRef, observer]);
return size;
}

View File

@@ -0,0 +1,49 @@
import { useEffect, useState } from 'react';
/**
* Listen for devicePixelRatio changes and set the new value accordingly. This could
* happen for reasons such as:
* - User moves window from retina screen display to a separate monitor
* - User controls zoom settings on the browser
*
* Source: https://github.com/rexxars/use-device-pixel-ratio/blob/main/index.ts
*
* @returns dpr: Number - Device pixel ratio; ratio of physical px to resolution in CSS pixels for current device
*/
export default function useDevicePixelRatio() {
const dpr = getDevicePixelRatio();
const [currentDpr, setCurrentDpr] = useState(dpr);
useEffect(() => {
const canListen = typeof window !== 'undefined' && 'matchMedia' in window;
if (!canListen) {
return;
}
const updateDpr = () => {
const newDpr = getDevicePixelRatio();
setCurrentDpr(newDpr);
};
const mediaMatcher = window.matchMedia(
`screen and (resolution: ${currentDpr}dppx)`
);
mediaMatcher.hasOwnProperty('addEventListener')
? mediaMatcher.addEventListener('change', updateDpr)
: mediaMatcher.addListener(updateDpr);
return () => {
mediaMatcher.hasOwnProperty('removeEventListener')
? mediaMatcher.removeEventListener('change', updateDpr)
: mediaMatcher.removeListener(updateDpr);
};
}, [currentDpr]);
return currentDpr;
}
function getDevicePixelRatio(): number {
const hasDprProp =
typeof window !== 'undefined' &&
typeof window.devicePixelRatio === 'number';
const dpr = hasDprProp ? window.devicePixelRatio : 1;
return Math.min(Math.max(1, dpr), 3);
}

View File

@@ -0,0 +1,186 @@
import { useEffect, useState, MutableRefObject, useCallback } from 'react';
import { Bounds } from '@rive-app/canvas';
import { Dimensions, UseRiveOptions } from '../types';
import useDevicePixelRatio from './useDevicePixelRatio';
import useContainerSize from './useContainerSize';
import { getOptions } from '../utils';
interface UseResizeCanvasProps {
/**
* Whether or not Rive is loaded and renderer is associated with the canvas
*/
riveLoaded: boolean;
/**
* Ref to the canvas element
*/
canvasRef: MutableRefObject<HTMLCanvasElement | null>;
/**
* Ref to the container element of the canvas
*/
containerRef: MutableRefObject<HTMLElement | null>;
/**
* (Optional) Callback to be invoked after the canvas has been resized due to a resize
* of its parent container. This is where you would want to reset the layout
* dimensions for the Rive renderer to dictate the new min/max bounds of the
* canvas.
*
* Using the high-level JS runtime, this might be a simple call to `rive.resizeToCanvas()`
* Using the low-level JSruntime, this might be invoking the renderer's `.align()` method
* with the Layout and min/max X/Y values of the canvas.
*
* @returns void
*/
onCanvasHasResized?: () => void;
/**
* (Optional) Options passed to the useRive hook, including the shouldResizeCanvasToContainer option
* which prevents the canvas element from resizing to its parent container
*/
options?: Partial<UseRiveOptions>;
/**
* (Optional) AABB bounds of the artboard. If provided, the canvas will be sized to the artboard
* height if the fitCanvasToArtboardHeight option is true.
*/
artboardBounds?: Bounds;
}
/**
* Helper hook to listen for changes in the <canvas> parent container size and size the <canvas>
* to match. If a resize event has occurred, a supplied callback (onCanvasHasResized)
* will be inokved to allow for any re-calculation needed (i.e. Rive layout on the canvas).
*
* This hook is useful if you are not intending to use the `useRive` hook yourself, but still
* want to use the auto-sizing logic on the canvas/container.
*
* @param props - Object to supply necessary props to the hook
*/
export default function useResizeCanvas({
riveLoaded = false,
canvasRef,
containerRef,
options = {},
onCanvasHasResized,
artboardBounds,
}: UseResizeCanvasProps) {
const presetOptions = getOptions(options);
const [
{ height: lastContainerHeight, width: lastContainerWidth },
setLastContainerDimensions,
] = useState<Dimensions>({
height: 0,
width: 0,
});
const [
{ height: lastCanvasHeight, width: lastCanvasWidth },
setLastCanvasSize,
] = useState<Dimensions>({
height: 0,
width: 0,
});
const [isFirstSizing, setIsFirstSizing] = useState(true);
const {
fitCanvasToArtboardHeight,
shouldResizeCanvasToContainer,
useDevicePixelRatio: shouldUseDevicePixelRatio,
} = presetOptions;
const containerSize = useContainerSize(
containerRef,
shouldResizeCanvasToContainer
);
const currentDevicePixelRatio = useDevicePixelRatio();
const { maxX, maxY } = artboardBounds ?? {};
const getContainerDimensions = useCallback(() => {
const width = containerRef.current?.clientWidth ?? 0;
const height = containerRef.current?.clientHeight ?? 0;
if (fitCanvasToArtboardHeight && artboardBounds) {
const { maxY, maxX } = artboardBounds;
return { width, height: width * (maxY / maxX) };
}
return {
width,
height,
};
}, [containerRef, fitCanvasToArtboardHeight, maxX, maxY]);
useEffect(() => {
// If Rive is not ready, the container is not ready, or the user supplies a flag
// to not resize the canvas to the container, then return early
if (
!shouldResizeCanvasToContainer ||
!containerRef.current ||
!riveLoaded
) {
return;
}
const { width, height } = getContainerDimensions();
let hasResized = false;
if (canvasRef.current) {
// Check if the canvas parent container bounds have changed and set
// new values accordingly
const boundsChanged =
width !== lastContainerWidth || height !== lastContainerHeight;
if (presetOptions.fitCanvasToArtboardHeight && boundsChanged) {
containerRef.current.style.height = height + 'px';
hasResized = true;
}
if (presetOptions.useDevicePixelRatio) {
// Check if devicePixelRatio may have changed and get new canvas
// width/height values to set the size
const canvasSizeChanged =
width * currentDevicePixelRatio !== lastCanvasWidth ||
height * currentDevicePixelRatio !== lastCanvasHeight;
if (boundsChanged || canvasSizeChanged) {
const newCanvasWidthProp = currentDevicePixelRatio * width;
const newCanvasHeightProp = currentDevicePixelRatio * height;
canvasRef.current.width = newCanvasWidthProp;
canvasRef.current.height = newCanvasHeightProp;
canvasRef.current.style.width = width + 'px';
canvasRef.current.style.height = height + 'px';
setLastCanvasSize({
width: newCanvasWidthProp,
height: newCanvasHeightProp,
});
hasResized = true;
}
} else if (boundsChanged) {
canvasRef.current.width = width;
canvasRef.current.height = height;
setLastCanvasSize({
width: width,
height: height,
});
hasResized = true;
}
setLastContainerDimensions({ width, height });
}
// Callback to perform any Rive-related actions after resizing the canvas
// (i.e., reset the Rive layout in the render loop)
if (onCanvasHasResized && (isFirstSizing || hasResized)) {
onCanvasHasResized && onCanvasHasResized();
}
isFirstSizing && setIsFirstSizing(false);
}, [
canvasRef,
containerRef,
containerSize,
currentDevicePixelRatio,
getContainerDimensions,
isFirstSizing,
setIsFirstSizing,
lastCanvasHeight,
lastCanvasWidth,
lastContainerHeight,
lastContainerWidth,
onCanvasHasResized,
shouldResizeCanvasToContainer,
fitCanvasToArtboardHeight,
shouldUseDevicePixelRatio,
riveLoaded,
]);
}

View File

@@ -7,13 +7,9 @@ import React, {
RefCallback,
} from 'react';
import { Rive, EventType } from '@rive-app/canvas';
import {
UseRiveParameters,
UseRiveOptions,
RiveState,
Dimensions,
} from '../types';
import { useSize } from '../utils';
import { UseRiveParameters, UseRiveOptions, RiveState } from '../types';
import useResizeCanvas from './useResizeCanvas';
import { getOptions } from '../utils';
type RiveComponentProps = {
setContainerRef: RefCallback<HTMLElement>;
@@ -25,6 +21,7 @@ function RiveComponent({
setCanvasRef,
className = '',
style,
children,
...rest
}: RiveComponentProps & ComponentProps<'canvas'>) {
const containerStyle = {
@@ -39,27 +36,17 @@ function RiveComponent({
className={className}
{...(!className && { style: containerStyle })}
>
<canvas ref={setCanvasRef} style={{ verticalAlign: 'top' }} {...rest} />
<canvas
ref={setCanvasRef}
style={{ verticalAlign: 'top', width: 0, height: 0 }}
{...rest}
>
{children}
</canvas>
</div>
);
}
const defaultOptions = {
useDevicePixelRatio: true,
fitCanvasToArtboardHeight: false,
useOffscreenRenderer: true,
};
/**
* Returns options, with defaults set.
*
* @param opts
* @returns
*/
function getOptions(opts: Partial<UseRiveOptions>) {
return Object.assign({}, defaultOptions, opts);
}
/**
* Custom Hook for loading a Rive file.
*
@@ -82,88 +69,30 @@ export default function useRive(
const containerRef = useRef<HTMLElement | null>(null);
const [rive, setRive] = useState<Rive | null>(null);
const [dimensions, setDimensions] = useState<Dimensions>({
height: 0,
width: 0,
});
// Listen to changes in the window sizes and update the bounds when changes
// occur.
const size = useSize(containerRef);
const isParamsLoaded = Boolean(riveParams);
const options = getOptions(opts);
/**
* Gets the intended dimensions of the canvas element.
*
* The intended dimensions are those of the container element, unless the
* option `fitCanvasToArtboardHeight` is true, then they are adjusted to
* the height of the artboard.
*
* @returns Dimensions object.
* When the canvas/parent container resize, reset the Rive layout to match the
* new (0, 0, canvas.width, canvas.height) bounds in the render loop
*/
function getCanvasDimensions() {
const { width, height } =
containerRef.current?.getBoundingClientRect() ?? new DOMRect(0, 0, 0, 0);
if (rive && options.fitCanvasToArtboardHeight) {
const { maxY, maxX } = rive.bounds;
return { width, height: width * (maxY / maxX) };
}
return { width, height };
}
/**
* Updates the width and height of the canvas.
*/
function updateBounds() {
if (!containerRef.current) {
return;
}
const { width, height } = getCanvasDimensions();
const boundsChanged =
width !== dimensions.width || height !== dimensions.height;
if (canvasRef.current && rive && boundsChanged) {
if (options.fitCanvasToArtboardHeight) {
containerRef.current.style.height = height + 'px';
}
if (options.useDevicePixelRatio) {
const dpr = window.devicePixelRatio || 1;
canvasRef.current.width = dpr * width;
canvasRef.current.height = dpr * height;
canvasRef.current.style.width = width + 'px';
canvasRef.current.style.height = height + 'px';
} else {
canvasRef.current.width = width;
canvasRef.current.height = height;
}
setDimensions({ width, height });
// Updating the canvas width or height will clear the canvas, so call
// startRendering() to redraw the current frame as the animation might
// be paused and not advancing.
rive.startRendering();
}
// Always resize to Canvas
const onCanvasHasResized = useCallback(() => {
if (rive) {
rive.startRendering();
rive.resizeToCanvas();
}
}
}, [rive]);
/**
* Listen to changes on the windowSize and the rive file being loaded
* and update the canvas bounds as needed.
*
* ie does not support ResizeObservers, so we fallback to the window listener there
*/
useEffect(() => {
if (rive) {
updateBounds();
}
}, [rive, size]);
// Watch the canvas parent container resize and size the canvas to match
useResizeCanvas({
riveLoaded: !!rive,
canvasRef,
containerRef,
options,
onCanvasHasResized,
artboardBounds: rive?.bounds,
});
/**
* Ref callback called when the canvas element mounts and unmounts.
@@ -177,7 +106,16 @@ export default function useRive(
...riveParams,
canvas,
});
r.on(EventType.Load, () => setRive(r));
r.on(EventType.Load, () => {
// Check if the component/canvas is mounted before setting state to avoid setState
// on an unmounted component in some rare cases
if (canvasRef.current) {
setRive(r);
} else {
// If unmounted, cleanup the rive object immediately
r.cleanup();
}
});
} else if (canvas === null && canvasRef.current) {
canvasRef.current.height = 0;
canvasRef.current.width = 0;
@@ -218,12 +156,13 @@ export default function useRive(
}, [rive]);
/**
* On unmount, stop rive from rendering.
* On unmount, call cleanup to cleanup any WASM generated objects that need
* to be manually destroyed.
*/
useEffect(() => {
return () => {
if (rive) {
rive.stop();
rive.cleanup();
setRive(null);
}
};
@@ -255,11 +194,12 @@ export default function useRive(
/>
);
},
[]
[setCanvasRef, setContainerRef]
);
return {
canvas: canvasRef.current,
container: containerRef.current,
setCanvasRef,
setContainerRef,
rive,

View File

@@ -1,5 +1,5 @@
import { useState, useEffect } from 'react';
import { Rive, StateMachineInput } from '@rive-app/canvas';
import { EventType, Rive, StateMachineInput } from '@rive-app/canvas';
/**
* Custom hook for fetching a stateMachine input from a rive file.
@@ -18,21 +18,33 @@ export default function useStateMachineInput(
const [input, setInput] = useState<StateMachineInput | null>(null);
useEffect(() => {
if (!rive || !stateMachineName || !inputName) {
setInput(null);
}
if (rive && stateMachineName && inputName) {
const inputs = rive.stateMachineInputs(stateMachineName);
if (inputs) {
const selectedInput = inputs.find((input) => input.name === inputName);
if (initialValue !== undefined && selectedInput) {
selectedInput.value = initialValue;
}
setInput(selectedInput || null);
function setStateMachineInput() {
if (!rive || !stateMachineName || !inputName) {
setInput(null);
}
} else {
setInput(null);
if (rive && stateMachineName && inputName) {
const inputs = rive.stateMachineInputs(stateMachineName);
if (inputs) {
const selectedInput = inputs.find(
(input) => input.name === inputName
);
if (initialValue !== undefined && selectedInput) {
selectedInput.value = initialValue;
}
setInput(selectedInput || null);
}
} else {
setInput(null);
}
}
setStateMachineInput();
if (rive) {
rive.on(EventType.Play, () => {
// Check if the component/canvas is mounted before setting state to avoid setState
// on an unmounted component in some rare cases
setStateMachineInput();
});
}
}, [rive]);

View File

@@ -1,8 +1,9 @@
import Rive from './components/Rive';
import useRive from './hooks/useRive';
import useStateMachineInput from './hooks/useStateMachineInput';
import useResizeCanvas from './hooks/useResizeCanvas';
export default Rive;
export { useRive, useStateMachineInput };
export { useRive, useStateMachineInput, useResizeCanvas };
export { RiveState, UseRiveParameters, UseRiveOptions } from './types';
export * from '@rive-app/canvas';

View File

@@ -7,6 +7,7 @@ export type UseRiveOptions = {
useDevicePixelRatio: boolean;
fitCanvasToArtboardHeight: boolean;
useOffscreenRenderer: boolean;
shouldResizeCanvasToContainer: boolean;
};
export type Dimensions = {
@@ -17,6 +18,7 @@ export type Dimensions = {
/**
* @typedef RiveState
* @property canvas - Canvas element the Rive Animation is attached to.
* @property container - Container element of the canvas.
* @property setCanvasRef - Ref callback to be passed to the canvas element.
* @property setContainerRef - Ref callback to be passed to the container element
* of the canvas. This is optional, however if not used then the hook will
@@ -26,6 +28,7 @@ export type Dimensions = {
*/
export type RiveState = {
canvas: HTMLCanvasElement | null;
container: HTMLElement | null;
setCanvasRef: RefCallback<HTMLCanvasElement>;
setContainerRef: RefCallback<HTMLElement>;
rive: Rive | null;

View File

@@ -1,62 +1,12 @@
import React, { useState, useEffect, useRef } from 'react';
import { Dimensions } from './types';
import { UseRiveOptions } from './types';
// There are polyfills for this, but they add hundreds of lines of code
class FakeResizeObserver {
observe() {}
unobserve() {}
disconnect() {}
}
const MyResizeObserver = globalThis.ResizeObserver || FakeResizeObserver;
const hasResizeObserver = globalThis.ResizeObserver !== undefined;
export function useSize(
containerRef: React.MutableRefObject<HTMLElement | null>
) {
const [size, setSize] = useState<Dimensions>({
width: 0,
height: 0,
});
// internet explorer does not support ResizeObservers.
useEffect(() => {
if (typeof window !== 'undefined') {
const handleResize = () => {
setSize({
width: window.innerWidth,
height: window.innerHeight,
});
};
if (!hasResizeObserver) {
// only pay attention to window size changes when we do not have the resizeObserver (IE only)
window.addEventListener('resize', handleResize);
handleResize();
}
return () => window.removeEventListener('resize', handleResize);
}
}, []);
const observer = useRef(
new MyResizeObserver((entries) => {
setSize({
width: entries[entries.length - 1].contentRect.width,
height: entries[entries.length - 1].contentRect.height,
});
})
);
useEffect(() => {
const current = observer.current;
if (containerRef.current) {
current.observe(containerRef.current);
}
return () => {
current.disconnect();
};
}, [containerRef, observer]);
return size;
const defaultOptions = {
useDevicePixelRatio: true,
fitCanvasToArtboardHeight: false,
useOffscreenRenderer: true,
shouldResizeCanvasToContainer: true,
};
export function getOptions(opts: Partial<UseRiveOptions>) {
return Object.assign({}, defaultOptions, opts);
}

View File

@@ -36,4 +36,19 @@ describe('Rive Component', () => {
expect(container.firstChild).toHaveClass('container-styles');
expect(getByLabelText('Foo label').tagName).toEqual('CANVAS');
});
it('allows children to render in the canvas body', () => {
const accessibleFallbackText = 'An animated test';
const { getByText } = render(
<RiveComponent
src="foo.riv"
className="container-styles"
aria-label="Foo label"
>
<p>{accessibleFallbackText}</p>
</RiveComponent>
);
expect(getByText(accessibleFallbackText)).not.toBeNull();
});
});

View File

@@ -29,6 +29,23 @@ jest.mock('@rive-app/canvas', () => ({
}));
describe('useRive', () => {
let controlledRiveloadCb: () => void;
let baseRiveMock: Partial<rive.Rive>;
beforeEach(() => {
baseRiveMock = {
on: (_: rive.EventType, cb: rive.EventCallback) =>
((controlledRiveloadCb as rive.EventCallback) = cb),
stop: jest.fn(),
stopRendering: jest.fn(),
startRendering: jest.fn(),
};
});
afterEach(() => {
controlledRiveloadCb = () => {};
});
it('returns rive as null if no params are passed', () => {
const { result } = renderHook(() => useRive());
expect(result.current.rive).toBe(null);
@@ -40,23 +57,17 @@ describe('useRive', () => {
src: 'file-src',
};
const riveMock = {
on: (_: string, cb: () => void) => cb(),
stop: jest.fn(),
stopRendering: jest.fn(),
};
// @ts-ignore
mocked(rive.Rive).mockImplementation(() => riveMock);
mocked(rive.Rive).mockImplementation(() => baseRiveMock);
const canvasSpy = document.createElement('canvas');
const { result } = renderHook(() => useRive(params));
await act(async () => {
result.current.setCanvasRef(canvasSpy);
controlledRiveloadCb();
});
expect(result.current.rive).toBe(riveMock);
expect(result.current.rive).toBe(baseRiveMock);
expect(result.current.canvas).toBe(canvasSpy);
});
@@ -68,9 +79,7 @@ describe('useRive', () => {
const resizeToCanvasMock = jest.fn();
const riveMock = {
on: (_: string, cb: () => void) => cb(),
stop: jest.fn(),
stopRendering: jest.fn(),
...baseRiveMock,
resizeToCanvas: resizeToCanvasMock,
};
@@ -84,6 +93,10 @@ describe('useRive', () => {
await act(async () => {
result.current.setCanvasRef(canvasSpy);
result.current.setContainerRef(containerSpy);
controlledRiveloadCb();
jest.spyOn(containerSpy, 'clientWidth', 'get').mockReturnValue(500);
jest.spyOn(containerSpy, 'clientHeight', 'get').mockReturnValue(500);
containerSpy.dispatchEvent(new Event('resize'));
});
expect(result.current.rive).toBe(riveMock);
@@ -92,16 +105,16 @@ describe('useRive', () => {
expect(resizeToCanvasMock).toBeCalled();
});
it('stops the rive object on unmount', async () => {
it('calls cleanup on the rive object on unmount', async () => {
const params = {
src: 'file-src',
};
const stopMock = jest.fn();
const cleanupMock = jest.fn();
const riveMock = {
on: (_: string, cb: () => void) => cb(),
stop: stopMock,
...baseRiveMock,
cleanup: cleanupMock,
};
// @ts-ignore
@@ -112,11 +125,12 @@ describe('useRive', () => {
await act(async () => {
result.current.setCanvasRef(canvasSpy);
controlledRiveloadCb();
});
unmount();
expect(stopMock).toBeCalled();
expect(cleanupMock).toBeCalled();
});
it('sets the a bounds with the devicePixelRatio by default', async () => {
@@ -126,26 +140,20 @@ describe('useRive', () => {
global.devicePixelRatio = 2;
const riveMock = {
on: (_: string, cb: () => void) => cb(),
stop: jest.fn(),
};
// @ts-ignore
mocked(rive.Rive).mockImplementation(() => riveMock);
mocked(rive.Rive).mockImplementation(() => baseRiveMock);
const canvasSpy = document.createElement('canvas');
const containerSpy = document.createElement('div');
containerSpy.getBoundingClientRect = jest.fn().mockImplementation(() => ({
width: 100,
height: 100,
}));
jest.spyOn(containerSpy, 'clientWidth', 'get').mockReturnValue(100);
jest.spyOn(containerSpy, 'clientHeight', 'get').mockReturnValue(100);
const { result } = renderHook(() => useRive(params));
await act(async () => {
result.current.setCanvasRef(canvasSpy);
result.current.setContainerRef(containerSpy);
controlledRiveloadCb();
});
// Height and width should be 2* the width and height returned from containers
@@ -166,26 +174,20 @@ describe('useRive', () => {
useDevicePixelRatio: false,
};
const riveMock = {
on: (_: string, cb: () => void) => cb(),
stop: jest.fn(),
};
// @ts-ignore
mocked(rive.Rive).mockImplementation(() => riveMock);
mocked(rive.Rive).mockImplementation(() => baseRiveMock);
const canvasSpy = document.createElement('canvas');
const containerSpy = document.createElement('div');
containerSpy.getBoundingClientRect = jest.fn().mockImplementation(() => ({
width: 100,
height: 100,
}));
jest.spyOn(containerSpy, 'clientWidth', 'get').mockReturnValue(100);
jest.spyOn(containerSpy, 'clientHeight', 'get').mockReturnValue(100);
const { result } = renderHook(() => useRive(params, opts));
await act(async () => {
result.current.setCanvasRef(canvasSpy);
result.current.setContainerRef(containerSpy);
controlledRiveloadCb();
});
// Height and width should be same as containers bounding rect
@@ -193,7 +195,7 @@ describe('useRive', () => {
expect(canvasSpy).toHaveAttribute('width', '100');
});
it('uses artbound height to set bounds if fitCanvasToArtboardHeight is true', async () => {
it('uses artboard height to set bounds if fitCanvasToArtboardHeight is true', async () => {
const params = {
src: 'file-src',
};
@@ -203,8 +205,7 @@ describe('useRive', () => {
};
const riveMock = {
on: (_: string, cb: () => void) => cb(),
stop: jest.fn(),
...baseRiveMock,
bounds: {
maxX: 100,
maxY: 50,
@@ -216,16 +217,15 @@ describe('useRive', () => {
const canvasSpy = document.createElement('canvas');
const containerSpy = document.createElement('div');
containerSpy.getBoundingClientRect = jest.fn().mockImplementation(() => ({
width: 100,
height: 100,
}));
jest.spyOn(containerSpy, 'clientWidth', 'get').mockReturnValue(100);
jest.spyOn(containerSpy, 'clientHeight', 'get').mockReturnValue(100);
const { result } = renderHook(() => useRive(params, opts));
await act(async () => {
result.current.setContainerRef(containerSpy);
result.current.setCanvasRef(canvasSpy);
controlledRiveloadCb();
});
// Height and width should be same as containers bounding rect
@@ -249,8 +249,7 @@ describe('useRive', () => {
}));
const riveMock = {
on: (_: string, cb: () => void) => cb(),
stop: jest.fn(),
...baseRiveMock,
bounds: {
maxX: 100,
maxY: 50,
@@ -266,6 +265,7 @@ describe('useRive', () => {
await act(async () => {
result.current.setCanvasRef(canvasSpy);
controlledRiveloadCb();
});
expect(observeMock).toBeCalledWith(canvasSpy);
@@ -283,7 +283,7 @@ describe('useRive', () => {
const stopMock = jest.fn();
const riveMock = {
on: (_: string, cb: () => void) => cb(),
...baseRiveMock,
stop: stopMock,
play: playMock,
animationNames: ['light'],
@@ -301,6 +301,7 @@ describe('useRive', () => {
await act(async () => {
result.current.setCanvasRef(canvasSpy);
controlledRiveloadCb();
});
rerender({
@@ -323,7 +324,7 @@ describe('useRive', () => {
const stopMock = jest.fn();
const riveMock = {
on: (_: string, cb: () => void) => cb(),
...baseRiveMock,
stop: stopMock,
play: playMock,
pause: pauseMock,
@@ -343,6 +344,7 @@ describe('useRive', () => {
await act(async () => {
result.current.setCanvasRef(canvasSpy);
controlledRiveloadCb();
});
rerender({
@@ -360,20 +362,15 @@ describe('useRive', () => {
src: 'file-src',
};
const riveMock = {
on: (_: string, cb: () => void) => cb(),
stop: jest.fn(),
stopRendering: jest.fn(),
};
// @ts-ignore
mocked(rive.Rive).mockImplementation(() => riveMock);
mocked(rive.Rive).mockImplementation(() => baseRiveMock);
const canvasSpy = document.createElement('canvas');
const { result } = renderHook(() => useRive(params));
await act(async () => {
result.current.setCanvasRef(canvasSpy);
controlledRiveloadCb();
});
const { RiveComponent: RiveTestComponent } = result.current;
@@ -382,4 +379,115 @@ describe('useRive', () => {
);
expect(container.firstChild).not.toHaveStyle('width: 50%');
});
it('has a canvas size of 0 by default', async () => {
const params = {
src: 'file-src',
};
// @ts-ignore
mocked(rive.Rive).mockImplementation(() => baseRiveMock);
const canvasSpy = document.createElement('canvas');
const { result } = renderHook(() => useRive(params));
await act(async () => {
result.current.setCanvasRef(canvasSpy);
controlledRiveloadCb();
});
const { RiveComponent: RiveTestComponent } = result.current;
const { container } = render(<RiveTestComponent />);
expect(container.querySelector('canvas')).toHaveStyle('width: 0');
});
it('sets the canvas width and height after calculating the container size', async () => {
const params = {
src: 'file-src',
};
global.devicePixelRatio = 2;
// @ts-ignore
mocked(rive.Rive).mockImplementation(() => baseRiveMock);
const canvasSpy = document.createElement('canvas');
const containerSpy = document.createElement('div');
jest.spyOn(containerSpy, 'clientWidth', 'get').mockReturnValue(100);
jest.spyOn(containerSpy, 'clientHeight', 'get').mockReturnValue(100);
const { result } = renderHook(() => useRive(params));
await act(async () => {
result.current.setCanvasRef(canvasSpy);
result.current.setContainerRef(containerSpy);
controlledRiveloadCb();
});
expect(canvasSpy).toHaveStyle('height: 100px');
expect(canvasSpy).toHaveStyle('width: 100px');
});
it('updates the canvas dimensions and size if there is a new canvas size calculation', async () => {
const params = {
src: 'file-src',
};
window.devicePixelRatio = 2;
// @ts-ignore
mocked(rive.Rive).mockImplementation(() => baseRiveMock);
const canvasSpy = document.createElement('canvas');
const containerSpy = document.createElement('div');
jest.spyOn(containerSpy, 'clientWidth', 'get').mockReturnValue(100);
jest.spyOn(containerSpy, 'clientHeight', 'get').mockReturnValue(100);
const { result } = renderHook(() => useRive(params));
await act(async () => {
result.current.setCanvasRef(canvasSpy);
result.current.setContainerRef(containerSpy);
controlledRiveloadCb();
jest.spyOn(containerSpy, 'clientWidth', 'get').mockReturnValue(200);
jest.spyOn(containerSpy, 'clientHeight', 'get').mockReturnValue(200);
containerSpy.dispatchEvent(new Event('resize'));
});
expect(canvasSpy).toHaveAttribute('width', '400');
expect(canvasSpy).toHaveAttribute('height', '400');
});
it('prevents resizing if shouldResizeCanvasToContainer option is false', async () => {
const params = {
src: 'file-src',
};
const options = {
shouldResizeCanvasToContainer: false,
};
window.devicePixelRatio = 2;
// @ts-ignore
mocked(rive.Rive).mockImplementation(() => baseRiveMock);
const canvasSpy = document.createElement('canvas');
canvasSpy.width = 200;
canvasSpy.height = 200;
const containerSpy = document.createElement('div');
const { result } = renderHook(() => useRive(params, options));
await act(async () => {
result.current.setCanvasRef(canvasSpy);
result.current.setContainerRef(containerSpy);
controlledRiveloadCb();
jest.spyOn(containerSpy, 'clientWidth', 'get').mockReturnValue(500);
jest.spyOn(containerSpy, 'clientHeight', 'get').mockReturnValue(500);
containerSpy.dispatchEvent(new Event('resize'));
});
expect(canvasSpy.width).toBe(200);
expect(canvasSpy.height).toBe(200);
});
});

View File

@@ -8,6 +8,7 @@ jest.mock('@rive-app/canvas', () => ({
Rive: jest.fn().mockImplementation(() => ({
on: jest.fn(),
stop: jest.fn(),
stateMachineInputs: jest.fn(),
})),
Layout: jest.fn(),
Fit: {
@@ -26,6 +27,21 @@ jest.mock('@rive-app/canvas', () => ({
},
}));
function getRiveMock({
smiInputs,
}: {
smiInputs?: null | StateMachineInput[];
} = {}) {
const riveMock = new Rive({
canvas: undefined as unknown as HTMLCanvasElement,
});
if (smiInputs) {
riveMock.stateMachineInputs = jest.fn().mockReturnValue(smiInputs);
}
return riveMock;
}
describe('useStateMachineInput', () => {
it('returns null if there is null rive object passed', () => {
const { result } = renderHook(() => useStateMachineInput(null));
@@ -33,31 +49,29 @@ describe('useStateMachineInput', () => {
});
it('returns null if there is no state machine name', () => {
const riveMock = {};
mocked(Rive).mockImplementation(() => riveMock as Rive);
const riveMock = getRiveMock();
mocked(Rive).mockImplementation(() => riveMock);
const { result } = renderHook(() =>
useStateMachineInput(riveMock as Rive, '', 'testInput')
useStateMachineInput(riveMock, '', 'testInput')
);
expect(result.current).toBeNull();
});
it('returns null if there is no state machine input name', () => {
const riveMock = {};
mocked(Rive).mockImplementation(() => riveMock as Rive);
const riveMock = getRiveMock();
const { result } = renderHook(() =>
useStateMachineInput(riveMock as Rive, 'smName', '')
useStateMachineInput(riveMock, 'smName', '')
);
expect(result.current).toBeNull();
});
it('returns null if there are no inputs for the state machine', () => {
const riveMock = {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
stateMachineInputs: (_: string) => [] as StateMachineInput[],
};
mocked(Rive).mockImplementation(() => riveMock as Rive);
const riveMock = getRiveMock({ smiInputs: [] });
mocked(Rive).mockImplementation(() => riveMock);
const { result } = renderHook(() =>
useStateMachineInput(riveMock as Rive, 'smName', '')
@@ -69,14 +83,12 @@ describe('useStateMachineInput', () => {
const smInput = {
name: 'boolInput',
} as StateMachineInput;
const riveMock = {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
stateMachineInputs: (_: string) => [smInput] as StateMachineInput[],
};
mocked(Rive).mockImplementation(() => riveMock as Rive);
const riveMock = getRiveMock({ smiInputs: [smInput] });
mocked(Rive).mockImplementation(() => riveMock);
const { result } = renderHook(() =>
useStateMachineInput(riveMock as Rive, 'smName', 'numInput')
useStateMachineInput(riveMock, 'smName', 'numInput')
);
expect(result.current).toBeNull();
});
@@ -85,14 +97,12 @@ describe('useStateMachineInput', () => {
const smInput = {
name: 'boolInput',
} as StateMachineInput;
const riveMock = {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
stateMachineInputs: (_: string) => [smInput] as StateMachineInput[],
};
mocked(Rive).mockImplementation(() => riveMock as Rive);
const riveMock = getRiveMock({ smiInputs: [smInput] });
mocked(Rive).mockImplementation(() => riveMock);
const { result } = renderHook(() =>
useStateMachineInput(riveMock as Rive, 'smName', 'boolInput')
useStateMachineInput(riveMock, 'smName', 'boolInput')
);
expect(result.current).toBe(smInput);
});
@@ -102,14 +112,11 @@ describe('useStateMachineInput', () => {
name: 'boolInput',
value: false,
} as StateMachineInput;
const riveMock = {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
stateMachineInputs: (_: string) => [smInput] as StateMachineInput[],
};
mocked(Rive).mockImplementation(() => riveMock as Rive);
const riveMock = getRiveMock({ smiInputs: [smInput] });
mocked(Rive).mockImplementation(() => riveMock);
const { result } = renderHook(() =>
useStateMachineInput(riveMock as Rive, 'smName', 'boolInput', true)
useStateMachineInput(riveMock, 'smName', 'boolInput', true)
);
expect(result.current).toStrictEqual({
...smInput,