├── .editorconfig
├── .gitattributes
├── .github
├── ISSUE_TEMPLATE
│ └── i-have-a-problem-with-rive-react-native.md
└── workflows
│ ├── add_to_project.yml
│ ├── publish-prerelease.yml
│ ├── publish-release.yml
│ └── typecheck-lint.yml
├── .gitignore
├── .watchmanconfig
├── .yarn
├── plugins
│ └── @yarnpkg
│ │ ├── plugin-interactive-tools.cjs
│ │ └── plugin-workspace-tools.cjs
└── releases
│ └── yarn-4.7.0.cjs
├── .yarnrc
├── .yarnrc.yml
├── Backup.swift
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── android
├── .project
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── rivereactnative
│ ├── RNAlignment.kt
│ ├── RNDirection.kt
│ ├── RNFit.kt
│ ├── RNLoopMode.kt
│ ├── RNPropertyType.kt
│ ├── RNRiveError.kt
│ ├── RNRiveRendererType.kt
│ ├── RiveReactNativeModule.kt
│ ├── RiveReactNativePackage.kt
│ ├── RiveReactNativeRendererModule.kt
│ ├── RiveReactNativeView.kt
│ └── RiveReactNativeViewManager.kt
├── babel.config.js
├── docs
├── rive-react-native-reference.md
├── types.md
└── usage-guide.md
├── example
├── .gitignore
├── README.md
├── android
│ ├── .gitignore
│ ├── app
│ │ ├── build.gradle
│ │ ├── debug.keystore
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── anonymous
│ │ │ │ └── example
│ │ │ │ ├── MainActivity.kt
│ │ │ │ └── MainApplication.kt
│ │ │ └── res
│ │ │ ├── Inter-594377.ttf
│ │ │ ├── drawable-hdpi
│ │ │ └── splashscreen_logo.png
│ │ │ ├── drawable-mdpi
│ │ │ └── splashscreen_logo.png
│ │ │ ├── drawable-xhdpi
│ │ │ └── splashscreen_logo.png
│ │ │ ├── drawable-xxhdpi
│ │ │ └── splashscreen_logo.png
│ │ │ ├── drawable-xxxhdpi
│ │ │ └── splashscreen_logo.png
│ │ │ ├── drawable
│ │ │ ├── ic_launcher_background.xml
│ │ │ └── rn_edit_text_material.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.webp
│ │ │ ├── ic_launcher_foreground.webp
│ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.webp
│ │ │ ├── ic_launcher_foreground.webp
│ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ ├── ic_launcher_foreground.webp
│ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ ├── ic_launcher_foreground.webp
│ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ ├── ic_launcher_foreground.webp
│ │ │ └── ic_launcher_round.webp
│ │ │ ├── raw
│ │ │ ├── artboard_animations.riv
│ │ │ ├── avatars.riv
│ │ │ ├── bird.riv
│ │ │ ├── constrained.riv
│ │ │ ├── flying_car.riv
│ │ │ ├── hello_world_nested.riv
│ │ │ ├── hello_world_text.riv
│ │ │ ├── hero_editor.riv
│ │ │ ├── layout_test.riv
│ │ │ ├── nested_inputs.riv
│ │ │ ├── nested_menu.riv
│ │ │ ├── out_of_band.riv
│ │ │ ├── rainy.riv
│ │ │ ├── rating.riv
│ │ │ ├── rewards.riv
│ │ │ ├── skills.riv
│ │ │ ├── skills_listener.riv
│ │ │ ├── truck_v7.riv
│ │ │ ├── two_bone_ik.riv
│ │ │ ├── ui_swipe_left_to_delete.riv
│ │ │ └── v6_file.riv
│ │ │ ├── referenced-image-2929282.png
│ │ │ ├── referenced_audio-2929340.wav
│ │ │ ├── values-night
│ │ │ └── colors.xml
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ └── settings.gradle
├── app.json
├── app
│ ├── (examples)
│ │ ├── DataBinding.tsx
│ │ ├── DynamicText.tsx
│ │ ├── ErrorHandledManually.tsx
│ │ ├── ErrorNotHandled.tsx
│ │ ├── Events.tsx
│ │ ├── Http.tsx
│ │ ├── Layout.tsx
│ │ ├── MeshExample.tsx
│ │ ├── MultipleArtboards.tsx
│ │ ├── NestedDynamicText.tsx
│ │ ├── NestedInputs.tsx
│ │ ├── OutOfBandAssets.tsx
│ │ ├── ResponsiveLayout.tsx
│ │ ├── Simple.tsx
│ │ ├── SimpleControls.tsx
│ │ ├── SourceProp.tsx
│ │ └── StateMachine.tsx
│ ├── +not-found.tsx
│ ├── _layout.tsx
│ └── index.tsx
├── assets
│ ├── audio
│ │ └── referenced_audio-2929340.wav
│ ├── fonts
│ │ ├── Inter-594377.ttf
│ │ └── SpaceMono-Regular.ttf
│ ├── images
│ │ ├── adaptive-icon.png
│ │ ├── favicon.png
│ │ ├── icon.png
│ │ ├── partial-react-logo.png
│ │ ├── react-logo.png
│ │ ├── react-logo@2x.png
│ │ ├── react-logo@3x.png
│ │ ├── referenced-image-2929282.png
│ │ └── splash-icon.png
│ └── rive
│ │ └── avatars.riv
├── components
│ ├── Themed.tsx
│ ├── ThemedText.tsx
│ └── ThemedView.tsx
├── constants
│ ├── Colors.ts
│ └── typesPredicates.ts
├── hooks
│ ├── useColorScheme.ts
│ ├── useColorScheme.web.ts
│ └── useThemeColor.ts
├── ios
│ ├── .gitignore
│ ├── .xcode.env
│ ├── Assets
│ │ ├── FollowPathCar.riv
│ │ ├── Inter-594377.ttf
│ │ ├── artboard_animations.riv
│ │ ├── avatars.riv
│ │ ├── bird.riv
│ │ ├── constrained.riv
│ │ ├── hello_world_nested.riv
│ │ ├── hello_world_text.riv
│ │ ├── hero_editor.riv
│ │ ├── layout_test.riv
│ │ ├── nested_inputs.riv
│ │ ├── nested_menu.riv
│ │ ├── out_of_band.riv
│ │ ├── rainy.riv
│ │ ├── rating.riv
│ │ ├── referenced-image-2929282.png
│ │ ├── referenced_audio-2929340.wav
│ │ ├── skills_listener.riv
│ │ ├── switch.riv
│ │ ├── truck_v7.riv
│ │ ├── two_bone_ik.riv
│ │ ├── ui_swipe_left_to_delete.riv
│ │ └── v6_file.riv
│ ├── Podfile
│ ├── Podfile.lock
│ ├── Podfile.properties.json
│ ├── example.xcodeproj
│ │ ├── project.pbxproj
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── example.xcscheme
│ ├── example.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ ├── example
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.mm
│ │ ├── Images.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ ├── App-Icon-1024x1024@1x.png
│ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ ├── SplashScreenBackground.colorset
│ │ │ │ └── Contents.json
│ │ │ └── SplashScreenLogo.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── image.png
│ │ │ │ ├── image@2x.png
│ │ │ │ └── image@3x.png
│ │ ├── Info.plist
│ │ ├── PrivacyInfo.xcprivacy
│ │ ├── SplashScreen.storyboard
│ │ ├── Supporting
│ │ │ └── Expo.plist
│ │ ├── example-Bridging-Header.h
│ │ ├── example.entitlements
│ │ ├── main.m
│ │ └── noop-file.swift
│ └── rewards.riv
├── metro.config.js
├── package.json
├── scripts
│ └── reset-project.js
└── tsconfig.json
├── ios
├── RCTLog.swift
├── RCTSwiftLog.h
├── RCTSwiftLog.m
├── RNAlignment.swift
├── RNDirection.swift
├── RNFit.swift
├── RNLoopMode.swift
├── RNPropertyType.swift
├── RNRiveError.swift
├── RNRiveRendererType.swift
├── RiveReactNative-Bridging-Header.h
├── RiveReactNative.xcodeproj
│ └── project.pbxproj
├── RiveReactNativeEventModule.h
├── RiveReactNativeEventModule.m
├── RiveReactNativeModule.swift
├── RiveReactNativeModuleBridge.m
├── RiveReactNativeRendererModule.swift
├── RiveReactNativeRendererModuleBridge.m
├── RiveReactNativeView.swift
├── RiveReactNativeViewManager.m
├── RiveReactNativeViewManager.swift
└── utility.swift
├── package.json
├── rive-react-native.podspec
├── scripts
├── add_build_number.sh
└── bootstrap.js
├── src
├── Rive.tsx
├── __tests__
│ └── index.test.tsx
├── helpers.ts
├── index.tsx
├── types.ts
└── utils.ts
├── tsconfig.build.json
├── tsconfig.json
├── version.txt
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 |
9 | indent_style = space
10 | indent_size = 2
11 |
12 | end_of_line = lf
13 | charset = utf-8
14 | trim_trailing_whitespace = true
15 | insert_final_newline = true
16 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj -text
2 | # specific for windows script files
3 | *.bat text eol=crlf
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/i-have-a-problem-with-rive-react-native.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: I have a problem with rive-react-native
3 | about: Tell us what's wrong
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | <-- Thanks for using Rive!
11 |
12 | If something isn't working like you expected, please:
13 | - Make sure you've updated rive-react-native to the latest version:
14 | https://www.npmjs.com/package/rive-react-native
15 | - Check out our help center
16 | https://help.rive.app/
17 | - You can file a new feature request at
18 | https://feedback.rive.app/
19 |
20 | If you think you found a bug or if you can't find what you're looking for
21 | in our docs, fill out the template below.
22 |
23 | -->
24 |
25 | ### Description
26 | <-- A clear and concise description of what the problem is. -->
27 |
28 | ### Provide a Repro
29 | <--
30 | Please provide the most **minimal repro** you can:
31 | - If the problem is small enough, paste a code snippet
32 | - Otherwise, you can attach a ZIP archive or paste a link to a GitHub repository with the bundle that reproduces the issue
33 |
34 | -->
35 |
36 | #### Source `.riv`/`.rev` file
37 | <--
38 | Attaching runtime-exported `.riv` file that reproduces the issue is immensely helpful for our team to identify the problem as fast as possible and fix it.
39 | Please also include the source (`.rev`) by [downloading a backup](https://help.rive.app/editor/exporting#for-backup) from the Editor.
40 |
41 | N.B. Because GitHub only supports certain file types use a ZIP archive to upload `.riv`/`.rev` files to this issue.
42 |
43 | You can also privately share the `.riv`/`.rev` file with us at hello@rive.app.
44 | -->
45 |
46 | ### Expected behavior
47 | <-- A clear and concise description of what you expected to happen. -->
48 |
49 | #### Screenshots
50 | <-- If applicable, add screenshots to help explain your problem. -->
51 |
52 | 
53 | ### Device & Versions (please complete the following information)
54 | - Device: [e.g. Android Emulator, iOS Simulator]
55 | - OS: [e.g. Android SDK API Level 30, iOS 14.5]
56 | - NPM Version: [Copy-paste the output of `npm --version` e.g.: `7.10.2`]
57 |
58 | #### Additional context
59 | <-- Add any other context about the problem here. -->
60 |
--------------------------------------------------------------------------------
/.github/workflows/add_to_project.yml:
--------------------------------------------------------------------------------
1 | name: Adds all new issues to project board
2 |
3 | on:
4 | issues:
5 | types:
6 | - opened
7 |
8 | jobs:
9 | add-to-project:
10 | name: Add issue to project
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/add-to-project@v0.5.0
14 | with:
15 | project-url: https://github.com/orgs/rive-app/projects/12/views/1
16 | github-token: ${{ secrets.ADD_TO_PROJECT_ACTION }}
17 |
18 | - uses: actions/github-script@v6
19 | with:
20 | script: |
21 | github.rest.issues.addLabels({
22 | issue_number: context.issue.number,
23 | owner: context.repo.owner,
24 | repo: context.repo.repo,
25 | labels: ["triage"]
26 | })
27 |
--------------------------------------------------------------------------------
/.github/workflows/publish-prerelease.yml:
--------------------------------------------------------------------------------
1 | name: Publish Rive React Native pre-release
2 | on:
3 | workflow_dispatch:
4 | jobs:
5 | publish:
6 | name: Install and publish
7 | runs-on: ubuntu-latest
8 | steps:
9 | - name: Checkout
10 | uses: actions/checkout@v4
11 | with:
12 | fetch-depth: 0
13 |
14 | - name: Git config
15 | run: |
16 | git config --local user.email 'hello@rive.app'
17 | git config --local user.name ${{ github.actor }}
18 |
19 | - name: Setup Node.js
20 | uses: actions/setup-node@v4
21 | with:
22 | node-version: 18.x
23 |
24 | - name: Enable Corepack and Use Correct Yarn Version
25 | run: |
26 | corepack enable
27 | corepack prepare yarn@4.7.0 --activate
28 |
29 | - name: Restore dependencies
30 | id: yarn-cache
31 | uses: actions/cache/restore@v4
32 | with:
33 | path: |
34 | **/node_modules
35 | .yarn/install-state.gz
36 | key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}-${{ hashFiles('**/package.json', '!node_modules/**') }}
37 | restore-keys: |
38 | ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}
39 | ${{ runner.os }}-yarn-
40 |
41 | - name: Debug Yarn State (Optional)
42 | run: yarn install --check-cache
43 |
44 | - name: Install dependencies
45 | if: steps.yarn-cache.outputs.cache-hit != 'true'
46 | run: yarn install --immutable
47 | shell: bash
48 |
49 | - name: Cache dependencies
50 | if: steps.yarn-cache.outputs.cache-hit != 'true'
51 | uses: actions/cache/save@v4
52 | with:
53 | path: |
54 | **/node_modules
55 | .yarn/install-state.gz
56 | key: ${{ steps.yarn-cache.outputs.cache-primary-key }}
57 |
58 | - name: Lint
59 | run: yarn lint
60 |
61 | - name: Type Check
62 | run: yarn typescript
63 |
64 | - name: Build lib
65 | run: yarn prepare
66 |
67 | - name: Authenticate with registry
68 | run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_AUTOMATION_TOKEN }}
69 |
70 | - name: Publish
71 | run: |
72 | chmod +x ./scripts/add_build_number.sh
73 | yarn release --increment=$(./scripts/add_build_number.sh) --preRelease=beta --ci
74 | env:
75 | GITHUB_TOKEN: ${{ secrets.REPO_PAT }}
76 |
--------------------------------------------------------------------------------
/.github/workflows/publish-release.yml:
--------------------------------------------------------------------------------
1 | name: Publish Rive React Native release
2 | on:
3 | workflow_dispatch:
4 | jobs:
5 | publish:
6 | name: Install and publish
7 | runs-on: ubuntu-latest
8 | steps:
9 | - name: Checkout
10 | uses: actions/checkout@v4
11 | with:
12 | fetch-depth: 0
13 |
14 | - name: Git config
15 | run: |
16 | git config --local user.email 'hello@rive.app'
17 | git config --local user.name ${{ github.actor }}
18 |
19 | - name: Setup Node.js
20 | uses: actions/setup-node@v4
21 | with:
22 | node-version: 18.x
23 |
24 | - name: Enable Corepack and Use Correct Yarn Version
25 | run: |
26 | corepack enable
27 | corepack prepare yarn@4.7.0 --activate
28 |
29 | - name: Restore dependencies
30 | id: yarn-cache
31 | uses: actions/cache/restore@v4
32 | with:
33 | path: |
34 | **/node_modules
35 | .yarn/install-state.gz
36 | key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}-${{ hashFiles('**/package.json', '!node_modules/**') }}
37 | restore-keys: |
38 | ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}
39 | ${{ runner.os }}-yarn-
40 |
41 | - name: Debug Yarn State (Optional)
42 | run: yarn install --check-cache
43 |
44 | - name: Install dependencies
45 | if: steps.yarn-cache.outputs.cache-hit != 'true'
46 | run: yarn install --immutable
47 | shell: bash
48 |
49 | - name: Cache dependencies
50 | if: steps.yarn-cache.outputs.cache-hit != 'true'
51 | uses: actions/cache/save@v4
52 | with:
53 | path: |
54 | **/node_modules
55 | .yarn/install-state.gz
56 | key: ${{ steps.yarn-cache.outputs.cache-primary-key }}
57 |
58 | - name: Lint
59 | run: yarn lint
60 |
61 | - name: Type Check
62 | run: yarn typescript
63 |
64 | - name: Build lib
65 | run: yarn prepare
66 |
67 | - name: Authenticate with registry
68 | run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_AUTOMATION_TOKEN }}
69 |
70 | - name: Publish
71 | run: |
72 | chmod +x ./scripts/add_build_number.sh
73 | yarn release --increment=$(cat version.txt)
74 | env:
75 | GITHUB_TOKEN: ${{ secrets.REPO_PAT }}
76 |
--------------------------------------------------------------------------------
/.github/workflows/typecheck-lint.yml:
--------------------------------------------------------------------------------
1 | name: Typecheck and Lint
2 |
3 | on: [push]
4 |
5 | jobs:
6 | typecheck-and-lint:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v4
10 |
11 | - name: Setup Node.js
12 | uses: actions/setup-node@v4
13 | with:
14 | node-version: 18.x
15 |
16 | - name: Enable Corepack and Use Correct Yarn Version
17 | run: |
18 | corepack enable
19 | corepack prepare yarn@4.7.0 --activate
20 |
21 | - name: Restore dependencies
22 | id: yarn-cache
23 | uses: actions/cache/restore@v4
24 | with:
25 | path: |
26 | **/node_modules
27 | .yarn/install-state.gz
28 | key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}-${{ hashFiles('**/package.json', '!node_modules/**') }}
29 | restore-keys: |
30 | ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}
31 | ${{ runner.os }}-yarn-
32 |
33 | - name: Debug Yarn State (Optional)
34 | run: yarn install --check-cache
35 |
36 | - name: Install dependencies
37 | if: steps.yarn-cache.outputs.cache-hit != 'true'
38 | run: yarn install --immutable
39 | shell: bash
40 |
41 | - name: Cache dependencies
42 | if: steps.yarn-cache.outputs.cache-hit != 'true'
43 | uses: actions/cache/save@v4
44 | with:
45 | path: |
46 | **/node_modules
47 | .yarn/install-state.gz
48 | key: ${{ steps.yarn-cache.outputs.cache-primary-key }}
49 |
50 | - name: Run Eslint Checks
51 | run: yarn lint
52 |
53 | - name: Run Typescript Checks
54 | run: yarn typescript
55 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # XDE
6 | .expo/
7 |
8 | # VSCode
9 | .vscode/
10 | jsconfig.json
11 |
12 | # Xcode
13 | #
14 | build/
15 | *.pbxuser
16 | !default.pbxuser
17 | *.mode1v3
18 | !default.mode1v3
19 | *.mode2v3
20 | !default.mode2v3
21 | *.perspectivev3
22 | !default.perspectivev3
23 | xcuserdata
24 | *.xccheckout
25 | *.moved-aside
26 | DerivedData
27 | *.hmap
28 | *.ipa
29 | *.xcuserstate
30 | project.xcworkspace
31 | **/.xcode.env.local
32 |
33 | # Android/IJ
34 | #
35 | .classpath
36 | .cxx
37 | .gradle
38 | .idea
39 | .project
40 | .settings
41 | local.properties
42 | android.iml
43 |
44 | # Cocoapods
45 | #
46 | example/ios/Pods
47 |
48 | # Ruby
49 | example/vendor/
50 |
51 | # node.js
52 | #
53 | node_modules/
54 | npm-debug.log
55 | yarn-debug.log
56 | yarn-error.log
57 |
58 | # Ignore files generated by npm pack
59 | /*.tgz
60 |
61 | # BUCK
62 | buck-out/
63 | \.buckd/
64 | android/app/libs
65 | android/keystores/debug.keystore
66 |
67 | # Yarn
68 | .yarn/*
69 | !.yarn/patches
70 | !.yarn/plugins
71 | !.yarn/releases
72 | !.yarn/sdks
73 | !.yarn/versions
74 |
75 | # Expo
76 | .expo/
77 |
78 | # Turborepo
79 | .turbo/
80 |
81 | # generated by bob
82 | lib/
83 |
84 | # React Native Codegen
85 | ios/generated
86 | android/generated
87 |
88 | # React Native Nitro Modules
89 | nitrogen/
90 | # OSX
91 | #
92 | .DS_Store
93 |
94 | # XDE
95 | .expo/
96 |
97 | # VSCode
98 | .vscode/
99 | jsconfig.json
100 |
101 | # Xcode
102 | #
103 | build/
104 | *.pbxuser
105 | !default.pbxuser
106 | *.mode1v3
107 | !default.mode1v3
108 | *.mode2v3
109 | !default.mode2v3
110 | *.perspectivev3
111 | !default.perspectivev3
112 | xcuserdata
113 | *.xccheckout
114 | *.moved-aside
115 | DerivedData
116 | *.hmap
117 | *.ipa
118 | *.xcuserstate
119 | project.xcworkspace
120 | **/.xcode.env.local
121 |
122 | # Android/IJ
123 | #
124 | .classpath
125 | .cxx
126 | .gradle
127 | .idea
128 | .project
129 | .settings
130 | local.properties
131 | android.iml
132 |
133 | # Cocoapods
134 | #
135 | example/ios/Pods
136 |
137 | # Ruby
138 | example/vendor/
139 |
140 | # node.js
141 | #
142 | node_modules/
143 | npm-debug.log
144 | yarn-debug.log
145 | yarn-error.log
146 |
147 | # BUCK
148 | buck-out/
149 | \.buckd/
150 | android/app/libs
151 | android/keystores/debug.keystore
152 |
153 | # Yarn
154 | .yarn/*
155 | !.yarn/patches
156 | !.yarn/plugins
157 | !.yarn/releases
158 | !.yarn/sdks
159 | !.yarn/versions
160 |
161 | # Expo
162 | .expo/
163 |
164 | # Turborepo
165 | .turbo/
166 |
167 | # generated by bob
168 | lib/
169 |
170 | # React Native Codegen
171 | ios/generated
172 | android/generated
173 |
174 | # React Native Nitro Modules
175 | nitrogen/
176 |
--------------------------------------------------------------------------------
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/.yarnrc:
--------------------------------------------------------------------------------
1 | # Override Yarn command so we can automatically setup the repo on running `yarn`
2 |
3 | yarn-path "scripts/bootstrap.js"
4 |
--------------------------------------------------------------------------------
/.yarnrc.yml:
--------------------------------------------------------------------------------
1 | nodeLinker: node-modules
2 |
3 | yarnPath: .yarn/releases/yarn-4.7.0.cjs
4 |
--------------------------------------------------------------------------------
/Backup.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Backup.swift
3 | // rive-react-native
4 | //
5 | // Created by Peter G Hayes on 02/03/2023.
6 | //
7 |
8 | import Foundation
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 TMaszko
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | 
3 | 
4 |
5 | # Rive React Native
6 |
7 | 
8 |
9 | A React Native runtime library for [Rive](https://rive.app).
10 |
11 | This library is a wrapper around the iOS/Android runtime, providing a component and ref pattern for React Native applications.
12 |
13 | ## Table of contents
14 |
15 | - :star: [Rive Overview](#rive-overview)
16 | - 🚀 [Getting Started & API docs](#getting-started)
17 | - :mag: [Supported Devices](#supported-devices)
18 | - :books: [Examples](#examples)
19 | - 🏃 [Migration Guides](#migration-guides)
20 | - 👨💻 [Contributing](#contributing)
21 | - :question: [Issues](#issues)
22 |
23 | ## Rive Overview
24 |
25 | [Rive](https://rive.app) is a real-time interactive design and animation tool that helps teams create and run interactive animations anywhere. Designers and developers use our collaborative editor to create motion graphics that respond to different states and user inputs. Our lightweight open-source runtime libraries allow them to load their animations into apps, games, and websites.
26 |
27 | :house_with_garden: [Homepage](https://rive.app/)
28 |
29 | :blue_book: [General help docs](https://help.rive.app/)
30 |
31 | 🛠 [Resources for building in Rive](https://rive.app/resources/)
32 |
33 | ## Getting Started
34 |
35 | Follow along with the link below for a quick start in getting Rive React Native integrated into your multi-platform applications.
36 |
37 | [Getting Started with Rive in React Native](https://help.rive.app/runtimes/overview/react-native)
38 |
39 | [API documentation](https://help.rive.app/runtimes/overview/react-native/props)
40 |
41 | ## Supported Devices
42 |
43 | Because this runtime library has a dependency on the [Rive Android](https://github.com/rive-app/rive-android) and [Rive iOS](https://github.com/rive-app/rive-ios) runtimes, the supported devices align with each of these dependencies minimum supported devices, as well as the minimum device requirements of the React Native framework.
44 |
45 | - iOS: **14.0+**
46 | - Android:
47 | - Minimum SDK version: **21**
48 | - Target SDK version: **33**
49 |
50 | ## Examples
51 |
52 | Check out the `example/` folder to run an example application using the Rive React Native runtime. It runs on the local build of this library, and showcases a number of ways to use the Rive component and `useRef` hook pattern:
53 |
54 | - Setting a Rive file via a URL, or asset in the Android/iOS projects
55 | - Displaying single or multiple animations / artboards on one component
56 | - Setting up and maniuplating a state machine via inputs
57 | - ...and more!
58 |
59 | Steps:
60 | 1. Run `yarn bootstrap`
61 | 2. cd `example`
62 | 3. `yarn expo run:android` or `yarn expo run:ios`
63 |
64 | iOS:
65 | - You may need to run `pod install` (first time) or `pod update RiveRuntime` (updates to the underlying Rive iOS runtime) in the `example/iOS` folder to get the runtime installed or updated
66 |
67 | ## Migration Guides
68 |
69 | Using an older version of the runtime and need to learn how to upgrade to the latest version? Check out the migration guides below in our help center that help guide you through version bumps; breaking changes and all!
70 |
71 | [Migration guides](https://help.rive.app/runtimes/overview/react-native/migrating-from-v3-to-v4)
72 |
73 | ## Contributing
74 |
75 | We love contributions! Check out our [contributing docs](./CONTRIBUTING.md) to get more details into how to run this project, the examples, and more all locally.
76 |
77 | ## Issues
78 |
79 | Have an issue with using the runtime, or want to suggest a feature/API to help make your development life better? Log an issue in our [issues](https://github.com/rive-app/rive-react-native/issues) tab! You can also browse older issues and discussion threads there to see solutions that may have worked for common problems.
80 |
--------------------------------------------------------------------------------
/android/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | rive-react-native
4 | Project example-android-rive-react-native created by Buildship.
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.buildship.core.gradleprojectbuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.jdt.core.javanature
21 | org.eclipse.buildship.core.gradleprojectnature
22 |
23 |
24 |
25 | 1740025890274
26 |
27 | 30
28 |
29 | org.eclipse.core.resources.regexFilterMatcher
30 | node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | RiveReactNative_kotlinVersion=1.8.10
2 | RiveReactNative_compileSdkVersion=34
3 | RiveReactNative_buildToolsVersion=30.0.3
4 | RiveReactNative_targetSdkVersion=34
5 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-bin.zip
4 | networkTimeout=10000
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
11 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/android/src/main/java/com/rivereactnative/RNAlignment.kt:
--------------------------------------------------------------------------------
1 | package com.rivereactnative
2 |
3 | import app.rive.runtime.kotlin.core.Alignment
4 |
5 | enum class RNAlignment(private val mValue: String) {
6 | TopLeft("topLeft"),
7 | TopCenter("topCenter"),
8 | TopRight("topRight"),
9 | CenterLeft("centerLeft"),
10 | Center("center"),
11 | CenterRight("centerRight"),
12 | BottomLeft("bottomLeft"),
13 | BottomCenter("bottomCenter"),
14 | BottomRight("bottomRight");
15 |
16 | override fun toString(): String {
17 | return mValue
18 | }
19 |
20 | companion object {
21 |
22 | fun mapToRNAlignment(alignment: String): RNAlignment {
23 | return valueOf(values().first() { it.toString() == alignment }.name)
24 | }
25 |
26 | fun mapToRiveAlignment(v: RNAlignment): Alignment {
27 | return when (v) {
28 | TopLeft -> Alignment.TOP_LEFT
29 | TopCenter -> Alignment.TOP_CENTER
30 | TopRight -> Alignment.TOP_RIGHT
31 | CenterLeft -> Alignment.CENTER_LEFT
32 | Center -> Alignment.CENTER
33 | CenterRight -> Alignment.CENTER_RIGHT
34 | BottomLeft -> Alignment.BOTTOM_LEFT
35 | BottomCenter -> Alignment.BOTTOM_CENTER
36 | BottomRight -> Alignment.BOTTOM_RIGHT
37 | else -> throw IllegalStateException("Unsupported Alignment type")
38 | }
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/android/src/main/java/com/rivereactnative/RNDirection.kt:
--------------------------------------------------------------------------------
1 | package com.rivereactnative
2 |
3 | import app.rive.runtime.kotlin.core.Direction
4 |
5 | enum class RNDirection(private val mValue: String) {
6 | Backwards("backwards"),
7 | Auto("auto"),
8 | Forwards("forwards");
9 |
10 | override fun toString(): String {
11 | return mValue
12 | }
13 |
14 | companion object {
15 | fun mapToRNDirection(direction: String): RNDirection {
16 | return valueOf(values().first() { it.toString() == direction }.name)
17 | }
18 |
19 | fun mapToRiveDirection(rnDirection: RNDirection): Direction {
20 | return when (rnDirection) {
21 | Backwards -> Direction.BACKWARDS
22 | Auto -> Direction.AUTO
23 | Forwards -> Direction.FORWARDS
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/android/src/main/java/com/rivereactnative/RNFit.kt:
--------------------------------------------------------------------------------
1 | package com.rivereactnative
2 |
3 | import app.rive.runtime.kotlin.core.Fit
4 |
5 | enum class RNFit(private val mValue: String) {
6 | Cover("cover"),
7 | Contain("contain"),
8 | Fill("fill"),
9 | FitWidth("fitWidth"),
10 | FitHeight("fitHeight"),
11 | None("none"),
12 | ScaleDown("scaleDown"),
13 | Layout("layout");
14 |
15 | override fun toString(): String {
16 | return mValue
17 | }
18 |
19 | companion object {
20 |
21 | fun mapToRNFit(fit: String): RNFit {
22 | return valueOf(values().first() { it.toString() == fit }.name)
23 | }
24 |
25 | fun mapToRiveFit(rnFit: RNFit): Fit {
26 | return when (rnFit) {
27 | Cover -> Fit.COVER
28 | Contain -> Fit.CONTAIN
29 | Fill -> Fit.FILL
30 | FitWidth -> Fit.FIT_WIDTH
31 | FitHeight -> Fit.FIT_HEIGHT
32 | None -> Fit.NONE
33 | ScaleDown -> Fit.SCALE_DOWN
34 | Layout -> Fit.LAYOUT
35 | }
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/android/src/main/java/com/rivereactnative/RNLoopMode.kt:
--------------------------------------------------------------------------------
1 | package com.rivereactnative
2 |
3 | import app.rive.runtime.kotlin.core.Loop as RiveLoop
4 |
5 | enum class RNLoopMode(private val mValue: String) {
6 | OneShot("oneShot"),
7 | Loop("loop"),
8 | PingPong("pingPong"),
9 | Auto("auto");
10 |
11 | override fun toString(): String {
12 | return mValue
13 | }
14 |
15 | companion object {
16 | fun mapToRNLoopMode(loopMode: String): RNLoopMode {
17 | return valueOf(values().first() { it.toString() == loopMode }.name)
18 | }
19 |
20 | fun mapToRNLoopMode(riveLoopMode: RiveLoop): RNLoopMode {
21 | return when (riveLoopMode) {
22 | RiveLoop.ONESHOT -> OneShot
23 | RiveLoop.LOOP -> Loop
24 | RiveLoop.PINGPONG -> PingPong
25 | RiveLoop.AUTO -> Auto
26 | }
27 | }
28 |
29 | fun mapToRiveLoop(rnLoopMode: RNLoopMode): RiveLoop {
30 | return when (rnLoopMode) {
31 | OneShot -> RiveLoop.ONESHOT
32 | Loop -> RiveLoop.LOOP
33 | PingPong -> RiveLoop.PINGPONG
34 | Auto -> RiveLoop.AUTO
35 | }
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/android/src/main/java/com/rivereactnative/RNPropertyType.kt:
--------------------------------------------------------------------------------
1 | package com.rivereactnative
2 |
3 | enum class RNPropertyType(private val mValue: kotlin.String) {
4 | Number("number"),
5 | String("string"),
6 | Boolean("boolean"),
7 | Color("color"),
8 | Trigger("trigger"),
9 | Enum("enum");
10 |
11 | override fun toString(): kotlin.String {
12 | return mValue
13 | }
14 |
15 | companion object {
16 |
17 | fun mapToRNPropertyType(propertyType: kotlin.String): RNPropertyType {
18 | return valueOf(entries.first() { it.toString() == propertyType }.name)
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/android/src/main/java/com/rivereactnative/RNRiveError.kt:
--------------------------------------------------------------------------------
1 | package com.rivereactnative
2 |
3 | import app.rive.runtime.kotlin.core.errors.*
4 |
5 | enum class RNRiveError(private val mValue: String) {
6 | FileNotFound("FileNotFound"),
7 | UnsupportedRuntimeVersion("UnsupportedRuntimeVersion"),
8 | IncorrectRiveFileUrl("IncorrectRiveFileUrl"),
9 | IncorrectAnimationName("IncorrectAnimationName"),
10 | MalformedFile("MalformedFile"),
11 | IncorrectArtboardName("IncorrectArtboardName"),
12 | IncorrectStateMachineName("IncorrectStateMachineName"),
13 | IncorrectStateMachineInput("IncorrectStateMachineInput"),
14 | TextRunNotFoundError("TextRunNotFoundError"),
15 | DataBindingError("DataBindingError");
16 |
17 | var message: String = "Default message"
18 |
19 | override fun toString(): String {
20 | return mValue
21 | }
22 |
23 | companion object {
24 | fun mapToRNRiveError(ex: RiveException): RNRiveError? {
25 | return when (ex) {
26 | is ArtboardException -> {
27 | val err = IncorrectArtboardName
28 | err.message = ex.message!!
29 | return err
30 | }
31 | is UnsupportedRuntimeVersionException -> {
32 | val err = UnsupportedRuntimeVersion
33 | err.message = ex.message!!
34 | return err
35 | }
36 | is MalformedFileException -> {
37 | val err = MalformedFile
38 | err.message = ex.message!!
39 | return err
40 | }
41 | is AnimationException -> {
42 | val err = IncorrectAnimationName
43 | err.message = ex.message!!
44 | return err
45 | }
46 | is StateMachineException -> {
47 | val err = IncorrectStateMachineName
48 | err.message = ex.message!!
49 | return err
50 | }
51 | is StateMachineInputException -> {
52 | val err = IncorrectStateMachineInput
53 | err.message = ex.message!!
54 | return err
55 | }
56 | is TextValueRunException -> {
57 | val err = TextRunNotFoundError
58 | err.message = ex.message!!
59 | return err
60 | }
61 | is ViewModelException -> {
62 | val err = DataBindingError
63 | err.message = ex.message!!
64 | return err;
65 | }
66 | else -> null
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/android/src/main/java/com/rivereactnative/RNRiveRendererType.kt:
--------------------------------------------------------------------------------
1 | package com.rivereactnative
2 |
3 | import app.rive.runtime.kotlin.core.RendererType
4 |
5 | enum class RNRiveRendererType(private val rendererTypeName: String) {
6 | Rive("rive"),
7 | Canvas("canvas");
8 |
9 | override fun toString(): String {
10 | return rendererTypeName
11 | }
12 |
13 | companion object {
14 | fun mapToRNRiveRendererType(rendererType: String): RNRiveRendererType {
15 | return values().first { it.rendererTypeName == rendererType }
16 | }
17 |
18 | fun mapToRiveRendererType(rnRendererType: RNRiveRendererType): RendererType {
19 | return when (rnRendererType) {
20 | Rive -> RendererType.Rive
21 | Canvas -> RendererType.Canvas
22 | }
23 | }
24 | }
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/android/src/main/java/com/rivereactnative/RiveReactNativeModule.kt:
--------------------------------------------------------------------------------
1 | package com.rivereactnative
2 |
3 | import com.facebook.react.bridge.*
4 | import com.facebook.react.uimanager.UIManagerHelper
5 | import com.facebook.react.uimanager.UIManagerModule
6 |
7 | class RiveReactNativeModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
8 | override fun getName() = "RiveReactNativeModule"
9 |
10 | private fun handleState(node: Int, promise: Promise, stateGetter: (RiveReactNativeView) -> T) {
11 | val uiManager = UIManagerHelper.getUIManager(reactApplicationContext, node)
12 | val view = uiManager?.resolveView(node) as? RiveReactNativeView
13 | if (view != null) {
14 | val value = stateGetter(view)
15 | promise.resolve(value)
16 | } else {
17 | promise.reject("VIEW_NOT_FOUND", "Could not find RiveReactNativeView")
18 | }
19 | }
20 |
21 | @ReactMethod
22 | fun getBooleanState(node: Int, inputName: String, promise: Promise) {
23 | handleState(node, promise) { view -> view.getBooleanState(inputName) }
24 | }
25 |
26 | @ReactMethod
27 | fun getNumberState(node: Int, inputName: String, promise: Promise) {
28 | handleState(node, promise) { view -> view.getNumberState(inputName) }
29 | }
30 |
31 | @ReactMethod
32 | fun getBooleanStateAtPath(node: Int, inputName: String, path: String, promise: Promise) {
33 | handleState(node, promise) { view -> view.getBooleanStateAtPath(inputName, path) }
34 | }
35 |
36 | @ReactMethod
37 | fun getNumberStateAtPath(node: Int, inputName: String, path: String, promise: Promise) {
38 | handleState(node, promise) { view -> view.getNumberStateAtPath(inputName, path) }
39 | }
40 |
41 | @ReactMethod
42 | fun addListener(type: String?) {
43 | // Keep: Required for RN built in Event Emitter Calls.
44 | }
45 |
46 | @ReactMethod
47 | fun removeListeners(type: Int?) {
48 | // Keep: Required for RN built in Event Emitter Calls.
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/android/src/main/java/com/rivereactnative/RiveReactNativePackage.kt:
--------------------------------------------------------------------------------
1 | package com.rivereactnative
2 |
3 | import com.facebook.react.ReactPackage
4 | import com.facebook.react.bridge.NativeModule
5 | import com.facebook.react.bridge.ReactApplicationContext
6 | import com.facebook.react.uimanager.ViewManager
7 |
8 |
9 | class RiveReactNativePackage : ReactPackage {
10 | override fun createNativeModules(
11 | reactContext: ReactApplicationContext
12 | ): MutableList = listOf(RiveReactNativeRendererModule(reactContext), RiveReactNativeModule(reactContext)).toMutableList()
13 |
14 | override fun createViewManagers(reactContext: ReactApplicationContext): List> {
15 | return listOf(RiveReactNativeViewManager())
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/android/src/main/java/com/rivereactnative/RiveReactNativeRendererModule.kt:
--------------------------------------------------------------------------------
1 | package com.rivereactnative
2 |
3 | import com.facebook.react.bridge.ReactApplicationContext
4 | import com.facebook.react.bridge.ReactContextBaseJavaModule
5 | import com.facebook.react.bridge.ReactMethod
6 | import app.rive.runtime.kotlin.core.Rive
7 |
8 | class RiveReactNativeRendererModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
9 | override fun getName() = "RiveReactNativeRendererModule"
10 |
11 | @ReactMethod fun defaultRenderer(iosRenderer: String, androidRenderer: String) {
12 | val rnRendererType = RNRiveRendererType.mapToRNRiveRendererType(androidRenderer);
13 | val rendererType = RNRiveRendererType.mapToRiveRendererType(rnRendererType);
14 | Rive.init(reactApplicationContext, defaultRenderer = rendererType)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['module:metro-react-native-babel-preset'],
3 | };
4 |
--------------------------------------------------------------------------------
/docs/types.md:
--------------------------------------------------------------------------------
1 | # Types and enums
2 |
3 | ## Fit
4 |
5 | ```ts
6 | export enum Fit {
7 | Cover = 'cover',
8 | Contain = 'contain',
9 | Fill = 'fill',
10 | FitWidth = 'fitWidth',
11 | FitHeight = 'fitHeight',
12 | None = 'none',
13 | ScaleDown = 'scaleDown',
14 | Layout = 'layout',
15 | }
16 | ```
17 |
18 | ## Alignment
19 |
20 | ```ts
21 | export enum Alignment {
22 | TopLeft = 'topLeft',
23 | TopCenter = 'topCenter',
24 | TopRight = 'topRight',
25 | CenterLeft = 'centerLeft',
26 | Center = 'center',
27 | CenterRight = 'centerRight',
28 | BottomLeft = 'bottomLeft',
29 | BottomCenter = 'bottomCenter',
30 | BottomRight = 'bottomRight',
31 | }
32 | ```
33 |
34 | ## LoopMode
35 |
36 | ```ts
37 | export enum LoopMode {
38 | OneShot = 'oneShot',
39 | Loop = 'loop',
40 | PingPong = 'pingPong',
41 | Auto = 'auto',
42 | }
43 | ```
44 |
45 | ## Direction
46 |
47 | ```ts
48 | export enum Direction {
49 | Backwards = 'backwards',
50 | Auto = 'auto',
51 | Forwards = 'forwards',
52 | }
53 | ```
54 |
55 | ## RNRiveError
56 |
57 | ```ts
58 | export type RNRiveError = {
59 | message: string;
60 | type: RNRiveErrorType;
61 | };
62 | ```
63 |
64 | ## RnRiveErrorType
65 |
66 | ```ts
67 | export enum RNRiveErrorType {
68 | FileNotFound = 'FileNotFound',
69 | UnsupportedRuntimeVersion = 'UnsupportedRuntimeVersion',
70 | IncorrectRiveFileUrl = 'IncorrectRiveFileUrl',
71 | IncorrectAnimationName = 'IncorrectAnimationName',
72 | MalformedFile = 'MalformedFile',
73 | IncorrectArtboardName = 'IncorrectArtboardName',
74 | IncorrectStateMachineName = 'IncorrectStateMachineName',
75 | IncorrectStateMachineInput = 'IncorrectStateMachineInput',
76 | }
77 | ```
78 |
--------------------------------------------------------------------------------
/docs/usage-guide.md:
--------------------------------------------------------------------------------
1 | # Rive component usage guide
2 |
3 | Rive component allows setup and interaction with the native implementation of the Rive runtime on iOS and Android.
4 |
5 | ## 1. Installing dependencies
6 |
7 | To install the SDK run the following command in your terminal:
8 |
9 | ```sh
10 | yarn add rive-react-native
11 | ```
12 |
13 | For iOS you will have to run `pod install` inside `ios` directory in order to install needed native dependencies. Android won't require any additional steps.
14 |
15 | ## 2. Rendering `Rive` component in your app
16 |
17 | To render the animation in your app just use [`Rive`](./rive-react-native-reference.md) component wherever you need it.
18 |
19 | ```jsx
20 | import Rive from 'rive-react-native';
21 |
22 | export default function App() {
23 | return (
24 |
25 |
26 |
27 | );
28 | }
29 | ```
30 |
31 | ## 3. Setting `resourceName` and other useful props
32 |
33 | To load and play the animation use[`resourceName`](./rive-react-native-reference.md#resourceName-optional) prop.
34 | In order to play the animation directly after loading [`autoplay`](./rive-react-native-reference.md#autoplay-optional) prop can be used.
35 |
36 | ```jsx
37 |
38 | ```
39 |
40 | You can also set the url as an animation source or control its layout/placement using component props. The whole list of available props can be found [here](rive-react-native-reference.md#props).
41 |
42 | ## 4. Triggering play/pause manually
43 |
44 | In addition to configuring the rive animation view declaratively there is also a way to trigger some actions imperatively using component's ref.
45 |
46 | On of those actions are `play` and `pause` which can be used to manually pause and start the animation.
47 |
48 | ```tsx
49 | import Rive, { RiveRef } from 'rive-react-native'
50 |
51 | export default function App() {
52 | const riveRef = React.useRef(null);
53 |
54 | const handlePlayPress = () => {
55 | riveRef?.current?.play();
56 | };
57 |
58 | return (
59 |
60 |
64 |
65 |
67 | );
68 | }
69 | ```
70 |
71 | The list of all available methods can be found [here](./rive-react-native-reference.md#ref-methods).
72 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
2 |
3 | # dependencies
4 | node_modules/
5 |
6 | # Expo
7 | .expo/
8 | dist/
9 | web-build/
10 | expo-env.d.ts
11 |
12 | # Native
13 | *.orig.*
14 | *.jks
15 | *.p8
16 | *.p12
17 | *.key
18 | *.mobileprovision
19 |
20 | # Metro
21 | .metro-health-check*
22 |
23 | # debug
24 | npm-debug.*
25 | yarn-debug.*
26 | yarn-error.*
27 |
28 | # macOS
29 | .DS_Store
30 | *.pem
31 |
32 | # local env files
33 | .env*.local
34 |
35 | # typescript
36 | *.tsbuildinfo
37 |
38 | app-example
39 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to your Expo app 👋
2 |
3 | This is an [Expo](https://expo.dev) project created with [`create-expo-app`](https://www.npmjs.com/package/create-expo-app).
4 |
5 | ## Get started
6 |
7 | 1. Install dependencies
8 |
9 | ```bash
10 | npm install
11 | ```
12 |
13 | 2. Start the app
14 |
15 | ```bash
16 | npx expo start
17 | ```
18 |
19 | In the output, you'll find options to open the app in a
20 |
21 | - [development build](https://docs.expo.dev/develop/development-builds/introduction/)
22 | - [Android emulator](https://docs.expo.dev/workflow/android-studio-emulator/)
23 | - [iOS simulator](https://docs.expo.dev/workflow/ios-simulator/)
24 | - [Expo Go](https://expo.dev/go), a limited sandbox for trying out app development with Expo
25 |
26 | You can start developing by editing the files inside the **app** directory. This project uses [file-based routing](https://docs.expo.dev/router/introduction).
27 |
28 | ## Get a fresh project
29 |
30 | When you're ready, run:
31 |
32 | ```bash
33 | npm run reset-project
34 | ```
35 |
36 | This command will move the starter code to the **app-example** directory and create a blank **app** directory where you can start developing.
37 |
38 | ## Learn more
39 |
40 | To learn more about developing your project with Expo, look at the following resources:
41 |
42 | - [Expo documentation](https://docs.expo.dev/): Learn fundamentals, or go into advanced topics with our [guides](https://docs.expo.dev/guides).
43 | - [Learn Expo tutorial](https://docs.expo.dev/tutorial/introduction/): Follow a step-by-step tutorial where you'll create a project that runs on Android, iOS, and the web.
44 |
45 | ## Join the community
46 |
47 | Join our community of developers creating universal apps.
48 |
49 | - [Expo on GitHub](https://github.com/expo/expo): View our open source platform and contribute.
50 | - [Discord community](https://chat.expo.dev): Chat with Expo users and ask questions.
51 |
--------------------------------------------------------------------------------
/example/android/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Android/IntelliJ
6 | #
7 | build/
8 | .idea
9 | .gradle
10 | local.properties
11 | *.iml
12 | *.hprof
13 | .cxx/
14 |
15 | # Bundle artifacts
16 | *.jsbundle
17 |
--------------------------------------------------------------------------------
/example/android/app/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/debug.keystore
--------------------------------------------------------------------------------
/example/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # react-native-reanimated
11 | -keep class com.swmansion.reanimated.** { *; }
12 | -keep class com.facebook.react.turbomodule.** { *; }
13 |
14 | # Add any project specific keep options here:
15 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/anonymous/example/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.anonymous.example
2 | import expo.modules.splashscreen.SplashScreenManager
3 |
4 | import android.os.Build
5 | import android.os.Bundle
6 |
7 | import com.facebook.react.ReactActivity
8 | import com.facebook.react.ReactActivityDelegate
9 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
10 | import com.facebook.react.defaults.DefaultReactActivityDelegate
11 |
12 | import expo.modules.ReactActivityDelegateWrapper
13 |
14 | class MainActivity : ReactActivity() {
15 | override fun onCreate(savedInstanceState: Bundle?) {
16 | // Set the theme to AppTheme BEFORE onCreate to support
17 | // coloring the background, status bar, and navigation bar.
18 | // This is required for expo-splash-screen.
19 | // setTheme(R.style.AppTheme);
20 | // @generated begin expo-splashscreen - expo prebuild (DO NOT MODIFY) sync-f3ff59a738c56c9a6119210cb55f0b613eb8b6af
21 | SplashScreenManager.registerOnActivity(this)
22 | // @generated end expo-splashscreen
23 | super.onCreate(null)
24 | }
25 |
26 | /**
27 | * Returns the name of the main component registered from JavaScript. This is used to schedule
28 | * rendering of the component.
29 | */
30 | override fun getMainComponentName(): String = "main"
31 |
32 | /**
33 | * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
34 | * which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
35 | */
36 | override fun createReactActivityDelegate(): ReactActivityDelegate {
37 | return ReactActivityDelegateWrapper(
38 | this,
39 | BuildConfig.IS_NEW_ARCHITECTURE_ENABLED,
40 | object : DefaultReactActivityDelegate(
41 | this,
42 | mainComponentName,
43 | fabricEnabled
44 | ){})
45 | }
46 |
47 | /**
48 | * Align the back button behavior with Android S
49 | * where moving root activities to background instead of finishing activities.
50 | * @see onBackPressed
51 | */
52 | override fun invokeDefaultOnBackPressed() {
53 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
54 | if (!moveTaskToBack(false)) {
55 | // For non-root activities, use the default implementation to finish them.
56 | super.invokeDefaultOnBackPressed()
57 | }
58 | return
59 | }
60 |
61 | // Use the default back button implementation on Android S
62 | // because it's doing more than [Activity.moveTaskToBack] in fact.
63 | super.invokeDefaultOnBackPressed()
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/anonymous/example/MainApplication.kt:
--------------------------------------------------------------------------------
1 | package com.anonymous.example
2 |
3 | import android.app.Application
4 | import android.content.res.Configuration
5 |
6 | import com.facebook.react.PackageList
7 | import com.facebook.react.ReactApplication
8 | import com.facebook.react.ReactNativeHost
9 | import com.facebook.react.ReactPackage
10 | import com.facebook.react.ReactHost
11 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
12 | import com.facebook.react.defaults.DefaultReactNativeHost
13 | import com.facebook.react.soloader.OpenSourceMergedSoMapping
14 | import com.facebook.soloader.SoLoader
15 |
16 | import expo.modules.ApplicationLifecycleDispatcher
17 | import expo.modules.ReactNativeHostWrapper
18 |
19 | class MainApplication : Application(), ReactApplication {
20 |
21 | override val reactNativeHost: ReactNativeHost = ReactNativeHostWrapper(
22 | this,
23 | object : DefaultReactNativeHost(this) {
24 | override fun getPackages(): List {
25 | val packages = PackageList(this).packages
26 | // Packages that cannot be autolinked yet can be added manually here, for example:
27 | // packages.add(new MyReactNativePackage());
28 | return packages
29 | }
30 |
31 | override fun getJSMainModuleName(): String = ".expo/.virtual-metro-entry"
32 |
33 | override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
34 |
35 | override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
36 | override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
37 | }
38 | )
39 |
40 | override val reactHost: ReactHost
41 | get() = ReactNativeHostWrapper.createReactHost(applicationContext, reactNativeHost)
42 |
43 | override fun onCreate() {
44 | super.onCreate()
45 | SoLoader.init(this, OpenSourceMergedSoMapping)
46 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
47 | // If you opted-in for the New Architecture, we load the native entry point for this app.
48 | load()
49 | }
50 | ApplicationLifecycleDispatcher.onApplicationCreate(this)
51 | }
52 |
53 | override fun onConfigurationChanged(newConfig: Configuration) {
54 | super.onConfigurationChanged(newConfig)
55 | ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig)
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/Inter-594377.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/Inter-594377.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable-hdpi/splashscreen_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/drawable-hdpi/splashscreen_logo.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable-mdpi/splashscreen_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/drawable-mdpi/splashscreen_logo.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable-xhdpi/splashscreen_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/drawable-xhdpi/splashscreen_logo.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable-xxhdpi/splashscreen_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/drawable-xxhdpi/splashscreen_logo.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable-xxxhdpi/splashscreen_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/drawable-xxxhdpi/splashscreen_logo.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/rn_edit_text_material.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
22 |
23 |
24 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/artboard_animations.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/artboard_animations.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/avatars.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/avatars.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/bird.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/bird.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/constrained.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/constrained.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/flying_car.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/flying_car.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/hello_world_nested.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/hello_world_nested.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/hello_world_text.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/hello_world_text.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/hero_editor.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/hero_editor.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/layout_test.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/layout_test.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/nested_inputs.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/nested_inputs.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/nested_menu.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/nested_menu.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/out_of_band.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/out_of_band.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/rainy.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/rainy.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/rating.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/rating.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/rewards.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/rewards.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/skills.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/skills.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/skills_listener.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/skills_listener.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/truck_v7.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/truck_v7.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/two_bone_ik.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/two_bone_ik.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/ui_swipe_left_to_delete.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/ui_swipe_left_to_delete.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/raw/v6_file.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/raw/v6_file.riv
--------------------------------------------------------------------------------
/example/android/app/src/main/res/referenced-image-2929282.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/referenced-image-2929282.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/referenced_audio-2929340.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/app/src/main/res/referenced_audio-2929340.wav
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values-night/colors.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 | #ffffff
3 | #ffffff
4 | #023c69
5 | #ffffff
6 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | example
3 | automatic
4 | contain
5 | false
6 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
14 |
19 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext {
5 | buildToolsVersion = findProperty('android.buildToolsVersion') ?: '35.0.0'
6 | minSdkVersion = Integer.parseInt(findProperty('android.minSdkVersion') ?: '24')
7 | compileSdkVersion = Integer.parseInt(findProperty('android.compileSdkVersion') ?: '35')
8 | targetSdkVersion = Integer.parseInt(findProperty('android.targetSdkVersion') ?: '34')
9 | kotlinVersion = findProperty('android.kotlinVersion') ?: '1.9.25'
10 |
11 | ndkVersion = "26.1.10909125"
12 | }
13 | repositories {
14 | google()
15 | mavenCentral()
16 | }
17 | dependencies {
18 | classpath('com.android.tools.build:gradle')
19 | classpath('com.facebook.react:react-native-gradle-plugin')
20 | classpath('org.jetbrains.kotlin:kotlin-gradle-plugin')
21 | }
22 | }
23 |
24 | apply plugin: "com.facebook.react.rootproject"
25 |
26 | allprojects {
27 | repositories {
28 | maven {
29 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
30 | url(new File(['node', '--print', "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), '../android'))
31 | }
32 | maven {
33 | // Android JSC is installed from npm
34 | url(new File(['node', '--print', "require.resolve('jsc-android/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim(), '../dist'))
35 | }
36 |
37 | google()
38 | mavenCentral()
39 | maven { url 'https://www.jitpack.io' }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m
13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | # AndroidX package structure to make it clearer which packages are bundled with the
21 | # Android operating system, and which are packaged with your app's APK
22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
23 | android.useAndroidX=true
24 |
25 | # Enable AAPT2 PNG crunching
26 | android.enablePngCrunchInReleaseBuilds=true
27 |
28 | # Use this property to specify which architecture you want to build.
29 | # You can also override it from the CLI using
30 | # ./gradlew -PreactNativeArchitectures=x86_64
31 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
32 |
33 | # Use this property to enable support to the new architecture.
34 | # This will allow you to use TurboModules and the Fabric render in
35 | # your application. You should enable this flag either if you want
36 | # to write custom TurboModules/Fabric components OR use libraries that
37 | # are providing them.
38 | newArchEnabled=true
39 |
40 | # Use this property to enable or disable the Hermes JS engine.
41 | # If set to false, you will be using JSC instead.
42 | hermesEnabled=true
43 |
44 | # Enable GIF support in React Native images (~200 B increase)
45 | expo.gif.enabled=true
46 | # Enable webp support in React Native images (~85 KB increase)
47 | expo.webp.enabled=true
48 | # Enable animated webp support (~3.4 MB increase)
49 | # Disabled by default because iOS doesn't support animated webp
50 | expo.webp.animated=false
51 |
52 | # Enable network inspector
53 | EX_DEV_CLIENT_NETWORK_INSPECTOR=true
54 |
55 | # Use legacy packaging to compress native libraries in the resulting APK.
56 | expo.useLegacyPackaging=false
57 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/example/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
74 |
75 |
76 | @rem Execute Gradle
77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
78 |
79 | :end
80 | @rem End local scope for the variables with windows NT shell
81 | if %ERRORLEVEL% equ 0 goto mainEnd
82 |
83 | :fail
84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
85 | rem the _cmd.exe /c_ return code!
86 | set EXIT_CODE=%ERRORLEVEL%
87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
89 | exit /b %EXIT_CODE%
90 |
91 | :mainEnd
92 | if "%OS%"=="Windows_NT" endlocal
93 |
94 | :omega
95 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | includeBuild(new File(["node", "--print", "require.resolve('@react-native/gradle-plugin/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile().toString())
3 | }
4 | plugins { id("com.facebook.react.settings") }
5 |
6 | extensions.configure(com.facebook.react.ReactSettingsExtension) { ex ->
7 | if (System.getenv('EXPO_USE_COMMUNITY_AUTOLINKING') == '1') {
8 | ex.autolinkLibrariesFromCommand()
9 | } else {
10 | def command = [
11 | 'node',
12 | '--no-warnings',
13 | '--eval',
14 | 'require(require.resolve(\'expo-modules-autolinking\', { paths: [require.resolve(\'expo/package.json\')] }))(process.argv.slice(1))',
15 | 'react-native-config',
16 | '--json',
17 | '--platform',
18 | 'android'
19 | ].toList()
20 | ex.autolinkLibrariesFromCommand(command)
21 | }
22 | }
23 |
24 | rootProject.name = 'example'
25 |
26 | dependencyResolutionManagement {
27 | versionCatalogs {
28 | reactAndroidLibs {
29 | from(files(new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), "../gradle/libs.versions.toml")))
30 | }
31 | }
32 | }
33 |
34 | apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle");
35 | useExpoModules()
36 |
37 | include ':app'
38 | includeBuild(new File(["node", "--print", "require.resolve('@react-native/gradle-plugin/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile())
39 |
--------------------------------------------------------------------------------
/example/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "expo": {
3 | "name": "example",
4 | "slug": "example",
5 | "version": "1.0.0",
6 | "orientation": "portrait",
7 | "icon": "./assets/images/icon.png",
8 | "scheme": "myapp",
9 | "userInterfaceStyle": "automatic",
10 | "newArchEnabled": true,
11 | "ios": {
12 | "supportsTablet": true,
13 | "bundleIdentifier": "com.anonymous.example"
14 | },
15 | "android": {
16 | "adaptiveIcon": {
17 | "foregroundImage": "./assets/images/adaptive-icon.png",
18 | "backgroundColor": "#ffffff"
19 | },
20 | "package": "com.anonymous.example"
21 | },
22 | "web": {
23 | "bundler": "metro",
24 | "output": "static",
25 | "favicon": "./assets/images/favicon.png"
26 | },
27 | "plugins": [
28 | "expo-router",
29 | [
30 | "expo-splash-screen",
31 | {
32 | "image": "./assets/images/splash-icon.png",
33 | "imageWidth": 200,
34 | "resizeMode": "contain",
35 | "backgroundColor": "#ffffff"
36 | }
37 | ]
38 | ],
39 | "experiments": {
40 | "typedRoutes": true
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/example/app/(examples)/DynamicText.tsx:
--------------------------------------------------------------------------------
1 | import { useRef } from 'react';
2 |
3 | import { SafeAreaView, ScrollView, StyleSheet } from 'react-native';
4 | import { TextInput } from 'react-native-gesture-handler';
5 | import Rive, {
6 | Alignment,
7 | Fit,
8 | RNRiveError,
9 | RNRiveErrorType,
10 | RiveRef,
11 | } from 'rive-react-native';
12 |
13 | export default function DynamicText() {
14 | const riveRef = useRef(null);
15 |
16 | const handleInputChange = (e: string) => {
17 | // Set the TextRun value of the 'name' TextRun
18 | // The name must exist else an error will be thrown
19 | // See: https://help.rive.app/runtimes/text
20 | riveRef.current?.setTextRunValue('name', e);
21 | };
22 |
23 | return (
24 |
25 |
26 | {
33 | switch (riveError.type) {
34 | case RNRiveErrorType.TextRunNotFoundError: {
35 | console.log(`${riveError.message}`);
36 | return;
37 | }
38 | default:
39 | console.log('Unhandled error');
40 | return;
41 | }
42 | }}
43 | />
44 |
49 |
50 |
51 | );
52 | }
53 |
54 | const styles = StyleSheet.create({
55 | safeAreaViewContainer: {
56 | flex: 1,
57 | },
58 | input: {
59 | height: 40,
60 | margin: 12,
61 | borderWidth: 1,
62 | padding: 10,
63 | },
64 | animation: {
65 | width: '100%',
66 | height: 100,
67 | },
68 | });
69 |
--------------------------------------------------------------------------------
/example/app/(examples)/ErrorHandledManually.tsx:
--------------------------------------------------------------------------------
1 | import { SafeAreaView, ScrollView, StyleSheet } from 'react-native';
2 | import Rive, {
3 | Alignment,
4 | Fit,
5 | RNRiveError,
6 | RNRiveErrorType,
7 | } from 'rive-react-native';
8 |
9 | export default function ErrorHandledManually() {
10 | return (
11 |
12 |
13 | {
20 | switch (riveError.type) {
21 | case RNRiveErrorType.IncorrectRiveFileUrl: {
22 | console.log(`${riveError.message}`);
23 | return;
24 | }
25 | case RNRiveErrorType.MalformedFile: {
26 | console.log('Malformed File');
27 | return;
28 | }
29 | case RNRiveErrorType.FileNotFound: {
30 | console.log('File not found');
31 | return;
32 | }
33 | case RNRiveErrorType.IncorrectArtboardName: {
34 | console.log('IncorrectAnimationName');
35 | return;
36 | }
37 | case RNRiveErrorType.UnsupportedRuntimeVersion: {
38 | console.log('Runtime version unsupported');
39 | return;
40 | }
41 | case RNRiveErrorType.IncorrectStateMachineName: {
42 | console.log(`${riveError.message}`);
43 | return;
44 | }
45 | case RNRiveErrorType.IncorrectStateMachineInput: {
46 | console.log(`${riveError.message}`);
47 | return;
48 | }
49 | default:
50 | return;
51 | }
52 | }}
53 | />
54 |
55 |
56 | );
57 | }
58 |
59 | const styles = StyleSheet.create({
60 | safeAreaViewContainer: {
61 | flex: 1,
62 | },
63 | container: {
64 | flexGrow: 1,
65 | alignItems: 'center',
66 | justifyContent: 'center',
67 | },
68 | animation: {
69 | width: '100%',
70 | height: 600,
71 | },
72 | });
73 |
--------------------------------------------------------------------------------
/example/app/(examples)/ErrorNotHandled.tsx:
--------------------------------------------------------------------------------
1 | import { SafeAreaView, ScrollView, StyleSheet } from 'react-native';
2 | import Rive, { Alignment, Fit } from 'rive-react-native';
3 |
4 | const resourceName = 'v6_file'; // unsupported Rive runtime
5 |
6 | export default function ErrorNotHandled() {
7 | return (
8 |
9 |
10 |
16 |
17 |
18 | );
19 | }
20 |
21 | const styles = StyleSheet.create({
22 | safeAreaViewContainer: {
23 | flex: 1,
24 | },
25 | container: {
26 | flexGrow: 1,
27 | alignItems: 'center',
28 | justifyContent: 'center',
29 | },
30 | animation: {
31 | width: '100%',
32 | height: 600,
33 | },
34 | });
35 |
--------------------------------------------------------------------------------
/example/app/(examples)/Events.tsx:
--------------------------------------------------------------------------------
1 | import { useRef, useState } from 'react';
2 | import {
3 | SafeAreaView,
4 | ScrollView,
5 | StyleSheet,
6 | Linking,
7 | Text,
8 | } from 'react-native';
9 | import Rive, { Fit, RiveOpenUrlEvent, RiveRef } from 'rive-react-native';
10 |
11 | export default function Events() {
12 | const riveRef = useRef(null);
13 | const [eventMessage, setEventMessage] = useState('');
14 |
15 | return (
16 |
17 |
18 | {
25 | const eventProperties = event.properties;
26 | if (eventProperties?.message) {
27 | setEventMessage(eventProperties.message as string);
28 | }
29 | if ('url' in event) {
30 | Linking.openURL((event as RiveOpenUrlEvent).url || '');
31 | }
32 | }}
33 | resourceName={'rating'}
34 | />
35 | {eventMessage}
36 |
37 |
38 | );
39 | }
40 |
41 | const styles = StyleSheet.create({
42 | safeAreaViewContainer: {
43 | flex: 1,
44 | },
45 | container: {
46 | flexGrow: 1,
47 | alignItems: 'center',
48 | justifyContent: 'center',
49 | marginBottom: 150,
50 | },
51 | box: {
52 | width: '100%',
53 | height: 500,
54 | marginVertical: 20,
55 | },
56 | });
57 |
--------------------------------------------------------------------------------
/example/app/(examples)/Http.tsx:
--------------------------------------------------------------------------------
1 | import { SafeAreaView, StyleSheet, ScrollView } from 'react-native';
2 | import Rive from 'rive-react-native';
3 |
4 | const url =
5 | 'https://public.rive.app/community/runtime-files/2195-4346-avatar-pack-use-case.riv';
6 |
7 | export default function Http() {
8 | return (
9 |
10 |
11 | {
18 | console.log('PLAY: NAME + SM', name, isSM);
19 | }}
20 | onStop={(name, isSM) => {
21 | console.log('STOP: NAME + SM', name, isSM);
22 | }}
23 | onPause={(name, isSM) => {
24 | console.log('PAUSE: NAME + SM', name, isSM);
25 | }}
26 | />
27 |
28 |
29 | );
30 | }
31 |
32 | const styles = StyleSheet.create({
33 | safeAreaViewContainer: {
34 | flex: 1,
35 | },
36 | container: {
37 | flexGrow: 1,
38 | alignItems: 'center',
39 | justifyContent: 'center',
40 | marginBottom: 150,
41 | },
42 | animation: {
43 | width: '100%',
44 | height: 400,
45 | marginVertical: 20,
46 | },
47 | });
48 |
--------------------------------------------------------------------------------
/example/app/(examples)/Layout.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SafeAreaView, StyleSheet, ScrollView, View } from 'react-native';
3 | import Rive, { Alignment, Fit } from 'rive-react-native';
4 | import { isEnumKey } from '../../constants/typesPredicates';
5 | import { Picker } from '@react-native-picker/picker';
6 |
7 | const resourceName = 'truck_v7';
8 |
9 | export default function Layout() {
10 | const [fit, setFit] = React.useState(Fit.Cover);
11 | const [alignment, setAlignment] = React.useState(Alignment.TopCenter);
12 |
13 | return (
14 |
15 |
22 |
23 |
24 |
25 | setFit(value)}
28 | mode={'dropdown'}
29 | style={styles.picker}
30 | >
31 | {Object.keys(Fit).map((key) =>
32 | isEnumKey(Fit, key) ? (
33 |
34 | ) : null
35 | )}
36 |
37 |
38 |
39 | setAlignment(value)}
42 | mode={'dropdown'}
43 | style={styles.picker}
44 | >
45 | {Object.keys(Alignment).map((key) =>
46 | isEnumKey(Alignment, key) ? (
47 |
48 | ) : null
49 | )}
50 |
51 |
52 |
53 |
54 |
55 | );
56 | }
57 |
58 | const styles = StyleSheet.create({
59 | safeAreaViewContainer: {
60 | flex: 1,
61 | },
62 | container: {
63 | flexGrow: 1,
64 | alignItems: 'center',
65 | justifyContent: 'flex-start',
66 | },
67 | animation: {
68 | width: '100%',
69 | height: 300,
70 | },
71 | picker: {
72 | flex: 1,
73 | width: '100%',
74 | },
75 | pickerWrapper: {
76 | borderWidth: 1,
77 | borderColor: 'black',
78 | borderRadius: 5,
79 | alignItems: 'center',
80 | margin: 16,
81 | },
82 | pickersWrapper: {
83 | flex: 1,
84 | padding: 16,
85 | alignSelf: 'stretch',
86 | },
87 | });
88 |
--------------------------------------------------------------------------------
/example/app/(examples)/MeshExample.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { Button, SafeAreaView, StyleSheet, ScrollView } from 'react-native';
3 | import Rive, { RiveRef } from 'rive-react-native';
4 |
5 | const url =
6 | 'https://public.uat.rive.app/community/runtime-files/148-325-tape.riv';
7 |
8 | const STATE_MACHINE_NAME = 'State Machine 1';
9 | export default function MeshExample() {
10 | const riveRef = React.useRef(null);
11 | const [isHovered, setIsHovered] = React.useState(true);
12 | return (
13 |
14 |
15 |
34 |
35 | );
36 | }
37 |
38 | const styles = StyleSheet.create({
39 | safeAreaViewContainer: {
40 | flex: 1,
41 | },
42 | container: {
43 | flexGrow: 1,
44 | alignItems: 'center',
45 | justifyContent: 'center',
46 | marginBottom: 150,
47 | },
48 | animation: {
49 | width: '100%',
50 | height: 400,
51 | marginVertical: 20,
52 | },
53 | });
54 |
--------------------------------------------------------------------------------
/example/app/(examples)/MultipleArtboards.tsx:
--------------------------------------------------------------------------------
1 | import { SafeAreaView, StyleSheet, ScrollView, Text } from 'react-native';
2 | import Rive, { Fit } from 'rive-react-native';
3 |
4 | export default function MultipleArtboards() {
5 | return (
6 |
7 |
8 | Avatar 1
9 |
16 |
17 | Avatar 2
18 |
25 |
26 | Avatar 3
27 |
34 |
35 | All Avatars
36 |
43 |
44 |
45 | );
46 | }
47 |
48 | const styles = StyleSheet.create({
49 | safeAreaViewContainer: {
50 | flex: 1,
51 | },
52 | container: {
53 | flexGrow: 1,
54 | alignItems: 'center',
55 | justifyContent: 'center',
56 | marginBottom: 150,
57 | paddingTop: 32,
58 | },
59 | animation: {
60 | width: '100%',
61 | height: 300,
62 | marginTop: 16,
63 | marginBottom: 32,
64 | },
65 | });
66 |
--------------------------------------------------------------------------------
/example/app/(examples)/NestedDynamicText.tsx:
--------------------------------------------------------------------------------
1 | import { useRef } from 'react';
2 |
3 | import { SafeAreaView, ScrollView, StyleSheet } from 'react-native';
4 | import { TextInput } from 'react-native-gesture-handler';
5 | import Rive, {
6 | Alignment,
7 | Fit,
8 | RNRiveError,
9 | RNRiveErrorType,
10 | RiveRef,
11 | } from 'rive-react-native';
12 |
13 | export default function NestedDynamicText() {
14 | const riveRef = useRef(null);
15 |
16 | const handleInputChange = (e: string) => {
17 | // Set the TextRun value of the 'name' TextRun
18 | // The name must exist else an error will be thrown
19 | // See: https://help.rive.app/runtimes/text
20 | riveRef.current?.setTextRunValue('Run A', e);
21 | // Set the TextRun value of the 'Run B' TextRun in nested Artboard 2.
22 | riveRef.current?.setTextRunValueAtPath('Run B', e, 'Artboard 2');
23 | };
24 |
25 | return (
26 |
27 |
28 | {
35 | switch (riveError.type) {
36 | case RNRiveErrorType.TextRunNotFoundError: {
37 | console.log(`${riveError.message}`);
38 | return;
39 | }
40 | default:
41 | console.log('Unhandled error');
42 | return;
43 | }
44 | }}
45 | />
46 |
51 |
52 |
53 | );
54 | }
55 |
56 | const styles = StyleSheet.create({
57 | safeAreaViewContainer: {
58 | flex: 1,
59 | },
60 | input: {
61 | height: 40,
62 | margin: 12,
63 | borderWidth: 1,
64 | padding: 10,
65 | },
66 | animation: {
67 | width: '100%',
68 | height: 100,
69 | },
70 | });
71 |
--------------------------------------------------------------------------------
/example/app/(examples)/NestedInputs.tsx:
--------------------------------------------------------------------------------
1 | import { useRef } from 'react';
2 | import { SafeAreaView, ScrollView, StyleSheet } from 'react-native';
3 | import { Button } from 'react-native-paper';
4 | import Rive, { Alignment, Fit, RiveRef } from 'rive-react-native';
5 |
6 | export default function NestedInputs() {
7 | const riveRef = useRef(null);
8 |
9 | return (
10 |
11 |
12 |
28 |
35 |
52 |
62 |
63 |
64 | );
65 | }
66 |
67 | const styles = StyleSheet.create({
68 | safeAreaViewContainer: {
69 | flex: 1,
70 | },
71 | container: {
72 | flexGrow: 1,
73 | width: '100%',
74 | height: '50%',
75 | },
76 | animation: {
77 | width: '100%',
78 | height: '50%',
79 | },
80 | });
81 |
--------------------------------------------------------------------------------
/example/app/(examples)/OutOfBandAssets.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SafeAreaView, ScrollView, StyleSheet, View } from 'react-native';
3 | import Rive, { Fit, RNRiveError } from 'rive-react-native';
4 | import { Picker } from '@react-native-picker/picker';
5 |
6 | export default function StateMachine() {
7 | const [uri, setUri] = React.useState('https://picsum.photos/id/372/500/500');
8 |
9 | return (
10 |
11 | {
57 | console.log(riveError);
58 | }}
59 | />
60 | {/*
61 | Load in an external asset from a URL, or bundled asset on the native
62 | platform, or as a source loaded directly from JavaScript.
63 | */}
64 |
65 |
66 |
67 | setUri(value)}
70 | mode={'dropdown'}
71 | style={styles.picker}
72 | >
73 | {[
74 | 'https://picsum.photos/id/372/500/500',
75 | 'https://picsum.photos/id/373/500/500',
76 | ].map((key) => (
77 |
78 | ))}
79 |
80 |
81 |
82 |
83 |
84 | );
85 | }
86 |
87 | const styles = StyleSheet.create({
88 | safeAreaViewContainer: {
89 | flex: 1,
90 | },
91 | container: {
92 | flexGrow: 1,
93 | alignItems: 'center',
94 | justifyContent: 'flex-start',
95 | },
96 | animation: {
97 | width: '100%',
98 | height: 400,
99 | },
100 | picker: {
101 | flex: 1,
102 | width: '100%',
103 | },
104 | pickerWrapper: {
105 | borderWidth: 1,
106 | borderColor: 'black',
107 | borderRadius: 5,
108 | alignItems: 'center',
109 | margin: 16,
110 | },
111 | pickersWrapper: {
112 | flex: 1,
113 | padding: 16,
114 | alignSelf: 'stretch',
115 | },
116 | });
117 |
--------------------------------------------------------------------------------
/example/app/(examples)/ResponsiveLayout.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SafeAreaView, StyleSheet, View, Button, Text } from 'react-native';
3 | import Rive, { Fit } from 'rive-react-native';
4 |
5 | const resourceName = 'layout_test';
6 |
7 | export default function ResponsiveLayout() {
8 | const [scaleFactor, setScaleFactor] = React.useState(4.0);
9 |
10 | const increaseScale = () => setScaleFactor((prev) => prev + 0.5);
11 | const decreaseScale = () =>
12 | setScaleFactor((prev) => Math.max(0.5, prev - 0.5));
13 |
14 | return (
15 |
16 |
25 |
26 | Layout Scale Factor
27 |
28 |
29 |
30 | {scaleFactor.toFixed(1)}x
31 |
32 |
33 |
34 |
35 |
36 | );
37 | }
38 |
39 | const styles = StyleSheet.create({
40 | safeAreaViewContainer: {
41 | flex: 1,
42 | },
43 | animation: {
44 | width: '100%',
45 | flex: 1,
46 | },
47 | controls: {
48 | padding: 16,
49 | alignItems: 'center',
50 | },
51 | picker: {
52 | flex: 1,
53 | width: '100%',
54 | },
55 | pickerWrapper: {
56 | borderWidth: 1,
57 | borderColor: 'black',
58 | borderRadius: 5,
59 | alignItems: 'center',
60 | margin: 16,
61 | },
62 | pickersWrapper: {
63 | flex: 1,
64 | padding: 16,
65 | alignSelf: 'stretch',
66 | },
67 | scaleControls: {
68 | flexDirection: 'row',
69 | alignItems: 'center',
70 | marginVertical: 16,
71 | gap: 16,
72 | },
73 | scaleText: {
74 | minWidth: 50,
75 | alignItems: 'center',
76 | },
77 | label: {
78 | fontSize: 16,
79 | fontWeight: '500',
80 | marginTop: 16,
81 | },
82 | });
83 |
--------------------------------------------------------------------------------
/example/app/(examples)/Simple.tsx:
--------------------------------------------------------------------------------
1 | import { SafeAreaView, ScrollView, StyleSheet } from 'react-native';
2 | import Rive, { Alignment, Fit } from 'rive-react-native';
3 |
4 | export default function Simple() {
5 | return (
6 |
7 |
8 |
16 |
17 |
18 | );
19 | }
20 |
21 | const styles = StyleSheet.create({
22 | safeAreaViewContainer: {
23 | flex: 1,
24 | },
25 | container: {
26 | flexGrow: 1,
27 | alignItems: 'center',
28 | justifyContent: 'center',
29 | },
30 | animation: {
31 | width: '100%',
32 | height: 300,
33 | },
34 | });
35 |
--------------------------------------------------------------------------------
/example/app/(examples)/SimpleControls.tsx:
--------------------------------------------------------------------------------
1 | import { useState, useRef } from 'react';
2 | import { SafeAreaView, StyleSheet, ScrollView, View } from 'react-native';
3 | import Rive, { RiveRef } from 'rive-react-native';
4 | import { Button, Text } from 'react-native-paper';
5 |
6 | const resourceName = 'truck_v7';
7 |
8 | const BUTTONS = ['stop', 'play', 'pause'] as const;
9 | type ButtonsKey = (typeof BUTTONS)[number];
10 |
11 | export default function SimpleControls() {
12 | const [activeButton, setActiveButton] = useState('stop');
13 |
14 | const riveRef = useRef(null);
15 |
16 | const playAnimation = () => {
17 | setActiveButton('play');
18 | riveRef.current?.play();
19 | };
20 |
21 | const pauseAnimation = () => {
22 | setActiveButton('pause');
23 | riveRef.current?.pause();
24 | };
25 |
26 | const stopAnimation = () => {
27 | setActiveButton('stop');
28 | riveRef.current?.stop();
29 | };
30 |
31 | const reset = () => {
32 | riveRef.current?.reset();
33 | setActiveButton('stop');
34 | };
35 |
36 | return (
37 |
38 |
39 | {
44 | console.log(
45 | 'onPlay: ',
46 | animationName,
47 | 'isStateMachine: ',
48 | isStateMachine
49 | );
50 | }}
51 | onPause={(animationName, isStateMachine) => {
52 | console.log(
53 | 'onPause:',
54 | animationName,
55 | 'isStateMachine: ',
56 | isStateMachine
57 | );
58 | }}
59 | onStop={(animationName, isStateMachine) => {
60 | console.log(
61 | 'onStop: ',
62 | animationName,
63 | 'isStateMachine: ',
64 | isStateMachine
65 | );
66 | }}
67 | onLoopEnd={(animationName, loopMode) => {
68 | console.log('onLoopEnd: ', animationName, 'loopMode: ', loopMode);
69 | }}
70 | resourceName={resourceName}
71 | />
72 |
73 |
74 |
77 |
78 | Animation:
79 |
80 |
87 |
95 |
103 |
104 |
105 |
106 |
107 |
108 | );
109 | }
110 |
111 | const styles = StyleSheet.create({
112 | controls: {
113 | paddingHorizontal: 20,
114 | flex: 1,
115 | alignSelf: 'stretch',
116 | },
117 | safeAreaViewContainer: {
118 | flex: 1,
119 | },
120 | container: {
121 | flexGrow: 1,
122 | alignItems: 'center',
123 | justifyContent: 'center',
124 | paddingBottom: 32,
125 | },
126 | box: {
127 | width: '100%',
128 | height: 400,
129 | marginVertical: 20,
130 | },
131 | row: {
132 | flexDirection: 'row',
133 | },
134 | controlButtonGap: {
135 | marginLeft: 8,
136 | },
137 | controlsRow: {
138 | flexDirection: 'row',
139 | justifyContent: 'space-between',
140 | alignItems: 'center',
141 | },
142 | resetButton: {
143 | alignSelf: 'flex-start',
144 | marginBottom: 20,
145 | },
146 | });
147 |
--------------------------------------------------------------------------------
/example/app/(examples)/SourceProp.tsx:
--------------------------------------------------------------------------------
1 | import { SafeAreaView, StyleSheet, ScrollView, Text } from 'react-native';
2 | import Rive, { Alignment, Fit } from 'rive-react-native';
3 |
4 | export default function SourceProp() {
5 | return (
6 |
7 |
8 | Require
9 |
17 | HTTP URI
18 |
28 | Resource name URI
29 |
39 |
40 |
41 | );
42 | }
43 |
44 | const styles = StyleSheet.create({
45 | safeAreaViewContainer: {
46 | flex: 1,
47 | },
48 | container: {
49 | flexGrow: 1,
50 | alignItems: 'center',
51 | justifyContent: 'center',
52 | },
53 | animation: {
54 | width: '100%',
55 | height: 300,
56 | },
57 | });
58 |
--------------------------------------------------------------------------------
/example/app/(examples)/StateMachine.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { useState } from 'react';
3 | import { SafeAreaView, ScrollView, StyleSheet, Text, View } from 'react-native';
4 | import Rive, { Fit, RiveRef } from 'rive-react-native';
5 | import { RadioButton } from 'react-native-paper';
6 |
7 | export default function StateMachine() {
8 | const riveRef = React.useRef(null);
9 | const [selectedLevel, setSelectedLevel] = useState('0');
10 |
11 | const setLevel = (n: number) => {
12 | setSelectedLevel(n.toString());
13 | riveRef.current?.setInputState('skill-controller', 'level', n);
14 | };
15 |
16 | return (
17 |
18 |
19 | {
26 | console.log(
27 | 'onStateChanged: ',
28 | 'stateMachineName: ',
29 | stateMachineName,
30 | 'stateName: ',
31 | stateName
32 | );
33 | }}
34 | resourceName={'skills_listener'}
35 | />
36 | setLevel(parseInt(newValue, 10))}
38 | value={selectedLevel}
39 | >
40 |
41 |
42 | {'Beginner'}
43 |
44 |
45 |
46 | {'Intermediate'}
47 |
48 |
49 |
50 | {'Expert'}
51 |
52 |
53 |
54 |
55 |
56 |
57 | );
58 | }
59 |
60 | const styles = StyleSheet.create({
61 | safeAreaViewContainer: {
62 | flex: 1,
63 | },
64 | container: {
65 | flexGrow: 1,
66 | alignItems: 'center',
67 | justifyContent: 'center',
68 | marginBottom: 150,
69 | },
70 | wrapper: {
71 | flex: 1,
72 | flexDirection: 'row',
73 | flexWrap: 'wrap',
74 | justifyContent: 'center',
75 | marginBottom: 20,
76 | },
77 | box: {
78 | width: '100%',
79 | height: 500,
80 | marginVertical: 20,
81 | },
82 | picker: {
83 | width: '100%',
84 | height: 50,
85 | },
86 | radioButtonsWrapper: {
87 | flexDirection: 'row',
88 | },
89 | radioButtonWrapper: {
90 | flexDirection: 'row',
91 | alignItems: 'center',
92 | marginRight: 16,
93 | },
94 | });
95 |
--------------------------------------------------------------------------------
/example/app/+not-found.tsx:
--------------------------------------------------------------------------------
1 | import { Link, Stack } from 'expo-router';
2 | import { StyleSheet } from 'react-native';
3 |
4 | import { ThemedText } from '@/components/ThemedText';
5 | import { ThemedView } from '@/components/ThemedView';
6 |
7 | export default function NotFoundScreen() {
8 | return (
9 | <>
10 |
11 |
12 | This screen doesn't exist.
13 |
14 | Go to home screen!
15 |
16 |
17 | >
18 | );
19 | }
20 |
21 | const styles = StyleSheet.create({
22 | container: {
23 | flex: 1,
24 | alignItems: 'center',
25 | justifyContent: 'center',
26 | padding: 20,
27 | },
28 | link: {
29 | marginTop: 15,
30 | paddingVertical: 15,
31 | },
32 | });
33 |
--------------------------------------------------------------------------------
/example/app/_layout.tsx:
--------------------------------------------------------------------------------
1 | import FontAwesome from '@expo/vector-icons/FontAwesome';
2 | import {
3 | DarkTheme,
4 | DefaultTheme,
5 | ThemeProvider,
6 | } from '@react-navigation/native';
7 | import { useFonts } from 'expo-font';
8 | import { Stack } from 'expo-router';
9 | import * as SplashScreen from 'expo-splash-screen';
10 | import { useEffect } from 'react';
11 | import 'react-native-reanimated';
12 | import { GestureHandlerRootView } from 'react-native-gesture-handler';
13 | import { StyleSheet } from 'react-native';
14 |
15 | import { useColorScheme } from '@/hooks/useColorScheme';
16 |
17 | export {
18 | // Catch any errors thrown by the Layout component.
19 | ErrorBoundary,
20 | } from 'expo-router';
21 |
22 | export const unstable_settings = {
23 | // Ensure that reloading on other pages keeps a back button present.
24 | initialRouteName: '/',
25 | };
26 |
27 | // Prevent the splash screen from auto-hiding before asset loading is complete.
28 | SplashScreen.preventAutoHideAsync();
29 |
30 | export default function RootLayout() {
31 | const [loaded, error] = useFonts({
32 | SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
33 | ...FontAwesome.font,
34 | });
35 |
36 | // Expo Router uses Error Boundaries to catch errors in the navigation tree.
37 | useEffect(() => {
38 | if (error) throw error;
39 | }, [error]);
40 |
41 | useEffect(() => {
42 | if (loaded) {
43 | SplashScreen.hideAsync();
44 | }
45 | }, [loaded]);
46 |
47 | if (!loaded) {
48 | return null;
49 | }
50 |
51 | return ;
52 | }
53 |
54 | function RootLayoutNav() {
55 | const colorScheme = useColorScheme();
56 |
57 | return (
58 |
59 |
60 |
61 |
62 |
63 |
67 |
71 |
75 |
79 |
83 |
84 |
88 |
92 |
96 |
100 |
104 |
108 |
112 |
116 |
120 |
124 |
128 |
129 |
130 |
131 | );
132 | }
133 |
134 | const styles = StyleSheet.create({
135 | container: {
136 | flex: 1,
137 | },
138 | });
139 |
--------------------------------------------------------------------------------
/example/app/index.tsx:
--------------------------------------------------------------------------------
1 | import { ScrollView, StyleSheet } from 'react-native';
2 | import { Link } from 'expo-router';
3 |
4 | import { ReactNode } from 'react';
5 |
6 | export function StyledLink({
7 | href,
8 | children,
9 | }: {
10 | // to do
11 | href: any;
12 | children: ReactNode;
13 | }) {
14 | return (
15 |
16 | {children}
17 |
18 | );
19 | }
20 |
21 | export default function Home() {
22 | return (
23 |
24 | Simple
25 | Data Binding
26 | HTTP
27 | Mesh Example
28 | Layout
29 |
30 | Responsive Layout
31 |
32 | Simple Controls
33 |
34 | Multiple Artboards
35 |
36 | State Machine
37 | Events
38 | Dynamic Text
39 |
40 | Out Of Band Assets
41 |
42 |
43 | Nested Dynamic Text
44 |
45 | Nested Inputs
46 |
47 | Error Not Handled
48 |
49 |
50 | Error Handled Manually
51 |
52 | SourceProp
53 |
54 | );
55 | }
56 |
57 | const styles = StyleSheet.create({
58 | button: {
59 | backgroundColor: '#6221ea',
60 | padding: 10,
61 | borderRadius: 5,
62 | marginBottom: 10,
63 | minWidth: 300,
64 | color: 'white',
65 | textAlign: 'center',
66 | fontSize: 16,
67 | textTransform: 'uppercase',
68 | },
69 | container: {
70 | flexGrow: 1,
71 | alignItems: 'center',
72 | justifyContent: 'center',
73 | padding: 16,
74 | },
75 | });
76 |
--------------------------------------------------------------------------------
/example/assets/audio/referenced_audio-2929340.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/assets/audio/referenced_audio-2929340.wav
--------------------------------------------------------------------------------
/example/assets/fonts/Inter-594377.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/assets/fonts/Inter-594377.ttf
--------------------------------------------------------------------------------
/example/assets/fonts/SpaceMono-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/assets/fonts/SpaceMono-Regular.ttf
--------------------------------------------------------------------------------
/example/assets/images/adaptive-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/assets/images/adaptive-icon.png
--------------------------------------------------------------------------------
/example/assets/images/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/assets/images/favicon.png
--------------------------------------------------------------------------------
/example/assets/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/assets/images/icon.png
--------------------------------------------------------------------------------
/example/assets/images/partial-react-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/assets/images/partial-react-logo.png
--------------------------------------------------------------------------------
/example/assets/images/react-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/assets/images/react-logo.png
--------------------------------------------------------------------------------
/example/assets/images/react-logo@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/assets/images/react-logo@2x.png
--------------------------------------------------------------------------------
/example/assets/images/react-logo@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/assets/images/react-logo@3x.png
--------------------------------------------------------------------------------
/example/assets/images/referenced-image-2929282.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/assets/images/referenced-image-2929282.png
--------------------------------------------------------------------------------
/example/assets/images/splash-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/assets/images/splash-icon.png
--------------------------------------------------------------------------------
/example/assets/rive/avatars.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/assets/rive/avatars.riv
--------------------------------------------------------------------------------
/example/components/Themed.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Learn more about Light and Dark modes:
3 | * https://docs.expo.io/guides/color-schemes/
4 | */
5 | import { Text as DefaultText, View as DefaultView } from 'react-native';
6 |
7 | import { Colors } from '@/constants/Colors';
8 | import { useColorScheme } from '@/hooks/useColorScheme';
9 |
10 | type ThemeProps = {
11 | lightColor?: string;
12 | darkColor?: string;
13 | };
14 |
15 | export type TextProps = ThemeProps & DefaultText['props'];
16 | export type ViewProps = ThemeProps & DefaultView['props'];
17 |
18 | export function useThemeColor(
19 | props: { light?: string; dark?: string },
20 | colorName: keyof typeof Colors.light & keyof typeof Colors.dark
21 | ) {
22 | const theme = useColorScheme() ?? 'light';
23 | const colorFromProps = props[theme];
24 |
25 | if (colorFromProps) {
26 | return colorFromProps;
27 | } else {
28 | return Colors[theme][colorName];
29 | }
30 | }
31 |
32 | export function Text(props: TextProps) {
33 | const { style, lightColor, darkColor, ...otherProps } = props;
34 | const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text');
35 |
36 | return ;
37 | }
38 |
39 | export function View(props: ViewProps) {
40 | const { style, lightColor, darkColor, ...otherProps } = props;
41 | const backgroundColor = useThemeColor(
42 | { light: lightColor, dark: darkColor },
43 | 'background'
44 | );
45 |
46 | return ;
47 | }
48 |
--------------------------------------------------------------------------------
/example/components/ThemedText.tsx:
--------------------------------------------------------------------------------
1 | import { Text, TextProps, StyleSheet } from 'react-native';
2 |
3 | import { useThemeColor } from '@/hooks/useThemeColor';
4 |
5 | export type ThemedTextProps = TextProps & {
6 | lightColor?: string;
7 | darkColor?: string;
8 | type?: 'default' | 'title' | 'defaultSemiBold' | 'subtitle' | 'link';
9 | };
10 |
11 | export function ThemedText({
12 | style,
13 | lightColor,
14 | darkColor,
15 | type = 'default',
16 | ...rest
17 | }: ThemedTextProps) {
18 | const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text');
19 |
20 | return (
21 |
33 | );
34 | }
35 |
36 | const styles = StyleSheet.create({
37 | default: {
38 | fontSize: 16,
39 | lineHeight: 24,
40 | },
41 | defaultSemiBold: {
42 | fontSize: 16,
43 | lineHeight: 24,
44 | fontWeight: '600',
45 | },
46 | title: {
47 | fontSize: 32,
48 | fontWeight: 'bold',
49 | lineHeight: 32,
50 | },
51 | subtitle: {
52 | fontSize: 20,
53 | fontWeight: 'bold',
54 | },
55 | link: {
56 | lineHeight: 30,
57 | fontSize: 16,
58 | color: '#0a7ea4',
59 | },
60 | });
61 |
--------------------------------------------------------------------------------
/example/components/ThemedView.tsx:
--------------------------------------------------------------------------------
1 | import { View, ViewProps } from 'react-native';
2 |
3 | import { useThemeColor } from '@/hooks/useThemeColor';
4 |
5 | export type ThemedViewProps = ViewProps & {
6 | lightColor?: string;
7 | darkColor?: string;
8 | };
9 |
10 | export function ThemedView({
11 | style,
12 | lightColor,
13 | darkColor,
14 | ...otherProps
15 | }: ThemedViewProps) {
16 | const backgroundColor = useThemeColor(
17 | { light: lightColor, dark: darkColor },
18 | 'background'
19 | );
20 |
21 | return ;
22 | }
23 |
--------------------------------------------------------------------------------
/example/constants/Colors.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Below are the colors that are used in the app. The colors are defined in the light and dark mode.
3 | * There are many other ways to style your app. For example, [Nativewind](https://www.nativewind.dev/), [Tamagui](https://tamagui.dev/), [unistyles](https://reactnativeunistyles.vercel.app), etc.
4 | */
5 |
6 | const tintColorLight = '#0a7ea4';
7 | const tintColorDark = '#fff';
8 |
9 | export const Colors = {
10 | light: {
11 | text: '#11181C',
12 | background: '#fff',
13 | tint: tintColorLight,
14 | icon: '#687076',
15 | tabIconDefault: '#687076',
16 | tabIconSelected: tintColorLight,
17 | },
18 | dark: {
19 | text: '#ECEDEE',
20 | background: '#151718',
21 | tint: tintColorDark,
22 | icon: '#9BA1A6',
23 | tabIconDefault: '#9BA1A6',
24 | tabIconSelected: tintColorDark,
25 | },
26 | };
27 |
--------------------------------------------------------------------------------
/example/constants/typesPredicates.ts:
--------------------------------------------------------------------------------
1 | export function isEnum(
2 | enumType: EnumType,
3 | enumValue: string
4 | ): enumValue is EnumType[keyof EnumType] {
5 | return Object.values(enumType).includes(enumValue);
6 | }
7 |
8 | export function isEnumKey(
9 | enumType: EnumType,
10 | enumKey: string | number | symbol
11 | ): enumKey is keyof EnumType {
12 | return Object.keys(enumType).includes(enumKey.toString());
13 | }
14 |
--------------------------------------------------------------------------------
/example/hooks/useColorScheme.ts:
--------------------------------------------------------------------------------
1 | export { useColorScheme } from 'react-native';
2 |
--------------------------------------------------------------------------------
/example/hooks/useColorScheme.web.ts:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 | import { useColorScheme as useRNColorScheme } from 'react-native';
3 |
4 | /**
5 | * To support static rendering, this value needs to be re-calculated on the client side for web
6 | */
7 | export function useColorScheme() {
8 | const [hasHydrated, setHasHydrated] = useState(false);
9 |
10 | useEffect(() => {
11 | setHasHydrated(true);
12 | }, []);
13 |
14 | const colorScheme = useRNColorScheme();
15 |
16 | if (hasHydrated) {
17 | return colorScheme;
18 | }
19 |
20 | return 'light';
21 | }
22 |
--------------------------------------------------------------------------------
/example/hooks/useThemeColor.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Learn more about light and dark modes:
3 | * https://docs.expo.dev/guides/color-schemes/
4 | */
5 |
6 | import { Colors } from '@/constants/Colors';
7 | import { useColorScheme } from '@/hooks/useColorScheme';
8 |
9 | export function useThemeColor(
10 | props: { light?: string; dark?: string },
11 | colorName: keyof typeof Colors.light & keyof typeof Colors.dark
12 | ) {
13 | const theme = useColorScheme() ?? 'light';
14 | const colorFromProps = props[theme];
15 |
16 | if (colorFromProps) {
17 | return colorFromProps;
18 | } else {
19 | return Colors[theme][colorName];
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/example/ios/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 | project.xcworkspace
24 | .xcode.env.local
25 |
26 | # Bundle artifacts
27 | *.jsbundle
28 |
29 | # CocoaPods
30 | /Pods/
31 |
--------------------------------------------------------------------------------
/example/ios/.xcode.env:
--------------------------------------------------------------------------------
1 | # This `.xcode.env` file is versioned and is used to source the environment
2 | # used when running script phases inside Xcode.
3 | # To customize your local environment, you can create an `.xcode.env.local`
4 | # file that is not versioned.
5 |
6 | # NODE_BINARY variable contains the PATH to the node executable.
7 | #
8 | # Customize the NODE_BINARY variable here.
9 | # For example, to use nvm with brew, add the following line
10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use
11 | export NODE_BINARY=$(command -v node)
12 |
--------------------------------------------------------------------------------
/example/ios/Assets/FollowPathCar.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/FollowPathCar.riv
--------------------------------------------------------------------------------
/example/ios/Assets/Inter-594377.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/Inter-594377.ttf
--------------------------------------------------------------------------------
/example/ios/Assets/artboard_animations.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/artboard_animations.riv
--------------------------------------------------------------------------------
/example/ios/Assets/avatars.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/avatars.riv
--------------------------------------------------------------------------------
/example/ios/Assets/bird.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/bird.riv
--------------------------------------------------------------------------------
/example/ios/Assets/constrained.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/constrained.riv
--------------------------------------------------------------------------------
/example/ios/Assets/hello_world_nested.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/hello_world_nested.riv
--------------------------------------------------------------------------------
/example/ios/Assets/hello_world_text.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/hello_world_text.riv
--------------------------------------------------------------------------------
/example/ios/Assets/hero_editor.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/hero_editor.riv
--------------------------------------------------------------------------------
/example/ios/Assets/layout_test.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/layout_test.riv
--------------------------------------------------------------------------------
/example/ios/Assets/nested_inputs.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/nested_inputs.riv
--------------------------------------------------------------------------------
/example/ios/Assets/nested_menu.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/nested_menu.riv
--------------------------------------------------------------------------------
/example/ios/Assets/out_of_band.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/out_of_band.riv
--------------------------------------------------------------------------------
/example/ios/Assets/rainy.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/rainy.riv
--------------------------------------------------------------------------------
/example/ios/Assets/rating.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/rating.riv
--------------------------------------------------------------------------------
/example/ios/Assets/referenced-image-2929282.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/referenced-image-2929282.png
--------------------------------------------------------------------------------
/example/ios/Assets/referenced_audio-2929340.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/referenced_audio-2929340.wav
--------------------------------------------------------------------------------
/example/ios/Assets/skills_listener.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/skills_listener.riv
--------------------------------------------------------------------------------
/example/ios/Assets/switch.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/switch.riv
--------------------------------------------------------------------------------
/example/ios/Assets/truck_v7.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/truck_v7.riv
--------------------------------------------------------------------------------
/example/ios/Assets/two_bone_ik.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/two_bone_ik.riv
--------------------------------------------------------------------------------
/example/ios/Assets/ui_swipe_left_to_delete.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/ui_swipe_left_to_delete.riv
--------------------------------------------------------------------------------
/example/ios/Assets/v6_file.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/Assets/v6_file.riv
--------------------------------------------------------------------------------
/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
2 | require File.join(File.dirname(`node --print "require.resolve('react-native/package.json')"`), "scripts/react_native_pods")
3 |
4 | require 'json'
5 | podfile_properties = JSON.parse(File.read(File.join(__dir__, 'Podfile.properties.json'))) rescue {}
6 |
7 | ENV['RCT_NEW_ARCH_ENABLED'] = podfile_properties['newArchEnabled'] == 'true' ? '1' : '0'
8 | ENV['EX_DEV_CLIENT_NETWORK_INSPECTOR'] = podfile_properties['EX_DEV_CLIENT_NETWORK_INSPECTOR']
9 |
10 | platform :ios, podfile_properties['ios.deploymentTarget'] || '15.1'
11 | install! 'cocoapods',
12 | :deterministic_uuids => false
13 |
14 | prepare_react_native_project!
15 |
16 | target 'example' do
17 | use_expo_modules!
18 |
19 | if ENV['EXPO_USE_COMMUNITY_AUTOLINKING'] == '1'
20 | config_command = ['node', '-e', "process.argv=['', '', 'config'];require('@react-native-community/cli').run()"];
21 | else
22 | config_command = [
23 | 'node',
24 | '--no-warnings',
25 | '--eval',
26 | 'require(require.resolve(\'expo-modules-autolinking\', { paths: [require.resolve(\'expo/package.json\')] }))(process.argv.slice(1))',
27 | 'react-native-config',
28 | '--json',
29 | '--platform',
30 | 'ios'
31 | ]
32 | end
33 |
34 | config = use_native_modules!(config_command)
35 |
36 | use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']
37 | use_frameworks! :linkage => ENV['USE_FRAMEWORKS'].to_sym if ENV['USE_FRAMEWORKS']
38 |
39 | use_react_native!(
40 | :path => config[:reactNativePath],
41 | :hermes_enabled => podfile_properties['expo.jsEngine'] == nil || podfile_properties['expo.jsEngine'] == 'hermes',
42 | # An absolute path to your application root.
43 | :app_path => "#{Pod::Config.instance.installation_root}/..",
44 | :privacy_file_aggregation_enabled => podfile_properties['apple.privacyManifestAggregationEnabled'] != 'false',
45 | )
46 |
47 | post_install do |installer|
48 | react_native_post_install(
49 | installer,
50 | config[:reactNativePath],
51 | :mac_catalyst_enabled => false,
52 | :ccache_enabled => podfile_properties['apple.ccacheEnabled'] == 'true',
53 | )
54 |
55 | # This is necessary for Xcode 14, because it signs resource bundles by default
56 | # when building for devices.
57 | installer.target_installation_results.pod_target_installation_results
58 | .each do |pod_name, target_installation_result|
59 | target_installation_result.resource_bundle_targets.each do |resource_bundle_target|
60 | resource_bundle_target.build_configurations.each do |config|
61 | config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
62 | end
63 | end
64 | end
65 | end
66 | end
67 |
--------------------------------------------------------------------------------
/example/ios/Podfile.properties.json:
--------------------------------------------------------------------------------
1 | {
2 | "expo.jsEngine": "hermes",
3 | "EX_DEV_CLIENT_NETWORK_INSPECTOR": "true",
4 | "newArchEnabled": "true"
5 | }
6 |
--------------------------------------------------------------------------------
/example/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
55 |
61 |
62 |
63 |
64 |
70 |
72 |
78 |
79 |
80 |
81 |
83 |
84 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/example/ios/example.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/example/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import
4 |
5 | @interface AppDelegate : EXAppDelegateWrapper
6 |
7 | @end
8 |
--------------------------------------------------------------------------------
/example/ios/example/AppDelegate.mm:
--------------------------------------------------------------------------------
1 | #import "AppDelegate.h"
2 |
3 | #import
4 | #import
5 |
6 | @implementation AppDelegate
7 |
8 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
9 | {
10 | self.moduleName = @"main";
11 |
12 | // You can add your custom initial props in the dictionary below.
13 | // They will be passed down to the ViewController used by React Native.
14 | self.initialProps = @{};
15 |
16 | return [super application:application didFinishLaunchingWithOptions:launchOptions];
17 | }
18 |
19 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
20 | {
21 | return [self bundleURL];
22 | }
23 |
24 | - (NSURL *)bundleURL
25 | {
26 | #if DEBUG
27 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@".expo/.virtual-metro-entry"];
28 | #else
29 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
30 | #endif
31 | }
32 |
33 | // Linking API
34 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary *)options {
35 | return [super application:application openURL:url options:options] || [RCTLinkingManager application:application openURL:url options:options];
36 | }
37 |
38 | // Universal Links
39 | - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray> * _Nullable))restorationHandler {
40 | BOOL result = [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
41 | return [super application:application continueUserActivity:userActivity restorationHandler:restorationHandler] || result;
42 | }
43 |
44 | // Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
45 | - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
46 | {
47 | return [super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
48 | }
49 |
50 | // Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
51 | - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
52 | {
53 | return [super application:application didFailToRegisterForRemoteNotificationsWithError:error];
54 | }
55 |
56 | // Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
57 | - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
58 | {
59 | return [super application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
60 | }
61 |
62 | @end
63 |
--------------------------------------------------------------------------------
/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png
--------------------------------------------------------------------------------
/example/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "filename": "App-Icon-1024x1024@1x.png",
5 | "idiom": "universal",
6 | "platform": "ios",
7 | "size": "1024x1024"
8 | }
9 | ],
10 | "info": {
11 | "version": 1,
12 | "author": "expo"
13 | }
14 | }
--------------------------------------------------------------------------------
/example/ios/example/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "expo"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/example/ios/example/Images.xcassets/SplashScreenBackground.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors": [
3 | {
4 | "color": {
5 | "components": {
6 | "alpha": "1.000",
7 | "blue": "1.00000000000000",
8 | "green": "1.00000000000000",
9 | "red": "1.00000000000000"
10 | },
11 | "color-space": "srgb"
12 | },
13 | "idiom": "universal"
14 | }
15 | ],
16 | "info": {
17 | "version": 1,
18 | "author": "expo"
19 | }
20 | }
--------------------------------------------------------------------------------
/example/ios/example/Images.xcassets/SplashScreenLogo.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "idiom": "universal",
5 | "filename": "image.png",
6 | "scale": "1x"
7 | },
8 | {
9 | "idiom": "universal",
10 | "filename": "image@2x.png",
11 | "scale": "2x"
12 | },
13 | {
14 | "idiom": "universal",
15 | "filename": "image@3x.png",
16 | "scale": "3x"
17 | }
18 | ],
19 | "info": {
20 | "version": 1,
21 | "author": "expo"
22 | }
23 | }
--------------------------------------------------------------------------------
/example/ios/example/Images.xcassets/SplashScreenLogo.imageset/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/example/Images.xcassets/SplashScreenLogo.imageset/image.png
--------------------------------------------------------------------------------
/example/ios/example/Images.xcassets/SplashScreenLogo.imageset/image@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/example/Images.xcassets/SplashScreenLogo.imageset/image@2x.png
--------------------------------------------------------------------------------
/example/ios/example/Images.xcassets/SplashScreenLogo.imageset/image@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/example/Images.xcassets/SplashScreenLogo.imageset/image@3x.png
--------------------------------------------------------------------------------
/example/ios/example/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CADisableMinimumFrameDurationOnPhone
6 |
7 | CFBundleDevelopmentRegion
8 | $(DEVELOPMENT_LANGUAGE)
9 | CFBundleDisplayName
10 | example
11 | CFBundleExecutable
12 | $(EXECUTABLE_NAME)
13 | CFBundleIdentifier
14 | $(PRODUCT_BUNDLE_IDENTIFIER)
15 | CFBundleInfoDictionaryVersion
16 | 6.0
17 | CFBundleName
18 | $(PRODUCT_NAME)
19 | CFBundlePackageType
20 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
21 | CFBundleShortVersionString
22 | 1.0.0
23 | CFBundleSignature
24 | ????
25 | CFBundleURLTypes
26 |
27 |
28 | CFBundleURLSchemes
29 |
30 | myapp
31 | com.anonymous.example
32 |
33 |
34 |
35 | CFBundleVersion
36 | 1
37 | LSMinimumSystemVersion
38 | 12.0
39 | LSRequiresIPhoneOS
40 |
41 | NSAppTransportSecurity
42 |
43 | NSAllowsArbitraryLoads
44 |
45 | NSAllowsLocalNetworking
46 |
47 |
48 | NSUserActivityTypes
49 |
50 | $(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route
51 |
52 | UILaunchStoryboardName
53 | SplashScreen
54 | UIRequiredDeviceCapabilities
55 |
56 | arm64
57 |
58 | UIRequiresFullScreen
59 |
60 | UIStatusBarStyle
61 | UIStatusBarStyleDefault
62 | UISupportedInterfaceOrientations
63 |
64 | UIInterfaceOrientationPortrait
65 | UIInterfaceOrientationPortraitUpsideDown
66 |
67 | UISupportedInterfaceOrientations~ipad
68 |
69 | UIInterfaceOrientationPortrait
70 | UIInterfaceOrientationPortraitUpsideDown
71 | UIInterfaceOrientationLandscapeLeft
72 | UIInterfaceOrientationLandscapeRight
73 |
74 | UIUserInterfaceStyle
75 | Automatic
76 | UIViewControllerBasedStatusBarAppearance
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/example/ios/example/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyAccessedAPITypes
6 |
7 |
8 | NSPrivacyAccessedAPIType
9 | NSPrivacyAccessedAPICategoryUserDefaults
10 | NSPrivacyAccessedAPITypeReasons
11 |
12 | CA92.1
13 |
14 |
15 |
16 | NSPrivacyAccessedAPIType
17 | NSPrivacyAccessedAPICategoryFileTimestamp
18 | NSPrivacyAccessedAPITypeReasons
19 |
20 | 0A2A.1
21 | 3B52.1
22 | C617.1
23 |
24 |
25 |
26 | NSPrivacyAccessedAPIType
27 | NSPrivacyAccessedAPICategoryDiskSpace
28 | NSPrivacyAccessedAPITypeReasons
29 |
30 | E174.1
31 | 85F4.1
32 |
33 |
34 |
35 | NSPrivacyAccessedAPIType
36 | NSPrivacyAccessedAPICategorySystemBootTime
37 | NSPrivacyAccessedAPITypeReasons
38 |
39 | 35F9.1
40 |
41 |
42 |
43 | NSPrivacyCollectedDataTypes
44 |
45 | NSPrivacyTracking
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/example/ios/example/SplashScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/example/ios/example/Supporting/Expo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | EXUpdatesCheckOnLaunch
6 | ALWAYS
7 | EXUpdatesEnabled
8 |
9 | EXUpdatesLaunchWaitMs
10 | 0
11 |
12 |
--------------------------------------------------------------------------------
/example/ios/example/example-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Use this file to import your target's public headers that you would like to expose to Swift.
3 | //
4 |
--------------------------------------------------------------------------------
/example/ios/example/example.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/example/ios/example/main.m:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char * argv[]) {
6 | @autoreleasepool {
7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
8 | }
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/example/noop-file.swift:
--------------------------------------------------------------------------------
1 | //
2 | // @generated
3 | // A blank Swift file must be created for native modules with Swift files to work correctly.
4 | //
5 |
--------------------------------------------------------------------------------
/example/ios/rewards.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-react-native/578dd4981bec2ac6f92fed51b93f815dec0b6f4a/example/ios/rewards.riv
--------------------------------------------------------------------------------
/example/metro.config.js:
--------------------------------------------------------------------------------
1 | const { getDefaultConfig } = require('expo/metro-config');
2 | const path = require('path');
3 |
4 | // Find the project and workspace directories
5 | const projectRoot = __dirname;
6 | // This can be replaced with `find-yarn-workspace-root`
7 | const monorepoRoot = path.resolve(projectRoot, '../');
8 |
9 | const config = getDefaultConfig(projectRoot);
10 |
11 | // 1. Watch all files within the monorepo
12 | config.watchFolders = [monorepoRoot];
13 | // 2. Let Metro know where to resolve packages and in what order
14 | config.resolver.nodeModulesPaths = [
15 | path.resolve(projectRoot, 'node_modules'),
16 | path.resolve(monorepoRoot, 'node_modules'),
17 | ];
18 |
19 | config.resolver.assetExts.push('riv');
20 |
21 | module.exports = config;
22 |
23 | // const path = require('path');
24 |
25 | // module.exports = {
26 | // resolver: {
27 | // extraNodeModules: {
28 | // 'rive-react-native': path.resolve(__dirname, '..'),
29 | // },
30 | // },
31 | // watchFolders: [path.resolve(__dirname, '..')],
32 | // };
33 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "main": "expo-router/entry",
4 | "version": "1.0.0",
5 | "scripts": {
6 | "start": "expo start",
7 | "reset-project": "node ./scripts/reset-project.js",
8 | "android": "expo run:android",
9 | "ios": "expo run:ios",
10 | "web": "expo start --web",
11 | "test": "jest --watchAll",
12 | "lint": "expo lint"
13 | },
14 | "installConfig": {
15 | "hoistingLimits": "workspaces"
16 | },
17 | "jest": {
18 | "preset": "jest-expo"
19 | },
20 | "dependencies": {
21 | "@expo/vector-icons": "^14.0.2",
22 | "@react-native-community/slider": "^4.5.6",
23 | "@react-native-picker/picker": "^2.11.0",
24 | "@react-navigation/bottom-tabs": "^7.2.0",
25 | "@react-navigation/native": "^7.0.14",
26 | "expo": "~52.0.35",
27 | "expo-blur": "~14.0.3",
28 | "expo-constants": "~17.0.6",
29 | "expo-font": "~13.0.3",
30 | "expo-haptics": "~14.0.1",
31 | "expo-linking": "~7.0.5",
32 | "expo-router": "~4.0.17",
33 | "expo-splash-screen": "~0.29.22",
34 | "expo-status-bar": "~2.0.1",
35 | "expo-symbols": "~0.2.2",
36 | "expo-system-ui": "~4.0.8",
37 | "expo-web-browser": "~14.0.2",
38 | "react": "18.3.1",
39 | "react-native": "0.76.7",
40 | "react-native-gesture-handler": "~2.20.2",
41 | "react-native-paper": "^5.13.1",
42 | "react-native-reanimated": "~3.16.1",
43 | "react-native-safe-area-context": "4.12.0",
44 | "react-native-screens": "~4.4.0",
45 | "react-native-webview": "13.12.5",
46 | "rive-react-native": "workspace:^"
47 | },
48 | "devDependencies": {
49 | "@babel/core": "^7.25.2",
50 | "@types/jest": "^29.5.12",
51 | "@types/react": "~18.3.12",
52 | "jest": "^29.2.1",
53 | "jest-expo": "~52.0.4",
54 | "typescript": "^5.3.3"
55 | },
56 | "private": true
57 | }
58 |
--------------------------------------------------------------------------------
/example/scripts/reset-project.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | /**
4 | * This script is used to reset the project to a blank state.
5 | * It deletes or moves the /app, /components, /hooks, /scripts, and /constants directories to /app-example based on user input and creates a new /app directory with an index.tsx and _layout.tsx file.
6 | * You can remove the `reset-project` script from package.json and safely delete this file after running it.
7 | */
8 |
9 | const fs = require('fs');
10 | const path = require('path');
11 | const readline = require('readline');
12 |
13 | const root = process.cwd();
14 | const oldDirs = ['app', 'components', 'hooks', 'constants', 'scripts'];
15 | const exampleDir = 'app-example';
16 | const newAppDir = 'app';
17 | const exampleDirPath = path.join(root, exampleDir);
18 |
19 | const indexContent = `import { Text, View } from "react-native";
20 |
21 | export default function Index() {
22 | return (
23 |
30 | Edit app/index.tsx to edit this screen.
31 |
32 | );
33 | }
34 | `;
35 |
36 | const layoutContent = `import { Stack } from "expo-router";
37 |
38 | export default function RootLayout() {
39 | return ;
40 | }
41 | `;
42 |
43 | const rl = readline.createInterface({
44 | input: process.stdin,
45 | output: process.stdout,
46 | });
47 |
48 | const moveDirectories = async (userInput) => {
49 | try {
50 | if (userInput === 'y') {
51 | // Create the app-example directory
52 | await fs.promises.mkdir(exampleDirPath, { recursive: true });
53 | console.log(`📁 /${exampleDir} directory created.`);
54 | }
55 |
56 | // Move old directories to new app-example directory or delete them
57 | for (const dir of oldDirs) {
58 | const oldDirPath = path.join(root, dir);
59 | if (fs.existsSync(oldDirPath)) {
60 | if (userInput === 'y') {
61 | const newDirPath = path.join(root, exampleDir, dir);
62 | await fs.promises.rename(oldDirPath, newDirPath);
63 | console.log(`➡️ /${dir} moved to /${exampleDir}/${dir}.`);
64 | } else {
65 | await fs.promises.rm(oldDirPath, { recursive: true, force: true });
66 | console.log(`❌ /${dir} deleted.`);
67 | }
68 | } else {
69 | console.log(`➡️ /${dir} does not exist, skipping.`);
70 | }
71 | }
72 |
73 | // Create new /app directory
74 | const newAppDirPath = path.join(root, newAppDir);
75 | await fs.promises.mkdir(newAppDirPath, { recursive: true });
76 | console.log('\n📁 New /app directory created.');
77 |
78 | // Create index.tsx
79 | const indexPath = path.join(newAppDirPath, 'index.tsx');
80 | await fs.promises.writeFile(indexPath, indexContent);
81 | console.log('📄 app/index.tsx created.');
82 |
83 | // Create _layout.tsx
84 | const layoutPath = path.join(newAppDirPath, '_layout.tsx');
85 | await fs.promises.writeFile(layoutPath, layoutContent);
86 | console.log('📄 app/_layout.tsx created.');
87 |
88 | console.log('\n✅ Project reset complete. Next steps:');
89 | console.log(
90 | `1. Run \`npx expo start\` to start a development server.\n2. Edit app/index.tsx to edit the main screen.${
91 | userInput === 'y'
92 | ? `\n3. Delete the /${exampleDir} directory when you're done referencing it.`
93 | : ''
94 | }`
95 | );
96 | } catch (error) {
97 | console.error(`❌ Error during script execution: ${error.message}`);
98 | }
99 | };
100 |
101 | rl.question(
102 | 'Do you want to move existing files to /app-example instead of deleting them? (Y/n): ',
103 | (answer) => {
104 | const userInput = answer.trim().toLowerCase() || 'y';
105 | if (userInput === 'y' || userInput === 'n') {
106 | moveDirectories(userInput).finally(() => rl.close());
107 | } else {
108 | console.log("❌ Invalid input. Please enter 'Y' or 'N'.");
109 | rl.close();
110 | }
111 | }
112 | );
113 |
--------------------------------------------------------------------------------
/example/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "expo/tsconfig.base",
3 | "compilerOptions": {
4 | "strict": true,
5 | "paths": {
6 | "@/*": ["./*"],
7 | "rive-react-native": ["../src/index"]
8 | }
9 | },
10 | "include": [
11 | "**/*.ts",
12 | "**/*.tsx",
13 | ".expo/types/**/*.ts",
14 | "expo-env.d.ts"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/ios/RCTLog.swift:
--------------------------------------------------------------------------------
1 | func RCTLogError(_ message: String, _ file: String=#file, _ line: UInt=#line) {
2 | DispatchQueue.main.async {
3 | RCTSwiftLog.error(message, file: file, line: line)
4 | }
5 |
6 | }
7 |
8 | func RCTLogWarn(_ message: String, _ file: String=#file, _ line: UInt=#line) {
9 | DispatchQueue.main.async {
10 | RCTSwiftLog.warn(message, file: file, line: line)
11 | }
12 | }
13 |
14 | func RCTLogInfo(_ message: String, _ file: String=#file, _ line: UInt=#line) {
15 | DispatchQueue.main.async {
16 | RCTSwiftLog.info(message, file: file, line: line)
17 | }
18 | }
19 |
20 | func RCTLog(_ message: String, _ file: String=#file, _ line: UInt=#line) {
21 | DispatchQueue.main.async {
22 | RCTSwiftLog.log(message, file: file, line: line)
23 | }
24 | }
25 |
26 | func RCTLogTrace(_ message: String, _ file: String=#file, _ line: UInt=#line) {
27 | DispatchQueue.main.async {
28 | RCTSwiftLog.trace(message, file: file, line: line)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/ios/RCTSwiftLog.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface RCTSwiftLog : NSObject
4 |
5 | + (void)error:(NSString * _Nonnull)message file:(NSString * _Nonnull)file line:(NSUInteger)line;
6 | + (void)warn:(NSString * _Nonnull)message file:(NSString * _Nonnull)file line:(NSUInteger)line;
7 | + (void)info:(NSString * _Nonnull)message file:(NSString * _Nonnull)file line:(NSUInteger)line;
8 | + (void)log:(NSString * _Nonnull)message file:(NSString * _Nonnull)file line:(NSUInteger)line;
9 | + (void)trace:(NSString * _Nonnull)message file:(NSString * _Nonnull)file line:(NSUInteger)line;
10 |
11 | @end
--------------------------------------------------------------------------------
/ios/RCTSwiftLog.m:
--------------------------------------------------------------------------------
1 | //
2 | // RCTSwiftLog.m
3 | //
4 | //
5 | //
6 |
7 | #import
8 |
9 | #import "RCTSwiftLog.h"
10 |
11 | @implementation RCTSwiftLog
12 |
13 | + (void)info:(NSString *)message file:(NSString *)file line:(NSUInteger)line
14 | {
15 | _RCTLogNativeInternal(RCTLogLevelInfo, file.UTF8String, (int)line, @"%@", message);
16 | }
17 |
18 | + (void)warn:(NSString *)message file:(NSString *)file line:(NSUInteger)line
19 | {
20 | _RCTLogNativeInternal(RCTLogLevelWarning, file.UTF8String, (int)line, @"%@", message);
21 | }
22 |
23 | + (void)error:(NSString *)message file:(NSString *)file line:(NSUInteger)line
24 | {
25 | _RCTLogNativeInternal(RCTLogLevelError, file.UTF8String, (int)line, @"%@", message);
26 | }
27 |
28 | + (void)log:(NSString *)message file:(NSString *)file line:(NSUInteger)line
29 | {
30 | _RCTLogNativeInternal(RCTLogLevelInfo, file.UTF8String, (int)line, @"%@", message);
31 | }
32 |
33 | + (void)trace:(NSString *)message file:(NSString *)file line:(NSUInteger)line
34 | {
35 | _RCTLogNativeInternal(RCTLogLevelTrace, file.UTF8String, (int)line, @"%@", message);
36 | }
37 |
38 | @end
--------------------------------------------------------------------------------
/ios/RNAlignment.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import RiveRuntime
3 |
4 | enum RNAlignment: String {
5 | case TopLeft = "topLeft"
6 | case TopCenter = "topCenter"
7 | case TopRight = "topRight"
8 | case CenterLeft = "centerLeft"
9 | case Center = "center"
10 | case CenterRight = "centerRight"
11 | case BottomLeft = "bottomLeft"
12 | case BottomCenter = "bottomCenter"
13 | case BottomRight = "bottomRight"
14 |
15 | static func mapToRNAlignment(value: String) -> RNAlignment {
16 | if let rnEnum = RNAlignment(rawValue: value) {
17 | return rnEnum
18 | } else {
19 | fatalError("Unsupported alignment type: \(value)")
20 | }
21 | }
22 |
23 | static func mapToRiveAlignment(rnAlignment: RNAlignment) -> RiveAlignment {
24 | switch rnAlignment {
25 | case .TopLeft:
26 | return RiveAlignment.topLeft
27 | case .TopCenter:
28 | return RiveAlignment.topCenter
29 | case .TopRight:
30 | return RiveAlignment.topRight
31 | case .CenterLeft:
32 | return RiveAlignment.centerLeft
33 | case .Center:
34 | return RiveAlignment.center
35 | case .CenterRight:
36 | return RiveAlignment.centerRight
37 | case .BottomLeft:
38 | return RiveAlignment.bottomLeft
39 | case .BottomCenter:
40 | return RiveAlignment.bottomCenter
41 | case .BottomRight:
42 | return RiveAlignment.bottomRight
43 | }
44 | }
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/ios/RNDirection.swift:
--------------------------------------------------------------------------------
1 | enum RNDirection: String {
2 | case Backwards = "backwards"
3 | case Auto = "auto"
4 | case Forwards = "forwards"
5 |
6 | static func mapToRNDirection(value: String) -> RNDirection {
7 | if let rnEnum = RNDirection(rawValue: value) {
8 | return rnEnum
9 | } else {
10 | fatalError("Unsupported direction type: \(value)")
11 | }
12 | }
13 |
14 | static func mapToRiveDirection(rnDirection: RNDirection) -> RiveDirection {
15 | switch rnDirection {
16 | case .Backwards:
17 | return .backwards
18 | case .Auto:
19 | return .autoDirection
20 | case .Forwards:
21 | return .forwards
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/ios/RNFit.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import RiveRuntime
3 |
4 | enum RNFit: String {
5 | case Contain = "contain"
6 | case Cover = "cover"
7 | case Fill = "fill"
8 | case FitWidth = "fitWidth"
9 | case FitHeight = "fitHeight"
10 | case None = "none"
11 | case ScaleDown = "scaleDown"
12 | case Layout = "layout"
13 |
14 | static func mapToRNFit(value: String) -> RNFit {
15 | if let rnEnum = RNFit(rawValue: value) {
16 | return rnEnum
17 | } else {
18 | fatalError("Unsupported fit type: \(value)")
19 | }
20 | }
21 |
22 | static func mapToRiveFit(rnFit: RNFit) -> RiveFit {
23 | switch rnFit {
24 | case .Contain:
25 | return RiveFit.contain
26 | case .Cover:
27 | return RiveFit.cover
28 | case .Fill:
29 | return RiveFit.fill
30 | case .FitWidth:
31 | return RiveFit.fitWidth
32 | case .FitHeight:
33 | return RiveFit.fitHeight
34 | case .None:
35 | return RiveFit.noFit
36 | case .ScaleDown:
37 | return RiveFit.scaleDown
38 | case .Layout:
39 | return RiveFit.layout
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/ios/RNLoopMode.swift:
--------------------------------------------------------------------------------
1 | enum RNLoopMode: String {
2 | case OneShot = "oneShot"
3 | case Loop = "loop"
4 | case PingPong = "pingPong"
5 | case Auto = "auto"
6 |
7 | static func mapToRNLoopMode(value: String) -> RNLoopMode {
8 | if let rnEnum = RNLoopMode(rawValue: value) {
9 | return rnEnum
10 | } else {
11 | fatalError("Unsupported loop mode type: \(value)")
12 | }
13 | }
14 |
15 |
16 | static func mapToRNLoopMode(value: Int) -> RNLoopMode {
17 | if let riveEnum = RiveRuntime.RiveLoop(rawValue: value) {
18 | switch (riveEnum) {
19 | case .oneShot:
20 | return .OneShot
21 | case .loop:
22 | return .Loop
23 | case .pingPong:
24 | return .PingPong
25 | case .autoLoop:
26 | return .Auto
27 | default:
28 | return .Auto
29 | }
30 |
31 |
32 | } else {
33 | fatalError("Unsupported loop mode type: \(value)")
34 | }
35 | }
36 |
37 | static func mapToRiveLoop(rnLoopMode: RNLoopMode) -> RiveLoop {
38 | switch rnLoopMode {
39 | case .OneShot:
40 | return .oneShot
41 | case .Loop:
42 | return .loop
43 | case .PingPong:
44 | return .pingPong
45 | case .Auto:
46 | return .autoLoop
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/ios/RNPropertyType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RNPropertyType.swift
3 | // rive-react-native
4 | //
5 | // Created by Peter G Hayes on 02/05/2025.
6 | //
7 |
8 | import Foundation
9 |
10 | enum RNPropertyType: String {
11 | case Number = "number"
12 | case String = "string"
13 | case Boolean = "boolean"
14 | case Color = "color"
15 | case Trigger = "trigger"
16 | case Enum = "enum"
17 |
18 | static func mapToRNPropertyType(value: String) -> RNPropertyType? {
19 | if let rnEnum = RNPropertyType(rawValue: value) {
20 | return rnEnum
21 | } else {
22 | return nil
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/ios/RNRiveError.swift:
--------------------------------------------------------------------------------
1 | struct BaseRNRiveError {
2 | let type: String;
3 | var message: String = "Default Message"
4 | }
5 |
6 |
7 | struct RNRiveError {
8 | static let FileNotFound = BaseRNRiveError(type: "FileNotFound")
9 | static let UnsupportedRuntimeVersion = BaseRNRiveError(type: "UnsupportedRuntimeVersion")
10 | static let IncorrectAnimationName = BaseRNRiveError(type: "IncorrectAnimationName")
11 | static let MalformedFile = BaseRNRiveError(type: "MalformedFile")
12 | static let IncorrectRiveFileUrl = BaseRNRiveError(type: "IncorrectRiveFileUrl")
13 | static let IncorrectArtboardName = BaseRNRiveError(type: "IncorrectArtboardName")
14 | static let IncorrectStateMachineName = BaseRNRiveError(type: "IncorrectStateMachineName")
15 | static let IncorrectStateMachineInput = BaseRNRiveError(type: "IncorrectStateMachineInput")
16 | static let TextRunNotFoundError = BaseRNRiveError(type: "TextRunNotFoundError")
17 | static let DataBindingError = BaseRNRiveError(type: "DataBindingError")
18 |
19 |
20 | static func mapToRNRiveError(riveError: NSError) -> BaseRNRiveError? {
21 | let riveErrorName = riveError.userInfo["name"] as! String
22 | var resultError: BaseRNRiveError? = nil
23 | switch riveErrorName {
24 | case "UnsupportedVersion":
25 | resultError = RNRiveError.UnsupportedRuntimeVersion
26 | break;
27 | case "Malformed":
28 | resultError = RNRiveError.MalformedFile
29 | break
30 | case "FileNotFound":
31 | resultError = RNRiveError.FileNotFound
32 | break;
33 | case "IncorrectRiveFileURL":
34 | resultError = RNRiveError.IncorrectRiveFileUrl
35 | break;
36 | case "NoAnimationFound":
37 | resultError = RNRiveError.IncorrectAnimationName
38 | break;
39 | case "NoArtboardFound":
40 | resultError = RNRiveError.IncorrectArtboardName
41 | break;
42 | case "NoStateMachineFound":
43 | resultError = RNRiveError.IncorrectStateMachineName
44 | break;
45 | case "NoStateMachineInputFound":
46 | resultError = RNRiveError.IncorrectStateMachineInput
47 | break;
48 | case "TextRunNotFoundError":
49 | resultError = RNRiveError.TextRunNotFoundError
50 | break;
51 | case "DataBindingError":
52 | resultError = RNRiveError.DataBindingError
53 | break;
54 | default:
55 | return nil
56 | }
57 | resultError?.message = riveError.localizedDescription
58 | return resultError
59 | }
60 | }
61 |
62 |
63 | func createFileNotFoundError() -> NSError {
64 | return NSError(domain: RiveErrorDomain, code: 800, userInfo: [NSLocalizedDescriptionKey: "File not found", "name": "FileNotFound"])
65 | }
66 |
67 | func createMalformedFileError() -> NSError {
68 | return NSError(domain: RiveErrorDomain, code: RiveErrorCode.malformedFile.rawValue, userInfo: [NSLocalizedDescriptionKey: "Malformed Rive File", "name": "Malformed"])
69 | }
70 |
71 | func createAssetFileError(_ assetName: String) -> NSError {
72 | return NSError(domain: RiveErrorDomain, code: 801, userInfo: [NSLocalizedDescriptionKey: "Could not load Rive asset: \(assetName)", "name": "FileNotFound"])
73 | }
74 |
75 | func createIncorrectRiveURL(_ url: String) -> NSError {
76 | return NSError(domain: RiveErrorDomain, code: 900, userInfo: [NSLocalizedDescriptionKey: "Unable to download Rive file from: \(url)", "name": "IncorrectRiveFileURL"])
77 | }
78 |
--------------------------------------------------------------------------------
/ios/RNRiveRendererType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RNRiveRendererType.swift
3 | // rive-react-native
4 | //
5 | // Created by Peter G Hayes on 31/05/2024.
6 | //
7 |
8 | import Foundation
9 | import RiveRuntime
10 |
11 | enum RNRiveRendererType: String {
12 | case Rive = "rive"
13 | case CoreGraphics = "coreGraphics"
14 |
15 | static func mapToRNRiveRendererType(value: String) -> RNRiveRendererType {
16 | if let rnEnum = RNRiveRendererType(rawValue: value) {
17 | return rnEnum
18 | } else {
19 | fatalError("Unsupported renderer type: \(value)")
20 | }
21 | }
22 |
23 | static func mapToRendererType(rnRendererType: RNRiveRendererType) -> RendererType {
24 | switch rnRendererType {
25 | case .Rive:
26 | return RendererType.riveRenderer
27 | case .CoreGraphics:
28 | return RendererType.cgRenderer
29 | }
30 | }
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/ios/RiveReactNative-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import
4 | #import
5 | #import
6 | #import
7 | #import
8 | #import
9 |
--------------------------------------------------------------------------------
/ios/RiveReactNativeEventModule.h:
--------------------------------------------------------------------------------
1 | //
2 | // RiveReactNativeEventModule.h
3 | // RiveReactNative
4 | //
5 | // Created by Peter G Hayes on 05/05/2025.
6 | // Copyright © 2025 Facebook. All rights reserved.
7 | //
8 |
9 | #ifndef RiveReactNativeEventModule_h
10 | #define RiveReactNativeEventModule_h
11 |
12 | #import
13 | #import
14 |
15 | @interface RiveReactNativeEventModule : RCTEventEmitter
16 | - (BOOL)isListenerActive:(NSString *)eventName;
17 | - (void)removeListenerByName:(NSString *)eventName;
18 | @end
19 |
20 | #endif /* RiveReactNativeEventModule_h */
21 |
--------------------------------------------------------------------------------
/ios/RiveReactNativeEventModule.m:
--------------------------------------------------------------------------------
1 | //
2 | // RiveReactNativeEventModule.m
3 | // RiveReactNative
4 | //
5 | // Created by Peter G Hayes on 05/05/2025.
6 | // Copyright © 2025 Facebook. All rights reserved.
7 | //
8 |
9 | #import "RiveReactNativeEventModule.h"
10 |
11 | @implementation RiveReactNativeEventModule {
12 | BOOL hasListeners;
13 | NSMutableSet *_activeListeners;
14 | }
15 |
16 | RCT_EXPORT_MODULE();
17 |
18 | - (instancetype)init {
19 | self = [super init];
20 | if (self) {
21 | _activeListeners = [NSMutableSet new];
22 | }
23 | return self;
24 | }
25 |
26 | // Called by React Native to determine which listeners are supported in JS
27 | - (NSArray *)supportedEvents {
28 | return _activeListeners.allObjects;
29 | }
30 |
31 | // Called by React Native when a listener is added from JS
32 | - (void)addListener:(NSString *)eventName {
33 | [_activeListeners addObject:eventName];
34 | [super addListener:eventName];
35 | }
36 |
37 | // Called by React Native when removeListeners is called from JS
38 | // We intentionally do not clean up all the listeners in
39 | // _activeListeners, as this object is shared between all
40 | // created views. We only ever clean up particular listeners
41 | // tied to a view. See removeListenerByName.
42 | - (void)removeListeners:(double)count {
43 | [super removeListeners:count];
44 | }
45 |
46 | // Used to manually clean up the listeners when a view is disposed
47 | - (void)removeListenerByName:(NSString *)eventName {
48 | [_activeListeners removeObject:eventName];
49 | }
50 |
51 | // Used to determine if a particular listener has already been added.
52 | // Used in RiveReactNativeView to send a "loaded" event to JS when Rive
53 | // is ready, which we only want to do if the listener was actually added
54 | // from JS (as part of the useRive() hook).
55 | - (BOOL)isListenerActive:(NSString *)eventName {
56 | return [_activeListeners containsObject:eventName];
57 | }
58 |
59 | @end
60 |
--------------------------------------------------------------------------------
/ios/RiveReactNativeModule.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RiveReactNativeModule.swift
3 | // RiveReactNative
4 | //
5 | // Created by Peter G Hayes on 07/03/2025.
6 | // Copyright © 2025 Facebook. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | @objc(RiveReactNativeModule)
12 | class RiveReactNativeModule: NSObject, RCTBridgeModule {
13 | static func moduleName() -> String! {
14 | return "RiveReactNativeModule";
15 | }
16 |
17 | @objc weak var bridge: RCTBridge?
18 |
19 | @objc(getBooleanState:inputName:resolver:rejecter:)
20 | func getBooleanState(_ node: NSNumber, inputName: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) -> Void {
21 |
22 | DispatchQueue.main.async {
23 | guard let bridge = self.bridge,
24 | let view = bridge.uiManager.view(forReactTag: node) as? RiveReactNativeView else {
25 | rejecter("VIEW_NOT_FOUND", "Could not find RiveReactNativeView", nil)
26 | return
27 | }
28 | let value = view.getBooleanState(inputName: inputName)
29 | resolver(value)
30 | }
31 | }
32 |
33 | @objc(getNumberState:inputName:resolver:rejecter:)
34 | func getNumberState(_ node: NSNumber, inputName: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) -> Void {
35 |
36 | DispatchQueue.main.async {
37 | guard let bridge = self.bridge,
38 | let view = bridge.uiManager.view(forReactTag: node) as? RiveReactNativeView else {
39 | rejecter("VIEW_NOT_FOUND", "Could not find RiveReactNativeView", nil)
40 | return
41 | }
42 | let value = view.getNumberState(inputName: inputName)
43 | resolver(value)
44 | }
45 | }
46 |
47 | @objc(getBooleanStateAtPath:inputName:path:resolver:rejecter:)
48 | func getBooleanStateAtPath(_ node: NSNumber, inputName: String, path: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) -> Void {
49 |
50 | DispatchQueue.main.async {
51 | guard let bridge = self.bridge,
52 | let view = bridge.uiManager.view(forReactTag: node) as? RiveReactNativeView else {
53 | rejecter("VIEW_NOT_FOUND", "Could not find RiveReactNativeView", nil)
54 | return
55 | }
56 | let value = view.getBooleanStateAtPath(inputName: inputName, path: path)
57 | resolver(value)
58 | }
59 | }
60 |
61 | @objc(getNumberStateAtPath:inputName:path:resolver:rejecter:)
62 | func getNumberStateAtPath(_ node: NSNumber, inputName: String, path: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) -> Void {
63 |
64 | DispatchQueue.main.async {
65 | guard let bridge = self.bridge,
66 | let view = bridge.uiManager.view(forReactTag: node) as? RiveReactNativeView else {
67 | rejecter("VIEW_NOT_FOUND", "Could not find RiveReactNativeView", nil)
68 | return
69 | }
70 | let value = view.getNumberStateAtPath(inputName: inputName, path: path)
71 | resolver(value)
72 | }
73 | }
74 |
75 | // Required to register the module with React Native
76 | @objc static func requiresMainQueueSetup() -> Bool {
77 | return true
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/ios/RiveReactNativeModuleBridge.m:
--------------------------------------------------------------------------------
1 | //
2 | // RiveReactNativeModuleBridge.m
3 | // RiveReactNative
4 | //
5 | // Created by Peter G Hayes on 07/03/2025.
6 | // Copyright © 2025 Facebook. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface RCT_EXTERN_MODULE(RiveReactNativeModule, NSObject)
12 |
13 | RCT_EXTERN_METHOD(getBooleanState:(nonnull NSNumber *)node inputName:(nonnull NSString *)inputName resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
14 | RCT_EXTERN_METHOD(getNumberState:(nonnull NSNumber *)node inputName:(nonnull NSString *)inputName resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
15 | RCT_EXTERN_METHOD(getBooleanStateAtPath:(nonnull NSNumber *)node inputName:(nonnull NSString *)inputName path:(nonnull NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
16 | RCT_EXTERN_METHOD(getNumberStateAtPath:(nonnull NSNumber *)node inputName:(nonnull NSString *)inputName path:(nonnull NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/ios/RiveReactNativeRendererModule.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RiveReactNativeRendererModule.swift
3 | // rive-react-native
4 | //
5 | // Created by Peter G Hayes on 31/05/2024.
6 | //
7 |
8 | import Foundation
9 | import RiveRuntime
10 |
11 | @objc(RiveReactNativeRendererModule)
12 | class RiveReactNativeRendererModule: NSObject {
13 |
14 | @objc(defaultRenderer:androidRenderer:)
15 | func defaultRenderer(_ iosRenderer: String, androidRenderer: String) -> Void {
16 | let rnRendererType = RNRiveRendererType.mapToRNRiveRendererType(value: iosRenderer)
17 | RenderContextManager.shared().defaultRenderer = RNRiveRendererType.mapToRendererType(rnRendererType: rnRendererType)
18 | }
19 | // Required to register the module with React Native
20 | @objc static func requiresMainQueueSetup() -> Bool {
21 | return true
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/ios/RiveReactNativeRendererModuleBridge.m:
--------------------------------------------------------------------------------
1 | //
2 | // RiveReactNativeRendererModuleBridge.m
3 | // rive-react-native
4 | //
5 | // Created by Peter G Hayes on 31/05/2024.
6 | //
7 |
8 | #import
9 |
10 | @interface RCT_EXTERN_MODULE(RiveReactNativeRendererModule, NSObject)
11 |
12 | RCT_EXTERN_METHOD(defaultRenderer:(NSString *)iosRenderer androidRenderer:(NSString *)androidRenderer)
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/ios/RiveReactNativeViewManager.m:
--------------------------------------------------------------------------------
1 |
2 | #import
3 |
4 | @interface RCT_EXTERN_MODULE(RiveReactNativeViewManager, RCTViewManager)
5 |
6 | RCT_EXPORT_VIEW_PROPERTY(resourceName, NSString)
7 | RCT_EXPORT_VIEW_PROPERTY(url, NSString)
8 | RCT_EXPORT_VIEW_PROPERTY(fit, NSString)
9 | RCT_EXPORT_VIEW_PROPERTY(layoutScaleFactor, NSNumber)
10 | RCT_EXPORT_VIEW_PROPERTY(alignment, NSString)
11 | RCT_EXPORT_VIEW_PROPERTY(autoplay, BOOL)
12 | RCT_EXPORT_VIEW_PROPERTY(artboardName, NSString)
13 | RCT_EXPORT_VIEW_PROPERTY(referencedAssets, NSDictionary)
14 | RCT_EXPORT_VIEW_PROPERTY(dataBinding, NSDictionary)
15 | RCT_EXPORT_VIEW_PROPERTY(animationName, NSString)
16 | RCT_EXPORT_VIEW_PROPERTY(stateMachineName, NSString)
17 | RCT_EXPORT_VIEW_PROPERTY(isUserHandlingErrors, BOOL)
18 | RCT_EXPORT_VIEW_PROPERTY(onPlay, RCTDirectEventBlock)
19 | RCT_EXPORT_VIEW_PROPERTY(onPause, RCTDirectEventBlock)
20 | RCT_EXPORT_VIEW_PROPERTY(onStop, RCTDirectEventBlock)
21 | RCT_EXPORT_VIEW_PROPERTY(onLoopEnd, RCTDirectEventBlock)
22 | RCT_EXPORT_VIEW_PROPERTY(onStateChanged, RCTDirectEventBlock)
23 | RCT_EXPORT_VIEW_PROPERTY(onError, RCTDirectEventBlock)
24 | RCT_EXPORT_VIEW_PROPERTY(onRiveEventReceived, RCTDirectEventBlock)
25 |
26 | RCT_EXTERN_METHOD(play:(nonnull NSNumber *)node animationName:(nonnull NSString)animationName loop:(NSString)loopMode direction:(NSString)direction isStateMachine:(BOOL)isStateMachine)
27 | RCT_EXTERN_METHOD(pause:(nonnull NSNumber *)node)
28 | RCT_EXTERN_METHOD(stop:(nonnull NSNumber *)node)
29 | RCT_EXTERN_METHOD(reset:(nonnull NSNumber *)node)
30 | RCT_EXTERN_METHOD(fireState:(nonnull NSNumber *)node stateMachineName:(nonnull NSString)stateMachineName inputName:(nonnull NSString)inputName)
31 | RCT_EXTERN_METHOD(setBooleanState:(nonnull NSNumber *)node stateMachineName:(nonnull NSString)stateMachineName inputName:(nonnull NSString)inputName value:(BOOL)value)
32 | RCT_EXTERN_METHOD(setNumberState:(nonnull NSNumber *)node stateMachineName:(nonnull NSString)stateMachineName inputName:(nonnull NSString)inputName value:(nonnull NSNumber *)value)
33 | RCT_EXTERN_METHOD(fireStateAtPath:(nonnull NSNumber *)node inputName:(nonnull NSString)inputName path:(nonnull NSString)path)
34 | RCT_EXTERN_METHOD(setBooleanStateAtPath:(nonnull NSNumber *)node inputName:(nonnull NSString)inputName value:(BOOL)value path:(nonnull NSString)path)
35 | RCT_EXTERN_METHOD(setNumberStateAtPath:(nonnull NSNumber *)node inputName:(nonnull NSString)inputName value:(nonnull NSNumber *)value path:(nonnull NSString)path)
36 | RCT_EXTERN_METHOD(touchBegan:(nonnull NSNumber *)node x:(nonnull NSNumber*)x y:(nonnull NSNumber*)y)
37 | RCT_EXTERN_METHOD(touchMoved:(nonnull NSNumber *)node x:(nonnull NSNumber*)x y:(nonnull NSNumber*)y)
38 | RCT_EXTERN_METHOD(touchEnded:(nonnull NSNumber *)node x:(nonnull NSNumber*)x y:(nonnull NSNumber*)y)
39 | RCT_EXTERN_METHOD(touchCancelled:(nonnull NSNumber *)node x:(nonnull NSNumber*)x y:(nonnull NSNumber*)y)
40 | RCT_EXTERN_METHOD(setTextRunValue:(nonnull NSNumber *)node textRunName:(nonnull NSString)textRunName textRunValue:(nonnull NSString)textRunValue)
41 | RCT_EXTERN_METHOD(setTextRunValueAtPath:(nonnull NSNumber *)node textRunName:(nonnull NSString)textRunName textRunValue:(nonnull NSString)textRunValue path:(nonnull NSString)path)
42 | RCT_EXTERN_METHOD(setBooleanPropertyValue:(nonnull NSNumber *)node path:(nonnull NSString)path value:(BOOL)value)
43 | RCT_EXTERN_METHOD(setStringPropertyValue:(nonnull NSNumber *)node path:(nonnull NSString)path value:(nonnull NSString)value)
44 | RCT_EXTERN_METHOD(setNumberPropertyValue:(nonnull NSNumber *)node path:(nonnull NSString)path value:(nonnull NSNumber *)value)
45 | RCT_EXTERN_METHOD(setColorPropertyValue:(nonnull NSNumber *)node path:(nonnull NSString)path r:(nonnull NSNumber *)r g:(nonnull NSNumber *)g b:(nonnull NSNumber *)b a:(nonnull NSNumber *)a)
46 | RCT_EXTERN_METHOD(setEnumPropertyValue:(nonnull NSNumber *)node path:(nonnull NSString)path value:(nonnull NSString)value)
47 | RCT_EXTERN_METHOD(fireTriggerProperty:(nonnull NSNumber *)node path:(nonnull NSString)path)
48 | RCT_EXTERN_METHOD(registerPropertyListener:(nonnull NSNumber *)node path:(nonnull NSString)path propertyType:(nonnull NSString)propertyType)
49 | @end
50 |
51 |
--------------------------------------------------------------------------------
/ios/utility.swift:
--------------------------------------------------------------------------------
1 | func getRiveFile(resourceName: String, resourceExt: String=".riv") throws -> RiveFile {
2 | guard let url = Bundle.main.url(forResource: resourceName, withExtension: resourceExt) else {
3 | throw createFileNotFoundError()
4 | }
5 | return try importRiveFile(from: url)
6 | }
7 |
8 | func getRiveURLResource(from urlString: String) throws -> RiveFile {
9 | guard let url = URL.init(string: urlString) else {
10 | throw createIncorrectRiveURL(urlString)
11 |
12 | }
13 |
14 | return try importRiveFile(from: url)
15 | }
16 |
17 | func importRiveFile(from url: URL) throws -> RiveFile {
18 | guard var data = try? Data(contentsOf: url) else {
19 | throw createIncorrectRiveURL(url.absoluteString)
20 | }
21 | let bytes = [UInt8](data)
22 |
23 | return try data.withUnsafeMutableBytes{(riveBytes:UnsafeMutableRawBufferPointer) throws ->RiveFile in
24 | guard let rawPointer = riveBytes.baseAddress else {
25 | throw createMalformedFileError()
26 | }
27 | let pointer = rawPointer.bindMemory(to: UInt8.self, capacity: bytes.count)
28 |
29 | let riveFile = try RiveFile(bytes:pointer, byteLength: UInt64(bytes.count), loadCdn: true)
30 | return riveFile
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rive-react-native",
3 | "version": "9.3.4",
4 | "workspaces": [
5 | "example"
6 | ],
7 | "description": "Rive React Native",
8 | "source": "src/index.tsx",
9 | "main": "lib/commonjs/index.js",
10 | "module": "lib/module/index.js",
11 | "types": "lib/typescript/index.d.ts",
12 | "react-native": "src/index.tsx",
13 | "files": [
14 | "src",
15 | "lib",
16 | "android",
17 | "ios",
18 | "cpp",
19 | "rive-react-native.podspec",
20 | "!lib/typescript/example",
21 | "!android/build",
22 | "!ios/build",
23 | "!**/__tests__",
24 | "!**/__fixtures__",
25 | "!**/__mocks__"
26 | ],
27 | "scripts": {
28 | "test": "jest",
29 | "typescript": "tsc --noEmit",
30 | "lint": "eslint \"**/*.{js,ts,tsx}\"",
31 | "prepare": "bob build",
32 | "release": "release-it",
33 | "example": "yarn --cwd example",
34 | "pods": "cd example && pod-install --quiet",
35 | "bootstrap": "yarn example && yarn && yarn pods"
36 | },
37 | "keywords": [
38 | "react-native",
39 | "ios",
40 | "android"
41 | ],
42 | "repository": "https://github.com/rive-app/rive-react-native",
43 | "author": "TMaszko (https://github.com/rive-app/rive-react-native)",
44 | "license": "MIT",
45 | "bugs": {
46 | "url": "https://github.com/rive-app/rive-react-native/issues"
47 | },
48 | "homepage": "https://github.com/rive-app/rive-react-native#readme",
49 | "publishConfig": {
50 | "registry": "https://registry.npmjs.org/"
51 | },
52 | "devDependencies": {
53 | "@commitlint/config-conventional": "^19.5.0",
54 | "@react-native/eslint-config": "^0.73.1",
55 | "@release-it/conventional-changelog": "^9.0.2",
56 | "@types/jest": "^29.5.14",
57 | "@types/react": "~18.3.12",
58 | "@types/react-native": "0.72.2",
59 | "commitlint": "^17.0.2",
60 | "eslint": "^8.51.0",
61 | "eslint-config-prettier": "^9.0.0",
62 | "eslint-plugin-prettier": "^5.0.1",
63 | "husky": "^4.2.5",
64 | "jest": "^29.7.0",
65 | "metro-react-native-babel-preset": "^0.73.10",
66 | "pod-install": "^0.1.0",
67 | "prettier": "^3.0.3",
68 | "react-native-builder-bob": "^0.20.4",
69 | "release-it": "^17.10.0",
70 | "typescript": "^5.2.2"
71 | },
72 | "peerDependencies": {
73 | "react": "*",
74 | "react-native": "*"
75 | },
76 | "engines": {
77 | "node": ">=16"
78 | },
79 | "resolutions": {
80 | "@types/react": "^18.2.44",
81 | "conventional-changelog-conventionalcommits": "8.0.0"
82 | },
83 | "commitlint": {
84 | "extends": [
85 | "@commitlint/config-conventional"
86 | ]
87 | },
88 | "release-it": {
89 | "git": {
90 | "commitMessage": "chore: release ${version}",
91 | "tagName": "v${version}"
92 | },
93 | "npm": {
94 | "publish": true
95 | },
96 | "github": {
97 | "release": true
98 | },
99 | "plugins": {
100 | "@release-it/conventional-changelog": {
101 | "preset": {
102 | "name": "conventionalcommits"
103 | }
104 | }
105 | }
106 | },
107 | "eslintConfig": {
108 | "root": true,
109 | "extends": [
110 | "@react-native",
111 | "prettier"
112 | ],
113 | "rules": {
114 | "react/react-in-jsx-scope": "off",
115 | "prettier/prettier": [
116 | "error",
117 | {
118 | "quoteProps": "consistent",
119 | "singleQuote": true,
120 | "tabWidth": 2,
121 | "trailingComma": "es5",
122 | "useTabs": false
123 | }
124 | ]
125 | }
126 | },
127 | "eslintIgnore": [
128 | "node_modules/",
129 | "lib/"
130 | ],
131 | "prettier": {
132 | "quoteProps": "consistent",
133 | "singleQuote": true,
134 | "tabWidth": 2,
135 | "trailingComma": "es5",
136 | "useTabs": false
137 | },
138 | "react-native-builder-bob": {
139 | "source": "src",
140 | "output": "lib",
141 | "targets": [
142 | [
143 | "commonjs",
144 | {
145 | "esm": true
146 | }
147 | ],
148 | [
149 | "module",
150 | {
151 | "esm": true
152 | }
153 | ],
154 | [
155 | "typescript",
156 | {
157 | "project": "tsconfig.build.json",
158 | "esm": true
159 | }
160 | ]
161 | ]
162 | },
163 | "packageManager": "yarn@4.7.0"
164 | }
165 |
--------------------------------------------------------------------------------
/rive-react-native.podspec:
--------------------------------------------------------------------------------
1 | require "json"
2 |
3 | package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4 |
5 | Pod::Spec.new do |s|
6 | s.name = "rive-react-native"
7 | s.version = package["version"]
8 | s.summary = package["description"]
9 | s.homepage = package["homepage"]
10 | s.license = package["license"]
11 | s.authors = package["author"]
12 |
13 | s.platforms = { :ios => "14.0" }
14 | s.source = { :git => "https://github.com/rive-app/rive-react-native.git", :tag => "#{s.version}" }
15 |
16 | s.source_files = "ios/**/*.{h,m,mm,swift}"
17 |
18 | s.swift_version = "5.0"
19 |
20 | s.dependency "React-Core"
21 | s.dependency "RiveRuntime", "6.9.4"
22 | end
23 |
--------------------------------------------------------------------------------
/scripts/add_build_number.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | get_package_version() {
4 | PACKAGE_VERSION="$(awk -F'"' '/"version": ".+"/{ print $4; exit; }' package.json)"
5 | }
6 | get_package_version
7 |
8 | echo "$PACKAGE_VERSION"
9 |
--------------------------------------------------------------------------------
/scripts/bootstrap.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const child_process = require('child_process');
3 |
4 | const root = path.resolve(__dirname, '..');
5 | const args = process.argv.slice(2);
6 | const options = {
7 | cwd: process.cwd(),
8 | env: process.env,
9 | stdio: 'inherit',
10 | encoding: 'utf-8',
11 | };
12 |
13 | let result;
14 |
15 | if (process.cwd() !== root || args.length) {
16 | // We're not in the root of the project, or additional arguments were passed
17 | // In this case, forward the command to `yarn`
18 | result = child_process.spawnSync('yarn', args, options);
19 | } else {
20 | // If `yarn` is run without arguments, perform bootstrap
21 | result = child_process.spawnSync('yarn', ['bootstrap'], options);
22 | }
23 |
24 | process.exitCode = result.status;
25 |
--------------------------------------------------------------------------------
/src/__tests__/index.test.tsx:
--------------------------------------------------------------------------------
1 | it.todo('write a test');
2 |
--------------------------------------------------------------------------------
/src/helpers.ts:
--------------------------------------------------------------------------------
1 | import { RNRiveError, RNRiveErrorType } from './types';
2 |
3 | export type Without = { [P in Exclude]?: never };
4 | export type XOR = T | U extends object
5 | ? (Without & U) | (Without & T)
6 | : T | U;
7 |
8 | export function isEnum(
9 | enumType: EnumType,
10 | enumValue: string
11 | ): enumValue is EnumType[keyof EnumType] {
12 | return Object.values(enumType).includes(enumValue);
13 | }
14 |
15 | export function convertErrorFromNativeToRN(errorFromNative: {
16 | type: string;
17 | message: string;
18 | }): RNRiveError | null {
19 | if (isEnum(RNRiveErrorType, errorFromNative.type)) {
20 | return {
21 | type: errorFromNative.type,
22 | message: errorFromNative.message,
23 | };
24 | }
25 | return null;
26 | }
27 |
--------------------------------------------------------------------------------
/src/index.tsx:
--------------------------------------------------------------------------------
1 | export * from './types';
2 | import Rive, {
3 | RiveRenderer,
4 | useRive,
5 | useRiveString,
6 | useRiveNumber,
7 | useRiveBoolean,
8 | useRiveColor,
9 | useRiveEnum,
10 | useRiveTrigger,
11 | } from './Rive';
12 |
13 | export {
14 | RiveRenderer,
15 | useRive,
16 | useRiveString,
17 | useRiveNumber,
18 | useRiveBoolean,
19 | useRiveColor,
20 | useRiveEnum,
21 | useRiveTrigger,
22 | };
23 |
24 | export default Rive;
25 |
--------------------------------------------------------------------------------
/src/utils.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-bitwise */
2 | import { Image } from 'react-native';
3 | import type {
4 | FileAssetSource,
5 | PropertyType,
6 | RiveAssetPropType,
7 | RiveRGBA,
8 | } from './types';
9 |
10 | function parsePossibleSources(source: RiveAssetPropType): FileAssetSource {
11 | if (typeof source === 'number') {
12 | const resolvedAsset = Image.resolveAssetSource(source);
13 | if (resolvedAsset && resolvedAsset.uri) {
14 | return { sourceAssetId: resolvedAsset.uri };
15 | } else {
16 | throw new Error('Invalid asset source provided.');
17 | }
18 | }
19 |
20 | const uri = (source as any).uri;
21 | if (typeof source === 'object' && uri) {
22 | return { sourceUrl: uri };
23 | }
24 |
25 | const asset = (source as any).fileName;
26 | const path = (source as any).path;
27 |
28 | if (typeof source === 'object' && asset) {
29 | const result: FileAssetSource = { sourceAsset: asset };
30 |
31 | if (path) {
32 | result.path = path;
33 | }
34 |
35 | return result;
36 | }
37 |
38 | throw new Error('Invalid source provided.');
39 | }
40 |
41 | function parseColor(color: string): RiveRGBA {
42 | const hex = color.replace(/^#/, '');
43 |
44 | const isValidHex = /^[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$/.test(hex);
45 | if (!isValidHex) {
46 | console.warn(`Rive invalid hex color: ${color}`);
47 | return { r: 0, g: 0, b: 0, a: 255 };
48 | }
49 |
50 | let r = parseInt(hex.slice(0, 2), 16),
51 | g = parseInt(hex.slice(2, 4), 16),
52 | b = parseInt(hex.slice(4, 6), 16),
53 | a = 255;
54 |
55 | // Optionally parse alpha channel if present
56 | if (hex.length === 8) {
57 | a = parseInt(hex.slice(6, 8), 16);
58 | }
59 |
60 | return { r, g, b, a };
61 | }
62 |
63 | function intToRiveRGBA(colorValue: number): RiveRGBA {
64 | const a = (colorValue >> 24) & 0xff;
65 | const r = (colorValue >> 16) & 0xff;
66 | const g = (colorValue >> 8) & 0xff;
67 | const b = colorValue & 0xff;
68 | return { r, g, b, a };
69 | }
70 |
71 | export { parsePossibleSources, parseColor, intToRiveRGBA };
72 |
73 | export const getPropertyTypeString = (propertyType: PropertyType): string =>
74 | propertyType;
75 |
--------------------------------------------------------------------------------
/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig",
3 | "exclude": ["example", "lib"]
4 | }
5 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowUnreachableCode": false,
4 | "allowUnusedLabels": false,
5 | "esModuleInterop": true,
6 | "forceConsistentCasingInFileNames": true,
7 | "jsx": "react-native",
8 | "lib": ["esnext"],
9 | "module": "esnext",
10 | "moduleResolution": "node",
11 | "noFallthroughCasesInSwitch": true,
12 | "noImplicitReturns": true,
13 | "noStrictGenericChecks": false,
14 | "noUnusedLocals": true,
15 | "noUnusedParameters": true,
16 | "noUncheckedIndexedAccess": true,
17 | "resolveJsonModule": true,
18 | "skipLibCheck": true,
19 | "strict": false,
20 | "target": "esnext"
21 | },
22 | "include": [
23 | "src",
24 | "babel.config.js",
25 | ],
26 | "exclude": [
27 | "node_modules",
28 | "lib",
29 | ]
30 | }
--------------------------------------------------------------------------------
/version.txt:
--------------------------------------------------------------------------------
1 | 9.3.4
--------------------------------------------------------------------------------