├── .autorc ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitattributes ├── .github └── ISSUE_TEMPLATE │ └── bug_report.yml ├── .gitignore ├── .prettierrc.js ├── .yarn └── install-state.gz ├── CHANGELOG.md ├── LICENSE ├── README.md ├── assets ├── banner.png └── banner2.png ├── babel.config.js ├── docs ├── .gitignore ├── .yarn │ ├── install-state.gz │ └── releases │ │ └── yarn-4.1.0.cjs ├── .yarnrc.yml ├── README.md ├── babel.config.js ├── docs-samples │ ├── doc1.md │ ├── doc2.md │ ├── doc3.md │ └── mdx.md ├── docs │ ├── animate-presence.md │ ├── animations-overview.md │ ├── animations-repeat.md │ ├── animations-sequence.md │ ├── api │ │ ├── components.md │ │ ├── motify-svg.md │ │ ├── motify.md │ │ ├── props.md │ │ └── transforms.md │ ├── examples │ │ ├── action-menu.md │ │ ├── animate-presence.md │ │ ├── auto-height.md │ │ ├── dropdown.md │ │ ├── exit-before-enter.md │ │ ├── hello-world.md │ │ ├── image-gallery.md │ │ ├── loop.md │ │ ├── menu-icon.md │ │ ├── skeleton.md │ │ └── variants.md │ ├── hello-world.md │ ├── hooks │ │ ├── use-animation-state.md │ │ └── use-dynamic-animation.md │ ├── index.mdx │ ├── installation.md │ ├── interactions │ │ ├── eslint.md │ │ ├── merge.md │ │ ├── overview.mdx │ │ ├── pressable.md │ │ ├── use-pressable-animated-props.md │ │ ├── use-pressable-interpolate.md │ │ ├── use-pressable-transition.md │ │ ├── use-pressable.md │ │ └── use-pressables.md │ ├── next-js.md │ ├── reanimated.md │ ├── resources │ │ └── videos.md │ ├── skeleton.mdx │ ├── starter.md │ ├── svg.md │ └── web.md ├── docusaurus.config.js ├── package.json ├── sidebars.js ├── src │ ├── css │ │ └── custom.css │ ├── pages │ │ └── styles.module.css │ └── plugins │ │ └── remark-npm2yarn │ │ └── index.js ├── static │ ├── .nojekyll │ ├── font │ │ ├── Satoshi-Bold.ttf │ │ ├── Satoshi-Italic.ttf │ │ ├── Satoshi-Medium.ttf │ │ ├── Satoshi-MediumItalic.ttf │ │ └── Satoshi-Regular.ttf │ └── img │ │ ├── Banner Gradient.png │ │ ├── Banner Gradient.svg │ │ ├── Header Logo.svg │ │ ├── Interactions.png │ │ ├── Logo White (flipped).svg │ │ ├── Logo White.svg │ │ ├── banner.svg │ │ ├── favicon.ico │ │ ├── favicon.svg │ │ ├── logo-grad.svg │ │ ├── logo.svg │ │ ├── panda.png │ │ ├── panda.svg │ │ ├── undraw_docusaurus_mountain.svg │ │ ├── undraw_docusaurus_react.svg │ │ ├── undraw_docusaurus_tree.svg │ │ └── white-flipped.svg └── yarn.lock ├── examples ├── sample │ ├── .gitignore │ ├── .yarn │ │ └── install-state.gz │ ├── App.js │ ├── app.json │ ├── assets │ │ ├── adaptive-icon.png │ │ ├── favicon.png │ │ ├── icon.png │ │ └── splash.png │ ├── babel.config.js │ ├── metro.config.js │ ├── package.json │ ├── src │ │ ├── Bug.tsx │ │ ├── Color-Bug.tsx │ │ ├── Color.tsx │ │ ├── Drip.Color.tsx │ │ ├── Drip.Presence.tsx │ │ ├── Drip.Repeat.tsx │ │ ├── Drip.tsx │ │ ├── Easing.tsx │ │ ├── Example.tsx │ │ ├── Gallery.tsx │ │ ├── Headless-Exit.tsx │ │ ├── Ideas.tsx │ │ ├── Measure.tsx │ │ ├── Moti.Callbacks.tsx │ │ ├── Moti.ChangeVariants.tsx │ │ ├── Moti.DynamicAnimation.tsx │ │ ├── Moti.ExitBeforeEnter.tsx │ │ ├── Moti.Factory.tsx │ │ ├── Moti.Gallery.tsx │ │ ├── Moti.HelloWorld.tsx │ │ ├── Moti.KeyPresence.tsx │ │ ├── Moti.Loop.tsx │ │ ├── Moti.NewTransition.tsx │ │ ├── Moti.Presence.tsx │ │ ├── Moti.Pressable.tsx │ │ ├── Moti.PressableMenu.tsx │ │ ├── Moti.PressableTooltip.tsx │ │ ├── Moti.Progress.tsx │ │ ├── Moti.Sequence.tsx │ │ ├── Moti.SequenceLoop.tsx │ │ ├── Moti.Skeleton.tsx │ │ ├── Moti.Svg.tsx │ │ ├── Moti.Transform.tsx │ │ ├── Moti.Variants.tsx │ │ ├── Perf.List.tsx │ │ ├── Reanimated.Bg-Bug.tsx │ │ ├── Reanimated.Width-Bug.tsx │ │ ├── Repeat.tsx │ │ ├── Sequence.Bug.tsx │ │ └── Web.tsx │ ├── tsconfig.json │ └── yarn.lock └── with-next │ ├── .gitignore │ ├── App.tsx │ ├── CHANGELOG.md │ ├── README.md │ ├── app.json │ ├── babel.config.js │ ├── next-env.d.ts │ ├── next.config.js │ ├── package.json │ ├── pages │ ├── _app.js │ ├── _document.js │ └── index.tsx │ └── tsconfig.json ├── lerna-debug.log ├── lerna.json ├── license.md ├── package.json ├── packages └── moti │ ├── .eslintrc.js │ ├── CHANGELOG.md │ ├── README.md │ ├── author │ ├── index.d.ts │ └── index.js │ ├── index.d.ts │ ├── interactions │ ├── index.d.ts │ ├── index.js │ └── index.js.map │ ├── metro.config.js │ ├── package.json │ ├── skeleton │ ├── index.d.ts │ ├── index.js │ └── react-native-linear-gradient.js │ ├── src │ ├── author │ │ └── index.ts │ ├── components │ │ ├── image.tsx │ │ ├── index.ts │ │ ├── progress │ │ │ └── index.tsx │ │ ├── safe-area-view.tsx │ │ ├── scroll-view.tsx │ │ ├── text.tsx │ │ └── view.tsx │ ├── core │ │ ├── constants │ │ │ ├── color-keys.ts │ │ │ ├── index.ts │ │ │ └── package-name.ts │ │ ├── index.ts │ │ ├── motify.tsx │ │ ├── types.ts │ │ ├── use-animator │ │ │ └── index.ts │ │ ├── use-dynamic-animation │ │ │ └── index.ts │ │ └── use-motify.ts │ ├── index.tsx │ ├── interactions │ │ ├── index.ts │ │ └── pressable │ │ │ ├── context.tsx │ │ │ ├── hoverable-context.tsx │ │ │ ├── hoverable.native.tsx │ │ │ ├── hoverable.tsx │ │ │ ├── index.tsx │ │ │ ├── merge-refs.ts │ │ │ ├── merge.ts │ │ │ ├── pressable.tsx │ │ │ ├── types.ts │ │ │ ├── use-moti-pressable-animated-props.ts │ │ │ ├── use-moti-pressable-interpolate.ts │ │ │ ├── use-moti-pressable-transition.ts │ │ │ ├── use-pressable.ts │ │ │ ├── use-pressables.ts │ │ │ └── use-validate-factory-or-id.ts │ ├── skeleton │ │ ├── expo.tsx │ │ ├── index.ts │ │ ├── native.tsx │ │ ├── shared.ts │ │ ├── skeleton-new.tsx │ │ ├── skeleton.tsx │ │ └── types.ts │ └── svg │ │ ├── index.ts │ │ └── motify-svg.tsx │ ├── svg │ ├── index.d.ts │ └── index.js │ └── tsconfig.json ├── tsconfig.json ├── tsconfig.tsbuildinfo └── yarn.lock /.autorc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["npm", "slack", "twitter", "all-contibutors", "first-time-contributor", "released"] 3 | } -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | lib 2 | example -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | // generated by @nandorojo/lint-expo 2 | { 3 | "rules": { 4 | "react-hooks/exhaustive-deps": [ 5 | "warn", 6 | { 7 | "additionalHooks": "(useDerivedValue|useAnimatedStyle|useAnimatedProps)" 8 | } 9 | ], 10 | "@typescript-eslint/array-type": "off" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | # specific for windows script files 3 | *.bat text eol=crlf -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: 🐞 🐞 🐞 🐞 🐞 3 | labels: [Bug, Needs Triage] 4 | body: 5 | - type: checkboxes 6 | attributes: 7 | label: Is there an existing issue for this? 8 | description: Please search to see if an issue already exists for the bug you encountered. 9 | options: 10 | - label: I have searched the existing issues 11 | required: true 12 | - type: checkboxes 13 | attributes: 14 | label: Do you want this issue prioritized? 15 | description: If this issue is urgent, you can add prioritize it via a sponsorship on GitHub. Feel free to tag @nandorojo here in the issue description if you sponsor. 16 | options: 17 | - label: Yes, I have sponsored 18 | - label: Not urgent 19 | - type: textarea 20 | attributes: 21 | label: Current Behavior 22 | description: Describe what's happening in 1-2 sentences. 23 | validations: 24 | required: false 25 | - type: textarea 26 | attributes: 27 | label: Expected Behavior 28 | description: A concise description of what you expected to happen. 29 | validations: 30 | required: false 31 | - type: textarea 32 | attributes: 33 | label: Steps To Reproduce 34 | description: Steps to reproduce the behavior. 35 | placeholder: | 36 | 1. Add a MotiView component... 37 | 2. Change to Animated.View... 38 | validations: 39 | required: false 40 | - type: textarea 41 | attributes: 42 | label: Versions 43 | description: | 44 | examples: 45 | - **Moti**: 0.18.0 46 | - **Reanimated**: 2.5.0 47 | - **React Native**: 0.68.0 48 | value: | 49 | - Moti: 50 | - Reanimated: 51 | - React Native: 52 | render: markdown 53 | validations: 54 | required: true 55 | - type: textarea 56 | attributes: 57 | label: Screenshots 58 | description: | 59 | Please add screenshots / videos that show the behavior if applicable. 60 | validations: 61 | required: false 62 | - type: textarea 63 | attributes: 64 | label: Reproduction 65 | description: | 66 | Please add a link to an Expo Snack or a **minimal reproduction**. 67 | 68 | If you can reproduce on Web, the easiest way to share a reproduction is by forking the StackBlitz starter. 69 | 70 | If the issue only happens on native, you can use the starter app: 71 | 72 | ```sh 73 | npx create-react-native-app -t with-moti 74 | ``` 75 | validations: 76 | required: true 77 | -------------------------------------------------------------------------------- /.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 | 32 | # Android/IJ 33 | # 34 | .idea 35 | .gradle 36 | local.properties 37 | android.iml 38 | 39 | # Cocoapods 40 | # 41 | example/ios/Pods 42 | 43 | # node.js 44 | # 45 | node_modules/ 46 | npm-debug.log 47 | yarn-debug.log 48 | yarn-error.log 49 | 50 | # BUCK 51 | buck-out/ 52 | \.buckd/ 53 | android/app/libs 54 | android/keystores/debug.keystore 55 | 56 | # Expo 57 | .expo/* 58 | 59 | # generated by bob 60 | lib/ 61 | 62 | 63 | # Expo 64 | **/web-build 65 | **/.expo 66 | .env 67 | 68 | **/*/ios 69 | 70 | # CocoaPods 71 | Pods 72 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | // generated by @nandorojo/lint-expo 2 | module.exports = { 3 | tabWidth: 2, 4 | useTabs: false, 5 | semi: false, 6 | singleQuote: true, 7 | } 8 | -------------------------------------------------------------------------------- /.yarn/install-state.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/.yarn/install-state.gz -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022 Fernando Rojo. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | The universal React Native animation library, powered by Reanimated 3. 4 | 5 | ```jsx 6 | 7 | ``` 8 | 9 | # Documentation & Examples 10 | 11 | - [Documentation](https://moti.fyi) 12 | - [Installation](https://moti.fyi/installation) 13 | - [Examples](https://moti.fyi/examples/hello-world) *(please use Chrome, other browsers are partially supported)* 14 | 15 | ## Next.js Conf 16 | 17 | Screen Shot 2021-10-22 at 3 00 05 PM 22 | 23 | I spoke at at [Next.js Conf 2021](https://fernandorojo.co/conf) on October 26 about React Native + Next.js. [Watch the video](https://t.co/LkmxHXVz3K?amp=1) to see how we do it. 24 | 25 | # Highlights 26 | 27 | - Universal: works on all platforms 28 | - 60 FPS animations on the native thread 29 | - Mount/unmount animations, like `framer-motion` 30 | - Powered by Reanimated 3 31 | - Web support, out-of-the-box 32 | - Expo support 33 | - Intuitive API 34 | - Variants 35 | - Strong TypeScript support 36 | - Highly-configurable animations 37 | - Sequence animations 38 | - Loop & repeat animations 39 | 40 | # Preview 41 | 42 | - [API](https://twitter.com/FernandoTheRojo/status/1348093995277299712) 43 | - [Unmount animations with `exit`](https://twitter.com/FernandoTheRojo/status/1349884929765765123) 44 | - [`exitBeforeEnter` animations](https://twitter.com/FernandoTheRojo/status/1351234878902333445) 45 | 46 | # Follow 47 | 48 | Follow me [on Twitter](https://twitter.com/fernandotherojo) to stay up to date. 49 | 50 | # Sponsor 51 | 52 | Sponsorships via GitHub are appreciated. 53 | 54 | 55 | Analytics by Splitbee.io 56 | 57 | 58 | # License 59 | 60 | Moti has an MIT license. That said, a lot of free work goes into it, so if your company uses it, please sponsor, write a blog post, or tweet about it! 61 | -------------------------------------------------------------------------------- /assets/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/assets/banner.png -------------------------------------------------------------------------------- /assets/banner2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/assets/banner2.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["module:metro-react-native-babel-preset"], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /docs/.yarn/install-state.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/docs/.yarn/install-state.gz -------------------------------------------------------------------------------- /docs/.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | 3 | yarnPath: .yarn/releases/yarn-4.1.0.cjs 4 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://v2.docusaurus.io/), a modern static website generator. 4 | 5 | ## Installation 6 | 7 | ```console 8 | yarn install 9 | ``` 10 | 11 | ## Local Development 12 | 13 | ```console 14 | yarn start 15 | ``` 16 | 17 | This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ## Build 20 | 21 | ```console 22 | yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ## Deployment 28 | 29 | ```console 30 | GIT_USER= USE_SSH=true yarn deploy 31 | ``` 32 | 33 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 34 | -------------------------------------------------------------------------------- /docs/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/docs-samples/doc2.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: doc2 3 | title: Document Number 2 4 | --- 5 | 6 | This is a link to [another document.](doc3.md) This is a link to an [external page.](http://www.example.com/) 7 | -------------------------------------------------------------------------------- /docs/docs-samples/doc3.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: doc3 3 | title: This is Document Number 3 4 | --- 5 | 6 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ac euismod odio, eu consequat dui. Nullam molestie consectetur risus id imperdiet. Proin sodales ornare turpis, non mollis massa ultricies id. Nam at nibh scelerisque, feugiat ante non, dapibus tortor. Vivamus volutpat diam quis tellus elementum bibendum. Praesent semper gravida velit quis aliquam. Etiam in cursus neque. Nam lectus ligula, malesuada et mauris a, bibendum faucibus mi. Phasellus ut interdum felis. Phasellus in odio pulvinar, porttitor urna eget, fringilla lectus. Aliquam sollicitudin est eros. Mauris consectetur quam vitae mauris interdum hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 7 | 8 | Duis et egestas libero, imperdiet faucibus ipsum. Sed posuere eget urna vel feugiat. Vivamus a arcu sagittis, fermentum urna dapibus, congue lectus. Fusce vulputate porttitor nisl, ac cursus elit volutpat vitae. Nullam vitae ipsum egestas, convallis quam non, porta nibh. Morbi gravida erat nec neque bibendum, eu pellentesque velit posuere. Fusce aliquam erat eu massa eleifend tristique. 9 | 10 | Sed consequat sollicitudin ipsum eget tempus. Integer a aliquet velit. In justo nibh, pellentesque non suscipit eget, gravida vel lacus. Donec odio ante, malesuada in massa quis, pharetra tristique ligula. Donec eros est, tristique eget finibus quis, semper non nisl. Vivamus et elit nec enim ornare placerat. Sed posuere odio a elit cursus sagittis. 11 | 12 | Phasellus feugiat purus eu tortor ultrices finibus. Ut libero nibh, lobortis et libero nec, dapibus posuere eros. Sed sagittis euismod justo at consectetur. Nulla finibus libero placerat, cursus sapien at, eleifend ligula. Vivamus elit nisl, hendrerit ac nibh eu, ultrices tempus dui. Nam tellus neque, commodo non rhoncus eu, gravida in risus. Nullam id iaculis tortor. 13 | 14 | Nullam at odio in sem varius tempor sit amet vel lorem. Etiam eu hendrerit nisl. Fusce nibh mauris, vulputate sit amet ex vitae, congue rhoncus nisl. Sed eget tellus purus. Nullam tempus commodo erat ut tristique. Cras accumsan massa sit amet justo consequat eleifend. Integer scelerisque vitae tellus id consectetur. 15 | -------------------------------------------------------------------------------- /docs/docs-samples/mdx.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: mdx 3 | title: Powered by MDX 4 | --- 5 | 6 | You can write JSX and use React components within your Markdown thanks to [MDX](https://mdxjs.com/). 7 | 8 | export const Highlight = ({children, color}) => ( {children} ); 14 | 15 | Docusaurus green and Facebook blue are my favorite colors. 16 | 17 | I can write **Markdown** alongside my _JSX_! 18 | -------------------------------------------------------------------------------- /docs/docs/animate-presence.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/docs/docs/animate-presence.md -------------------------------------------------------------------------------- /docs/docs/animations-repeat.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/docs/docs/animations-repeat.md -------------------------------------------------------------------------------- /docs/docs/animations-sequence.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/docs/docs/animations-sequence.md -------------------------------------------------------------------------------- /docs/docs/api/components.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: imports 3 | title: Imports 4 | --- 5 | 6 | Currently, moti exports typical React Native components. 7 | 8 | You can import like so: 9 | 10 | ```ts 11 | import { MotiView, MotiText, MotiScrollView, MotiSafeAreaView, MotiImage } from 'moti' 12 | ``` 13 | 14 | Which looks like this in use: 15 | 16 | ```tsx 17 | 18 | ``` 19 | -------------------------------------------------------------------------------- /docs/docs/api/motify-svg.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: motify-svg 3 | title: motifySvg() 4 | --- 5 | 6 | ```tsx 7 | import { motifySvg } from 'moti/svg' 8 | ``` 9 | 10 | A higher-order component that turns any React Native SVG component into an animated `moti` component. It's the same as `motify`, but for SVG elements. 11 | 12 | ```ts 13 | import { motifySvg } from 'moti/svg' 14 | import { Svg, Rect } from 'react-native-svg' 15 | 16 | const MotiRect = motifySvg(Rect)() 17 | ``` 18 | 19 | You can now pass any SVG props to the `animate` property, and they will animate there: 20 | 21 | ```tsx 22 | 36 | ``` 37 | 38 | This functionality is compatible with all Moti features, including hooks like `useDynamicAnimation`: 39 | 40 | ```tsx 41 | import { Rect } from 'react-native-svg' 42 | import { motifySvg } from 'moti/svg' 43 | import { useDynamicAnimation } from 'moti' 44 | 45 | const MotiRect = motifySvg(Rect)() 46 | 47 | export default function App() { 48 | const animation = useDynamicAnimation>(() => ({ 49 | x: 0, 50 | })) 51 | 52 | return 53 | } 54 | ``` 55 | 56 | ## How it works 57 | 58 | Under the hood, `motifySvg` runs `Animated.createAnimatedComponent` for you, so don't call that yourself. 59 | 60 | Instead, just pass a normal `View` (or its equivalent). 61 | 62 | Notice that `motifySvg()` returns a function. At the moment, the function it returns doesn't take any arguments. But I like this composition pattern, so I built the API this way to account for using the returned function in the future. 63 | -------------------------------------------------------------------------------- /docs/docs/api/motify.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: motify 3 | title: motify() 4 | --- 5 | 6 | ```ts 7 | import { motify } from 'moti' 8 | 9 | const MotifiedComponent = motify(MyComponent)() 10 | ``` 11 | 12 | A higher-order component that turns any React Native class component into an animated `moti` component. 13 | 14 | You can now animate like you normally would: 15 | 16 | ```tsx 17 | // height sequence animation 18 | 19 | ``` 20 | 21 | Under the hood, `motify` runs `Animated.createAnimatedComponent` for you, so don't pass an `Animated.View`. 22 | 23 | Instead, just pass a normal `View` (or its equivalent). 24 | 25 | Notice that `motify()` returns a function. At the moment, the function it returns doesn't take any arguments. But I like this composition pattern, so I built the API this way to account for using the returned function in the future. 26 | 27 | ## Context 28 | 29 | `motify` is the function that Moti uses under the hood to create its primitives. 30 | 31 | This is the component file in `moti`: 32 | 33 | ```tsx 34 | import { motify } from '../moti' 35 | import { 36 | View as RView, 37 | Text as RText, 38 | Image as RImage, 39 | ScrollView as RScrollView, 40 | SafeAreaView as RSafeAreaView, 41 | } from 'react-native' 42 | 43 | export const View = motify(RView)() 44 | export const Text = motify(RText)() 45 | export const Image = motify(RImage)() 46 | export const ScrollView = motify(RScrollView)() 47 | export const SafeAreaView = motify(RSafeAreaView)() 48 | ``` 49 | 50 | That should be all you need for any custom usage. 51 | 52 | - Fernando Rojo 53 | -------------------------------------------------------------------------------- /docs/docs/api/props.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: props 3 | title: Component Props 4 | sidebar_label: Component Props 5 | --- 6 | 7 | All `moti` components have a few useful props: 8 | 9 | - `animate` Magically animate any value passed here. 10 | - `from` The initial animation styles when the component mounts. 11 | - `exit` Unmount animation styles. This works the exact same as `framer-motion`'s exit prop, and requires wrapping your component with `AnimatePresence`. The only difference is you import `AnimatePresence` from `moti`. 12 | - `transition` Take full control over your animation configuration. You can set options for your entire animation (such as `type: 'timing'`), or set transition options per-style (`translateY: { type: 'timing' }`). 13 | - `exitTransition` The exact same as `transition`, except that it only applies to `exit` animations. 14 | - `state` If you're using the `useAnimationState` hook, you should pass the state it returns to this prop. 15 | - `onDidAnimate` Callback function called after finishing a given animation. 16 | - First argument is the style prop string (`opacity`, `scale`, etc.) 17 | - The second argument is whether the animation `finished` or not (boolean) 18 | - The third argument is `value`, which only exists in a sequence. 19 | - The fourth argument is an event dictionary. 20 | - It has an `attemptedValue` field, which indicates the value that the animation tried to get to. 21 | - This is probably a better field to check for than the third argument. 22 | - As long as the second argument, `finished`, is `true`, then the `attemptedValue` represents that the value that was animated to. 23 | 24 | ## `exitTransition` 25 | 26 |
34 | 50 |
51 | 52 | Define animation configurations for exiting components. 53 | 54 | Options passed to `exitTransition` will only apply to the `exit` prop, when a component is exiting. 55 | 56 | ```jsx 57 | 65 | ``` 66 | 67 | By default, `exit` uses `transition` to configure its animations, so this prop is not required. 68 | 69 | However, if you pass `exitTransition`, it will override `transition` for exit animations. 70 | 71 | To see how to use this prop, see the `transition` docs. 72 | -------------------------------------------------------------------------------- /docs/docs/api/transforms.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: transforms 3 | title: Transforms 4 | --- 5 | 6 | Moti has the same API for transforms as a normal React Native component. 7 | 8 | It also comes with some added convenience. 9 | 10 | Like always, you can use a `transform` array: 11 | 12 | ```tsx 13 | 21 | ``` 22 | 23 | Writing a transform array can be bulky. You can also pass your transforms directly: 24 | 25 | ```tsx 26 | 34 | ``` 35 | 36 | ## Using multiple transforms 37 | 38 | If you're using multiple transforms, be sure to retain their order inside of each prop. 39 | 40 | ```tsx 41 | // ✅ scale first, then translateX 42 | 52 | ``` 53 | 54 | > This only works with Reanimated `2.3.0`+. For older versions, scroll down. 55 | 56 | This will break your animation, since they have different orders: 57 | 58 | ```tsx 59 | // 🚨 from & animate don't have the same orders for transforms! 60 | // this will break 61 | 71 | ``` 72 | 73 | If you prefer to use an array for multiple transforms, you can do that too. Be sure to retain the order of your transforms across props. 74 | 75 | ```tsx 76 | 84 | ``` 85 | 86 | ## Using multiple transforms (on old versions of Reanimated) 87 | 88 | > The following only applies if you're using Reanimated `2.2` or older. As of `2.3.0`, you can use multiple transforms without an array if you want. 89 | 90 | If you're using multiple transforms together, such as `scale` and `translateY`, and you're using Reanimated `2.2` or older, you _must_ use an array. 91 | 92 | This example is okay, since `scale` is the only transform: 93 | 94 | ```tsx 95 | // ✅ if you're only using one transform 96 | 104 | ``` 105 | 106 | But this won't work: 107 | 108 | ```tsx 109 | // 🚨 if you're only using multiple transforms, use an array 110 | 120 | ``` 121 | 122 | Instead, pass `transform` arrays. 123 | 124 | ```tsx 125 | // ✅ for multiple transforms, use an array 126 | 141 | ``` 142 | 143 | Make sure the order in the `from` and `animate` prop is the same. In this case, we put `scale` before `translateY`. 144 | 145 | ## Sequences 146 | 147 | Sequences for `transform` works like normal. Simply pass an array in place of your value 148 | 149 | ```tsx 150 | 155 | ``` 156 | 157 | That's equivalent to doing this: 158 | 159 | ```tsx 160 | 165 | ``` 166 | -------------------------------------------------------------------------------- /docs/docs/examples/action-menu.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: action-menu 3 | title: Action Menu 4 | hide_title: true 5 | hide_table_of_contents: true 6 | --- 7 | 8 | 13 | 14 | For more info on Fernando's talk, head to [fernandorojo.co/conf](https://fernandorojo.co/conf). 15 | 16 | ## Moti Animations in 4 min 17 | 18 | A great overview of Moti by [Arunaud, AKA Evening Kid](https://twitter.com/eveningkid). 19 | 20 | 21 | 22 | Check out Evening Kid's [YouTube channel](https://www.youtube.com/c/eveningkid) for more React Native content. 23 | 24 | ## Can Moti simplify React Native animations? 25 | 26 | [Evening Kid](https://twitter.com/eveningkid) takes us through Moti's potential to simplify performant animations. 27 | 28 | 29 | 30 | ## Live Stream: Fernando Rojo & Catalin Miron 31 | 32 | When Fernando Rojo released Moti in February 2021, [Catalin Miron](https://twitter.com/mironcatalin) invited him onto his popular YouTube channel for a (nearly) 2 hour walk through. 33 | 34 | 35 | 36 | ## Catalin Miron Tutorials 37 | 38 | [Catalin Miron](https://twitter.com/mironcatalin) has a number of great tutorials that show the power of Moti. 39 | 40 | ### Phone Ring Indicator Wave with Moti 41 | 42 | 43 | 44 | ### Loading indicator with Moti 45 | 46 | 47 | 48 | ### 🎛 Custom Animated Switch component with Moti 49 | 50 | 51 | -------------------------------------------------------------------------------- /docs/docs/starter.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: starter 3 | title: Moti Starter Project 4 | sidebar_label: Starter Project 5 | --- 6 | 7 | If you're starting a project from scratch, or just want to play around, you can use the Expo + Moti [starter template](https://github.com/expo/examples/tree/master/with-moti). 8 | 9 | ```sh 10 | npx create-react-native-app -t with-moti 11 | ``` 12 | 13 | Thanks to Evan Bacon for making that! 14 | -------------------------------------------------------------------------------- /docs/docs/svg.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: SVG Animations 3 | --- 4 | 5 | As of `0.23`, Moti has built-in support for animating SVG elements with [`motifySvg`](/api/motify-svg). 6 | -------------------------------------------------------------------------------- /docs/docs/web.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: web 3 | title: Web Support 4 | sidebar_label: Web Support 5 | --- 6 | 7 | Moti works on all platforms, including Web. Make sure you've installed `react-native-web`. 8 | 9 | ## Expo Web support 10 | 11 | Expo Web should work out of the box. 12 | 13 | ## Expo Router / Metro Web 14 | 15 | You'll need to add `mjs` to your `sourceExts` in `metro.config.js`. For example: 16 | 17 | ```js 18 | const { getDefaultConfig } = require('expo/metro-config'); 19 | 20 | const config = getDefaultConfig(__dirname); 21 | 22 | config.resolver.assetExts.push( 23 | 'mjs’ 24 | ); 25 | 26 | module.exports = config; 27 | ``` 28 | 29 | ### Troubleshooting 30 | 31 | If you get the following Reanimated error in your console: `ReferenceError: _frameTimestamp is not defined`, you can add add this to `App.js` at the top: 32 | 33 | ```ts 34 | import { Platform } from 'react-native' 35 | if (Platform.OS === 'web') { 36 | global._frameTimestamp = null 37 | } 38 | ``` 39 | 40 | This should go away in Reanimated v3. See [react-native-reanimated#3355](https://github.com/software-mansion/react-native-reanimated/issues/3355). 41 | 42 | ## Vanilla React Native Web 43 | 44 | You may need to add a custom `webpack.config.js` to your project and export the config from `@expo/webpack-config`. 45 | 46 | 70 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "NODE_OPTIONS='--openssl-legacy-provider' docusaurus start", 8 | "build": "NODE_OPTIONS='--openssl-legacy-provider' docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "serve": "docusaurus serve", 12 | "clear": "docusaurus clear" 13 | }, 14 | "dependencies": { 15 | "@docusaurus/core": "^2", 16 | "@docusaurus/preset-classic": "^2", 17 | "@mdx-js/react": "^1.6.21", 18 | "clsx": "^1.1.1", 19 | "react": "17.0.1", 20 | "react-dom": "17.0.1" 21 | }, 22 | "browserslist": { 23 | "production": [ 24 | ">0.5%", 25 | "not dead", 26 | "not op_mini all" 27 | ], 28 | "development": [ 29 | "last 1 chrome version", 30 | "last 1 firefox version", 31 | "last 1 safari version" 32 | ] 33 | }, 34 | "packageManager": "yarn@4.1.0" 35 | } 36 | -------------------------------------------------------------------------------- /docs/sidebars.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | someSidebar: { 3 | Welcome: ['welcome', 'installation', 'starter', 'hello-world'], 4 | Usage: ['animations', 'api/transforms', 'reanimated', 'svg'], 5 | Examples: [ 6 | 'examples/hello-world', 7 | 'examples/animate-presence', 8 | 'examples/image-gallery', 9 | 'examples/menu-icon', 10 | // 'examples/auto-height', 11 | 'examples/exit-before-enter', 12 | 'examples/loop', 13 | 'examples/variants', 14 | // 'examples/dropdown', 15 | 'examples/action-menu', 16 | 'examples/skeleton', 17 | ], 18 | Hooks: ['hooks/use-animation-state', 'hooks/use-dynamic-animation'], 19 | ['Interactions']: [ 20 | 'interactions/overview', 21 | 'interactions/pressable', 22 | 'interactions/use-pressable', 23 | 'interactions/use-pressables', 24 | 'interactions/use-pressable-animated-props', 25 | 'interactions/use-pressable-transition', 26 | 'interactions/use-pressable-interpolate', 27 | 'interactions/merge', 28 | 'interactions/eslint', 29 | ], 30 | Skeleton: ['skeleton'], 31 | 32 | Resources: ['resources/videos'], 33 | Web: ['web', 'next'], 34 | 'API Reference': [ 35 | 'api/motify', 36 | 'api/motify-svg', 37 | 'api/imports', 38 | 'api/props', 39 | ], 40 | }, 41 | } 42 | -------------------------------------------------------------------------------- /docs/src/pages/styles.module.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | 3 | /** 4 | * CSS files with the .module.css suffix will be treated as CSS modules 5 | * and scoped locally. 6 | */ 7 | 8 | .heroBanner { 9 | padding: 4rem 0; 10 | text-align: center; 11 | position: relative; 12 | overflow: hidden; 13 | min-height: calc(100vh - 4rem); 14 | background-color: var(--ifm-color-background); 15 | color: var(--ifm-color-text); 16 | } 17 | 18 | .hero__primary .hero__title { 19 | font-size: 3rem; 20 | } 21 | 22 | @media screen and (max-width: 966px) { 23 | .heroBanner { 24 | padding: 2rem; 25 | } 26 | } 27 | 28 | .buttons { 29 | display: flex; 30 | align-items: center; 31 | justify-content: center; 32 | } 33 | 34 | .features { 35 | display: flex; 36 | align-items: center; 37 | padding: 2rem 0; 38 | width: 100%; 39 | } 40 | 41 | .featureImage { 42 | height: 200px; 43 | width: 200px; 44 | } 45 | -------------------------------------------------------------------------------- /docs/src/plugins/remark-npm2yarn/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // This is a very naive implementation of converting npm commands to yarn commands 9 | // Works well for our use case since we only use either 'npm install', or 'npm run ' 10 | // Its impossible to convert it right since some commands at npm are not available in yarn and vice/versa 11 | const convertNpmToYarn = (npmCode) => { 12 | // global install: 'npm i' -> 'yarn' 13 | return ( 14 | npmCode 15 | .replace(/^npm i$/gm, 'yarn') 16 | // install: 'npm install foo' -> 'yarn add foo' 17 | .replace(/npm install/gm, 'yarn add') 18 | // run command: 'npm run start' -> 'yarn run start' 19 | .replace(/npm run/gm, 'yarn run') 20 | ) 21 | } 22 | 23 | const transformNode = (node) => { 24 | const npmCode = node.value 25 | const yarnCode = convertNpmToYarn(node.value) 26 | return [ 27 | { 28 | type: 'jsx', 29 | value: 30 | ` 36 | `, 37 | }, 38 | { 39 | type: node.type, 40 | lang: node.lang, 41 | value: npmCode, 42 | }, 43 | { 44 | type: 'jsx', 45 | value: '\n', 46 | }, 47 | { 48 | type: node.type, 49 | lang: node.lang, 50 | value: yarnCode, 51 | }, 52 | { 53 | type: 'jsx', 54 | value: '\n', 55 | }, 56 | ] 57 | } 58 | 59 | const matchNode = (node) => node.type === 'code' && node.meta === 'npm2yarn' 60 | const nodeForImport = { 61 | type: 'import', 62 | value: 63 | "import Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';", 64 | } 65 | 66 | module.exports = () => { 67 | let transformed = false 68 | const transformer = (node) => { 69 | if (matchNode(node)) { 70 | transformed = true 71 | return transformNode(node) 72 | } 73 | if (Array.isArray(node.children)) { 74 | let index = 0 75 | while (index < node.children.length) { 76 | const result = transformer(node.children[index]) 77 | if (result) { 78 | node.children.splice(index, 1, ...result) 79 | index += result.length 80 | } else { 81 | index += 1 82 | } 83 | } 84 | } 85 | if (node.type === 'root' && transformed) { 86 | node.children.unshift(nodeForImport) 87 | } 88 | return null 89 | } 90 | return transformer 91 | } 92 | -------------------------------------------------------------------------------- /docs/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/docs/static/.nojekyll -------------------------------------------------------------------------------- /docs/static/font/Satoshi-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/docs/static/font/Satoshi-Bold.ttf -------------------------------------------------------------------------------- /docs/static/font/Satoshi-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/docs/static/font/Satoshi-Italic.ttf -------------------------------------------------------------------------------- /docs/static/font/Satoshi-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/docs/static/font/Satoshi-Medium.ttf -------------------------------------------------------------------------------- /docs/static/font/Satoshi-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/docs/static/font/Satoshi-MediumItalic.ttf -------------------------------------------------------------------------------- /docs/static/font/Satoshi-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/docs/static/font/Satoshi-Regular.ttf -------------------------------------------------------------------------------- /docs/static/img/Banner Gradient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/docs/static/img/Banner Gradient.png -------------------------------------------------------------------------------- /docs/static/img/Interactions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/docs/static/img/Interactions.png -------------------------------------------------------------------------------- /docs/static/img/Logo White (flipped).svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/static/img/Logo White.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/docs/static/img/favicon.ico -------------------------------------------------------------------------------- /docs/static/img/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/static/img/logo-grad.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/static/img/panda.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/docs/static/img/panda.png -------------------------------------------------------------------------------- /docs/static/img/panda.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/sample/.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 | 11 | # Native 12 | *.orig.* 13 | *.jks 14 | *.p8 15 | *.p12 16 | *.key 17 | *.mobileprovision 18 | 19 | # Metro 20 | .metro-health-check* 21 | 22 | # debug 23 | npm-debug.* 24 | yarn-debug.* 25 | yarn-error.* 26 | 27 | # macOS 28 | .DS_Store 29 | *.pem 30 | 31 | # local env files 32 | .env*.local 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | -------------------------------------------------------------------------------- /examples/sample/.yarn/install-state.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/examples/sample/.yarn/install-state.gz -------------------------------------------------------------------------------- /examples/sample/App.js: -------------------------------------------------------------------------------- 1 | export { default } from './src/Perf.List' 2 | -------------------------------------------------------------------------------- /examples/sample/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "sample", 4 | "slug": "sample", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/icon.png", 8 | "userInterfaceStyle": "light", 9 | "splash": { 10 | "image": "./assets/splash.png", 11 | "resizeMode": "contain", 12 | "backgroundColor": "#ffffff" 13 | }, 14 | "assetBundlePatterns": [ 15 | "**/*" 16 | ], 17 | "ios": { 18 | "supportsTablet": true 19 | }, 20 | "android": { 21 | "adaptiveIcon": { 22 | "foregroundImage": "./assets/adaptive-icon.png", 23 | "backgroundColor": "#ffffff" 24 | } 25 | }, 26 | "web": { 27 | "favicon": "./assets/favicon.png" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/sample/assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/examples/sample/assets/adaptive-icon.png -------------------------------------------------------------------------------- /examples/sample/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/examples/sample/assets/favicon.png -------------------------------------------------------------------------------- /examples/sample/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/examples/sample/assets/icon.png -------------------------------------------------------------------------------- /examples/sample/assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nandorojo/moti/1854a19e5f18446b3ea459f8ba88028fbb6dce2c/examples/sample/assets/splash.png -------------------------------------------------------------------------------- /examples/sample/babel.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | module.exports = function (api) { 4 | api.cache(true) 5 | return { 6 | presets: ['babel-preset-expo'], 7 | plugins: [ 8 | 'react-native-reanimated/plugin', 9 | [ 10 | 'module-resolver', 11 | { 12 | extensions: ['.tsx', '.ts', '.js', '.json'], 13 | alias: { 14 | // For development, we want to alias the library to the source 15 | moti$: path.join(__dirname, '../../packages/moti/src/index.tsx'), 16 | 'moti/skeleton': path.join( 17 | __dirname, 18 | '../../packages/moti/src/skeleton/index.ts' 19 | ), 20 | 'moti/interactions': path.join( 21 | __dirname, 22 | '../../packages/moti/src/interactions/index.ts' 23 | ), 24 | }, 25 | }, 26 | ], 27 | ], 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /examples/sample/metro.config.js: -------------------------------------------------------------------------------- 1 | // Learn more https://docs.expo.io/guides/customizing-metro 2 | const { getDefaultConfig } = require('expo/metro-config') 3 | const path = require('path') 4 | 5 | const config = getDefaultConfig(__dirname) 6 | 7 | // npm v7+ will install ../node_modules/react-native because of peerDependencies. 8 | // To prevent the incompatible react-native bewtween ./node_modules/react-native and ../node_modules/react-native, 9 | // excludes the one from the parent folder when bundling. 10 | config.resolver.blockList = [ 11 | ...Array.from(config.resolver.blockList ?? []), 12 | new RegExp(path.resolve('../..', 'node_modules', 'react-native')), 13 | ] 14 | 15 | config.resolver.nodeModulesPaths = [ 16 | path.resolve(__dirname, './node_modules'), 17 | path.resolve(__dirname, '../../node_modules'), 18 | ] 19 | 20 | config.resolver.assetExts.push('mjs') 21 | config.resolver.assetExts.push('cjs') 22 | 23 | config.watchFolders = [path.resolve(__dirname, '../..')] 24 | 25 | config.transformer.getTransformOptions = async () => ({ 26 | transform: { 27 | experimentalImportSupport: false, 28 | inlineRequires: true, 29 | }, 30 | }) 31 | 32 | module.exports = config 33 | -------------------------------------------------------------------------------- /examples/sample/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "start": "expo start", 6 | "android": "expo start --android", 7 | "ios": "expo start --ios", 8 | "web": "expo start --web" 9 | }, 10 | "dependencies": { 11 | "expo": "~51.0.6", 12 | "expo-status-bar": "~1.12.1", 13 | "moti": "^0.27.2", 14 | "react": "18.2.0", 15 | "react-native": "^0.74.1", 16 | "react-native-gesture-handler": "~2.16.1", 17 | "react-native-reanimated": "~3.10.1" 18 | }, 19 | "devDependencies": { 20 | "@babel/core": "^7.20.0", 21 | "babel-plugin-module-resolver": "^5.0.0" 22 | }, 23 | "private": true 24 | } 25 | -------------------------------------------------------------------------------- /examples/sample/src/Bug.tsx: -------------------------------------------------------------------------------- 1 | import { View, Button, StyleSheet } from 'react-native' 2 | import React from 'react' 3 | import Animated, { 4 | useAnimatedStyle, 5 | useSharedValue, 6 | withSpring, 7 | withTiming, 8 | processColor, 9 | } from 'react-native-reanimated' 10 | 11 | export default function AnimatedStyleUpdateExample() { 12 | const size = useSharedValue(200) 13 | 14 | const style = useAnimatedStyle( 15 | () => ({ 16 | width: withTiming(size.value), 17 | height: withTiming(size.value), 18 | backgroundColor: withTiming( 19 | size.value > 150 ? processColor('#333333') : processColor('#e8e') 20 | ), 21 | }), 22 | [size] 23 | ) 24 | 25 | return ( 26 | 27 | 28 |