mirror of
https://github.com/rive-app/rive-react.git
synced 2026-03-13 08:22:30 +08:00
Compare commits
74 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9abee34d12 | ||
|
|
12801b10cc | ||
|
|
da11387558 | ||
|
|
3902948a2e | ||
|
|
21a17ed40e | ||
|
|
f0e70924ec | ||
|
|
f4eccbe2ce | ||
|
|
83c81b49c5 | ||
|
|
5de40fad5b | ||
|
|
aab811b975 | ||
|
|
965507ac34 | ||
|
|
74b791ffa4 | ||
|
|
2853851d52 | ||
|
|
4f37bbdb76 | ||
|
|
39f1990eac | ||
|
|
bb7d3e4e6c | ||
|
|
7f2bd76eb3 | ||
|
|
5c0b9cd613 | ||
|
|
92dd811948 | ||
|
|
4429be44f2 | ||
|
|
9398e0d74e | ||
|
|
563dca3608 | ||
|
|
1da73aac05 | ||
|
|
5c4336b84f | ||
|
|
6e72ed5271 | ||
|
|
464fa97c20 | ||
|
|
ac01b7ec69 | ||
|
|
cd9baef250 | ||
|
|
3a2ed32856 | ||
|
|
d35f5b53c5 | ||
|
|
73b57d0b81 | ||
|
|
0a18b522cc | ||
|
|
5e34e13563 | ||
|
|
c3f138014d | ||
|
|
b13413ba8b | ||
|
|
881e38fe6a | ||
|
|
38c85624a7 | ||
|
|
a9732e141e | ||
|
|
59edf6f67e | ||
|
|
4be496cc15 | ||
|
|
4c9de18b1c | ||
|
|
c688b9f17a | ||
|
|
fcfe3cf6cf | ||
|
|
8ce856270f | ||
|
|
1e1cabd057 | ||
|
|
0be3bc7e93 | ||
|
|
48af4b00ad | ||
|
|
fe44977e47 | ||
|
|
24d9e871d6 | ||
|
|
8b8d6bc44b | ||
|
|
956b76d01c | ||
|
|
2517efaebd | ||
|
|
019cadf5f2 | ||
|
|
e599b1a38c | ||
|
|
78d3118dcc | ||
|
|
536c8325f2 | ||
|
|
9e65654274 | ||
|
|
75420d2f1d | ||
|
|
e6b036ee17 | ||
|
|
bfbb8a59ee | ||
|
|
5a19354ab3 | ||
|
|
c4dc027522 | ||
|
|
e54a0d42d3 | ||
|
|
1a597943cb | ||
|
|
026d097658 | ||
|
|
a4777ec7e3 | ||
|
|
416334ef44 | ||
|
|
f309481a43 | ||
|
|
06500e6dcf | ||
|
|
33e34a46e1 | ||
|
|
c8f57f5896 | ||
|
|
5d0822836c | ||
|
|
1c3cc69f40 | ||
|
|
44056eb565 |
@@ -19,4 +19,9 @@ module.exports = {
|
||||
'no-var': 'error',
|
||||
eqeqeq: ['error', 'smart'],
|
||||
},
|
||||
settings: {
|
||||
react: {
|
||||
version: 'detect',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
80
.github/workflows/publish.yml
vendored
80
.github/workflows/publish.yml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
@@ -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
1
.gitignore
vendored
@@ -5,3 +5,4 @@ dist
|
||||
.idea
|
||||
.vscode
|
||||
examples/**/package-lock.json
|
||||
package-lock.json
|
||||
@@ -12,6 +12,6 @@
|
||||
"releaseName": "${version}"
|
||||
},
|
||||
"hooks": {
|
||||
"after:bump": "npx auto-changelog -p"
|
||||
"after:bump": ["npx auto-changelog -p", "git add ./CHANGELOG.md"]
|
||||
}
|
||||
}
|
||||
|
||||
270
CHANGELOG.md
270
CHANGELOG.md
@@ -4,6 +4,274 @@ 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).
|
||||
|
||||
#### 0.0.19
|
||||
#### [v3.0.4](https://github.com/rive-app/rive-react/compare/v3.0.3...v3.0.4)
|
||||
|
||||
- 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)
|
||||
|
||||
> 26 April 2022
|
||||
|
||||
- Maint: Bump rive wasm to include fps counter API and take off major tag [`83c81b4`](https://github.com/rive-app/rive-react/commit/83c81b49c5a53c5ec9092b83607a78b6e4a69768)
|
||||
- chore: release 3.0.1 [`f4eccbe`](https://github.com/rive-app/rive-react/commit/f4eccbe2ce8795f55a6bed7d8b17c2ac59c94c30)
|
||||
|
||||
### [v3.0.0](https://github.com/rive-app/rive-react/compare/v2.0.0...v3.0.0)
|
||||
|
||||
> 26 April 2022
|
||||
|
||||
- Fix animation playing with autoplay false when animation name passed [`aab811b`](https://github.com/rive-app/rive-react/commit/aab811b975d8832c2be14779675392a17b1db5ff)
|
||||
- chore: release 3.0.0 [`5de40fa`](https://github.com/rive-app/rive-react/commit/5de40fad5b716be7dcec59c15422e9d41a4962b1)
|
||||
|
||||
### [v2.0.0](https://github.com/rive-app/rive-react/compare/v1.0.7...v2.0.0)
|
||||
|
||||
> 22 April 2022
|
||||
|
||||
- Breaking: Spread non-style props onto canvas element instead of containing div [`5c0b9cd`](https://github.com/rive-app/rive-react/commit/5c0b9cd613873ee565b4ec40d71042c3850a502c)
|
||||
- Update: Adding build scripts to prepare for split of rive-react into 2 package derivatives for canvas and webgl [`5c4336b`](https://github.com/rive-app/rive-react/commit/5c4336b84fe55afea1ec9d5e42f530cf29d6d176)
|
||||
- Change rive-react-* references to be the shortened namespace-named convention [`4429be4`](https://github.com/rive-app/rive-react/commit/4429be44f2af2b91d9d5e26a65b70e59d9647979)
|
||||
|
||||
#### [v1.0.7](https://github.com/rive-app/rive-react/compare/v1.0.6...v1.0.7)
|
||||
|
||||
> 20 April 2022
|
||||
|
||||
- chore: release 1.0.7 [`6e72ed5`](https://github.com/rive-app/rive-react/commit/6e72ed5271976e886a576f5a6c0d7162eedc81d8)
|
||||
- Maint: Allow peer dep React to use v18.0+ [`464fa97`](https://github.com/rive-app/rive-react/commit/464fa97c207e780d31866ecad0437dc16aefd1f2)
|
||||
|
||||
#### [v1.0.6](https://github.com/rive-app/rive-react/compare/v1.0.5...v1.0.6)
|
||||
|
||||
> 14 April 2022
|
||||
|
||||
- chore: release 1.0.6 [`ac01b7e`](https://github.com/rive-app/rive-react/commit/ac01b7ec691c435371f9553df88144c75af18ed4)
|
||||
- Maint: Bump webgl dependency up to 1.0.39 [`cd9baef`](https://github.com/rive-app/rive-react/commit/cd9baef25003b491d40d5649ba1d3b5f88bce870)
|
||||
|
||||
#### [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)
|
||||
|
||||
> 7 September 2021
|
||||
|
||||
- chore: release 0.0.20 [`1c3cc69`](https://github.com/rive-app/rive-react/commit/1c3cc69f401b91810105b16ccce1dd7612da037a)
|
||||
- rive-0.7.30: Fix ghosting where aspect ratio of canvas is different to that of artboard [`44056eb`](https://github.com/rive-app/rive-react/commit/44056eb5654e90de6ba10ed4892a4e2a5ebf6716)
|
||||
|
||||
#### [v0.0.19](https://github.com/rive-app/rive-react/compare/v0.0.18...v0.0.19)
|
||||
|
||||
> 7 September 2021
|
||||
|
||||
- chore: release 0.0.19 [`a9c3233`](https://github.com/rive-app/rive-react/commit/a9c3233452d9f6465c761cda0763d314ba712267)
|
||||
- Update rive-js to 0.7.29 [`ce2c706`](https://github.com/rive-app/rive-react/commit/ce2c7065f567e43cfcca4c8f98e98aaf6e92f4c3)
|
||||
|
||||
#### [v0.0.18](https://github.com/rive-app/rive-react/compare/v0.0.17...v0.0.18)
|
||||
|
||||
> 12 August 2021
|
||||
|
||||
- chore: release 0.0.18 [`203faf9`](https://github.com/rive-app/rive-react/commit/203faf9ce22ee307af815ebdc2790f6bacbe0016)
|
||||
- Update rive-js version to 0.7.25 [`fd0efb1`](https://github.com/rive-app/rive-react/commit/fd0efb1b815ae833e3b50b643b00464542f6f800)
|
||||
|
||||
#### [v0.0.17](https://github.com/rive-app/rive-react/compare/v0.0.16...v0.0.17)
|
||||
|
||||
> 12 August 2021
|
||||
|
||||
- chore: release 0.0.17 [`11b6f2e`](https://github.com/rive-app/rive-react/commit/11b6f2e8792781ad38dce745f080b69a94c35c3a)
|
||||
- Update rive-js version to 0.7.24 [`8a1adf1`](https://github.com/rive-app/rive-react/commit/8a1adf147d25f4616ef048a84986314e9397ad43)
|
||||
|
||||
#### [v0.0.16](https://github.com/rive-app/rive-react/compare/v0.0.15...v0.0.16)
|
||||
|
||||
> 11 August 2021
|
||||
|
||||
- chore: release 0.0.16 [`80ffb5e`](https://github.com/rive-app/rive-react/commit/80ffb5ee2d3b3dd22d1c229e1f4e772e7fe763b3)
|
||||
- Update rive-js version to 0.7.23 [`cf1baa6`](https://github.com/rive-app/rive-react/commit/cf1baa6661f643996e37b26a5a9a6dd9a9950e06)
|
||||
|
||||
#### [v0.0.15](https://github.com/rive-app/rive-react/compare/v0.0.14...v0.0.15)
|
||||
|
||||
> 30 July 2021
|
||||
|
||||
- chore: release 0.0.15 [`f0b1aeb`](https://github.com/rive-app/rive-react/commit/f0b1aeb7d850103b61310c9251a827f835fadf58)
|
||||
- update rive-js with support for distance and transform constraints [`8612e0b`](https://github.com/rive-app/rive-react/commit/8612e0b15f6c93d4e5c276c95e7f36543466e4d6)
|
||||
|
||||
#### [v0.0.14](https://github.com/rive-app/rive-react/compare/v0.0.11...v0.0.14)
|
||||
|
||||
> 21 July 2021
|
||||
|
||||
- Bump rive-js to 0.7.19 with support for IK constraints [`6c80c53`](https://github.com/rive-app/rive-react/commit/6c80c5311e99ee47e9f4fc3c5f35ab908ddfa326)
|
||||
- chore: release 0.0.14 [`d7f7eab`](https://github.com/rive-app/rive-react/commit/d7f7eab65577732fa1e9f792bc14f10d89c0ccaf)
|
||||
- chore: bump to 0.0.13 [`29bd502`](https://github.com/rive-app/rive-react/commit/29bd502208efa6928ffb47f06b5e548f071a8ade)
|
||||
|
||||
#### [v0.0.11](https://github.com/rive-app/rive-react/compare/v0.0.10...v0.0.11)
|
||||
|
||||
> 14 July 2021
|
||||
|
||||
- Update README with camelCase params [`#26`](https://github.com/rive-app/rive-react/pull/26)
|
||||
- Update README with camel case params [`14b7746`](https://github.com/rive-app/rive-react/commit/14b774676b41fa3082cb6554ee2062aa7d773da9)
|
||||
- chore: release 0.0.11 [`9db4ee5`](https://github.com/rive-app/rive-react/commit/9db4ee52bf919add026c4c5487a5ca399cc0b823)
|
||||
|
||||
#### [v0.0.10](https://github.com/rive-app/rive-react/compare/v0.0.9...v0.0.10)
|
||||
|
||||
> 28 June 2021
|
||||
|
||||
- Include types in npm publish [`#23`](https://github.com/rive-app/rive-react/pull/23)
|
||||
- chore: release 0.0.10 [`0b14c4c`](https://github.com/rive-app/rive-react/commit/0b14c4cd4cc49f6b7b1567b23752688092ca73b4)
|
||||
|
||||
#### [v0.0.9](https://github.com/rive-app/rive-react/compare/v0.0.8...v0.0.9)
|
||||
|
||||
> 28 June 2021
|
||||
|
||||
- Fix build automation and only include dist files [`#22`](https://github.com/rive-app/rive-react/pull/22)
|
||||
- chore: release 0.0.9 [`2ec726c`](https://github.com/rive-app/rive-react/commit/2ec726cf12361254403539b30ebafb9adef9254d)
|
||||
|
||||
#### v0.0.8
|
||||
|
||||
> 28 June 2021
|
||||
|
||||
- Add release it dependency [`#21`](https://github.com/rive-app/rive-react/pull/21)
|
||||
- add release it for automated github releases and npm publish [`#20`](https://github.com/rive-app/rive-react/pull/20)
|
||||
- Add token to publish step [`#17`](https://github.com/rive-app/rive-react/pull/17)
|
||||
- Publish on merge to master [`#16`](https://github.com/rive-app/rive-react/pull/16)
|
||||
- version bump [`#15`](https://github.com/rive-app/rive-react/pull/15)
|
||||
- Bump rive-js version to 0.7.15 [`#14`](https://github.com/rive-app/rive-react/pull/14)
|
||||
- lower react peer dependency version [`#13`](https://github.com/rive-app/rive-react/pull/13)
|
||||
- Bump version to 0.0.5 [`#12`](https://github.com/rive-app/rive-react/pull/12)
|
||||
- Add Readme and change Rive Component [`#11`](https://github.com/rive-app/rive-react/pull/11)
|
||||
- Export rive-js types [`#10`](https://github.com/rive-app/rive-react/pull/10)
|
||||
- Add eslint and prettier configs [`#9`](https://github.com/rive-app/rive-react/pull/9)
|
||||
- Add basic github action for running tests [`#8`](https://github.com/rive-app/rive-react/pull/8)
|
||||
- Add typescript example [`#7`](https://github.com/rive-app/rive-react/pull/7)
|
||||
- Add examples for using rive-react [`#1`](https://github.com/rive-app/rive-react/pull/1)
|
||||
- Initial commit of existing implementation [`3b1d759`](https://github.com/rive-app/rive-react/commit/3b1d7593fe95da652857f7d362f90d8facad05ee)
|
||||
- Add changelog managed by auto-changelog [`5916f38`](https://github.com/rive-app/rive-react/commit/5916f384bbcb8af250a5ae3fb6f4061a742551a0)
|
||||
- Update README.md with usage docs [`c0a6b83`](https://github.com/rive-app/rive-react/commit/c0a6b835eacc2939f82923fb0c6c2d3b3cc12ed2)
|
||||
|
||||
77
README.md
77
README.md
@@ -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
|
||||
|
||||
@@ -73,12 +83,12 @@ export default Example;
|
||||
|
||||
#### Parameters
|
||||
|
||||
- `riveParams`: Set of parameters that are passed to the Rive.js `Rive` class constructor. `null` and `undefined` can be passed to conditionally display the .rive file.
|
||||
- `riveParams`: Set of parameters that are passed to the Rive.js `Rive` class constructor. `null` and `undefined` can be passed to conditionally display the .riv file.
|
||||
- `opts`: Rive React specific options.
|
||||
|
||||
#### 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
|
||||
|
||||
@@ -115,25 +126,36 @@ The `useStateMachineInput` hook is provided to make it easier to interact with s
|
||||
import { useRive, useStateMachineInput } from 'rive-react';
|
||||
|
||||
function Example() {
|
||||
const STATE_MACHINE_NAME = 'button';
|
||||
const INPUT_NAME = 'onClick';
|
||||
|
||||
const { RiveComponent, rive } = useRive({
|
||||
src: 'button.riv',
|
||||
stateMachines: 'button',
|
||||
stateMachines: STATE_MACHINE_NAME,
|
||||
autoplay: true,
|
||||
});
|
||||
|
||||
const onClickInput = useStateMachineInput(rive, 'button', 'onClick');
|
||||
const onClickInput = useStateMachineInput(
|
||||
rive,
|
||||
STATE_MACHINE_NAME,
|
||||
INPUT_NAME
|
||||
);
|
||||
|
||||
return <RiveComponent onClick={() => onClickInput && onClickInput.fire())} />;
|
||||
// This example is using a state machine with a trigger input.
|
||||
return <RiveComponent onClick={() => onClickInput.fire()} />;
|
||||
}
|
||||
|
||||
export default Example;
|
||||
```
|
||||
|
||||
See our [examples](examples) folder for working examples of [Boolean](examples/state-machine-boolean-input) and [Number](examples/state-machine-number-input) inputs.
|
||||
|
||||
#### Parameters
|
||||
|
||||
- `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
|
||||
|
||||
@@ -141,4 +163,45 @@ A Rive.js `stateMachineInput` object.
|
||||
|
||||
## Examples
|
||||
|
||||
The `examples` shows a number of different ways to use Rive React. See the instructions for each example to run locally.
|
||||
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.
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-scripts": "4.0.3",
|
||||
"rive-react": "0.0.1",
|
||||
"rive-react": "latest",
|
||||
"typescript": "^4.3.2",
|
||||
"web-vitals": "^1.1.2"
|
||||
},
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useRive, UseRiveParameters } from "rive-react";
|
||||
import { useRive, UseRiveParameters } from 'rive-react';
|
||||
|
||||
function App() {
|
||||
const params: UseRiveParameters = {
|
||||
src: "poison-loader.riv",
|
||||
src: 'poison-loader.riv',
|
||||
autoplay: true,
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ function App() {
|
||||
|
||||
return (
|
||||
// The animation will fit to the parent element.
|
||||
<div style={{ height: "500px", width: "500px" }}>
|
||||
<div style={{ height: '500px', width: '500px' }}>
|
||||
<RiveComponent />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import App from "./App";
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById("root")
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
"@testing-library/jest-dom": "^5.13.0",
|
||||
"@testing-library/react": "^11.2.7",
|
||||
"@testing-library/user-event": "^12.8.3",
|
||||
"react": "^17.0.2",
|
||||
"react": "file:../../node_modules/react",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-scripts": "4.0.3",
|
||||
"rive-react": "0.0.1",
|
||||
"rive-react": "file:../..",
|
||||
"web-vitals": "^1.1.2"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
BIN
examples/basic-with-hook/public/magic-ball.riv
Normal file
BIN
examples/basic-with-hook/public/magic-ball.riv
Normal file
Binary file not shown.
@@ -1,18 +1,28 @@
|
||||
import { useRive } from "rive-react";
|
||||
import { useRive } from 'rive-react';
|
||||
|
||||
function App() {
|
||||
const params = {
|
||||
src: "poison-loader.riv",
|
||||
src: 'poison-loader.riv',
|
||||
autoplay: true,
|
||||
};
|
||||
|
||||
const { RiveComponent } = useRive(params);
|
||||
const { RiveComponent: RiveComponentBasic } = useRive(params);
|
||||
|
||||
const { RiveComponent: RiveComponentTouch } = useRive({
|
||||
src: 'magic-ball.riv',
|
||||
autoplay: true,
|
||||
stateMachines: "Main State Machine",
|
||||
});
|
||||
|
||||
return (
|
||||
// The animation will fit to the parent element.
|
||||
<div style={{ height: "500px", width: "500px" }}>
|
||||
<RiveComponent />
|
||||
</div>
|
||||
<>
|
||||
<div style={{ height: '500px', width: '500px' }}>
|
||||
<RiveComponentBasic />
|
||||
</div>
|
||||
<div style={{ height: '300px', width: '300px' }}>
|
||||
<RiveComponentTouch />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import App from "./App";
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById("root")
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
"@testing-library/jest-dom": "^5.13.0",
|
||||
"@testing-library/react": "^11.2.7",
|
||||
"@testing-library/user-event": "^12.8.3",
|
||||
"react": "^17.0.2",
|
||||
"react": "file:../../node_modules/react",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-scripts": "4.0.3",
|
||||
"rive-react": "0.0.1",
|
||||
"rive-react": "file:../..",
|
||||
"web-vitals": "^1.1.2"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import Rive from "rive-react";
|
||||
import Rive from 'rive-react';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
// The animation will fit to the parent element.
|
||||
<div style={{ height: "500px", width: "500px" }}>
|
||||
<div style={{ height: '500px', width: '500px' }}>
|
||||
<Rive src="poison-loader.riv" autoplay />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import App from "./App";
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById("root")
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-scripts": "4.0.3",
|
||||
"rive-react": "0.0.1",
|
||||
"rive-react": "latest",
|
||||
"web-vitals": "^1.1.2"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useRive } from "rive-react";
|
||||
import { useRive } from 'rive-react';
|
||||
|
||||
function App() {
|
||||
const params = {
|
||||
src: "poison-loader.riv",
|
||||
src: 'poison-loader.riv',
|
||||
autoplay: false,
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@ function App() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ height: "600px", width: "600px" }}>
|
||||
<div style={{ height: '600px', width: '600px' }}>
|
||||
<RiveComponent onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import App from "./App";
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById("root")
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-scripts": "4.0.3",
|
||||
"rive-react": "0.0.1",
|
||||
"rive-react": "latest",
|
||||
"web-vitals": "^1.1.2"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<title>Rive React - Basic with Hook</title>
|
||||
<title>Rive React - Play/Pause Button</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useRive } from "rive-react";
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useRive } from 'rive-react';
|
||||
|
||||
function App() {
|
||||
const [buttonText, setButtonText] = useState("Pause");
|
||||
const [buttonText, setButtonText] = useState('Pause');
|
||||
const { RiveComponent, rive } = useRive({
|
||||
src: "poison-loader.riv",
|
||||
src: 'poison-loader.riv',
|
||||
autoplay: true,
|
||||
});
|
||||
|
||||
@@ -12,13 +12,13 @@ function App() {
|
||||
if (rive) {
|
||||
// "play" event is fired when the animation starts to play, so we update
|
||||
// button text on this event.
|
||||
rive.on("play", () => {
|
||||
setButtonText("Pause");
|
||||
rive.on('play', () => {
|
||||
setButtonText('Pause');
|
||||
});
|
||||
|
||||
// As above, the "pause" event is fired when the animation pauses.
|
||||
rive.on("pause", () => {
|
||||
setButtonText("Play");
|
||||
rive.on('pause', () => {
|
||||
setButtonText('Play');
|
||||
});
|
||||
}
|
||||
// We listen for changes to the rive object. The rive object will be null
|
||||
@@ -40,7 +40,7 @@ function App() {
|
||||
return (
|
||||
// The animation will fit to the parent element, so we set a large height
|
||||
// and width for this example.
|
||||
<div style={{ height: "500px", width: "500px" }}>
|
||||
<div style={{ height: '500px', width: '500px' }}>
|
||||
<RiveComponent />
|
||||
<button onClick={onButtonClick}>{buttonText}</button>
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import App from "./App";
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById("root")
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# State Machine Button
|
||||
# State Machine Boolean Input
|
||||
|
||||
This example shows how to interact with a state machine, using various onMouse\* callbacks to trigger transations.
|
||||
|
||||
36
examples/state-machine-boolean-input/package.json
Normal file
36
examples/state-machine-boolean-input/package.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "state-machine-boolean-input",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@testing-library/jest-dom": "^5.13.0",
|
||||
"@testing-library/react": "^11.2.7",
|
||||
"@testing-library/user-event": "^12.8.3",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-scripts": "4.0.3",
|
||||
"rive-react": "latest",
|
||||
"web-vitals": "^1.1.2"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "SKIP_PREFLIGHT_CHECK=true react-scripts start"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
||||
17
examples/state-machine-boolean-input/public/index.html
Normal file
17
examples/state-machine-boolean-input/public/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<title>Rive React - State Machine Boolean Input</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
58
examples/state-machine-boolean-input/src/App.js
Normal file
58
examples/state-machine-boolean-input/src/App.js
Normal file
@@ -0,0 +1,58 @@
|
||||
import { useRive, useStateMachineInput } from 'rive-react';
|
||||
|
||||
function App() {
|
||||
const STATE_MACHINE_NAME = 'State Machine 1';
|
||||
const ON_HOVER_INPUT_NAME = 'Hover';
|
||||
const ON_PRESSED_INPUT_NAME = 'Pressed';
|
||||
|
||||
const { RiveComponent, rive } = useRive({
|
||||
src: 'like.riv',
|
||||
stateMachines: STATE_MACHINE_NAME,
|
||||
artboard: 'New Artboard',
|
||||
autoplay: true,
|
||||
});
|
||||
|
||||
// Both onHoverInput and onPressedInput are boolean inputs. To transition
|
||||
// states we need to set the value property to true or false.
|
||||
const onHoverInput = useStateMachineInput(
|
||||
rive,
|
||||
STATE_MACHINE_NAME,
|
||||
ON_HOVER_INPUT_NAME
|
||||
);
|
||||
const onPressedInput = useStateMachineInput(
|
||||
rive,
|
||||
STATE_MACHINE_NAME,
|
||||
ON_PRESSED_INPUT_NAME
|
||||
);
|
||||
|
||||
function onMouseEnter() {
|
||||
onHoverInput.value = true;
|
||||
}
|
||||
|
||||
function onMouseLeave() {
|
||||
onHoverInput.value = false;
|
||||
}
|
||||
|
||||
function onMouseDown() {
|
||||
onPressedInput.value = true;
|
||||
}
|
||||
|
||||
function onMouseUp() {
|
||||
onPressedInput.value = false;
|
||||
}
|
||||
|
||||
return (
|
||||
// The animation will fit to the parent element, so we set a large height
|
||||
// and width for this example.
|
||||
<div style={{ height: '500px', width: '500px' }}>
|
||||
<RiveComponent
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
onMouseDown={onMouseDown}
|
||||
onMouseUp={onMouseUp}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
10
examples/state-machine-boolean-input/src/index.js
Normal file
10
examples/state-machine-boolean-input/src/index.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
@@ -1,54 +0,0 @@
|
||||
import { useRive, useStateMachineInput } from "rive-react";
|
||||
|
||||
function App() {
|
||||
const { RiveComponent, rive } = useRive({
|
||||
src: "like.riv",
|
||||
stateMachines: "State Machine 1",
|
||||
artboard: "New Artboard",
|
||||
autoplay: true,
|
||||
});
|
||||
|
||||
const hoverInput = useStateMachineInput(rive, "State Machine 1", "Hover");
|
||||
const pressedInput = useStateMachineInput(rive, "State Machine 1", "Pressed");
|
||||
|
||||
function onMouseEnter() {
|
||||
// state machine inputs will be null until the rive file has loaded, so we
|
||||
// put these guards in place to avoid any errors.
|
||||
if (hoverInput) {
|
||||
hoverInput.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseLeave() {
|
||||
if (hoverInput) {
|
||||
hoverInput.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseDown() {
|
||||
if (pressedInput) {
|
||||
pressedInput.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseUp() {
|
||||
if (pressedInput) {
|
||||
pressedInput.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
// The animation will fit to the parent element, so we set a large height
|
||||
// and width for this example.
|
||||
<div style={{ height: "500px", width: "500px" }}>
|
||||
<RiveComponent
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
onMouseDown={onMouseDown}
|
||||
onMouseUp={onMouseUp}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
@@ -1,10 +0,0 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import App from "./App";
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById("root")
|
||||
);
|
||||
14
examples/state-machine-number-input/README.md
Normal file
14
examples/state-machine-number-input/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# State Machine Number Input
|
||||
|
||||
This example shows how to interact with a state machine with number inputs. We trigger the transistions by changing the value of a number input.
|
||||
|
||||
## To Run
|
||||
|
||||
This example is created using [Create React App](https://reactjs.org/docs/create-a-new-react-app.html).
|
||||
|
||||
To install and run:
|
||||
|
||||
```
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "state-machine-button",
|
||||
"name": "state-machine-number-input",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
@@ -9,7 +9,7 @@
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-scripts": "4.0.3",
|
||||
"rive-react": "0.0.1",
|
||||
"rive-react": "latest",
|
||||
"web-vitals": "^1.1.2"
|
||||
},
|
||||
"scripts": {
|
||||
@@ -8,7 +8,7 @@
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<title>Rive React - Basic with Hook</title>
|
||||
<title>Rive React - State Machine Number Input</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
BIN
examples/state-machine-number-input/public/skills.riv
Normal file
BIN
examples/state-machine-number-input/public/skills.riv
Normal file
Binary file not shown.
34
examples/state-machine-number-input/src/App.js
Normal file
34
examples/state-machine-number-input/src/App.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import { useRive, useStateMachineInput } from 'rive-react';
|
||||
|
||||
function App() {
|
||||
const STATE_MACHINE_NAME = 'State Machine ';
|
||||
const INPUT_NAME = 'Level';
|
||||
|
||||
const { RiveComponent, rive } = useRive({
|
||||
src: 'skills.riv',
|
||||
stateMachines: STATE_MACHINE_NAME,
|
||||
artboard: 'New Artboard',
|
||||
autoplay: true,
|
||||
});
|
||||
|
||||
// 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);
|
||||
|
||||
return (
|
||||
// The animation will fit to the parent element, so we set a large height
|
||||
// and width for this example.
|
||||
<div style={{ height: '500px', width: '500px' }}>
|
||||
<RiveComponent />
|
||||
<div>
|
||||
Level:
|
||||
<button onClick={() => (levelInput.value = 0)}>0</button>
|
||||
<button onClick={() => (levelInput.value = 1)}>1</button>
|
||||
<button onClick={() => (levelInput.value = 2)}>2</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
10
examples/state-machine-number-input/src/index.js
Normal file
10
examples/state-machine-number-input/src/index.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
14
examples/state-machine-trigger-input/README.md
Normal file
14
examples/state-machine-trigger-input/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# State Machine Trigger Input
|
||||
|
||||
This example shows how to interact with a state machine with a trigger input. We call the `fire()` function on the state machine input to transition the state when the animation is clicked.
|
||||
|
||||
## To Run
|
||||
|
||||
This example is created using [Create React App](https://reactjs.org/docs/create-a-new-react-app.html).
|
||||
|
||||
To install and run:
|
||||
|
||||
```
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
36
examples/state-machine-trigger-input/package.json
Normal file
36
examples/state-machine-trigger-input/package.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "state-machine-trigger-input",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@testing-library/jest-dom": "^5.13.0",
|
||||
"@testing-library/react": "^11.2.7",
|
||||
"@testing-library/user-event": "^12.8.3",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-scripts": "4.0.3",
|
||||
"rive-react": "latest",
|
||||
"web-vitals": "^1.1.2"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "SKIP_PREFLIGHT_CHECK=true react-scripts start"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
||||
17
examples/state-machine-trigger-input/public/index.html
Normal file
17
examples/state-machine-trigger-input/public/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<title>Rive React - State Machine Trigger Input</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
examples/state-machine-trigger-input/public/piggy-bank.riv
Normal file
BIN
examples/state-machine-trigger-input/public/piggy-bank.riv
Normal file
Binary file not shown.
31
examples/state-machine-trigger-input/src/App.js
Normal file
31
examples/state-machine-trigger-input/src/App.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import { useRive, useStateMachineInput } from 'rive-react';
|
||||
|
||||
function App() {
|
||||
const STATE_MACHINE_NAME = 'State Machine 1';
|
||||
const INPUT_NAME = 'Pressed';
|
||||
|
||||
const { RiveComponent, rive } = useRive({
|
||||
src: 'piggy-bank.riv',
|
||||
stateMachines: STATE_MACHINE_NAME,
|
||||
artboard: 'New Artboard',
|
||||
autoplay: true,
|
||||
});
|
||||
|
||||
// pressedInput in a trigger state machine input. To transition the state
|
||||
// we need to call the `fire()` method on the input.
|
||||
const pressedInput = 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.
|
||||
<div style={{ height: '500px', width: '500px' }}>
|
||||
<RiveComponent onClick={() => pressedInput.fire()} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
10
examples/state-machine-trigger-input/src/index.js
Normal file
10
examples/state-machine-trigger-input/src/index.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
3
npm/react-canvas/README.md
Normal file
3
npm/react-canvas/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# @rive-app/react-canvas
|
||||
|
||||
Output for `rive-react` using the backing `@rive-app/canvas` JS runtime
|
||||
3
npm/react-webgl/README.md
Normal file
3
npm/react-webgl/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# @rive-app/react-webgl
|
||||
|
||||
Output for `rive-react` using the backing `@rive-app/webgl` JS runtime
|
||||
8103
package-lock.json
generated
8103
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
23
package.json
23
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "rive-react",
|
||||
"version": "0.0.19",
|
||||
"version": "3.0.4",
|
||||
"description": "React wrapper around the rive-js library",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/types/index.d.ts",
|
||||
@@ -10,6 +10,7 @@
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"build": "bunchee src/index.ts -m --no-sourcemap",
|
||||
"dev": "watch 'npm run build' src",
|
||||
"lint": "eslint -c .eslintrc.js 'src/**/*{.ts,.tsx}'",
|
||||
"format": "prettier --write src",
|
||||
"types:check": "tsc --noEmit",
|
||||
@@ -26,22 +27,24 @@
|
||||
},
|
||||
"homepage": "https://github.com/rive-app/rive-react#readme",
|
||||
"dependencies": {
|
||||
"rive-js": "0.7.29"
|
||||
"@rive-app/canvas": "1.0.63",
|
||||
"@rive-app/webgl": "1.0.60"
|
||||
},
|
||||
"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.6.0",
|
||||
"bunchee": "^1.7.3",
|
||||
"eslint": "^7.28.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-config-standard": "^16.0.3",
|
||||
@@ -49,12 +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
18
scripts/build.sh
Executable 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
11
scripts/bump_all_versions.sh
Executable 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
12
scripts/bump_version.sh
Executable 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
33
scripts/nextVersion.js
Normal 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
10
scripts/publish_all.sh
Executable 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
21
scripts/setup_all_packages.sh
Executable 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
6
scripts/setup_package.sh
Executable 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"
|
||||
22
scripts/trimPackageJson.js
Normal file
22
scripts/trimPackageJson.js
Normal 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();
|
||||
}
|
||||
@@ -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(),
|
||||
|
||||
@@ -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} />;
|
||||
};
|
||||
|
||||
|
||||
@@ -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} />
|
||||
<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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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
33
test/Rive.test.tsx
Normal 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');
|
||||
});
|
||||
});
|
||||
@@ -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%');
|
||||
});
|
||||
});
|
||||
|
||||
107
test/useStateMachine.test.tsx
Normal file
107
test/useStateMachine.test.tsx
Normal 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,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user