Compare commits

...

53 Commits

Author SHA1 Message Date
zplata
f4eccbe2ce chore: release 3.0.1 2022-04-26 19:25:32 +00:00
Zach Plata
83c81b49c5 Maint: Bump rive wasm to include fps counter API and take off major tag 2022-04-26 12:23:17 -07:00
avivian
5de40fad5b chore: release 3.0.0 2022-04-26 15:05:29 +00:00
Arthur Vivian
aab811b975 Fix animation playing with autoplay false when animation name passed 2022-04-26 16:03:06 +01:00
zplata
965507ac34 chore: release 2.0.0 2022-04-22 22:04:35 +00:00
Zach Plata
74b791ffa4 Fix: Authenticate registry before doing npm release dryrun 2022-04-22 15:02:27 -07:00
Zach Plata
2853851d52 Fix: Do npm install instead 2022-04-22 14:54:53 -07:00
Zach Plata
4f37bbdb76 fix up test 2022-04-22 14:48:17 -07:00
Zach Plata
39f1990eac Maint: Bump wasm dependencies and add major flags for the publish script 2022-04-22 14:48:17 -07:00
Zach Plata
bb7d3e4e6c Feat: Setup workflow to npm publish 2 new rive-react packages 2022-04-22 14:48:17 -07:00
Zach Plata
7f2bd76eb3 Fix up test 2022-04-22 14:48:17 -07:00
Zach Plata
5c0b9cd613 Breaking: Spread non-style props onto canvas element instead of containing div 2022-04-22 14:48:17 -07:00
Zach Plata
92dd811948 fix version compare function 2022-04-22 14:48:17 -07:00
Zach Plata
4429be44f2 Change rive-react-* references to be the shortened namespace-named convention 2022-04-22 14:48:17 -07:00
Zach Plata
9398e0d74e Update tests 2022-04-22 14:48:17 -07:00
Zach Plata
563dca3608 Move to using @rive-app/canvas as the backing renderer and update scripts accordingly. 2022-04-22 14:48:17 -07:00
Zach Plata
1da73aac05 Only run the publish job on PR merges to main 2022-04-22 14:48:17 -07:00
Zach Plata
5c4336b84f Update: Adding build scripts to prepare for split of rive-react into 2 package derivatives for canvas and webgl 2022-04-22 14:48:17 -07:00
zplata
6e72ed5271 chore: release 1.0.7 2022-04-20 15:28:24 +00:00
Zach Plata
464fa97c20 Maint: Allow peer dep React to use v18.0+ 2022-04-20 08:27:04 -07:00
zplata
ac01b7ec69 chore: release 1.0.6 2022-04-14 17:00:16 +00:00
Zach Plata
cd9baef250 Maint: Bump webgl dependency up to 1.0.39 2022-04-14 09:58:59 -07:00
zplata
3a2ed32856 chore: release 1.0.5 2022-04-11 17:04:44 +00:00
Zach Plata
d35f5b53c5 update readme 2022-04-11 10:03:36 -07:00
Zach Plata
73b57d0b81 Update readme 2022-04-11 10:03:36 -07:00
Zach Plata
0a18b522cc Feat: Add extra param to useStateMachineInput to set an initial value on the input when its loaded 2022-04-11 10:03:36 -07:00
avivian
5e34e13563 chore: release 1.0.4 2022-04-06 15:58:19 +00:00
Arthur Vivian
c3f138014d Add test for animations change on param update 2022-04-06 16:57:03 +01:00
Arthur Vivian
b13413ba8b Update animations on param change 2022-04-06 16:57:03 +01:00
zplata
881e38fe6a chore: release 1.0.3 2022-03-31 16:55:27 +00:00
Zach Plata
38c85624a7 Maint: Bump rive-cpp to help fix safari and performance issues 2022-03-31 09:54:16 -07:00
zplata
a9732e141e chore: release 1.0.2 2022-03-28 16:42:52 +00:00
Zach Plata
59edf6f67e Patch: Bump rive-cpp to fix DAG issue 2022-03-28 09:41:33 -07:00
zplata
4be496cc15 chore: release 1.0.1 2022-03-24 03:38:43 +00:00
Zach Plata
4c9de18b1c Chore: Bump webgl and remove major flag from release-it command 2022-03-23 20:37:35 -07:00
zplata
c688b9f17a chore: release 1.0.0 2022-03-23 20:13:43 +00:00
Zach Plata
fcfe3cf6cf bump webgl 2022-03-23 13:12:26 -07:00
Zach Plata
8ce856270f Put back the release steps in the publish workflow and add major flag temporarily 2022-03-23 13:12:26 -07:00
Zach Plata
1e1cabd057 Breaking: Switch from using the canvas renderer as default to the webgl renderer 2022-03-23 13:12:26 -07:00
avivian
0be3bc7e93 chore: release 0.0.31 2022-01-18 19:21:22 +00:00
Arthur Vivian
48af4b00ad Update @rive-app/canvas to 1.0.18 to fix playback lag when animations are left idle 2022-01-18 19:19:30 +00:00
avivian
fe44977e47 chore: release 0.0.30 2022-01-10 13:18:41 +00:00
Arthur Vivian
24d9e871d6 Update rive/canvas to with fixes for image clipping 2022-01-10 13:17:13 +00:00
avivian
8b8d6bc44b chore: release 0.0.29 2021-12-16 19:36:04 +00:00
Arthur Vivian
956b76d01c Add offscreencanvas types 2021-12-16 19:34:58 +00:00
Arthur Vivian
2517efaebd Bump rive-app/canvas to 1.0.8 2021-12-16 19:34:58 +00:00
avivian
019cadf5f2 chore: release 0.0.28 2021-12-16 15:16:59 +00:00
Arthur Vivian
e599b1a38c Use @rive-app/canvas directly to fix path issues in downstream libs 2021-12-16 15:15:36 +00:00
avivian
78d3118dcc chore: release 0.0.27 2021-12-16 14:31:01 +00:00
Arthur Vivian
536c8325f2 Fix lint error during build 2021-12-16 14:29:43 +00:00
Arthur Vivian
9e65654274 Update @types/jest 2021-12-16 12:59:11 +00:00
Arthur Vivian
75420d2f1d Remove lock file 2021-12-16 12:59:11 +00:00
Arthur Vivian
e6b036ee17 Use @rive-app/canvas as underlying repo 2021-12-16 12:59:11 +00:00
28 changed files with 722 additions and 19325 deletions

View File

@@ -19,4 +19,9 @@ module.exports = {
'no-var': 'error',
eqeqeq: ['error', 'smart'],
},
settings: {
react: {
version: 'detect',
},
},
};

View File

@@ -5,31 +5,75 @@ on:
branches:
- main
jobs:
merge_job:
determine_version:
name: Determine the next build version
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
outputs:
version: ${{ steps.echo_version.outputs.version }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '12.x'
registry-url: 'https://registry.npmjs.org'
- name: Install Modules
run: npm ci
- name: Run type check
run: npm run types:check
- name: Run Linter
run: npm run lint
- name: Run Tests
run: npm test
- name: Build
run: npm run build
- name: Checkout
uses: actions/checkout@v2
- name: Install dependencies
run: npm install
working-directory: ./
- name: Git config
run: |
git config --local user.email 'hello@rive.app'
git config --local user.name ${{ github.actor }}
- name: Authenticate with registry
run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
- name: Release
- id: determine_version
name: Get Version
run: npm run release -- --ci --release-version | tail -n 1 > RELEASE_VERSION
working-directory: ./
env:
GITHUB_TOKEN: ${{ secrets.REPO_TOKEN }}
run: npm run release
- id: echo_version
run: echo "::set-output name=version::$(cat ./RELEASE_VERSION)"
merge_job:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
needs: [determine_version]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16.x'
registry-url: 'https://registry.npmjs.org'
- name: Install Modules
run: npm install
- name: Run type check
run: npm run types:check
- name: Run Linter
run: npm run lint
- name: Run Tests
run: npm test
- name: Build main dist
run: npm run build
- name: Copy separated builds
run: ./scripts/build.sh
- name: Copy package jsons to separate react outputs
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: ./scripts/setup_all_packages.sh
- name: Bump Versions of react outputs
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
RELEASE_VERSION: ${{ needs.determine_version.outputs.version }}
run: ./scripts/bump_all_versions.sh
- name: Git config
run: |
git config --local user.email 'hello@rive.app'
git config --local user.name ${{ github.actor }}
- name: Authenticate with registry
run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
- name: Release rive-react
env:
GITHUB_TOKEN: ${{ secrets.REPO_TOKEN }}
run: npm run release -- --ci
- name: Release @rive-app/react-* variants
env:
GITHUB_TOKEN: ${{ secrets.REPO_TOKEN }}
run: ./scripts/publish_all.sh

View File

@@ -7,7 +7,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v2
- name: Install Modules
run: npm ci
run: npm install
- name: Run type check
run: npm run types:check
- name: Run Linter

1
.gitignore vendored
View File

@@ -5,3 +5,4 @@ dist
.idea
.vscode
examples/**/package-lock.json
package-lock.json

View File

@@ -4,9 +4,133 @@ 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).
#### [v0.0.26](https://github.com/rive-app/rive-react/compare/v0.0.20...v0.0.26)
#### [v3.0.1](https://github.com/rive-app/rive-react/compare/v1.0.5...v3.0.1)
- Maint: Bump rive wasm to include fps counter API and take off major tag [`83c81b4`](https://github.com/rive-app/rive-react/commit/83c81b49c5a53c5ec9092b83607a78b6e4a69768)
#### [v1.0.5](https://github.com/rive-app/rive-react/compare/v1.0.4...v1.0.5)
> 11 April 2022
- Feat: Add extra param to useStateMachineInput to set an initial value on the input when its loaded [`0a18b52`](https://github.com/rive-app/rive-react/commit/0a18b522cc8efdffb0b681a7b1234d7829fee808)
- chore: release 1.0.5 [`3a2ed32`](https://github.com/rive-app/rive-react/commit/3a2ed32856ad4de09da4a875f3b0c2967c8a8e5e)
- update readme [`d35f5b5`](https://github.com/rive-app/rive-react/commit/d35f5b53c5c7cb2794c8891e8f30d8ba8aa403cf)
#### [v1.0.4](https://github.com/rive-app/rive-react/compare/v1.0.3...v1.0.4)
> 6 April 2022
- Add test for animations change on param update [`c3f1380`](https://github.com/rive-app/rive-react/commit/c3f138014d233258206bde2497baed711276e3dc)
- chore: release 1.0.4 [`5e34e13`](https://github.com/rive-app/rive-react/commit/5e34e1356379a21c051c48f214dbce0e14a41c8b)
- Update animations on param change [`b13413b`](https://github.com/rive-app/rive-react/commit/b13413ba8bd99d1e89cb927d194bc2179e8e9dcf)
#### [v1.0.3](https://github.com/rive-app/rive-react/compare/v1.0.2...v1.0.3)
> 31 March 2022
- chore: release 1.0.3 [`881e38f`](https://github.com/rive-app/rive-react/commit/881e38fe6a357503d23cc6449c1e41908ba796b0)
- Maint: Bump rive-cpp to help fix safari and performance issues [`38c8562`](https://github.com/rive-app/rive-react/commit/38c85624a72782dd4f05a482b9c57137fe289e4c)
#### [v1.0.2](https://github.com/rive-app/rive-react/compare/v1.0.1...v1.0.2)
> 28 March 2022
- chore: release 1.0.2 [`a9732e1`](https://github.com/rive-app/rive-react/commit/a9732e141ec519bfc07b11a1b5b48c3d36182f4b)
- Patch: Bump rive-cpp to fix DAG issue [`59edf6f`](https://github.com/rive-app/rive-react/commit/59edf6f67ea7d26067009786bb84014a61fe6f24)
#### [v1.0.1](https://github.com/rive-app/rive-react/compare/v1.0.0...v1.0.1)
> 24 March 2022
- chore: release 1.0.1 [`4be496c`](https://github.com/rive-app/rive-react/commit/4be496cc15ff7c205903f3a3ef1f44cb7ed710d4)
- Chore: Bump webgl and remove major flag from release-it command [`4c9de18`](https://github.com/rive-app/rive-react/commit/4c9de18b1cbf19ede7d5400a1b3f67d59f882cee)
### [v1.0.0](https://github.com/rive-app/rive-react/compare/v0.0.31...v1.0.0)
> 23 March 2022
- Breaking: Switch from using the canvas renderer as default to the webgl renderer [`1e1cabd`](https://github.com/rive-app/rive-react/commit/1e1cabd05707fa135e1706c0821c0272b3d94bbc)
- chore: release 1.0.0 [`c688b9f`](https://github.com/rive-app/rive-react/commit/c688b9f17a4e287b4120a0739125123ce0e880e4)
- Put back the release steps in the publish workflow and add major flag temporarily [`8ce8562`](https://github.com/rive-app/rive-react/commit/8ce856270f9403c165b2a4c2f0b8c6558ed929a2)
#### [v0.0.31](https://github.com/rive-app/rive-react/compare/v0.0.30...v0.0.31)
> 18 January 2022
- chore: release 0.0.31 [`0be3bc7`](https://github.com/rive-app/rive-react/commit/0be3bc7e930ce6b39dae82e808dd81a0720a5ebb)
- Update @rive-app/canvas to 1.0.18 to fix playback lag when animations are left idle [`48af4b0`](https://github.com/rive-app/rive-react/commit/48af4b00ad7654acde0fc5e97c9cd0f768371843)
#### [v0.0.30](https://github.com/rive-app/rive-react/compare/v0.0.29...v0.0.30)
> 10 January 2022
- chore: release 0.0.30 [`fe44977`](https://github.com/rive-app/rive-react/commit/fe44977e47e13276051a665559e1f68f42f47d3a)
- Update rive/canvas to with fixes for image clipping [`24d9e87`](https://github.com/rive-app/rive-react/commit/24d9e871d6580df1b985e61793babd1067640b5b)
#### [v0.0.29](https://github.com/rive-app/rive-react/compare/v0.0.28...v0.0.29)
> 16 December 2021
- chore: release 0.0.29 [`8b8d6bc`](https://github.com/rive-app/rive-react/commit/8b8d6bc44bfcecd6f126dcaa9c6c4cb7fda9b6ac)
- Bump rive-app/canvas to 1.0.8 [`2517efa`](https://github.com/rive-app/rive-react/commit/2517efaebd4ccc6270be52c2947acc9190f858cc)
- Add offscreencanvas types [`956b76d`](https://github.com/rive-app/rive-react/commit/956b76d01c59a04eb83f3b0b2ca722798af80fb2)
#### [v0.0.28](https://github.com/rive-app/rive-react/compare/v0.0.27...v0.0.28)
> 16 December 2021
- Use @rive-app/canvas directly to fix path issues in downstream libs [`e599b1a`](https://github.com/rive-app/rive-react/commit/e599b1a38cc0f6606d7505551a046b28a3533422)
- chore: release 0.0.28 [`019cadf`](https://github.com/rive-app/rive-react/commit/019cadf5f22d87a0449ff1aecfdc242a26e64a46)
#### [v0.0.27](https://github.com/rive-app/rive-react/compare/v0.0.26...v0.0.27)
> 16 December 2021
- Use @rive-app/canvas as underlying repo [`e6b036e`](https://github.com/rive-app/rive-react/commit/e6b036ee17db316f189773a801f6ade514f44d4d)
- Update basic example to listen to changes in parent directory [`bfbb8a5`](https://github.com/rive-app/rive-react/commit/bfbb8a59ee3284d9512f0006ad518afdc1a801ea)
- chore: release 0.0.27 [`78d3118`](https://github.com/rive-app/rive-react/commit/78d3118dcc648dc8755ec23cb79ef2724a9b4d05)
#### [v0.0.26](https://github.com/rive-app/rive-react/compare/v0.0.25...v0.0.26)
> 16 November 2021
- bump rive-js to0.7.33 [`c4dc027`](https://github.com/rive-app/rive-react/commit/c4dc027522502f6aaa0f85392a5e90396c8b719d)
- chore: release 0.0.26 [`5a19354`](https://github.com/rive-app/rive-react/commit/5a19354ab3fcf128b52973bb1882690f98b0ebe2)
#### [v0.0.25](https://github.com/rive-app/rive-react/compare/v0.0.24...v0.0.25)
> 12 November 2021
- Update rive-js to 0.7.32 to fixed nested artboard speed [`1a59794`](https://github.com/rive-app/rive-react/commit/1a597943cb629be520052f2a86733998f44d6885)
- chore: release 0.0.25 [`e54a0d4`](https://github.com/rive-app/rive-react/commit/e54a0d42d3910c39a944a144a856a33cae87f3ed)
#### [v0.0.24](https://github.com/rive-app/rive-react/compare/v0.0.23...v0.0.24)
> 12 November 2021
- Update package.json to version 2 [`a4777ec`](https://github.com/rive-app/rive-react/commit/a4777ec7e33ded6a3581c88f2e708f45f7ea1828)
- chore: release 0.0.24 [`026d097`](https://github.com/rive-app/rive-react/commit/026d0976582eaeb68daf09977fef5d16917c09d8)
#### [v0.0.23](https://github.com/rive-app/rive-react/compare/v0.0.22...v0.0.23)
> 8 November 2021
- chore: release 0.0.23 [`416334e`](https://github.com/rive-app/rive-react/commit/416334ef44b7a9bdaa8c6ff8dac937cfda59d77d)
- Add verticalAlign = top to canvas to prevent canvas growth on resize [`f309481`](https://github.com/rive-app/rive-react/commit/f309481a43307b1e2b7f77cd418498cacd8022d2)
#### [v0.0.22](https://github.com/rive-app/rive-react/compare/v0.0.21...v0.0.22)
> 15 October 2021
- chore: release 0.0.22 [`06500e6`](https://github.com/rive-app/rive-react/commit/06500e6dcf38165ac8b5f7bf60e0503666947819)
- Bump rive-js version to 0.7.31 [`33e34a4`](https://github.com/rive-app/rive-react/commit/33e34a46e1e394d67d6981307534fb5512df9dcf)
#### [v0.0.21](https://github.com/rive-app/rive-react/compare/v0.0.20...v0.0.21)
> 10 September 2021
- Update examples to use latest rive-react [`5d08228`](https://github.com/rive-app/rive-react/commit/5d0822836cbc7c5645d7580173c3cdda772b616d)
- chore: release 0.0.21 [`c8f57f5`](https://github.com/rive-app/rive-react/commit/c8f57f58960987d238ca48646b354c460bfeee59)
#### [v0.0.20](https://github.com/rive-app/rive-react/compare/v0.0.19...v0.0.20)

View File

@@ -44,7 +44,17 @@ export default Example;
- `artboard`: _(optional)_ Name to display.
- `animations`: _(optional)_ Name or list of names of animtions to play.
- `layout`: _(optional)_ Layout object to define how animations are displayed on the canvas. See [Rive.js](https://github.com/rive-app/rive-wasm#layout) for more details.
- _All attributes and eventHandlers that can be passed to a `div` element can also be passed to the `Rive` component and used in the same manner._
- _All attributes and eventHandlers that can be passed to a `canvas` element can also be passed to the `Rive` component and used in the same manner._
#### Styles and Classes
When rendering out a Rive component, in the DOM, it will show as a `<div>` element that contains the `<canvas>` element that powers the Rive animations. The purpose of the `<div>` element is to help control the sizing of the component. By default, the container has the following styles set on the `style` attribute:
```css
width: 100%;
height: 100%;
```
If you decide to pass in a `className` to the Rive component, you will override these attributes, and you will need to either set these style attributes in your CSS associated with that `className`, or set your own sizing preferences.
### useRive Hook
@@ -78,7 +88,7 @@ export default Example;
#### Return Values
- `RiveComponent`: A Component that can be used to display your .riv file. This component accepts the same attributes and event handlers as a `div` element.
- `RiveComponent`: A Component that can be used to display your .riv file. This component accepts the same attributes and event handlers as a `canvas` element.
- `rive`: A Rive.js `Rive` object. This will return as null until the .riv file has fully loaded.
- `canvas`: HTMLCanvasElement object, on which the .riv file is rendering.
- `setCanvasRef`: A callback ref that can be passed to your own canvas element, if you wish to have control over the rendering of the Canvas element.
@@ -106,6 +116,7 @@ export default Example;
- `useDevicePixelRatio`: _(optional)_ If `true`, the hook will scale the resolution of the animation based the [devicePixelRatio](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio). Defaults to `true`. NOTE: Requires the `setContainerRef` ref callback to be passed to a element wrapping a canvas element. If you use the `RiveComponent`, then this will happen automatically.
- `fitCanvasToArtboardHeight`: _(optional)_ If `true`, then the canvas will resize based on the height of the artboard. Defaults to `false`.
- `useOffscreenRenderer`: _(optional)_ If `true`, the Rive instance will share (or create if one does not exist) an offscreen `WebGL` context. This allows you to display multiple Rive animations on one screen to work around some browser limitations regarding multiple concurrent WebGL contexts. If `false`, each Rive instance will have its own dedicated `WebGL` context, and you may need to be cautious of the browser limitations just mentioned. Defaults to `true`.
### useStateMachineInput Hook
@@ -144,6 +155,7 @@ See our [examples](examples) folder for working examples of [Boolean](examples/s
- `rive`: A `Rive` object. This is returned by the `useRive` hook.
- `stateMachineName`: Name of the state machine.
- `inputName`: Name of the state machine input.
- `initialValue`: Initial value to set on a state machine input when it's loaded in, for number or boolean inputs. **Note** that this may trigger any transitional animations between the initial state and any next states that depend on the input this `initialValue` is being set to. If this is problematic or conflicting for your case, we recommend setting the true initial value of the input on your state machine in the Rive editor.
#### Return Value
@@ -152,3 +164,44 @@ A Rive.js `stateMachineInput` object.
## Examples
The [examples](examples) shows a number of different ways to use Rive React. See the instructions for each example to run locally.
## Migration notes
### Migrating from version 0.0.x to 1.x.x
Starting in v 1.0.0, we've migrated from wrapping around the `@rive-app/canvas` runtime (which uses the `CanvasRendereringContext2D` renderer) to the `@rive-app/webgl` runtime (which uses the WebGL renderer). The high-level API doesn't require any change to upgrade, but there are some notes to consider about the backing renderer.
The backing `WebGL` runtime allows for best performance across all devices, as well as support for some features that are not supported in the `canvas` renderer runtime. To allow the `react` runtime to support some of the newer features in Rive, we needed to switch the `rive-react` backing runtime to `@rive-app/webgl`.
One note about this switch is that some browsers may limit the number of concurrent WebGL contexts. For example, Chrome may only support up to 16 contexts concurrently. We pass a property called `useOffscreenRenderer` set to true to the backing runtime when instantiating Rive by default, which helps to manage the lifecycle of the `canvas` with a single offscreen `WebGL` context, even if there are many Rive animations on the screen (i.e 16+). If you need a single `WebGL` context per Rive animation/instance, pass in the `useOffscreenRenderer` property set to `false` in the `useRive` options, or as a prop in the default export component from this runtime. See below for an example:
```js
const {rive, RiveComponent} = useRive({
src: 'foo.riv',
}, {
// Default (you don't need to set this)
useOffscreenRenderer: true,
// To override and use one context per Rive instance, uncomment and use the line below
// useOffscreenRenderer: false,
});
// or you can override the flag in JSX via props
return (
<Rive src="foo.riv" useOffscreenRenderer={false} />
);
```
### Migrating from version 1.x.x to 2.x.x
#### Package split
In most cases, you may be able to migrate safely. We are mainly enabling the React runtime to work with both backing renderers `@rive-app/webgl` and `@rive-app/canvas`, such that you can use either `@rive-app/react-canvas` or `@rive-app/react-webgl` as the dependency in your React applications. Another change that is mostly internal is that by default, `rive-react` will now use `@rive-app/canvas` (as opposed to `@rive-app/webgl`) to wrap around, as it currently yields the fastest performance across devices. Therefore, **we recommend installing `@rive-app/react-canvas` in your applicaions**. However, if you need a WebGL backing renderer, you may want to use `@rive-app/react-webgl`.
#### Classes, styles, and component props
Starting in v2.0, we introduce one breaking change where any non-style props set on the `RiveComponent` (i.e `aria-*`, `role`, etc.) will be set on the inner `<canvas>` element. Previously, all extra props would be set onto the containing `<div>` element. Both the `className` and `style` props will continue to be set on the `<div>` element that wraps the canvas, as this dictates the sizing of the Rive component.
### Migrating to 3.0
There are no breaking changes here. If you have migrated to v2.x.x, you can safely migrate to 3.0.

View File

@@ -0,0 +1,3 @@
# @rive-app/react-canvas
Output for `rive-react` using the backing `@rive-app/canvas` JS runtime

View File

@@ -0,0 +1,3 @@
# @rive-app/react-webgl
Output for `rive-react` using the backing `@rive-app/webgl` JS runtime

19267
package-lock.json generated
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "rive-react",
"version": "0.0.26",
"version": "3.0.1",
"description": "React wrapper around the rive-js library",
"main": "dist/index.js",
"typings": "dist/types/index.d.ts",
@@ -27,20 +27,22 @@
},
"homepage": "https://github.com/rive-app/rive-react#readme",
"dependencies": {
"rive-js": "0.7.33"
"@rive-app/canvas": "1.0.47",
"@rive-app/webgl": "1.0.44"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0"
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.13.0",
"@testing-library/react": "^11.2.7",
"@testing-library/react-hooks": "^7.0.0",
"@types/jest": "^26.0.23",
"@types/jest": "^27.0.3",
"@types/offscreencanvas": "^2019.6.4",
"@types/react": "^17.0.9",
"@types/testing-library__jest-dom": "^5.9.5",
"@typescript-eslint/eslint-plugin": "^4.26.0",
"@typescript-eslint/parser": "^4.26.0",
"@typescript-eslint/eslint-plugin": "^5.7.0",
"@typescript-eslint/parser": "^5.7.0",
"auto-changelog": "^2.3.0",
"bunchee": "^1.7.3",
"eslint": "^7.28.0",
@@ -50,13 +52,14 @@
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-react": "^7.24.0",
"eslint-plugin-react": "^7.27.1",
"jest": "^27.0.4",
"prettier": "^2.3.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"release-it": "^14.10.0",
"ts-jest": "^27.0.2",
"ts-jest": "^27.1.1",
"typescript": "^4.5.4",
"watch": "^1.0.2"
}
}

18
scripts/build.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/bash
set -e
# Copy the build to each react-variant build for npm release
cp -r ./dist ./npm/react-webgl
cp -r ./dist ./npm/react-canvas
echo "Replacing the canvas with webgl references in react-webgl"
pushd ./npm/react-webgl/dist
if [[ "$OSTYPE" == "darwin"* ]]; then
find . -type f -name "*.ts" -print0 | xargs -0 sed -i '' -e 's/@rive-app\/canvas/@rive-app\/webgl/g'
find . -type f -name "*.js" -print0 | xargs -0 sed -i '' -e 's/@rive-app\/canvas/@rive-app\/webgl/g'
else
find . -type f -name "*.ts" -print0 | xargs -0 sed -i -e 's/@rive-app\/canvas/@rive-app\/webgl/g'
find . -type f -name "*.js" -print0 | xargs -0 sed -i -e 's/@rive-app\/canvas/@rive-app\/webgl/g'
fi
popd

11
scripts/bump_all_versions.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/bin/bash
set -e
# Bump the version number of every npm module in the npm folder.
for dir in ./npm/*; do
pushd $dir > /dev/null
repo_name=`echo $dir | sed 's:.*/::' | sed 's/_/-/g'`
echo Bumping version of $repo_name
../../scripts/bump_version.sh $repo_name $RELEASE_VERSION
popd > /dev/null
done

12
scripts/bump_version.sh Executable file
View File

@@ -0,0 +1,12 @@
#!/bin/bash
# Bumps the version of a single npm module found in the current working
# directory. Call bump_version.sh from the path with package.json in it.
set -e
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
# RELEASE_VERSION will come from an env variable passed in from the GH action workflow
node $SCRIPT_DIR/nextVersion.js "$RELEASE_VERSION" `pwd`
# Replace the dist package json with the newly trimmed one
cp -f ./package.json ./dist/package.json

33
scripts/nextVersion.js Normal file
View File

@@ -0,0 +1,33 @@
const fs = require('fs');
const path = process.argv[3];
const package = require(path + '/package.json');
const currentVersion = package.version;
const nextVersion = process.argv[2].trim().replace(/\'/g, '"');
if (!nextVersion || nextVersion === currentVersion) {
throw new Error('Next version is not defined or is a version that already exists');
}
// Returns -1 if first is less than second, 1 if first is greater than second, otherwise 0 if equal.
function compareVersion(first, second) {
// Assumption: only numbers in our versions.
const firstParts = first.split('.').map((value) => parseInt(value));
const secondParts = second.split('.').map((value) => parseInt(value));
for (let i = 0; i < Math.max(firstParts.length, secondParts.length); i++) {
const first = i < firstParts.length ? firstParts[i] : 0;
const second = i < secondParts.length ? secondParts[i] : 0;
if (first < second) {
return -1;
}
if (second < first) {
return 1;
}
}
return 0;
}
if (compareVersion(currentVersion, nextVersion) <= 0) {
package.version = nextVersion;
fs.writeFileSync(path + '/package.json', JSON.stringify(package, null, 2));
}

10
scripts/publish_all.sh Executable file
View File

@@ -0,0 +1,10 @@
#!/bin/bash
set -e
# Bump the version number of every npm module in the npm folder.
for dir in ./npm/*; do
pushd $dir > /dev/null
echo Publishing `echo $dir | sed 's:.*/::'`
npm publish --access public
popd > /dev/null
done

21
scripts/setup_all_packages.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/bash
set -e
echo "Copying package.json to rive-react npm package folders"
cp package.json npm/react-canvas
cp package.json npm/react-webgl
# Bump the version number of every npm module in the npm folder.
for dir in ./npm/*; do
echo $dir
pushd $dir > /dev/null
echo $dir
repo_name=`echo $dir | sed 's:.*/::' | sed 's/_/-/g'`
echo Setting package.json on npm packages
echo $repo_name
../../scripts/setup_package.sh $repo_name
echo Finished setting up package.json
popd > /dev/null
done

6
scripts/setup_package.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/bash
set -e
# Setup the package.json for a given npm module
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
node $SCRIPT_DIR/trimPackageJson.js `pwd` "$1"

View File

@@ -0,0 +1,22 @@
const fs = require('fs');
const path = process.argv[2];
const npmPackageSplit = process.argv[3].split('-');
const renderer = npmPackageSplit[npmPackageSplit.length - 1];
const package = require(path + '/package.json');
function trimNpmPackage() {
package.name = `@rive-app/react-${renderer}`;
package.description = `React wrapper around the @rive-app/${renderer} library`;
const webDependencyName = `@rive-app/${renderer}`;
const canvasDep = package.dependencies[webDependencyName];
package.dependencies = {
[webDependencyName]: canvasDep,
};
delete package.devDependencies;
delete package.scripts;
fs.writeFileSync(path + '/package.json', JSON.stringify(package, null, 2));
}
if (renderer) {
trimNpmPackage();
}

View File

@@ -24,7 +24,7 @@ window.IntersectionObserver = class IntersectionObserver {
unobserve() {}
};
jest.mock('rive-js', () => ({
jest.mock('@rive-app/canvas', () => ({
Rive: jest.fn().mockImplementation(() => ({
on: jest.fn(),
stop: jest.fn(),

View File

@@ -1,4 +1,4 @@
import { Layout } from 'rive-js';
import { Layout } from '@rive-app/canvas';
import React, { ComponentProps } from 'react';
import useRive from '../hooks/useRive';
@@ -7,6 +7,7 @@ export type RiveProps = {
artboard?: string;
animations?: string | string[];
layout?: Layout;
useOffscreenRenderer?: boolean;
};
const Rive = ({
@@ -14,8 +15,9 @@ const Rive = ({
artboard,
animations,
layout,
useOffscreenRenderer = true,
...rest
}: RiveProps & ComponentProps<'div'>) => {
}: RiveProps & ComponentProps<'canvas'>) => {
const params = {
src,
artboard,
@@ -24,7 +26,11 @@ const Rive = ({
autoplay: true,
};
const { RiveComponent } = useRive(params);
const options = {
useOffscreenRenderer,
};
const { RiveComponent } = useRive(params, options);
return <RiveComponent {...rest} />;
};

View File

@@ -6,7 +6,7 @@ import React, {
ComponentProps,
RefCallback,
} from 'react';
import { Rive, EventType } from 'rive-js';
import { Rive, EventType } from '@rive-app/canvas';
import {
UseRiveParameters,
UseRiveOptions,
@@ -23,20 +23,23 @@ type RiveComponentProps = {
function RiveComponent({
setContainerRef,
setCanvasRef,
className = '',
style,
...rest
}: RiveComponentProps & ComponentProps<'div'>) {
}: RiveComponentProps & ComponentProps<'canvas'>) {
const containerStyle = {
width: '100%',
height: '100%',
...style,
};
return (
<div
ref={setContainerRef}
style={'className' in rest ? undefined : containerStyle}
{...rest}
className={className}
{...(!className && { style: containerStyle })}
>
<canvas ref={setCanvasRef} style={{ verticalAlign: 'top' }} />
<canvas ref={setCanvasRef} style={{ verticalAlign: 'top' }} {...rest} />
</div>
);
}
@@ -44,6 +47,7 @@ function RiveComponent({
const defaultOptions = {
useDevicePixelRatio: true,
fitCanvasToArtboardHeight: false,
useOffscreenRenderer: true,
};
/**
@@ -164,7 +168,12 @@ export default function useRive(
const setCanvasRef: RefCallback<HTMLCanvasElement> = useCallback(
(canvas: HTMLCanvasElement | null) => {
if (canvas && riveParams) {
const r = new Rive({ ...riveParams, canvas });
const { useOffscreenRenderer } = options;
const r = new Rive({
useOffscreenRenderer,
...riveParams,
canvas,
});
r.on(EventType.Load, () => setRive(r));
} else if (canvas === null && canvasRef.current) {
canvasRef.current.height = 0;
@@ -218,15 +227,34 @@ export default function useRive(
};
}, [rive]);
const Component = useCallback((props: ComponentProps<'div'>): JSX.Element => {
return (
<RiveComponent
setContainerRef={setContainerRef}
setCanvasRef={setCanvasRef}
{...props}
/>
);
}, []);
/**
* Listen for changes in the animations params
*/
const animations = riveParams?.animations;
useEffect(() => {
if (rive && animations) {
if (rive.isPlaying) {
rive.stop(rive.animationNames);
rive.play(animations);
} else if (rive.isPaused) {
rive.stop(rive.animationNames);
rive.pause(animations);
}
}
}, [animations, rive]);
const Component = useCallback(
(props: ComponentProps<'canvas'>): JSX.Element => {
return (
<RiveComponent
setContainerRef={setContainerRef}
setCanvasRef={setCanvasRef}
{...props}
/>
);
},
[]
);
return {
canvas: canvasRef.current,

View File

@@ -1,5 +1,5 @@
import { useState, useEffect } from 'react';
import { Rive, StateMachineInput } from 'rive-js';
import { Rive, StateMachineInput } from '@rive-app/canvas';
/**
* Custom hook for fetching a stateMachine input from a rive file.
@@ -12,7 +12,8 @@ import { Rive, StateMachineInput } from 'rive-js';
export default function useStateMachineInput(
rive: Rive | null,
stateMachineName?: string,
inputName?: string
inputName?: string,
initialValue?: number | boolean
) {
const [input, setInput] = useState<StateMachineInput | null>(null);
@@ -25,6 +26,9 @@ export default function useStateMachineInput(
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 {

View File

@@ -5,4 +5,4 @@ import useStateMachineInput from './hooks/useStateMachineInput';
export default Rive;
export { useRive, useStateMachineInput };
export { RiveState, UseRiveParameters, UseRiveOptions } from './types';
export * from 'rive-js';
export * from '@rive-app/canvas';

View File

@@ -1,11 +1,12 @@
import { RefCallback, ComponentProps } from 'react';
import { Rive, RiveParameters } from 'rive-js';
import { Rive, RiveParameters } from '@rive-app/canvas';
export type UseRiveParameters = Partial<Omit<RiveParameters, 'canvas'>> | null;
export type UseRiveOptions = {
useDevicePixelRatio: boolean;
fitCanvasToArtboardHeight: boolean;
useOffscreenRenderer: boolean;
};
export type Dimensions = {
@@ -28,5 +29,5 @@ export type RiveState = {
setCanvasRef: RefCallback<HTMLCanvasElement>;
setContainerRef: RefCallback<HTMLElement>;
rive: Rive | null;
RiveComponent: (props: ComponentProps<'div'>) => JSX.Element;
RiveComponent: (props: ComponentProps<'canvas'>) => JSX.Element;
};

33
test/Rive.test.tsx Normal file
View File

@@ -0,0 +1,33 @@
import React from 'react';
import RiveComponent from '../src/components/Rive';
import {render} from '@testing-library/react'
jest.mock('@rive-app/canvas', () => ({
Rive: jest.fn().mockImplementation(() => ({
on: jest.fn(),
stop: jest.fn(),
})),
Layout: jest.fn(),
Fit: {
Cover: 'cover',
},
Alignment: {
Center: 'center',
},
EventType: {
Load: 'load',
},
StateMachineInputType: {
Number: 1,
Boolean: 2,
Trigger: 3,
},
}));
describe('Rive Component', () => {
it('renders the component as a canvas and a div wrapper', () => {
const {container, getByLabelText} = render(<RiveComponent src="foo.riv" className="container-styles" aria-label="Foo label" />);
expect(container.firstChild).toHaveClass('container-styles');
expect(getByLabelText('Foo label').tagName).toEqual('CANVAS');
});
});

View File

@@ -1,10 +1,12 @@
import React from 'react';
import { mocked } from 'jest-mock';
import { renderHook, act } from '@testing-library/react-hooks';
import { mocked } from 'ts-jest/utils';
import useRive from '../src/hooks/useRive';
import * as rive from 'rive-js';
import * as rive from '@rive-app/canvas';
import { render } from '@testing-library/react';
jest.mock('rive-js', () => ({
jest.mock('@rive-app/canvas', () => ({
Rive: jest.fn().mockImplementation(() => ({
on: jest.fn(),
stop: jest.fn(),
@@ -241,6 +243,7 @@ describe('useRive', () => {
const observeMock = jest.fn();
const restore = global.IntersectionObserver;
global.IntersectionObserver = jest.fn().mockImplementation(() => ({
observe: observeMock,
}));
@@ -266,5 +269,117 @@ describe('useRive', () => {
});
expect(observeMock).toBeCalledWith(canvasSpy);
global.IntersectionObserver = restore;
});
it('updates the playing animations when the animations param changes', async () => {
const params = {
src: 'file-src',
animations: 'light',
};
const playMock = jest.fn();
const stopMock = jest.fn();
const riveMock = {
on: (_: string, cb: () => void) => cb(),
stop: stopMock,
play: playMock,
animationNames: ['light'],
isPlaying: true,
};
// @ts-ignore
mocked(rive.Rive).mockImplementation(() => riveMock);
const canvasSpy = document.createElement('canvas');
const { result, rerender } = renderHook((params) => useRive(params), {
initialProps: params,
});
await act(async () => {
result.current.setCanvasRef(canvasSpy);
});
rerender({
src: 'file-src',
animations: 'dark',
});
expect(stopMock).toBeCalledWith(['light']);
expect(playMock).toBeCalledWith('dark');
});
it('updates the paused animation when the animations param changes if the animation is paused', async () => {
const params = {
src: 'file-src',
animations: 'light',
};
const playMock = jest.fn();
const pauseMock = jest.fn();
const stopMock = jest.fn();
const riveMock = {
on: (_: string, cb: () => void) => cb(),
stop: stopMock,
play: playMock,
pause: pauseMock,
animationNames: ['light'],
isPlaying: false,
isPaused: true,
};
// @ts-ignore
mocked(rive.Rive).mockImplementation(() => riveMock);
const canvasSpy = document.createElement('canvas');
const { result, rerender } = renderHook((params) => useRive(params), {
initialProps: params,
});
await act(async () => {
result.current.setCanvasRef(canvasSpy);
});
rerender({
src: 'file-src',
animations: 'dark',
});
expect(stopMock).toBeCalledWith(['light']);
expect(pauseMock).toBeCalledWith('dark');
expect(playMock).not.toBeCalled();
});
it('does not set styles if className is passed in for the canvas container', async () => {
const params = {
src: 'file-src',
};
const riveMock = {
on: (_: string, cb: () => void) => cb(),
stop: jest.fn(),
stopRendering: jest.fn(),
};
// @ts-ignore
mocked(rive.Rive).mockImplementation(() => riveMock);
const canvasSpy = document.createElement('canvas');
const { result } = renderHook(() => useRive(params));
await act(async () => {
result.current.setCanvasRef(canvasSpy);
});
const { RiveComponent: RiveTestComponent } = result.current;
const { container } = render(
<RiveTestComponent className="rive-test-clas" style={{ width: '50%' }} />
);
expect(container.firstChild).not.toHaveStyle('width: 50%');
});
});

View File

@@ -0,0 +1,107 @@
import { mocked } from 'jest-mock';
import { renderHook } from '@testing-library/react-hooks';
import useStateMachineInput from '../src/hooks/useStateMachineInput';
import {Rive, StateMachineInput} from '@rive-app/canvas';
jest.mock('@rive-app/canvas', () => ({
Rive: jest.fn().mockImplementation(() => ({
on: jest.fn(),
stop: jest.fn(),
})),
Layout: jest.fn(),
Fit: {
Cover: 'cover',
},
Alignment: {
Center: 'center',
},
EventType: {
Load: 'load',
},
StateMachineInputType: {
Number: 1,
Boolean: 2,
Trigger: 3,
},
}));
describe('useStateMachineInput', () => {
it('returns null if there is null rive object passed', () => {
const { result } = renderHook(() => useStateMachineInput(null));
expect(result.current).toBeNull();
});
it('returns null if there is no state machine name', () => {
const riveMock = {};
mocked(Rive).mockImplementation(() => riveMock as Rive);
const { result } = renderHook(() => useStateMachineInput(riveMock as Rive, '', '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 { result } = renderHook(() => useStateMachineInput(riveMock as Rive, '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 { result } = renderHook(() => useStateMachineInput(riveMock as Rive, 'smName', ''));
expect(result.current).toBeNull();
});
it('returns null if the input has no association to the inputs of the state machine', () => {
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 { result } = renderHook(() => useStateMachineInput(riveMock as Rive, 'smName', 'numInput'));
expect(result.current).toBeNull();
});
it('returns a selected input if the input requested is part of the state machine', () => {
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 { result } = renderHook(() => useStateMachineInput(riveMock as Rive, 'smName', 'boolInput'));
expect(result.current).toBe(smInput);
});
it('returns a selected input with an initial value if the input requested is part of the state machine', () => {
const smInput = {
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 { result } = renderHook(() => useStateMachineInput(riveMock as Rive, 'smName', 'boolInput', true));
expect(result.current).toStrictEqual({
...smInput,
value: true,
});
});
});

View File

@@ -6,11 +6,12 @@
"lib": ["esnext", "dom"],
"module": "commonjs",
"moduleResolution": "node",
"noImplicitAny": true,
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"outDir": "./dist",
"types": ["node", "jest"],
"types": ["node", "jest", "offscreencanvas"],
"rootDir": "src",
"strict": true,
"target": "es5",