├── .buckconfig
├── .eslintrc.js
├── .gitattributes
├── .gitignore
├── .prettierrc.js
├── .vscode
├── launch.json
└── settings.json
├── .watchmanconfig
├── LICENSE.md
├── README.md
├── TODO.md
├── android
├── app
│ ├── _BUCK
│ ├── build.gradle
│ ├── build_defs.bzl
│ ├── proguard-rules.pro
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── com
│ │ │ └── fluidtransitions
│ │ │ ├── MainActivity.java
│ │ │ └── MainApplication.java
│ │ └── res
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── strings.xml
│ │ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
├── app.json
├── babel.config.js
├── index.js
├── ios
├── FluidTransitions.xcodeproj
│ ├── project.pbxproj
│ └── xcshareddata
│ │ └── xcschemes
│ │ ├── FluidTransitions-tvOS.xcscheme
│ │ └── FluidTransitions.xcscheme
├── FluidTransitions.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── FluidTransitions
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Base.lproj
│ │ └── LaunchScreen.xib
│ ├── Images.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ ├── AppIcon-1024px.png
│ │ │ ├── AppIcon-120px-40pt@3x.png
│ │ │ ├── AppIcon-120px-60pt@2x.png
│ │ │ ├── AppIcon-180px-60pt@3x.png
│ │ │ ├── AppIcon-29px-29pt@1x.png
│ │ │ ├── AppIcon-40px-20pt@2x.png
│ │ │ ├── AppIcon-58px-29pt@2x.png
│ │ │ ├── AppIcon-60px-20pt@3x.png
│ │ │ ├── AppIcon-80px-40pt@2x.png
│ │ │ ├── AppIcon-87px-29pt@3x.png
│ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ └── Logo.imageset
│ │ │ ├── Contents.json
│ │ │ ├── logo-symbol-text@1x.png
│ │ │ ├── logo-symbol-text@2x.png
│ │ │ └── logo-symbol-text@3x.png
│ ├── Info.plist
│ └── main.m
├── Podfile
└── Podfile.lock
├── metro.config.js
├── package.json
├── src
├── App.tsx
├── examples
│ ├── AppStore
│ │ └── index.tsx
│ ├── Assets
│ │ ├── logo-symbol-text@1x.png
│ │ ├── logo-symbol-text@2x.png
│ │ └── logo-symbol-text@3x.png
│ ├── Children
│ │ ├── bubble.tsx
│ │ └── index.tsx
│ ├── Dragging
│ │ └── index.tsx
│ ├── Driver
│ │ ├── MovingButton.tsx
│ │ └── index.tsx
│ ├── Easings
│ │ └── index.tsx
│ ├── Flutter
│ │ ├── assets
│ │ │ ├── earrings.png
│ │ │ ├── hat.png
│ │ │ ├── icon.png
│ │ │ ├── splash.png
│ │ │ ├── sunnies.png
│ │ │ └── table.png
│ │ ├── components
│ │ │ ├── Cursor.tsx
│ │ │ ├── Header.tsx
│ │ │ ├── Headers.tsx
│ │ │ ├── Label.tsx
│ │ │ ├── MockCard.tsx
│ │ │ ├── MockEntry.tsx
│ │ │ ├── Model.ts
│ │ │ ├── Pages.tsx
│ │ │ ├── Sections.tsx
│ │ │ └── index.tsx
│ │ └── index.tsx
│ ├── HomeScreen.tsx
│ ├── HomeScreenButton.tsx
│ ├── Interactions
│ │ ├── AnimatedNumber.tsx
│ │ ├── CallButton.tsx
│ │ ├── FloatingLabel.tsx
│ │ ├── InteractionContainer.tsx
│ │ ├── LikeHeart.tsx
│ │ ├── LoginButton.tsx
│ │ └── index.tsx
│ ├── Interpolate
│ │ └── index.tsx
│ ├── Lists
│ │ └── index.tsx
│ ├── Maze
│ │ ├── MazeItem.tsx
│ │ ├── index.tsx
│ │ └── styles.ts
│ ├── Navigation
│ │ ├── box.tsx
│ │ ├── bubble.tsx
│ │ ├── button.tsx
│ │ ├── index.tsx
│ │ └── screen.tsx
│ ├── Parallax
│ │ └── index.tsx
│ ├── Repeating
│ │ ├── Repeater.tsx
│ │ └── index.tsx
│ ├── SVG
│ │ └── index.tsx
│ ├── Stagger
│ │ └── index.tsx
│ ├── Style
│ │ └── index.tsx
│ ├── Styles
│ │ ├── EMailFolder.tsx
│ │ ├── MovingButton.tsx
│ │ ├── Pager.tsx
│ │ ├── ProgressBar.tsx
│ │ └── index.tsx
│ ├── Text
│ │ ├── AdCard.tsx
│ │ ├── Ticker.tsx
│ │ └── index.tsx
│ ├── colors.ts
│ ├── helpers.ts
│ ├── index.tsx
│ └── scratch.tsx
├── packages
│ ├── animated
│ │ ├── index.ts
│ │ ├── index.web.ts
│ │ ├── package.json
│ │ ├── src
│ │ │ ├── Types
│ │ │ │ ├── IAnimationNode.ts
│ │ │ │ ├── IAnimationProvider.ts
│ │ │ │ ├── IAnimationValue.ts
│ │ │ │ ├── Interpolation.ts
│ │ │ │ └── index.ts
│ │ │ ├── react-native-animated
│ │ │ │ ├── Implementation
│ │ │ │ │ ├── ColorNode.ts
│ │ │ │ │ ├── RadNode.ts
│ │ │ │ │ ├── bezier.ts
│ │ │ │ │ ├── createValue.ts
│ │ │ │ │ ├── getColorDisplayValue.ts
│ │ │ │ │ ├── getColorDisplayValue.web.ts
│ │ │ │ │ ├── getProcessedColor.ts
│ │ │ │ │ ├── getProcessedColor.web.ts
│ │ │ │ │ ├── getProcessedRotation.ts
│ │ │ │ │ ├── normalizeColor.ts
│ │ │ │ │ ├── runTiming.ts
│ │ │ │ │ └── utils.ts
│ │ │ │ ├── __tests__
│ │ │ │ │ ├── assign.spec.ts
│ │ │ │ │ ├── bezier.spec.ts
│ │ │ │ │ ├── block.spec.ts
│ │ │ │ │ ├── conditions.spec.ts
│ │ │ │ │ ├── operators.spec.ts
│ │ │ │ │ └── proc.spec.ts
│ │ │ │ └── index.ts
│ │ │ └── react-native-reanimated
│ │ │ │ ├── Implementation
│ │ │ │ ├── createValue.ts
│ │ │ │ ├── getColorFromString.ts
│ │ │ │ ├── getDegreesInRadian.ts
│ │ │ │ ├── getProcessedColor.ts
│ │ │ │ ├── getProcessedRotation.ts
│ │ │ │ ├── runTiming.ts
│ │ │ │ └── utils.ts
│ │ │ │ ├── index.native.ts
│ │ │ │ └── index.web.ts
│ │ └── tsconfig.json
│ ├── gestures
│ │ ├── index.ts
│ │ ├── package.json
│ │ ├── src
│ │ │ └── index.tsx
│ │ └── tsconfig.json
│ ├── navigation
│ │ ├── index.ts
│ │ ├── package.json
│ │ ├── src
│ │ │ ├── Functions
│ │ │ │ ├── getNavigationStates.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── safeGetState.ts
│ │ │ ├── Hooks
│ │ │ │ ├── index.ts
│ │ │ │ ├── useNavigationDirection.ts
│ │ │ │ ├── useNavigationStates.ts
│ │ │ │ └── useVisibilityStyle.ts
│ │ │ ├── Transitions
│ │ │ │ ├── createNavigationTransition.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── useNavigationTransition.ts
│ │ │ │ └── useTranslateTransitions.ts
│ │ │ ├── createFluidStackNavigator.tsx
│ │ │ ├── hooks
│ │ │ │ ├── useCurrentValue.ts
│ │ │ │ ├── useDriverContext.ts
│ │ │ │ └── useNavigationState.ts
│ │ │ ├── index.tsx
│ │ │ ├── navigationContainer.tsx
│ │ │ └── types.ts
│ │ └── tsconfig.json
│ ├── svg
│ │ ├── index.ts
│ │ ├── package.json
│ │ ├── src
│ │ │ └── Components
│ │ │ │ └── index.ts
│ │ └── tsconfig.json
│ └── transitions
│ │ ├── index.ts
│ │ ├── package.json
│ │ ├── src
│ │ ├── Animation
│ │ │ ├── Builder
│ │ │ │ ├── __tests__
│ │ │ │ │ └── getInterpolationTree.spec.ts
│ │ │ │ ├── dumpTree.ts
│ │ │ │ ├── getAnimationOnEnd.ts
│ │ │ │ ├── getInterpolationTree.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── types.ts
│ │ │ ├── Functions
│ │ │ │ ├── createProc.ts
│ │ │ │ ├── easing.ts
│ │ │ │ ├── getResolvedAnimation.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── spring.ts
│ │ │ ├── Runner
│ │ │ │ ├── Functions
│ │ │ │ │ ├── __tests__
│ │ │ │ │ │ ├── createAnimationNode.spec.ts
│ │ │ │ │ │ ├── easing.spec.ts
│ │ │ │ │ │ ├── interpolate.spec.ts
│ │ │ │ │ │ ├── interpolateColor.spec.ts
│ │ │ │ │ │ └── normalize.spec.ts
│ │ │ │ │ ├── createAnimationNode.ts
│ │ │ │ │ ├── createInterpolationNode.ts
│ │ │ │ │ ├── getExtrapolationValue.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── interpolate.ts
│ │ │ │ │ ├── interpolateColor.ts
│ │ │ │ │ ├── interpolateValue.ts
│ │ │ │ │ ├── lifecycle.ts
│ │ │ │ │ ├── normalize.ts
│ │ │ │ │ ├── setAnimationValue.ts
│ │ │ │ │ └── setInterpolationValue.ts
│ │ │ │ ├── addAnimations.ts
│ │ │ │ ├── addInterpolation.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── interpolationStorage.ts
│ │ │ ├── commitAnimations.ts
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ ├── Components
│ │ │ ├── FluidTransitions
│ │ │ │ ├── index.ts
│ │ │ │ ├── useAnimationContext.ts
│ │ │ │ ├── useConfiguration.tsx
│ │ │ │ ├── useInitialStyle.ts
│ │ │ │ ├── useInterpolatorConfig.ts
│ │ │ │ ├── useInterpolatorContext.tsx
│ │ │ │ ├── useLayout.ts
│ │ │ │ ├── useMountUpdate.ts
│ │ │ │ ├── useOnConfig.ts
│ │ │ │ ├── usePropContext.ts
│ │ │ │ ├── useSharedInterpolation.tsx
│ │ │ │ ├── useStateChanges.ts
│ │ │ │ ├── useStyleContext.ts
│ │ │ │ ├── useTouchable.tsx
│ │ │ │ ├── useTransitionItems.tsx
│ │ │ │ ├── useValueContext.ts
│ │ │ │ ├── useValueInterpolation.ts
│ │ │ │ ├── useWhenConfig.ts
│ │ │ │ └── withFluidTransitions.tsx
│ │ │ ├── Types
│ │ │ │ ├── AnimatedStyleKeys.ts
│ │ │ │ ├── AnimationContext.ts
│ │ │ │ ├── AnimationInfo.ts
│ │ │ │ ├── ConfigurationContext.ts
│ │ │ │ ├── DriverContext.ts
│ │ │ │ ├── Easing.ts
│ │ │ │ ├── InterpolationTypes.ts
│ │ │ │ ├── InterpolatorContext.ts
│ │ │ │ ├── SharedContext.ts
│ │ │ │ ├── StateContext.ts
│ │ │ │ ├── StyleTypes.ts
│ │ │ │ ├── TransitionItem.ts
│ │ │ │ ├── TransitionItemContext.ts
│ │ │ │ ├── ValueContextType.ts
│ │ │ │ └── index.ts
│ │ │ └── index.tsx
│ │ ├── Configuration
│ │ │ ├── Types.ts
│ │ │ ├── __tests__
│ │ │ │ ├── mergeConfig.spec.ts
│ │ │ │ └── validateConfig.spec.ts
│ │ │ ├── animationType.ts
│ │ │ ├── childAnimation.ts
│ │ │ ├── createConfig.ts
│ │ │ ├── createState.ts
│ │ │ ├── index.ts
│ │ │ ├── interpolation.ts
│ │ │ ├── interpolationValue.ts
│ │ │ ├── mergeConfigs.ts
│ │ │ ├── onState.ts
│ │ │ ├── validateConfig.ts
│ │ │ └── whenState.ts
│ │ ├── Hooks
│ │ │ ├── index.ts
│ │ │ ├── useFluidConfig.ts
│ │ │ ├── useFluidState.ts
│ │ │ ├── useForceUpdate.ts
│ │ │ └── useLog.ts
│ │ ├── Props
│ │ │ ├── getAnimatedProps.ts
│ │ │ └── index.ts
│ │ ├── Shared
│ │ │ ├── createSharedInterpolation.ts
│ │ │ ├── getSharedInterpolationMetrics.ts
│ │ │ ├── getSharedInterpolationStyles.ts
│ │ │ ├── getStates.ts
│ │ │ ├── index.ts
│ │ │ └── setupSharedInterpolation.ts
│ │ ├── Styles
│ │ │ ├── __tests__
│ │ │ │ ├── getStyleValueFromKey.spec.ts
│ │ │ │ └── setStyleValueForKey.spec.ts
│ │ │ ├── getCalculatedStyle.ts
│ │ │ ├── getMergedStyles.ts
│ │ │ ├── getResolvedStyle.ts
│ │ │ ├── getStyleInfo.ts
│ │ │ ├── getStyleKeys.ts
│ │ │ ├── getStyleValueFromKey.ts
│ │ │ └── setStyleValueForKey.ts
│ │ ├── Types
│ │ │ ├── AnimatedValueType.ts
│ │ │ ├── ComponentProps.ts
│ │ │ ├── Constants.ts
│ │ │ ├── FluidException.ts
│ │ │ ├── LogTypes.ts
│ │ │ ├── MetricTypes.ts
│ │ │ └── index.ts
│ │ ├── Utilities
│ │ │ ├── Springs.ts
│ │ │ ├── Timings.ts
│ │ │ ├── index.ts
│ │ │ └── measureItem.ts
│ │ ├── Values
│ │ │ ├── __tests__
│ │ │ │ ├── getInputRange.spec.ts
│ │ │ │ └── getOutputRange.spec.ts
│ │ │ ├── addValue.ts
│ │ │ ├── createValue.ts
│ │ │ ├── getChangedKeys.ts
│ │ │ ├── getInputRange.ts
│ │ │ ├── getKeys.ts
│ │ │ ├── getOutputRange.ts
│ │ │ ├── getValueFromKey.ts
│ │ │ ├── index.ts
│ │ │ └── setValueForKey.ts
│ │ └── config.ts
│ │ └── tsconfig.json
└── web
│ ├── .gitignore
│ ├── config-overrides.js
│ ├── package.json
│ ├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
│ ├── src
│ ├── App.tsx
│ ├── Easings
│ │ └── index.tsx
│ ├── Interpolate
│ │ └── index.tsx
│ ├── Maze
│ │ ├── MazeItem.tsx
│ │ ├── index.tsx
│ │ └── styles.ts
│ ├── Stagger
│ │ └── index.tsx
│ ├── Styles
│ │ ├── MovingButton.tsx
│ │ ├── Pager.tsx
│ │ ├── ProgressBar.tsx
│ │ └── index.tsx
│ ├── Text
│ │ ├── AdCard.tsx
│ │ ├── Ticker.tsx
│ │ └── index.tsx
│ ├── colors.ts
│ ├── helpers.ts
│ ├── index.tsx
│ ├── react-app-env.d.ts
│ └── serviceWorker.ts
│ ├── tsconfig.json
│ └── yarn.lock
├── tsconfig.json
└── yarn.lock
/.buckconfig:
--------------------------------------------------------------------------------
1 |
2 | [android]
3 | target = Google Inc.:Google APIs:23
4 |
5 | [maven_repositories]
6 | central = https://repo1.maven.org/maven2
7 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | jest: true,
4 | },
5 | parser: "@typescript-eslint/parser", // Specifies the ESLint parser
6 | extends: [
7 | "@react-native-community", // Uses the recommended rules from the @typescript-eslint/eslint-plugin
8 | "prettier/@typescript-eslint", // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier
9 | "plugin:prettier/recommended",
10 | ],
11 | plugins: ["react-hooks"],
12 | parserOptions: {
13 | ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
14 | sourceType: "module", // Allows for the use of imports
15 | },
16 | rules: {
17 | "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks
18 | "react-hooks/exhaustive-deps": "warn", // Checks effect dependencies
19 | "no-dupe-class-members": "off",
20 | },
21 | overrides: [
22 | {
23 | files: ["**/*.ts", "**/*.tsx"],
24 | rules: {
25 | "no-unused-vars": ["off"],
26 | "no-undef": ["off"],
27 | },
28 | },
29 | ],
30 | };
31 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj -text
2 |
--------------------------------------------------------------------------------
/.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 |
25 | # Android/IntelliJ
26 | #
27 | build/
28 | .idea
29 | .gradle
30 | local.properties
31 | *.iml
32 |
33 | # Visual Studio Code
34 | #
35 | .vscode/.react
36 |
37 | # node.js
38 | #
39 | node_modules/
40 | npm-debug.log
41 | yarn-error.log
42 |
43 | # BUCK
44 | buck-out/
45 | \.buckd/
46 | *.keystore
47 |
48 | # fastlane
49 | #
50 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
51 | # screenshots whenever they are needed.
52 | # For more information about the recommended setup visit:
53 | # https://docs.fastlane.tools/best-practices/source-control/
54 |
55 | */fastlane/report.xml
56 | */fastlane/Preview.html
57 | */fastlane/screenshots
58 |
59 | # Bundle artifact
60 | *.jsbundle
61 |
62 | # CocoaPods
63 | /ios/Pods/
64 | /ios/budbuddy.xcworkspace/xcshareddata/
65 |
66 | # Build
67 | /**/dist/**
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | bracketSpacing: true,
3 | jsxBracketSameLine: true,
4 | singleQuote: false,
5 | trailingComma: 'all',
6 | };
7 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "Debug iOS",
9 | "cwd": "${workspaceFolder}",
10 | "type": "reactnative",
11 | "request": "launch",
12 | "platform": "ios"
13 | },
14 | {
15 | "name": "Debug Android",
16 | "cwd": "${workspaceFolder}",
17 | "type": "reactnative",
18 | "request": "launch",
19 | "platform": "android"
20 | },
21 | {
22 | "name": "Debug Android (Hermes) - Experimental",
23 | "cwd": "${workspaceFolder}",
24 | "type": "reactnativedirect",
25 | "request": "launch",
26 | "platform": "android"
27 | },
28 | {
29 | "type": "chrome",
30 | "request": "launch",
31 | "name": "Launch Chrome",
32 | "url": "http://localhost:3000",
33 | "webRoot": "${workspaceFolder}"
34 | },
35 |
36 | {
37 | "name": "Attach to packager",
38 | "cwd": "${workspaceFolder}",
39 | "type": "reactnative",
40 | "request": "attach"
41 | }
42 | ]
43 | }
44 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.formatOnSave": true,
3 | "eslint.validate": [
4 | "javascript",
5 | "javascriptreact",
6 | {"language": "typescript", "autoFix": true},
7 | {"language": "typescriptreact", "autoFix": true}
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Fram X AS / Christian Falch
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 |
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 | # Getting started
2 |
3 | ## Bugs
4 |
5 | * [x] Fix issue with removing a when interpolation. See Styles example and press on/off
6 | * [x] Style-flash in Styles example - press button and while it is animating, press inbox-button
7 | * [x] Create central function for removing interpolations and animations
8 | * [x] Fix createAnimationNode impl so that tests only needs to run once
9 | * [ ] Shared transitions (WIP)
10 | * [ ] Fix running second shared transition while one is running
11 | Should we skip providing shared transitions in first version?
12 | * [ ] Fix issue with when.interpolation.value not using animation (is it possible?)
13 |
14 | ### Web
15 |
16 | * [ ] Fix measure of rotated elements on Web
17 | * [ ] Styles example: Button is not moving
18 |
19 | ### Android
20 |
21 | * [ ] Parallax example, not interpolating change of header color correctly
22 | * [x] SVG - ValueNode cannot be cast to a number
23 | * [x] Interpolation
24 | * [x] "Error while updating transform"
25 | * [x] Rotated image is not displayed correctly
26 | * [x] Interactions - some alignment issue
27 |
28 | ## TODO
29 |
30 | * [x] ConfigStateType should be accepted as state
31 | * [x] StaggerMs & StaggerFunc => stagger
32 | * [x] Test/implement stagger custom function
33 | * [x] Create dragging example
34 | * [ ] Navigation with new Stack navigator
35 |
36 | ## Later
37 |
38 | * [ ] Prop animation - support nested props and arrays WIP
39 | * [ ] Fix Spotify example, find out why changing to static styles fixes initial pos
40 | * [ ] Add velocity calculation to spring functions, find a way to keep velocity on
41 | animations and pass them to the spring function
42 | * [ ] Optimize running multiple animation updates when nodes are equal (duration, offset, easing)
--------------------------------------------------------------------------------
/android/app/_BUCK:
--------------------------------------------------------------------------------
1 | # To learn about Buck see [Docs](https://buckbuild.com/).
2 | # To run your application with Buck:
3 | # - install Buck
4 | # - `npm start` - to start the packager
5 | # - `cd android`
6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
8 | # - `buck install -r android/app` - compile, install and run application
9 | #
10 |
11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets")
12 |
13 | lib_deps = []
14 |
15 | create_aar_targets(glob(["libs/*.aar"]))
16 |
17 | create_jar_targets(glob(["libs/*.jar"]))
18 |
19 | android_library(
20 | name = "all-libs",
21 | exported_deps = lib_deps,
22 | )
23 |
24 | android_library(
25 | name = "app-code",
26 | srcs = glob([
27 | "src/main/java/**/*.java",
28 | ]),
29 | deps = [
30 | ":all-libs",
31 | ":build_config",
32 | ":res",
33 | ],
34 | )
35 |
36 | android_build_config(
37 | name = "build_config",
38 | package = "com.fluidtransitions",
39 | )
40 |
41 | android_resource(
42 | name = "res",
43 | package = "com.fluidtransitions",
44 | res = "src/main/res",
45 | )
46 |
47 | android_binary(
48 | name = "app",
49 | keystore = "//android/keystores:debug",
50 | manifest = "src/main/AndroidManifest.xml",
51 | package_type = "debug",
52 | deps = [
53 | ":app-code",
54 | ],
55 | )
56 |
--------------------------------------------------------------------------------
/android/app/build_defs.bzl:
--------------------------------------------------------------------------------
1 | """Helper definitions to glob .aar and .jar targets"""
2 |
3 | def create_aar_targets(aarfiles):
4 | for aarfile in aarfiles:
5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")]
6 | lib_deps.append(":" + name)
7 | android_prebuilt_aar(
8 | name = name,
9 | aar = aarfile,
10 | )
11 |
12 | def create_jar_targets(jarfiles):
13 | for jarfile in jarfiles:
14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")]
15 | lib_deps.append(":" + name)
16 | prebuilt_jar(
17 | name = name,
18 | binary_jar = jarfile,
19 | )
20 |
--------------------------------------------------------------------------------
/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 | # Add any project specific keep options here:
11 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
13 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/fluidtransitions/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.fluidtransitions;
2 |
3 | import com.facebook.react.ReactActivity;
4 | import com.facebook.react.ReactActivityDelegate;
5 | import com.facebook.react.ReactRootView;
6 | import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
7 |
8 | public class MainActivity extends ReactActivity {
9 |
10 | /**
11 | * Returns the name of the main component registered from JavaScript.
12 | * This is used to schedule rendering of the component.
13 | */
14 | @Override
15 | protected String getMainComponentName() {
16 | return "FluidTransitions";
17 | }
18 |
19 | @Override
20 | protected ReactActivityDelegate createReactActivityDelegate() {
21 | return new ReactActivityDelegate(this, getMainComponentName()) {
22 | @Override
23 | protected ReactRootView createRootView() {
24 | return new RNGestureHandlerEnabledRootView(MainActivity.this);
25 | }
26 | };
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/fluidtransitions/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.fluidtransitions;
2 |
3 | import android.app.Application;
4 | import android.util.Log;
5 |
6 | import com.facebook.react.PackageList;
7 | import com.facebook.hermes.reactexecutor.HermesExecutorFactory;
8 | import com.facebook.react.bridge.JavaScriptExecutorFactory;
9 | import com.facebook.react.ReactApplication;
10 | import com.facebook.react.ReactNativeHost;
11 | import com.facebook.react.ReactPackage;
12 | import com.facebook.soloader.SoLoader;
13 |
14 | import java.util.List;
15 |
16 | public class MainApplication extends Application implements ReactApplication {
17 |
18 | private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
19 | @Override
20 | public boolean getUseDeveloperSupport() {
21 | return BuildConfig.DEBUG;
22 | }
23 |
24 | @Override
25 | protected List getPackages() {
26 | @SuppressWarnings("UnnecessaryLocalVariable")
27 | List packages = new PackageList(this).getPackages();
28 | // Packages that cannot be autolinked yet can be added manually here, for example:
29 | // packages.add(new MyReactNativePackage());
30 | return packages;
31 | }
32 |
33 | @Override
34 | protected String getJSMainModuleName() {
35 | return "index";
36 | }
37 | };
38 |
39 | @Override
40 | public ReactNativeHost getReactNativeHost() {
41 | return mReactNativeHost;
42 | }
43 |
44 | @Override
45 | public void onCreate() {
46 | super.onCreate();
47 | SoLoader.init(this, /* native exopackage */ false);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Fluid Transitions
3 |
4 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/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 = "28.0.3"
6 | minSdkVersion = 16
7 | compileSdkVersion = 28
8 | targetSdkVersion = 28
9 | supportLibVersion = "28.0.0"
10 | }
11 | repositories {
12 | google()
13 | jcenter()
14 | }
15 | dependencies {
16 | classpath("com.android.tools.build:gradle:3.4.1")
17 |
18 | // NOTE: Do not place your application dependencies here; they belong
19 | // in the individual module build.gradle files
20 | }
21 | }
22 |
23 | allprojects {
24 | repositories {
25 | mavenLocal()
26 | maven {
27 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
28 | url("$rootDir/../node_modules/react-native/android")
29 | }
30 | maven {
31 | // Android JSC is installed from npm
32 | url("$rootDir/../node_modules/jsc-android/dist")
33 | }
34 |
35 | google()
36 | jcenter()
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/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: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
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 | android.useAndroidX=true
21 | android.enableJetifier=true
22 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/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-5.4.1-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'FluidTransitions'
2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
3 | include ':app'
4 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "FluidTransitions",
3 | "displayName": "FluidTransitions"
4 | }
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = api => {
2 | api.cache(false);
3 | return {
4 | presets: ["module:metro-react-native-babel-preset"],
5 | plugins: [
6 | [
7 | "module-resolver",
8 | {
9 | alias: {
10 | "react-native-fluid-transitions": "./src/packages/transitions",
11 | "react-native-fluid-animations": "./src/packages/animated",
12 | "react-native-fluid-svg": "./src/packages/svg",
13 | "react-native-fluid-gestures": "./src/packages/gestures",
14 | "react-native-fluid-navigation": "./src/packages/navigation",
15 | },
16 | },
17 | ],
18 | ],
19 | };
20 | };
21 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import {AppRegistry} from 'react-native';
2 | import App from './src/App';
3 | import {name as appName} from './app.json';
4 |
5 | AppRegistry.registerComponent(appName, () => App);
6 |
--------------------------------------------------------------------------------
/ios/FluidTransitions.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ios/FluidTransitions.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/FluidTransitions/AppDelegate.h:
--------------------------------------------------------------------------------
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 | #import
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (nonatomic, strong) UIWindow *window;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-1024px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-1024px.png
--------------------------------------------------------------------------------
/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-120px-40pt@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-120px-40pt@3x.png
--------------------------------------------------------------------------------
/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-120px-60pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-120px-60pt@2x.png
--------------------------------------------------------------------------------
/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-180px-60pt@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-180px-60pt@3x.png
--------------------------------------------------------------------------------
/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-29px-29pt@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-29px-29pt@1x.png
--------------------------------------------------------------------------------
/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-40px-20pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-40px-20pt@2x.png
--------------------------------------------------------------------------------
/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-58px-29pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-58px-29pt@2x.png
--------------------------------------------------------------------------------
/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-60px-20pt@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-60px-20pt@3x.png
--------------------------------------------------------------------------------
/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-80px-40pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-80px-40pt@2x.png
--------------------------------------------------------------------------------
/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-87px-29pt@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/AppIcon-87px-29pt@3x.png
--------------------------------------------------------------------------------
/ios/FluidTransitions/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "AppIcon-40px-20pt@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "AppIcon-60px-20pt@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "AppIcon-29px-29pt@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "AppIcon-58px-29pt@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "AppIcon-87px-29pt@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "AppIcon-80px-40pt@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "AppIcon-120px-40pt@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "AppIcon-120px-60pt@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "AppIcon-180px-60pt@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "1024x1024",
59 | "idiom" : "ios-marketing",
60 | "filename" : "AppIcon-1024px.png",
61 | "scale" : "1x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/ios/FluidTransitions/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/ios/FluidTransitions/Images.xcassets/Logo.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "logo-symbol-text@1x.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "logo-symbol-text@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "logo-symbol-text@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/ios/FluidTransitions/Images.xcassets/Logo.imageset/logo-symbol-text@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/ios/FluidTransitions/Images.xcassets/Logo.imageset/logo-symbol-text@1x.png
--------------------------------------------------------------------------------
/ios/FluidTransitions/Images.xcassets/Logo.imageset/logo-symbol-text@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/ios/FluidTransitions/Images.xcassets/Logo.imageset/logo-symbol-text@2x.png
--------------------------------------------------------------------------------
/ios/FluidTransitions/Images.xcassets/Logo.imageset/logo-symbol-text@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/ios/FluidTransitions/Images.xcassets/Logo.imageset/logo-symbol-text@3x.png
--------------------------------------------------------------------------------
/ios/FluidTransitions/main.m:
--------------------------------------------------------------------------------
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 | #import
9 |
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/metro.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Metro configuration for React Native
3 | * https://github.com/facebook/react-native
4 | *
5 | * @format
6 | */
7 | const blacklist = require("metro-config/src/defaults/blacklist");
8 |
9 | module.exports = {
10 | resolver: { blacklistRE: blacklist([/src\/web\/.*/]) },
11 | transformer: {
12 | getTransformOptions: async () => ({
13 | transform: {
14 | experimentalImportSupport: false,
15 | inlineRequires: false,
16 | },
17 | }),
18 | },
19 | };
20 |
--------------------------------------------------------------------------------
/src/App.tsx:
--------------------------------------------------------------------------------
1 | import App from './examples';
2 | export default App;
3 |
--------------------------------------------------------------------------------
/src/examples/Assets/logo-symbol-text@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/src/examples/Assets/logo-symbol-text@1x.png
--------------------------------------------------------------------------------
/src/examples/Assets/logo-symbol-text@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/src/examples/Assets/logo-symbol-text@2x.png
--------------------------------------------------------------------------------
/src/examples/Assets/logo-symbol-text@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/src/examples/Assets/logo-symbol-text@3x.png
--------------------------------------------------------------------------------
/src/examples/Children/bubble.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { StyleSheet } from "react-native";
3 | import Fluid, {
4 | useFluidConfig,
5 | AnimationType,
6 | OnEnterState,
7 | WhenState,
8 | } from "react-native-fluid-transitions";
9 |
10 | type Props = {
11 | label: string;
12 | color: string;
13 | active: boolean;
14 | };
15 |
16 | const Bubble: React.FunctionComponent = ({ label, color, active }) => {
17 | const activeState = { name: "active", active };
18 | const config = useFluidConfig(
19 | AnimationType(Fluid.Animations.Springs.Gentle),
20 | WhenState(activeState, {
21 | opacity: 0,
22 | transform: [{ scale: 0.009 }, { translateY: -64 }],
23 | }),
24 | OnEnterState(Fluid.States.Mounted, {
25 | inputRange: [0, 0.5, 1],
26 | outputRange: [1, 0.5, 1],
27 | styleKey: "transform.scaleY",
28 | }),
29 | );
30 |
31 | return (
32 |
40 | );
41 | };
42 |
43 | const styles = StyleSheet.create({
44 | container: {
45 | opacity: 1,
46 | width: 20,
47 | height: 20,
48 | borderRadius: 10,
49 | margin: 10,
50 | },
51 | containerInitialStyle: {
52 | opacity: 0,
53 | transform: [{ scale: 0.009 }, { translateY: -64 }],
54 | },
55 | });
56 |
57 | export { Bubble };
58 |
--------------------------------------------------------------------------------
/src/examples/Driver/MovingButton.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { StyleSheet, Text } from "react-native";
3 | import Fluid, { useFluidConfig } from "react-native-fluid-transitions";
4 | import * as Colors from "../colors";
5 |
6 | type Props = {
7 | toggled: boolean;
8 | onToggle: () => void;
9 | };
10 | const MovingButton: React.FunctionComponent = ({
11 | toggled,
12 | onToggle,
13 | }) => {
14 | const toggledState = { name: "toggled", active: toggled };
15 | const notToggledState = { name: "nottoggled", active: !toggled };
16 |
17 | const config = useFluidConfig({
18 | animation: Fluid.Animations.Springs.WobblySlow,
19 | when: [
20 | { state: toggledState, style: styles.activeButton },
21 | { state: notToggledState, style: styles.inactiveButton },
22 | ],
23 | });
24 |
25 | return (
26 |
33 | Tap me!
34 |
35 | );
36 | };
37 |
38 | const styles = StyleSheet.create({
39 | button: {
40 | borderColor: Colors.ColorA,
41 | borderWidth: 4,
42 | alignItems: "center",
43 | justifyContent: "center",
44 | borderRadius: 8,
45 | padding: 12,
46 | marginTop: 20,
47 | marginBottom: 15,
48 | backgroundColor: "white",
49 | },
50 | initialStyle: {
51 | transform: [{ scale: 0.009 }],
52 | },
53 | activeButton: {
54 | transform: [{ rotate: "-15deg" }, { translateX: 100 }],
55 | },
56 | inactiveButton: {
57 | transform: [{ rotate: "15deg" }, { translateX: -100 }],
58 | },
59 | pressed: {
60 | backgroundColor: "#CCC",
61 | },
62 | });
63 |
64 | export default MovingButton;
65 |
--------------------------------------------------------------------------------
/src/examples/Flutter/assets/earrings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/src/examples/Flutter/assets/earrings.png
--------------------------------------------------------------------------------
/src/examples/Flutter/assets/hat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/src/examples/Flutter/assets/hat.png
--------------------------------------------------------------------------------
/src/examples/Flutter/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/src/examples/Flutter/assets/icon.png
--------------------------------------------------------------------------------
/src/examples/Flutter/assets/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/src/examples/Flutter/assets/splash.png
--------------------------------------------------------------------------------
/src/examples/Flutter/assets/sunnies.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/src/examples/Flutter/assets/sunnies.png
--------------------------------------------------------------------------------
/src/examples/Flutter/assets/table.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fram-x/react-native-fluid/22f39543059f7c38709f55b9f2eb928ae42f8ab8/src/examples/Flutter/assets/table.png
--------------------------------------------------------------------------------
/src/examples/Flutter/components/Cursor.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import { View, StyleSheet, Dimensions } from "react-native";
3 |
4 | import { CURSOR_WIDTH } from "./Model";
5 |
6 | type CursorProps = {};
7 |
8 | const { width } = Dimensions.get("window");
9 |
10 | export default class Cursor extends React.PureComponent {
11 | render() {
12 | return (
13 |
14 |
15 |
16 | );
17 | }
18 | }
19 |
20 | const styles = StyleSheet.create({
21 | container: {
22 | flex: 1,
23 | width,
24 | justifyContent: "center",
25 | alignItems: "center",
26 | },
27 | cursor: {
28 | top: 30,
29 | width: CURSOR_WIDTH,
30 | height: 5,
31 | backgroundColor: "white",
32 | },
33 | });
34 |
--------------------------------------------------------------------------------
/src/examples/Flutter/components/Header.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import { View, StyleSheet, Image, Dimensions } from "react-native";
3 | import { Section } from "./Model";
4 | import Svg, { LinearGradient, Stop, Rect } from "react-native-svg";
5 |
6 | type HeaderProps = {
7 | section: Section;
8 | };
9 |
10 | const { width } = Dimensions.get("window");
11 |
12 | export default class Header extends React.PureComponent {
13 | render() {
14 | const { section } = this.props;
15 | const colors = [section.leftColor, section.rightColor];
16 | return (
17 |
18 |
19 |
26 |
27 | );
28 | }
29 | }
30 |
31 | const styles = StyleSheet.create({
32 | container: {
33 | flex: 1,
34 | width,
35 | },
36 | image: {
37 | ...StyleSheet.absoluteFillObject,
38 | width: null,
39 | height: null,
40 | },
41 | gradient: {
42 | ...StyleSheet.absoluteFillObject,
43 | opacity: 0.9,
44 | },
45 | });
46 |
--------------------------------------------------------------------------------
/src/examples/Flutter/components/MockCard.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import { View, StyleSheet, Image } from "react-native";
3 |
4 | type MockCardProps = {
5 | image: string;
6 | };
7 |
8 | export default class MockCard extends React.PureComponent {
9 | render() {
10 | const { image: source } = this.props;
11 | return (
12 |
13 |
14 |
15 | );
16 | }
17 | }
18 |
19 | const styles = StyleSheet.create({
20 | container: {},
21 | image: {
22 | borderRadius: 5,
23 | height: 200,
24 | width: null,
25 | resizeMode: "cover",
26 | margin: 8,
27 | },
28 | });
29 |
--------------------------------------------------------------------------------
/src/examples/Flutter/components/MockEntry.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import { View, Image, Text, StyleSheet } from "react-native";
3 |
4 | type MockEntryProps = {
5 | image: string;
6 | };
7 |
8 | export default class MockEntry extends React.PureComponent {
9 | render() {
10 | const { image: source } = this.props;
11 | return (
12 |
13 |
14 |
15 |
16 |
17 | React Native enables interactive animation
18 | 3K views - 5 days
19 |
20 |
21 | );
22 | }
23 | }
24 |
25 | const styles = StyleSheet.create({
26 | container: {
27 | flexDirection: "row",
28 | },
29 | leftCell: {
30 | padding: 8,
31 | },
32 | rightCell: {
33 | paddingVertical: 8,
34 | paddingRight: 8,
35 | justifyContent: "center",
36 | },
37 | image: {
38 | width: 45,
39 | height: 45,
40 | borderRadius: 5,
41 | },
42 | subtitle: {
43 | color: "gray",
44 | },
45 | });
46 |
--------------------------------------------------------------------------------
/src/examples/Flutter/components/Model.ts:
--------------------------------------------------------------------------------
1 | export const PADDING = 8;
2 | export const CURSOR_WIDTH = 50;
3 | export const SMALL_HEADER_HEIGHT = 109;
4 | export const MEDIUM_HEADER_HEIGHT = 300;
5 |
6 | export type Section = {
7 | title: string;
8 | leftColor: string;
9 | rightColor: string;
10 | image: string;
11 | };
12 |
--------------------------------------------------------------------------------
/src/examples/Flutter/components/Pages.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import { StyleSheet, View, Dimensions } from "react-native";
3 | import Animated from "react-native-reanimated";
4 |
5 | import { Section, SMALL_HEADER_HEIGHT } from "./Model";
6 | import MockEntry from "./MockEntry";
7 | import MockCard from "./MockCard";
8 |
9 | type PagesProps = {
10 | sections: Section[];
11 | x: Animated.Value;
12 | y: Animated.Value;
13 | };
14 |
15 | const { height, width } = Dimensions.get("window");
16 | const { multiply } = Animated;
17 | export default class Pages extends React.PureComponent {
18 | render() {
19 | const { sections, y, x } = this.props;
20 | const translateX = multiply(x, -1);
21 | const translateY = multiply(y, -1);
22 | return (
23 |
24 | {sections.map(({ image }, key) => (
25 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | ))}
39 |
40 | );
41 | }
42 | }
43 |
44 | const styles = StyleSheet.create({
45 | container: {
46 | flexDirection: "row",
47 | },
48 | page: {
49 | backgroundColor: "white",
50 | width,
51 | height: height - SMALL_HEADER_HEIGHT,
52 | },
53 | });
54 |
--------------------------------------------------------------------------------
/src/examples/Flutter/components/index.tsx:
--------------------------------------------------------------------------------
1 | export { default as Sections } from "./Sections";
2 |
--------------------------------------------------------------------------------
/src/examples/Flutter/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Sections, Section } from "./components";
3 |
4 | const mariner = "#3B5F8F";
5 | const mediumPurple = "#8266D4";
6 | const tomato = "#F95B57";
7 | const mySin = "#F3A646";
8 |
9 | const sections: Section[] = [
10 | {
11 | title: "SUNGLASSES",
12 | leftColor: mediumPurple,
13 | rightColor: mariner,
14 | image: require("./assets/sunnies.png"),
15 | },
16 | {
17 | title: "FURNITURE",
18 | leftColor: tomato,
19 | rightColor: mediumPurple,
20 | image: require("./assets/table.png"),
21 | },
22 | {
23 | title: "JEWELRY",
24 | leftColor: mySin,
25 | rightColor: tomato,
26 | image: require("./assets/earrings.png"),
27 | },
28 | {
29 | title: "HEADWEAR",
30 | leftColor: "white",
31 | rightColor: tomato,
32 | image: require("./assets/hat.png"),
33 | },
34 | ];
35 |
36 | export default () => {
37 | return ;
38 | };
39 |
--------------------------------------------------------------------------------
/src/examples/HomeScreenButton.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Text, TouchableOpacity, StyleSheet, Dimensions } from "react-native";
3 | import Icon from "react-native-vector-icons/MaterialCommunityIcons";
4 | import * as Colors from "./colors";
5 |
6 | interface CardProps {
7 | text: string;
8 | icon: string;
9 | onPress: () => void;
10 | }
11 |
12 | const HomeScreenButton = (props: CardProps) => {
13 | const { text, icon, onPress } = props;
14 | return (
15 |
16 |
17 | {text}
18 |
19 | );
20 | };
21 |
22 | const { width } = Dimensions.get("window");
23 |
24 | const styles = StyleSheet.create({
25 | card: {
26 | alignItems: "center",
27 | justifyContent: "center",
28 | width: width / 3 - 30,
29 | height: width / 3 - 30,
30 | borderColor: "#444",
31 | borderWidth: StyleSheet.hairlineWidth,
32 | borderRadius: 4,
33 | margin: 10,
34 | },
35 | cardIcon: {
36 | marginBottom: 10,
37 | color: Colors.ColorA,
38 | },
39 | cardText: {
40 | textAlign: "center",
41 | },
42 | });
43 |
44 | export default HomeScreenButton;
45 |
--------------------------------------------------------------------------------
/src/examples/Interactions/AnimatedNumber.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { StyleSheet, Text, Platform } from "react-native";
3 | import Fluid from "react-native-fluid-transitions";
4 |
5 | type AnimatedNumberProps = {
6 | value: number;
7 | };
8 |
9 | const AnimatedNumber: React.FC = ({ value }) => {
10 | const digits = value.toString().split("");
11 | return (
12 |
13 | {digits.map((s, index) => (
14 |
15 | ))}
16 |
17 | );
18 | };
19 |
20 | type NumberProps = {
21 | value: number;
22 | };
23 | const Number: React.FC = ({ value }) => {
24 | const style = {
25 | transform: [{ translateY: -(value * boxHeight) }],
26 | };
27 | return (
28 |
31 | {[...Array(10).keys()].map((_, index) => (
32 |
33 | {index}
34 |
35 | ))}
36 |
37 | );
38 | };
39 |
40 | const boxHeight = Platform.select({ default: 24, android: 28 });
41 | const styles = StyleSheet.create({
42 | container: {
43 | flexDirection: "row",
44 | height: boxHeight,
45 | overflow: "hidden",
46 | },
47 | numberContainer: {
48 | height: boxHeight,
49 | },
50 | digit: {
51 | height: boxHeight,
52 | fontFamily: "Arial",
53 | fontSize: 24,
54 | },
55 | });
56 |
57 | export { AnimatedNumber };
58 |
--------------------------------------------------------------------------------
/src/examples/Interactions/FloatingLabel.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import { Platform, TextInput, StyleSheet, View } from "react-native";
3 | import Fluid from "react-native-fluid-transitions";
4 | import { ColorA } from "../colors";
5 |
6 | type Props = {
7 | placeholder?: string;
8 | };
9 | const FloatingLabel: React.FC = ({ placeholder }) => {
10 | const [value, setValue] = useState("");
11 | const onChangeText = (t: string) => setValue(t);
12 | return (
13 |
14 | {/* Placeholder */}
15 |
16 | {placeholder}
17 |
18 | {/* Input */}
19 |
25 |
26 | );
27 | };
28 |
29 | const styles = StyleSheet.create({
30 | container: {
31 | paddingTop: 8,
32 | justifyContent: "center",
33 | borderBottomColor: "#333",
34 | borderBottomWidth: StyleSheet.hairlineWidth,
35 | minWidth: 130,
36 | },
37 | placeholderEmpty: {
38 | ...StyleSheet.absoluteFillObject,
39 | marginVertical: 3,
40 | transform: [{ translateY: Platform.select({ default: 4, android: 8 }) }],
41 | color: "#555",
42 | fontSize: 14,
43 | },
44 | placeholder: {
45 | ...StyleSheet.absoluteFillObject,
46 | marginVertical: 3,
47 | transform: [{ translateY: -10 }],
48 | color: ColorA,
49 | fontSize: 10,
50 | },
51 | input: {
52 | alignSelf: "stretch",
53 | padding: 0,
54 | margin: 0,
55 | },
56 | });
57 |
58 | export { FloatingLabel };
59 |
--------------------------------------------------------------------------------
/src/examples/Interactions/InteractionContainer.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { View, StyleSheet, Dimensions, Text } from "react-native";
3 | import Fluid from "react-native-fluid-transitions";
4 |
5 | type Props = {
6 | text: string;
7 | onPress?: () => void;
8 | };
9 | const InteractionContainer: React.FC = ({ text, onPress, children }) => {
10 | return (
11 |
12 | {children}
13 |
14 | {text}
15 |
16 |
17 | );
18 | };
19 |
20 | const { width } = Dimensions.get("window");
21 |
22 | const styles = StyleSheet.create({
23 | container: {
24 | width: width / 2 - 30,
25 | height: width / 2 - 30,
26 | borderColor: "#444",
27 | borderWidth: StyleSheet.hairlineWidth,
28 | borderRadius: 4,
29 | margin: 10,
30 | overflow: "hidden"
31 | },
32 | controlContainer: {
33 | alignItems: "center",
34 | justifyContent: "center",
35 | alignSelf: "stretch",
36 | flex: 1
37 | },
38 | textContainer: {
39 | alignItems: "center",
40 | justifyContent: "center",
41 | padding: 4
42 | },
43 | text: {
44 | textAlign: "center",
45 | fontSize: 11
46 | }
47 | });
48 |
49 | export { InteractionContainer };
50 |
--------------------------------------------------------------------------------
/src/examples/Interactions/LikeHeart.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import { StyleSheet, View, TextStyle } from "react-native";
3 | import Fluid, { createFluidComponent } from "react-native-fluid-transitions";
4 | import Icon from "react-native-vector-icons/MaterialCommunityIcons";
5 | import { IconProps } from "react-native-vector-icons/Icon";
6 | import { ColorA } from "../colors";
7 |
8 | const FluidIcon = createFluidComponent(Icon, false);
9 |
10 | const LikeHeart = () => {
11 | const [likes, setLikes] = useState(0);
12 | const state = { name: "likes", active: true, value: likes };
13 | const onLike = () => setLikes(l => l + 1);
14 | const config = Fluid.createConfig({
15 | onEnter: {
16 | state: "likes",
17 | interpolation: {
18 | styleKey: "transform.scale",
19 | outputRange: [1, 1.5, 1],
20 | },
21 | animation: Fluid.Animations.Springs.Gentle,
22 | },
23 | });
24 | return (
25 |
26 |
34 |
35 | );
36 | };
37 |
38 | const styles = StyleSheet.create({
39 | container: {
40 | flexDirection: "row",
41 | alignItems: "center",
42 | justifyContent: "center",
43 | width: 44,
44 | height: 44,
45 | },
46 | });
47 |
48 | export { LikeHeart };
49 |
--------------------------------------------------------------------------------
/src/examples/Maze/MazeItem.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { View } from "react-native";
3 | import { styles } from "./styles";
4 | import Fluid from "react-native-fluid-transitions";
5 | import { Easings } from "react-native-fluid-transitions";
6 |
7 | interface MazeItemProps {
8 | size: number;
9 | index: number;
10 | isSet: boolean;
11 | }
12 |
13 | export const MazeItem: React.FC = ({ isSet, index, size }) => {
14 | return (
15 |
16 |
22 |
23 | );
24 | };
25 |
--------------------------------------------------------------------------------
/src/examples/Maze/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useRef } from "react";
2 | import { Dimensions } from "react-native";
3 | import Fluid from "react-native-fluid-transitions";
4 | import { styles } from "./styles";
5 | import { MazeItem } from "./MazeItem";
6 |
7 | const columns = 6;
8 |
9 | const { width, height } = Dimensions.get("window");
10 | const boxSize = width / columns;
11 |
12 | const createMaze = () => {
13 | const nextMaze: boolean[] = [];
14 | for (let y = 0; y < height / boxSize; y++) {
15 | for (let x = 0; x < columns; x++) {
16 | nextMaze.push(Math.random() < 0.5);
17 | }
18 | }
19 | return nextMaze;
20 | };
21 |
22 | const swapMaze = (maze: Array) => {
23 | const nextMaze: Array = [];
24 | let i = 0;
25 | for (let y = 0; y < height / boxSize; y++) {
26 | for (let x = 0; x < columns; x++) {
27 | nextMaze.push(!maze[i++]);
28 | }
29 | }
30 | return nextMaze;
31 | };
32 |
33 | const MazeExampleScreen = () => {
34 | const [maze, setMaze] = useState(() => createMaze());
35 | const cur = useRef(1);
36 | if (cur.current === 0) {
37 | cur.current = 1;
38 | } else {
39 | cur.current = 0;
40 | }
41 | const toggleLabyrinth = () => {
42 | setMaze(swapMaze(maze));
43 | };
44 |
45 | return (
46 |
51 | {/* */}
52 | {maze.map((b, index) => (
53 |
54 | ))}
55 |
56 | );
57 | };
58 |
59 | MazeExampleScreen.navigationOptions = {
60 | title: "Maze",
61 | };
62 |
63 | export default MazeExampleScreen;
64 |
--------------------------------------------------------------------------------
/src/examples/Maze/styles.ts:
--------------------------------------------------------------------------------
1 | import { StyleSheet } from "react-native";
2 | import { ColorC } from "../colors";
3 |
4 | export const styles = StyleSheet.create({
5 | container: {
6 | flex: 1,
7 | flexDirection: "row",
8 | flexWrap: "wrap"
9 | },
10 | box: {
11 | alignItems: "center",
12 | justifyContent: "center",
13 | backgroundColor: ColorC,
14 | overflow: "hidden"
15 | },
16 | line: {
17 | width: 2,
18 | backgroundColor: "#000"
19 | },
20 | setBox: {
21 | transform: [{ rotate: "-45deg" }]
22 | },
23 | offsetBox: {
24 | transform: [{ rotate: "45deg" }]
25 | }
26 | });
27 |
--------------------------------------------------------------------------------
/src/examples/Navigation/box.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Fluid from "react-native-fluid-transitions";
3 | import { useHorizontalTransition } from "react-native-fluid-navigation";
4 | import { Dimensions, StyleSheet } from "react-native";
5 |
6 | type Props = {
7 | color: string;
8 | };
9 |
10 | export const Box: React.FC = ({ color }) => {
11 | const horizontalTransition = useHorizontalTransition(
12 | Dimensions.get("screen").width,
13 | );
14 |
15 | return (
16 |
20 | );
21 | };
22 |
23 | const styles = StyleSheet.create({
24 | container: {
25 | width: 40,
26 | height: 40,
27 | margin: 20,
28 | },
29 | });
30 |
--------------------------------------------------------------------------------
/src/examples/Navigation/bubble.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Fluid from "react-native-fluid-transitions";
3 | import { useHorizontalTransition } from "react-native-fluid-navigation";
4 | import { Dimensions, StyleSheet } from "react-native";
5 |
6 | type Props = {
7 | color: string;
8 | };
9 |
10 | export const Bubble: React.FC = ({ color }) => {
11 | const horizontalTransition = useHorizontalTransition(
12 | 30 + Dimensions.get("screen").width / 2,
13 | );
14 |
15 | return (
16 |
20 | );
21 | };
22 |
23 | const styles = StyleSheet.create({
24 | container: {
25 | width: 40,
26 | height: 40,
27 | borderRadius: 20,
28 | margin: 20,
29 | },
30 | });
31 |
--------------------------------------------------------------------------------
/src/examples/Navigation/button.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import { StyleSheet, Dimensions } from "react-native";
3 | import Fluid from "react-native-fluid-transitions";
4 | import { ColorC, ColorE } from "../colors";
5 | import { useHorizontalTransition } from "react-native-fluid-navigation";
6 |
7 | const styles = StyleSheet.create({
8 | container: {
9 | alignItems: "center",
10 | justifyContent: "center",
11 | padding: 14,
12 | },
13 | active: {
14 | backgroundColor: ColorE,
15 | width: 200,
16 | height: 50,
17 | borderRadius: 25,
18 | },
19 | inactive: {
20 | backgroundColor: ColorC,
21 | width: 300,
22 | height: 50,
23 | borderRadius: 0,
24 | },
25 | });
26 |
27 | const AnimatedButton: React.FC = ({ children }) => {
28 | const [active, setActive] = useState(true);
29 | const toggle = () => setActive(p => !p);
30 | const horizontalTransition = useHorizontalTransition(
31 | Dimensions.get("window").width,
32 | );
33 | return (
34 |
39 | {children}
40 |
41 | );
42 | };
43 |
44 | export { AnimatedButton };
45 |
--------------------------------------------------------------------------------
/src/examples/Navigation/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { FluidNavigationContainer } from "react-native-fluid-navigation";
3 | import { createFluidStackNavigator } from "react-native-fluid-navigation";
4 |
5 | import { Screen } from "./screen";
6 | import { ColorA, ColorB, ColorC, ColorE } from "../colors";
7 |
8 | const NavigationExampleScreen = createFluidStackNavigator({
9 | screen1: () => (
10 |
11 |
18 |
19 | ),
20 |
21 | screen2: () => (
22 |
23 |
32 |
33 | ),
34 |
35 | screen3: () => (
36 |
37 |
45 |
46 | ),
47 |
48 | screen4: () => (
49 |
50 |
58 |
59 | ),
60 | });
61 |
62 | export default NavigationExampleScreen;
63 |
--------------------------------------------------------------------------------
/src/examples/Repeating/Repeater.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Fluid, { Easings, useFluidConfig } from "react-native-fluid-transitions";
3 | import { StyleSheet } from "react-native";
4 |
5 | type Props = {
6 | loop: number;
7 | flip: number;
8 | yoyo: number;
9 | color: string;
10 | isRepeating: boolean;
11 | };
12 | const styles = StyleSheet.create({
13 | container: {
14 | width: 30,
15 | height: 30,
16 | borderRadius: 15,
17 | marginBottom: 3,
18 | },
19 | });
20 |
21 | export const Repeater: React.FC = ({
22 | loop,
23 | flip,
24 | yoyo,
25 | color,
26 | isRepeating,
27 | }) => {
28 | const state = { name: "repeat", active: isRepeating };
29 | const config = useFluidConfig({
30 | when: {
31 | animation: {
32 | type: "timing",
33 | duration: 1200,
34 | easing: Easings.back(),
35 | },
36 | state: state,
37 | flip,
38 | yoyo,
39 | loop,
40 | interpolation: {
41 | outputRange: [-50, 0, 50],
42 | styleKey: "transform.translateX",
43 | },
44 | },
45 | });
46 | return (
47 |
54 | );
55 | };
56 |
--------------------------------------------------------------------------------
/src/examples/SVG/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import { StyleSheet, View, Dimensions } from "react-native";
3 | import Fluid from "react-native-fluid-svg";
4 | import { ColorC } from "../colors";
5 | import Svg, { Defs, Stop } from "react-native-svg";
6 |
7 | const SvgExampleScreen = () => {
8 | const [isToggled, setIsToggled] = useState(false);
9 | const toggle = () => setIsToggled(p => !p);
10 | const { width, height } = Dimensions.get("window");
11 | return (
12 |
13 |
36 |
37 | );
38 | };
39 |
40 | SvgExampleScreen.navigationOptions = {
41 | title: "SVG",
42 | };
43 |
44 | const styles = StyleSheet.create({
45 | container: {
46 | justifyContent: "center",
47 | alignItems: "center",
48 | padding: 40,
49 | flex: 1,
50 | },
51 | });
52 |
53 | export default SvgExampleScreen;
54 |
--------------------------------------------------------------------------------
/src/examples/Styles/Pager.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { StyleSheet } from "react-native";
3 | import Fluid from "react-native-fluid-transitions";
4 | import * as Colors from "../colors";
5 |
6 | const PagerItem: React.FunctionComponent<{
7 | active: boolean;
8 | label: string;
9 | }> = ({ active, label }) => {
10 | const style = [styles.item, active ? styles.itemActive : styles.itemInactive];
11 | return ;
12 | };
13 |
14 | const Pager: React.FunctionComponent<{
15 | activeIndex: number;
16 | count: number;
17 | }> = ({ activeIndex, count }) => {
18 | const items = Array.from({ length: count }, (_, k) => k);
19 | return (
20 |
21 | {items.map(i => (
22 |
27 | ))}
28 |
29 | );
30 | };
31 |
32 | const styles = StyleSheet.create({
33 | container: {
34 | flexDirection: "row",
35 | alignItems: "center",
36 | justifyContent: "center",
37 | marginBottom: 24
38 | },
39 | item: {
40 | borderRadius: 5,
41 | height: 10,
42 | marginHorizontal: 10
43 | },
44 | itemActive: {
45 | backgroundColor: Colors.ColorA,
46 | width: 30
47 | },
48 | itemInactive: {
49 | backgroundColor: "#CCC",
50 | width: 10
51 | }
52 | });
53 |
54 | export { Pager, PagerItem };
55 |
--------------------------------------------------------------------------------
/src/examples/Text/Ticker.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Fluid, { Staggered } from "react-native-fluid-transitions";
3 | import { Text, StyleSheet } from "react-native";
4 |
5 | const Ticker: React.FunctionComponent<{
6 | text: string;
7 | appear: any;
8 | }> = ({ text, appear }) => {
9 | return (
10 |
14 | {text.split("").map((s: string, index: number) =>
15 | s === " " ? (
16 |
17 | ) : (
18 |
22 | {s}
23 |
24 | ),
25 | )}
26 |
27 | );
28 | };
29 |
30 | const styles = StyleSheet.create({
31 | container: {
32 | borderColor: "#CCC",
33 | borderWidth: StyleSheet.hairlineWidth,
34 | overflow: "hidden",
35 | justifyContent: "center",
36 | alignItems: "center",
37 | flexDirection: "row",
38 | marginTop: 20,
39 | padding: 20,
40 | },
41 | });
42 |
43 | export default Ticker;
44 |
--------------------------------------------------------------------------------
/src/examples/colors.ts:
--------------------------------------------------------------------------------
1 | export const ColorA = "#B52B38";
2 | export const ColorB = "#E17140";
3 | export const ColorC = "#FBB958";
4 | export const ColorD = "#C8CB55";
5 | export const ColorE = "#6B7449";
6 |
--------------------------------------------------------------------------------
/src/examples/helpers.ts:
--------------------------------------------------------------------------------
1 | import { Dimensions } from "react-native";
2 |
3 | export const generateRandomImageUri = (width?: number, height?: number) => {
4 | const randomNumber = Math.floor(Math.random() * 100 + 1);
5 | return generateImageUri(randomNumber, width, height);
6 | };
7 |
8 | export const generateImageUri = (
9 | imageId: number,
10 | width?: number,
11 | height?: number
12 | ) => {
13 | const size = Dimensions.get("window");
14 | const imageHeight = Math.round(height || size.width * 0.4);
15 | const imageWidth = Math.round(width || size.width);
16 | return `https://picsum.photos/${imageWidth}/${imageHeight}?image=${imageId}`;
17 | };
18 |
--------------------------------------------------------------------------------
/src/packages/animated/index.ts:
--------------------------------------------------------------------------------
1 | import { IAnimationProvider } from "./src/Types/IAnimationProvider";
2 | import { NativeModules } from "react-native";
3 |
4 | const _renimatedAvailable =
5 | // false &&
6 | NativeModules !== undefined && NativeModules.ReanimatedModule !== undefined;
7 |
8 | console.log(
9 | `**** Render engine ${
10 | _renimatedAvailable ? "react-native-reanimated" : "React Native Animated"
11 | }`,
12 | );
13 | export const AnimationProvider: IAnimationProvider = _renimatedAvailable
14 | ? require("./src/react-native-reanimated").ReanimatedAnimationProvider
15 | : require("./src/react-native-animated").ReactNativeAnimationProvider;
16 |
17 | export * from "./src/Types";
18 |
--------------------------------------------------------------------------------
/src/packages/animated/index.web.ts:
--------------------------------------------------------------------------------
1 | import { ReactNativeAnimationProvider } from "./src/react-native-animated";
2 |
3 | export default ReactNativeAnimationProvider;
4 |
5 | export * from "./src/Types";
6 |
--------------------------------------------------------------------------------
/src/packages/animated/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-fluid-animations",
3 | "version": "0.1.1",
4 | "description": "Animations for animated / reanimated",
5 | "repository": {
6 | "type": "git",
7 | "url": "git+https://github.com/fram-x/react-native-fluid.git"
8 | },
9 | "main": "dist/index.js",
10 | "types": "dist/index.d.ts",
11 | "scripts": {
12 | "test": "echo \"Error: no test specified\" && exit 1"
13 | },
14 | "author": "Fram X AS / Christian Falch",
15 | "license": "MIT"
16 | }
17 |
--------------------------------------------------------------------------------
/src/packages/animated/src/Types/IAnimationNode.ts:
--------------------------------------------------------------------------------
1 | export interface IAnimationNode {}
2 |
--------------------------------------------------------------------------------
/src/packages/animated/src/Types/IAnimationValue.ts:
--------------------------------------------------------------------------------
1 | import { IAnimationNode } from "./IAnimationNode";
2 |
3 | export interface IAnimationValue extends IAnimationNode {
4 | setValue: (value: any) => void;
5 | }
6 |
--------------------------------------------------------------------------------
/src/packages/animated/src/Types/Interpolation.ts:
--------------------------------------------------------------------------------
1 | import { IAnimationNode } from "./IAnimationNode";
2 |
3 | export type ExtrapolateType = "extend" | "identity" | "clamp";
4 |
5 | export type InterpolationConfig = {
6 | inputRange?: number[];
7 | outputRange: Array;
8 | extrapolate?: ExtrapolateType;
9 | extrapolateLeft?: ExtrapolateType;
10 | extrapolateRight?: ExtrapolateType;
11 | };
12 |
--------------------------------------------------------------------------------
/src/packages/animated/src/Types/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./IAnimationNode";
2 | export * from "./IAnimationProvider";
3 | export * from "./IAnimationValue";
4 | export * from "./Interpolation";
5 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-animated/Implementation/ColorNode.ts:
--------------------------------------------------------------------------------
1 | import { Animated } from "react-native";
2 |
3 | export class ColorNode extends Animated.Value {
4 | constructor(parent: Animated.Value) {
5 | // @ts-ignore
6 | super(parent.__getValue());
7 | this._parent = parent;
8 | }
9 |
10 | _parent: Animated.Value;
11 |
12 | __attach(): void {
13 | // @ts-ignore
14 | this._parent.__addChild(this);
15 | }
16 |
17 | __detach(): void {
18 | // @ts-ignore
19 | this._parent.__removeChild(this);
20 | // @ts-ignore
21 | super.__detach();
22 | }
23 |
24 | setValue = (value: number) => {
25 | if (Number.isNaN(value)) {
26 | throw new Error("Value is not a number");
27 | }
28 | this._parent.setValue(value);
29 | };
30 |
31 | __getValue = () => {
32 | // @ts-ignore
33 | const l = this._parent.__getValue();
34 | // const r = (l >> 24) & 0xff;
35 | // const g = (l >> 16) & 0xff;
36 | // const b = (l >> 8) & 0xff;
37 | // const a = l & 0xff;
38 | const clr = `rgba(${(l >> 24) & 0xff},${(l >> 16) & 0xff},${(l >> 8) &
39 | 0xff},${l & 0xff})`;
40 | return clr;
41 | };
42 | }
43 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-animated/Implementation/RadNode.ts:
--------------------------------------------------------------------------------
1 | import { Animated } from "react-native";
2 |
3 | export class RadNode extends Animated.Value {
4 | constructor(parent: Animated.Value) {
5 | // @ts-ignore
6 | super(parent.__getValue());
7 | this._parent = parent;
8 | }
9 |
10 | _parent: Animated.Value;
11 |
12 | __attach(): void {
13 | // @ts-ignore
14 | this._parent.__addChild(this);
15 | }
16 |
17 | __detach(): void {
18 | // @ts-ignore
19 | this._parent.__removeChild(this);
20 | // @ts-ignore
21 | super.__detach();
22 | }
23 |
24 | setValue = (value: number) => {
25 | if (Number.isNaN(value)) {
26 | throw new Error("Value is not a number");
27 | }
28 | this._parent.setValue(value);
29 | };
30 |
31 | __getValue = () => {
32 | // @ts-ignore
33 | return this._parent.__getValue() + "rad";
34 | };
35 | }
36 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-animated/Implementation/bezier.ts:
--------------------------------------------------------------------------------
1 | export function bezier(mX1: number, mY1: number, mX2: number, mY2: number) {
2 | // Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1).
3 | const cx = 3.0 * mX1;
4 | const bx = 3.0 * (mX2 - mX1) - cx;
5 | const ax = 1.0 - cx - bx;
6 |
7 | const cy = 3.0 * mY1;
8 | const by = 3.0 * (mY2 - mY1) - cy;
9 | const ay = 1.0 - cy - by;
10 |
11 | const sampleCurveX = (t: number) => {
12 | // `ax t^3 + bx t^2 + cx t' expanded using Horner's rule.
13 | return ((ax * t + bx) * t + cx) * t;
14 | };
15 |
16 | const sampleCurveY = (t: number) => {
17 | return ((ay * t + by) * t + cy) * t;
18 | };
19 |
20 | const sampleCurveDerivativeX = (t: number) => {
21 | return (3.0 * ax * t + 2.0 * bx) * t + cx;
22 | };
23 |
24 | const solveCurveX = (x: number, epsilon: number) => {
25 | let t0, t1, t2, x2, d2: number;
26 | let i: number;
27 |
28 | // First try a few iterations of Newton's method -- normally very fast.
29 | for (t2 = x, i = 0; i < 8; i++) {
30 | x2 = sampleCurveX(t2) - x;
31 | if (Math.abs(x2) < epsilon) return t2;
32 | d2 = sampleCurveDerivativeX(t2);
33 | if (Math.abs(d2) < 1e-6) break;
34 | t2 = t2 - x2 / d2;
35 | }
36 |
37 | // Fall back to the bisection method for reliability.
38 | t0 = 0.0;
39 | t1 = 1.0;
40 | t2 = x;
41 |
42 | if (t2 < t0) return t0;
43 | if (t2 > t1) return t1;
44 |
45 | while (t0 < t1) {
46 | x2 = sampleCurveX(t2);
47 | if (Math.abs(x2 - x) < epsilon) return t2;
48 | if (x > x2) t0 = t2;
49 | else t1 = t2;
50 | t2 = (t1 - t0) * 0.5 + t0;
51 | }
52 |
53 | // Failure.
54 | return t2;
55 | };
56 |
57 | return function BezierEasing(x: number) {
58 | return sampleCurveY(solveCurveX(x, Number.EPSILON));
59 | };
60 | }
61 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-animated/Implementation/createValue.ts:
--------------------------------------------------------------------------------
1 | import { Animated } from "react-native";
2 | import { isAnimatedNode } from "./utils";
3 | import { IAnimationNode } from "../../Types";
4 |
5 | export const createValue = (v: number | IAnimationNode) => {
6 | if (isAnimatedNode(v)) {
7 | // @ts-ignore
8 | return new Animated.Value(v.__getValue());
9 | }
10 | return new Animated.Value(v as number);
11 | };
12 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-animated/Implementation/getColorDisplayValue.ts:
--------------------------------------------------------------------------------
1 | import { IAnimationNode } from "../../Types/IAnimationNode";
2 |
3 | export const getColorDisplayValue = (input: IAnimationNode) => input;
4 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-animated/Implementation/getColorDisplayValue.web.ts:
--------------------------------------------------------------------------------
1 | import { IAnimationNode } from "../../Types/IAnimationNode";
2 | import { ColorNode } from "./ColorNode";
3 | import { Animated } from "react-native";
4 |
5 | export const getColorDisplayValue = (input: IAnimationNode) => {
6 | return new ColorNode(input as Animated.Value);
7 | };
8 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-animated/Implementation/getProcessedColor.ts:
--------------------------------------------------------------------------------
1 | import { IAnimationNode } from "../../Types";
2 | import { isAnimatedNode } from "./utils";
3 | import { Animated } from "react-native";
4 |
5 | import { normalizeColor } from "./normalizeColor";
6 |
7 | export const getProcessedColor = (
8 | value: string | number | IAnimationNode,
9 | ): number => {
10 | if (isAnimatedNode(value)) {
11 | // @ts-ignore
12 | return normalizeColor((value as Animated.Value).__getValue());
13 | }
14 | // @ts-ignore
15 | return normalizeColor(value as number);
16 | };
17 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-animated/Implementation/getProcessedColor.web.ts:
--------------------------------------------------------------------------------
1 | import { IAnimationNode } from "../../Types";
2 | import { isAnimatedNode } from "./utils";
3 | import { Animated } from "react-native";
4 |
5 | const normalizeColor = require("normalize-css-color");
6 |
7 | export const getProcessedColor = (
8 | value: string | number | IAnimationNode
9 | ): number => {
10 | if (isAnimatedNode(value)) {
11 | // @ts-ignore
12 | return normalizeColor((value as Animated.Value).__getValue());
13 | }
14 | return normalizeColor(value);
15 | };
16 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-animated/Implementation/getProcessedRotation.ts:
--------------------------------------------------------------------------------
1 | import { IAnimationNode } from "../../Types";
2 | import { isAnimatedNode } from "./utils";
3 | import { Animated } from "react-native";
4 |
5 | export const getProcessedRotation = (
6 | value: string | IAnimationNode
7 | ): number | IAnimationNode => {
8 | let resolvedValue: string;
9 | if (isAnimatedNode(value)) {
10 | // @ts-ignore
11 | resolvedValue = (value as Animated.Node).__getValue();
12 | } else {
13 | resolvedValue = value as string;
14 | }
15 |
16 | if (/deg$/.test(resolvedValue)) {
17 | const degrees = parseFloat(resolvedValue) || 0;
18 | const radians = (degrees * Math.PI) / 180.0;
19 | return radians;
20 | } else {
21 | // Assume radians
22 | return resolvedValue;
23 | }
24 | };
25 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-animated/Implementation/runTiming.ts:
--------------------------------------------------------------------------------
1 | import { Animated, Easing } from "react-native";
2 | import { IAnimationValue } from "../../Types";
3 |
4 | export const runTiming = (master: IAnimationValue, duration: number): void => {
5 | Animated.timing(master as Animated.Value, {
6 | toValue: duration,
7 | duration,
8 | easing: Easing.linear,
9 | isInteraction: false,
10 | }).start(() => {
11 | (master as Animated.Value).removeAllListeners();
12 | });
13 | };
14 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-animated/Implementation/utils.ts:
--------------------------------------------------------------------------------
1 | export function isAnimatedNode(value: Object): boolean {
2 | // @ts-ignore
3 | return value && value.__getValue !== undefined;
4 | }
5 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-animated/__tests__/assign.spec.ts:
--------------------------------------------------------------------------------
1 | import { ReactNativeAnimationProvider as P, AnimatedNode } from "..";
2 | const { Animated } = P;
3 |
4 | describe("assign", () => {
5 | it("should assign numberic value", () => {
6 | const a = P.createValue(1);
7 | const statement = Animated.set(a, 10);
8 | const valueToTest = (statement as AnimatedNode).evaluate();
9 | expect(valueToTest).toBe(10);
10 | });
11 |
12 | it("should assign animated value", () => {
13 | const a = P.createValue(1);
14 | const b = P.createValue(2);
15 | const statement = Animated.set(a, b);
16 | const valueToTest = (statement as AnimatedNode).evaluate();
17 | expect(valueToTest).toEqual(2);
18 | });
19 |
20 | it("should assign expression", () => {
21 | const a = P.createValue(1);
22 | const b = P.createValue(2);
23 | const expression = Animated.add(a, b);
24 | const statement = Animated.set(a, expression);
25 | const valueToTest = (statement as AnimatedNode).evaluate();
26 | expect(valueToTest).toEqual(3);
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-animated/__tests__/bezier.spec.ts:
--------------------------------------------------------------------------------
1 | import { AnimationProvider } from "../../..";
2 | import { AnimatedNode } from "..";
3 | const { Animated } = AnimationProvider;
4 |
5 | describe("bezier / linear", () => {
6 | it("should return 0", () => {
7 | const val = AnimationProvider.createValue(0);
8 | const retVal = Animated.bezier(0, 0, 1, 1)(val);
9 | expect((retVal as AnimatedNode).evaluate()).toBe(0);
10 | });
11 |
12 | it("should return 1", () => {
13 | const val = AnimationProvider.createValue(1);
14 | const retVal = Animated.bezier(0, 0, 1, 1)(val);
15 | expect((retVal as AnimatedNode).evaluate()).toBe(1);
16 | });
17 |
18 | it("should return 0.5", () => {
19 | const val = AnimationProvider.createValue(0.5);
20 | const retVal = Animated.bezier(0, 0, 1, 1)(val);
21 | expect((retVal as AnimatedNode).evaluate()).toBe(0.5);
22 | });
23 | });
24 |
25 | describe("bezier / curves", () => {
26 | it("should return 0.627", () => {
27 | const val = AnimationProvider.createValue(0.5);
28 | const retVal = Animated.bezier(0.17, 0.67, 0.83, 0.67)(val);
29 | expect((retVal as AnimatedNode).evaluate()).toBe(0.6275000000000001);
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-animated/__tests__/block.spec.ts:
--------------------------------------------------------------------------------
1 | import { ReactNativeAnimationProvider as P, AnimatedNode } from "..";
2 | const { Animated } = P;
3 |
4 | describe("assign", () => {
5 | it("should execute all nodes in a block", () => {
6 | const a = P.createValue(1);
7 | const statement = Animated.block([
8 | Animated.set(a, Animated.add(a, 10)),
9 | Animated.set(a, Animated.add(a, 10)),
10 | Animated.set(a, Animated.add(a, 10)),
11 | Animated.set(a, Animated.add(a, 10)),
12 | Animated.set(a, Animated.add(a, 10))
13 | ]);
14 | const valueToTest = (statement as AnimatedNode).evaluate();
15 | expect(valueToTest).toBe(51);
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-animated/__tests__/proc.spec.ts:
--------------------------------------------------------------------------------
1 | import { ReactNativeAnimationProvider as P, AnimatedNode } from "..";
2 | const { Animated } = P;
3 |
4 | describe("proc", () => {
5 | it("should call proc", () => {
6 | const addNumbers = Animated.proc("", (a, b) => Animated.add(a, b));
7 | const valueToTest = addNumbers(10, 10);
8 | expect((valueToTest as AnimatedNode).evaluate()).toEqual(20);
9 | });
10 |
11 | it("should call nested procs", () => {
12 | const addNumbers = Animated.proc("", (a, b) => Animated.add(a, b));
13 | const valueToTest = addNumbers(10, addNumbers(10, 10));
14 | expect((valueToTest as AnimatedNode).evaluate()).toEqual(30);
15 | });
16 |
17 | it("should call composite procs", () => {
18 | const addNumbers = Animated.proc("", (a, b) => Animated.add(a, b));
19 | const multiplyNumber = Animated.proc("", (a, b) => Animated.multiply(a, b));
20 | const valueToTest = multiplyNumber(addNumbers(10, 10), addNumbers(10, 10));
21 | expect((valueToTest as AnimatedNode).evaluate()).toEqual(400);
22 | });
23 |
24 | it("should call with nested args", () => {
25 | const subcalc = Animated.proc("", (a, b) => Animated.add(a, b));
26 | const calculate = Animated.proc("", (a, b) =>
27 | Animated.multiply(subcalc(a, b), subcalc(a, b)),
28 | );
29 | const valueToTest = calculate(10, 10);
30 | expect((valueToTest as AnimatedNode).evaluate()).toEqual(400);
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-reanimated/Implementation/createValue.ts:
--------------------------------------------------------------------------------
1 | import Animated from "react-native-reanimated";
2 | import { IAnimationNode, IAnimationValue } from "../../Types";
3 | import { isAnimatedNode } from "./utils";
4 | // @ts-ignore
5 | import { always } from "react-native-reanimated/src/base";
6 |
7 | const { set, eq, cond, call } = Animated;
8 |
9 | export const createValue = (v: number | IAnimationNode): IAnimationValue => {
10 | if (isAnimatedNode(v)) {
11 | const retVal = new Animated.Value(0);
12 | const flag = new Animated.Value(0);
13 |
14 | const evaluateOnce = cond(eq(flag, 0), [
15 | set(flag, 1),
16 | set(retVal, v as Animated.Node),
17 | call([], () => {
18 | // @ts-ignore
19 | alwaysNode.__detach();
20 | }),
21 | ]);
22 |
23 | const alwaysNode = always(evaluateOnce);
24 | // @ts-ignore
25 | alwaysNode.__attach();
26 | return retVal;
27 | }
28 | return new Animated.Value(v as number);
29 | };
30 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-reanimated/Implementation/getColorFromString.ts:
--------------------------------------------------------------------------------
1 | import { processColor } from "react-native";
2 |
3 | const getColorFromStringOrNumber = (color: string | number) => {
4 | // 0xaarrggbb
5 | const l = processColor(color);
6 | return {
7 | rgba: [
8 | (l >> 16) & 0x0000ff,
9 | (l >> 8) & 0x00ff,
10 | l & 0xff,
11 | (l >> 24) & 0x000000ff
12 | ]
13 | };
14 | };
15 |
16 | export { getColorFromStringOrNumber };
17 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-reanimated/Implementation/getDegreesInRadian.ts:
--------------------------------------------------------------------------------
1 | export const getDegreesInRadian = (rotation: string): number => {
2 | if (!rotation) return 0;
3 | if (rotation.endsWith("deg")) {
4 | return degToRad(parseFloat(rotation.substring(0, rotation.length - 3)));
5 | } else if (rotation.endsWith("rad")) {
6 | return parseFloat(rotation.substring(0, rotation.length - 3));
7 | }
8 | return 0;
9 | };
10 |
11 | const degToRad = (deg: number): number => (deg * Math.PI) / 180;
12 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-reanimated/Implementation/getProcessedColor.ts:
--------------------------------------------------------------------------------
1 | import { processColor } from "react-native";
2 | import { IAnimationNode } from "../../Types";
3 | import { isAnimatedNode } from "./utils";
4 |
5 | export const getProcessedColor = (
6 | value: IAnimationNode | string | number
7 | ): IAnimationNode | number => {
8 | const isAnimatedValue = isAnimatedNode(value);
9 | if (isAnimatedValue) return value;
10 | return processColor(value);
11 | };
12 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-reanimated/Implementation/getProcessedRotation.ts:
--------------------------------------------------------------------------------
1 | import { IAnimationNode } from "../../Types";
2 | import { isAnimatedNode } from "./utils";
3 |
4 | export const getProcessedRotation = (
5 | value: IAnimationNode | string
6 | ): IAnimationNode | number => {
7 | if (isAnimatedNode(value)) return value;
8 | if (/deg$/.test(value as string)) {
9 | const degrees = parseFloat(value as string) || 0;
10 | const radians = (degrees * Math.PI) / 180.0;
11 | return radians;
12 | } else {
13 | // Assume radians
14 | return parseFloat(value as string);
15 | }
16 | };
17 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-reanimated/Implementation/runTiming.ts:
--------------------------------------------------------------------------------
1 | import Animated from "react-native-reanimated";
2 | import { IAnimationValue } from "../../Types";
3 | // @ts-ignore
4 | import { always } from "react-native-reanimated/src/base";
5 |
6 | const {
7 | Clock,
8 | Value,
9 | sub,
10 | cond,
11 | greaterOrEq,
12 | call,
13 | stopClock,
14 | set,
15 | startClock,
16 | clockRunning,
17 | } = Animated;
18 |
19 | export const runTiming = (master: IAnimationValue, duration: number) => {
20 | const clock = new Clock();
21 | let timing: Animated.Node;
22 |
23 | const startTime = new Value(0);
24 | const frameTime = sub(clock, startTime);
25 | const value = master as Animated.Value;
26 |
27 | timing = always(
28 | cond(
29 | clockRunning(clock),
30 | [
31 | cond(greaterOrEq(frameTime, duration), [
32 | // Stop animation (duration has been reached)
33 | stopClock(clock),
34 | set(value, duration),
35 | call([], () =>
36 | // @ts-ignore
37 | timing.__detach(),
38 | ),
39 | ]),
40 | // Update animation value
41 | set(value, frameTime),
42 | ],
43 | [
44 | // Start (clock is not running)
45 | set(startTime, clock),
46 | set(value, frameTime),
47 | startClock(clock),
48 | ],
49 | ),
50 | );
51 |
52 | // @ts-ignore
53 | timing.__attach();
54 | };
55 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-reanimated/Implementation/utils.ts:
--------------------------------------------------------------------------------
1 | export function isAnimatedNode(value: Object): boolean {
2 | return value && value.hasOwnProperty("__nodeID");
3 | }
4 |
--------------------------------------------------------------------------------
/src/packages/animated/src/react-native-reanimated/index.web.ts:
--------------------------------------------------------------------------------
1 | export const dummy = 10;
2 |
--------------------------------------------------------------------------------
/src/packages/animated/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "skipLibCheck": true,
6 | "esModuleInterop": true,
7 | "allowSyntheticDefaultImports": true,
8 | "strict": true,
9 | "forceConsistentCasingInFileNames": true,
10 | "module": "commonjs",
11 | "outDir": "dist",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "declaration": true,
15 | "sourceMap": true,
16 | "jsx": "react"
17 | },
18 | "include": ["src", "index.web.ts", "index.ts"],
19 | "exclude": ["node_modules", "**/*.spec.ts"]
20 | }
21 |
--------------------------------------------------------------------------------
/src/packages/gestures/index.ts:
--------------------------------------------------------------------------------
1 | import { GestureContainer } from "./src";
2 | export { GestureContainer };
3 |
--------------------------------------------------------------------------------
/src/packages/gestures/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-fluid-gestures",
3 | "version": "0.1.1",
4 | "description": "Gestures for react-native-fluid-transitions",
5 | "repository": {
6 | "type": "git",
7 | "url": "git+https://github.com/fram-x/react-native-fluid.git"
8 | },
9 | "main": "dist/index.js",
10 | "types": "dist/index.d.ts",
11 | "scripts": {
12 | "test": "echo \"Error: no test specified\" && exit 1"
13 | },
14 | "author": "Fram X AS / Christian Falch",
15 | "license": "MIT",
16 | "peerDependencies": {
17 | "react-native-fluid-animations": "*",
18 | "react-native-fluid-transitions": "*"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/packages/gestures/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "skipLibCheck": true,
6 | "esModuleInterop": true,
7 | "allowSyntheticDefaultImports": true,
8 | "strict": true,
9 | "forceConsistentCasingInFileNames": true,
10 | "module": "commonjs",
11 | "outDir": "dist",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "declaration": true,
15 | "sourceMap": true,
16 | "jsx": "react",
17 | "baseUrl": ".",
18 | "paths": {
19 | "react-native-fluid-animations": ["../../packages/animated"],
20 | "react-native-fluid-transitions": ["../../packages/transitions"]
21 | }
22 | },
23 | "include": ["src", "index.ts"],
24 | "exclude": ["node_modules", "**/*.spec.ts"]
25 | }
26 |
--------------------------------------------------------------------------------
/src/packages/navigation/index.ts:
--------------------------------------------------------------------------------
1 | export { createFluidStackNavigator, FluidNavigationContainer } from "./src";
2 | export { NavigationState } from "./src/types";
3 | export * from "./src/Transitions";
4 | export { useNavigationDirection, useNavigationStates } from "./src/Hooks";
5 |
--------------------------------------------------------------------------------
/src/packages/navigation/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-fluid-navigation",
3 | "version": "0.1.1",
4 | "description": "Navigation transitions for React Navigation and react-nativve-fluid-transitions",
5 | "repository": {
6 | "type": "git",
7 | "url": "git+https://github.com/fram-x/react-native-fluid.git"
8 | },
9 | "main": "dist/index.js",
10 | "types": "dist/index.d.ts",
11 | "scripts": {
12 | "test": "echo \"Error: no test specified\" && exit 1"
13 | },
14 | "author": "Fram X AS",
15 | "license": "MIT",
16 | "peerDependencies": {
17 | "react-navigation-stack": "*",
18 | "react-native-reanimated": "*",
19 | "react-navigation-hooks": "*",
20 | "react-native-fluid-animations": "*",
21 | "react-native-fluid-transitions": "*"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/packages/navigation/src/Functions/getNavigationStates.ts:
--------------------------------------------------------------------------------
1 | import { NavigationState } from "../types";
2 |
3 | export const getNavigationStates = (
4 | index: number,
5 | navigationState: NavigationState,
6 | ) => {
7 | const states = [
8 | {
9 | name: NavigationState.None,
10 | active: navigationState === NavigationState.None,
11 | },
12 | {
13 | name: NavigationState.ForwardTo,
14 | active: navigationState === NavigationState.ForwardTo,
15 | },
16 | {
17 | name: NavigationState.ForwardFrom,
18 | active: navigationState === NavigationState.ForwardFrom,
19 | },
20 | {
21 | name: NavigationState.BackTo,
22 | active: navigationState === NavigationState.BackTo,
23 | },
24 | {
25 | name: NavigationState.BackFrom,
26 | active: navigationState === NavigationState.BackFrom,
27 | },
28 | {
29 | name: NavigationState.InTransition,
30 | active: navigationState !== NavigationState.None,
31 | },
32 | {
33 | name: NavigationState.Forward,
34 | active:
35 | navigationState === NavigationState.ForwardFrom ||
36 | navigationState === NavigationState.ForwardTo,
37 | },
38 | {
39 | name: NavigationState.Index,
40 | active: true,
41 | value: index,
42 | },
43 | ];
44 | return states;
45 | };
46 |
--------------------------------------------------------------------------------
/src/packages/navigation/src/Functions/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./getNavigationStates";
2 | export * from "./safeGetState";
3 |
--------------------------------------------------------------------------------
/src/packages/navigation/src/Functions/safeGetState.ts:
--------------------------------------------------------------------------------
1 | import { ConfigStateType } from "react-native-fluid-transitions";
2 |
3 | export const safeGetState = (
4 | name: string,
5 | states: ConfigStateType[],
6 | ): ConfigStateType => {
7 | const state = states.find(s => s.name === name);
8 | if (!state) throw Error("State " + name + " not found.");
9 | return state;
10 | };
11 |
--------------------------------------------------------------------------------
/src/packages/navigation/src/Hooks/index.ts:
--------------------------------------------------------------------------------
1 | export { useDriverContext } from "./useDriverContext";
2 | export { useCurrentValue } from "./useCurrentValue";
3 | export { useNavigationState } from "./useNavigationState";
4 | export { useVisibilityStyle } from "./useVisibilityStyle";
5 | export { useNavigationDirection } from "./useNavigationDirection";
6 | export { useNavigationStates } from "./useNavigationStates";
7 |
--------------------------------------------------------------------------------
/src/packages/navigation/src/Hooks/useNavigationDirection.ts:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import { StateContext } from "react-native-fluid-transitions";
3 | import { safeGetState } from "../Functions";
4 | import { NavigationState } from "../types";
5 | import { DirectionConfig } from "react-native-fluid-transitions";
6 |
7 | export const useNavigationDirection = (): DirectionConfig => {
8 | const stateContext = useContext(StateContext);
9 | if (!stateContext) {
10 | throw Error("State context is missing");
11 | }
12 |
13 | const forwardState = safeGetState(
14 | NavigationState.Forward,
15 | stateContext.states,
16 | );
17 |
18 | return forwardState.active ? "forward" : "backward";
19 | };
20 |
--------------------------------------------------------------------------------
/src/packages/navigation/src/Hooks/useNavigationStates.ts:
--------------------------------------------------------------------------------
1 | import { safeGetState } from "../Functions";
2 | import { NavigationState } from "../types";
3 | import { useContext } from "react";
4 | import { StateContext } from "react-native-fluid-transitions";
5 |
6 | export const useNavigationStates = () => {
7 | const stateContext = useContext(StateContext);
8 | if (!stateContext) throw Error("State context is missing.");
9 |
10 | const forwardFrom = safeGetState(
11 | NavigationState.ForwardFrom,
12 | stateContext.states,
13 | );
14 | const forwardTo = safeGetState(
15 | NavigationState.ForwardTo,
16 | stateContext.states,
17 | );
18 | const backFrom = safeGetState(NavigationState.BackFrom, stateContext.states);
19 | const backTo = safeGetState(NavigationState.BackTo, stateContext.states);
20 | return { forwardFrom, forwardTo, backFrom, backTo };
21 | };
22 |
--------------------------------------------------------------------------------
/src/packages/navigation/src/Hooks/useVisibilityStyle.ts:
--------------------------------------------------------------------------------
1 | import { useRef, useEffect } from "react";
2 | import { StyleProp, ViewStyle } from "react-native";
3 | import Animated from "react-native-reanimated";
4 |
5 | export const useVisibilityStyle = (
6 | index: number,
7 | _normalizedProgress: Animated.Node,
8 | ) => {
9 | // Set opacity to 0 for all screens except the first one
10 | const styleRef = useRef>({
11 | opacity: index > 0 ? 0 : 1,
12 | });
13 |
14 | useEffect(() => {
15 | styleRef.current = {};
16 | }, []);
17 |
18 | return styleRef.current;
19 | };
20 |
--------------------------------------------------------------------------------
/src/packages/navigation/src/Transitions/createNavigationTransition.ts:
--------------------------------------------------------------------------------
1 | import Fluid, {
2 | // @ts-ignore
3 | ConfigWhenType,
4 | // @ts-ignore
5 | ConfigStateType,
6 | } from "react-native-fluid-transitions";
7 | import { NavigationState } from "../types";
8 | import { safeGetState } from "../Functions";
9 |
10 | export const createWhenConfiguration = (
11 | states: ConfigStateType[],
12 | styleKey: string,
13 | inputRange: Array,
14 | outputRangeForwardFrom: Array,
15 | outputRangeForwardTo: Array,
16 | outputRangeBackFrom: Array,
17 | outputRangeBackTo: Array,
18 | ): ConfigWhenType[] => {
19 | const { forwardTo, forwardFrom, backTo, backFrom } = getNavigationStates(
20 | states,
21 | );
22 |
23 | const interpolationForState = (
24 | state: ConfigStateType,
25 | _isForward: boolean,
26 | outputRange: Array,
27 | ) => ({
28 | state: state.name,
29 | animation: Fluid.Animations.Springs.Gentle,
30 | interpolation: [
31 | {
32 | styleKey,
33 | inputRange,
34 | outputRange,
35 | },
36 | ],
37 | });
38 |
39 | return [
40 | interpolationForState(forwardTo, true, outputRangeForwardTo),
41 | interpolationForState(forwardFrom, false, outputRangeForwardFrom),
42 | interpolationForState(backTo, true, outputRangeBackTo),
43 | interpolationForState(backFrom, false, outputRangeBackFrom),
44 | ];
45 | };
46 |
47 | const getNavigationStates = (states: ConfigStateType[]) => {
48 | const forwardTo = safeGetState(NavigationState.ForwardTo, states);
49 | const forwardFrom = safeGetState(NavigationState.ForwardFrom, states);
50 | const backTo = safeGetState(NavigationState.BackTo, states);
51 | const backFrom = safeGetState(NavigationState.BackFrom, states);
52 | return {
53 | forwardTo,
54 | forwardFrom,
55 | backTo,
56 | backFrom,
57 | };
58 | };
59 |
--------------------------------------------------------------------------------
/src/packages/navigation/src/Transitions/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./createNavigationTransition";
2 | export * from "./useNavigationTransition";
3 | export * from "./useTranslateTransitions";
4 |
--------------------------------------------------------------------------------
/src/packages/navigation/src/Transitions/useNavigationTransition.ts:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import { StateContext, useFluidConfig } from "react-native-fluid-transitions";
3 | import { createWhenConfiguration } from "./createNavigationTransition";
4 | import { ConfigType } from "react-native-fluid-transitions";
5 |
6 | export const useNavigationTransition = (
7 | styleKey: string,
8 | inputRange: Array,
9 | outputRangeForwardFrom: Array,
10 | outputRangeForwardTo: Array,
11 | outputRangeBackFrom: Array,
12 | outputRangeBackTo: Array,
13 | ): ConfigType => {
14 | const stateContext = useContext(StateContext);
15 | if (!stateContext) {
16 | throw Error("State context is missing");
17 | }
18 |
19 | return useFluidConfig({
20 | when: createWhenConfiguration(
21 | stateContext.states,
22 | styleKey,
23 | inputRange,
24 | outputRangeForwardFrom,
25 | outputRangeForwardTo,
26 | outputRangeBackFrom,
27 | outputRangeBackTo,
28 | ),
29 | });
30 | };
31 |
32 | export const useAllDirectionTransition = (styleKey: string, value: number) => {
33 | return useNavigationTransition(
34 | styleKey,
35 | [0, 1],
36 | [0, -value], // Forward from
37 | [value, 0], // Forward to
38 | [0, value], // Back from
39 | [-value, 0], // Back to
40 | );
41 | };
42 |
43 | export const useDirectionTransition = (styleKey: string, value: number) => {
44 | return useNavigationTransition(
45 | styleKey,
46 | [0, 1],
47 | [0, value], // Forward from
48 | [value, 0], // Forward to
49 | [0, value], // Back from
50 | [value, 0], // Back to
51 | );
52 | };
53 |
--------------------------------------------------------------------------------
/src/packages/navigation/src/Transitions/useTranslateTransitions.ts:
--------------------------------------------------------------------------------
1 | import {
2 | useAllDirectionTransition,
3 | useDirectionTransition,
4 | } from "./useNavigationTransition";
5 |
6 | export const useHorizontalTransition = (width: number) => {
7 | return useAllDirectionTransition("transform.translateX", width);
8 | };
9 |
10 | export const useVerticalTransition = (height: number) => {
11 | return useAllDirectionTransition("transform.translateY", height);
12 | };
13 |
14 | export const useTopTransition = (height: number) => {
15 | return useDirectionTransition("transform.translateY", -height);
16 | };
17 |
18 | export const useBottomTransition = (height: number) => {
19 | return useDirectionTransition("transform.translateY", height);
20 | };
21 |
22 | export const useLeftTransition = (width: number) => {
23 | return useDirectionTransition("transform.translateY", -width);
24 | };
25 |
26 | export const useRightTransition = (width: number) => {
27 | return useDirectionTransition("transform.translateY", width);
28 | };
29 |
--------------------------------------------------------------------------------
/src/packages/navigation/src/hooks/useDriverContext.ts:
--------------------------------------------------------------------------------
1 | import Animated from "react-native-reanimated";
2 | import { useMemo } from "react";
3 | import { DriverContextType } from "react-native-fluid-transitions";
4 | import { NavigationState } from "../types";
5 |
6 | export const useDriverContext = (
7 | _screenName: string,
8 | navigationState: NavigationState,
9 | durationValue: Animated.Value,
10 | current: Animated.Node,
11 | ): DriverContextType => {
12 | return useMemo(
13 | () => ({
14 | isActive: () => navigationState !== NavigationState.None,
15 | driver: current,
16 | requestDuration: (duration: number) => {
17 | durationValue.setValue(duration);
18 | // console.log("---", screenName, "got duration", duration);
19 | },
20 | }),
21 | [current, durationValue, navigationState],
22 | );
23 | };
24 |
--------------------------------------------------------------------------------
/src/packages/navigation/src/index.tsx:
--------------------------------------------------------------------------------
1 | export * from "./navigationContainer";
2 | export * from "./createFluidStackNavigator";
3 |
--------------------------------------------------------------------------------
/src/packages/navigation/src/navigationContainer.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { StyleSheet } from "react-native";
3 | import Fluid, {
4 | StateContext,
5 | DriverContext,
6 | } from "react-native-fluid-transitions";
7 | import { useNavigationState, useDriverContext, useCurrentValue } from "./Hooks";
8 | import { getNavigationStates } from "./Functions";
9 |
10 | type Props = {
11 | name: string;
12 | };
13 |
14 | export const FluidNavigationContainer: React.FC = ({
15 | name,
16 | ...props
17 | }) => {
18 | const { navigationState, index } = useNavigationState(name);
19 |
20 | // Current
21 | const { current, duration } = useCurrentValue(navigationState);
22 |
23 | // Driver context
24 | const driverContextValue = useDriverContext(
25 | name,
26 | navigationState,
27 | duration,
28 | current,
29 | );
30 |
31 | const states = getNavigationStates(index, navigationState);
32 | // console.log(name, "NavState", navigationState);
33 |
34 | // Render
35 | return (
36 |
37 |
38 |
43 |
44 |
45 | );
46 | };
47 |
--------------------------------------------------------------------------------
/src/packages/navigation/src/types.ts:
--------------------------------------------------------------------------------
1 | export enum NavigationState {
2 | None = "None",
3 | ForwardTo = "ForwardTo",
4 | ForwardFrom = "ForwardFrom",
5 | BackTo = "BackTo",
6 | BackFrom = "BackFrom",
7 | Index = "Index",
8 | Current = "Current",
9 | Focused = "Focused",
10 | Forward = "Forward",
11 | InTransition = "InTransition",
12 | }
13 |
14 | export const NavigationTiming: number = 1250;
15 |
--------------------------------------------------------------------------------
/src/packages/navigation/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "skipLibCheck": true,
6 | "esModuleInterop": true,
7 | "allowSyntheticDefaultImports": true,
8 | "strict": true,
9 | "forceConsistentCasingInFileNames": true,
10 | "module": "commonjs",
11 | "outDir": "dist",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "declaration": true,
15 | "sourceMap": true,
16 | "jsx": "react",
17 | "baseUrl": ".",
18 | "paths": {
19 | "react-native-fluid-animations": ["../../packages/animated"],
20 | "react-native-fluid-transitions": ["../../packages/transitions"]
21 | }
22 | },
23 | "include": ["src", "index.ts"],
24 | "exclude": ["node_modules", "**/*.spec.ts"]
25 | }
26 |
--------------------------------------------------------------------------------
/src/packages/svg/index.ts:
--------------------------------------------------------------------------------
1 | import Fluid from "react-native-fluid-transitions";
2 | import Svg, { Defs, Stop } from "react-native-svg";
3 | import {
4 | FluidEllipse,
5 | FluidCircle,
6 | FluidRect,
7 | FluidLine,
8 | FluidLinearGradient
9 | } from "./src/Components";
10 |
11 | const SvgViews = {
12 | Ellipse: FluidEllipse,
13 | Circle: FluidCircle,
14 | Rect: FluidRect,
15 | Line: FluidLine,
16 | LinearGradient: FluidLinearGradient,
17 | Defs,
18 | Stop,
19 | Svg
20 | };
21 |
22 | const SvgFluid = {
23 | ...Fluid,
24 | Svg: SvgViews
25 | };
26 |
27 | export default SvgFluid;
28 |
--------------------------------------------------------------------------------
/src/packages/svg/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-fluid-svg",
3 | "version": "0.1.1",
4 | "description": "",
5 | "main": "index.ts",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "Fram X AS / Christian Falch",
10 | "license": "MIT",
11 | "peerDependencies": {
12 | "react-native-fluid-animations": "*",
13 | "react-native-fluid-transitions": "*"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/packages/svg/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "skipLibCheck": true,
6 | "esModuleInterop": true,
7 | "allowSyntheticDefaultImports": true,
8 | "strict": true,
9 | "forceConsistentCasingInFileNames": true,
10 | "module": "commonjs",
11 | "outDir": "dist",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "declaration": true,
15 | "sourceMap": true,
16 | "jsx": "react",
17 | "baseUrl": ".",
18 | "paths": {
19 | "react-native-fluid-animations": ["../../packages/animated"],
20 | "react-native-fluid-transitions": ["../../packages/transitions"]
21 | }
22 | },
23 | "include": ["src", "index.ts"],
24 | "exclude": ["node_modules", "**/*.spec.ts"]
25 | }
26 |
--------------------------------------------------------------------------------
/src/packages/transitions/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-fluid-transitions",
3 | "version": "0.1.1",
4 | "description": "Fluid transition component for React Native and React Native Web",
5 | "repository": {
6 | "type": "git",
7 | "url": "git+https://github.com/fram-x/react-native-fluid.git"
8 | },
9 | "main": "dist/index.js",
10 | "types": "dist/index.d.ts",
11 | "scripts": {
12 | "test": "echo \"Error: no test specified\" && exit 1"
13 | },
14 | "author": "Fram X AS / Christian Falch",
15 | "license": "MIT",
16 | "peerDependencies": {
17 | "react-native-fluid-animations": "*"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Animation/Builder/dumpTree.ts:
--------------------------------------------------------------------------------
1 | import { AnimationNode } from "./types";
2 |
3 | export const dumpTree = (
4 | node: AnimationNode,
5 | output: (message?: any, ...optionalParams: any[]) => void,
6 | indent: number = 0,
7 | ) => {
8 | const indentStr = new Array(indent).map(_ => "").join(" ");
9 | // @ts-ignore
10 | if (node.childDirection === "-") {
11 | output(
12 | indentStr,
13 | indentStr,
14 | getNodeName(node),
15 | "subduration:",
16 | // @ts-ignore
17 | node.subtreeDuration.toFixed(2),
18 | );
19 | } else {
20 | output(
21 | indentStr,
22 | getNodeName(node),
23 | "dur:",
24 | node.duration.toFixed(2),
25 | "anim:",
26 | node.animation ? node.animation.type : "unknown",
27 | "subdur:",
28 | // @ts-ignore
29 | node.subtreeDuration.toFixed(2),
30 | "delay:",
31 | node.delay,
32 | "offset:",
33 | node.offset,
34 | "stgr:",
35 | node.stagger,
36 | node.childAnimation,
37 | node.childDirection,
38 | );
39 | }
40 | node.children.forEach(c => dumpTree(c, output, indent + 2));
41 | };
42 |
43 | const getNodeName = (node: AnimationNode) => {
44 | return "[" + node.label || "id: " + node.id + "]: ";
45 | };
46 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Animation/Builder/getAnimationOnEnd.ts:
--------------------------------------------------------------------------------
1 | import { OnAnimationFunction } from "../../Components/Types/InterpolationTypes";
2 |
3 | export const getAnimationOnEnd = (
4 | length: number,
5 | onEnd: OnAnimationFunction | undefined
6 | ) => {
7 | if (onEnd === undefined) return undefined;
8 | let animationCount = length;
9 | return () => {
10 | animationCount--;
11 | if (animationCount === 0) {
12 | onEnd && onEnd();
13 | }
14 | };
15 | };
16 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Animation/Builder/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./getInterpolationTree";
2 | export * from "./dumpTree";
3 | export * from "./types";
4 | export * from "./getAnimationOnEnd";
5 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Animation/Builder/types.ts:
--------------------------------------------------------------------------------
1 | import { Metrics } from "../../Types";
2 | import {
3 | ChildAnimationDirection,
4 | ConfigAnimationType,
5 | ConfigStaggerFunction,
6 | } from "../../Configuration";
7 |
8 | export type AnimationNode = {
9 | id: number;
10 | interpolationId: number;
11 | childAnimation: "staggered" | "parallel" | "sequential";
12 | childDirection: ChildAnimationDirection;
13 | children: Array;
14 | metrics: Metrics;
15 | parent?: AnimationNode;
16 | offset: number;
17 | duration: number;
18 | subtreeDuration?: number;
19 | delay: number;
20 | stagger: number;
21 | staggerFunction?: ConfigStaggerFunction;
22 | waitForMetrics?: () => Promise;
23 | animation?: ConfigAnimationType;
24 | label?: string;
25 | isHidden: boolean;
26 | };
27 |
28 | export type Animations = { [key: string]: boolean };
29 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Animation/Functions/createProc.ts:
--------------------------------------------------------------------------------
1 | import { IAnimationNode } from "react-native-fluid-animations";
2 |
3 | let _functionCache: {
4 | [key: string]: (...args: IAnimationNode[]) => IAnimationNode;
5 | } = {};
6 |
7 | export const createProc = (
8 | key: string,
9 | cb: () => (...args: IAnimationNode[]) => IAnimationNode,
10 | ): ((...args: IAnimationNode[]) => IAnimationNode) => {
11 | if (!_functionCache[key]) {
12 | _functionCache[key] = cb();
13 | Object.defineProperty(_functionCache[key], "name", { value: key });
14 | }
15 | return _functionCache[key];
16 | };
17 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Animation/Functions/getResolvedAnimation.ts:
--------------------------------------------------------------------------------
1 | import { createSpring } from "./spring";
2 | import {
3 | ConfigTimingAnimationType,
4 | ConfigAnimationType
5 | } from "../../Configuration";
6 |
7 | export const getResolvedAnimation = (
8 | animation: ConfigAnimationType
9 | ): ConfigTimingAnimationType => {
10 | if (animation.type === "spring") {
11 | // We need to change to a timing animation with easing
12 | const springInfo = createSpring(
13 | 0,
14 | 1,
15 | animation.mass,
16 | animation.stiffness,
17 | animation.damping
18 | );
19 | return {
20 | ...animation,
21 | type: "timing",
22 | duration: springInfo.duration,
23 | easing: springInfo.easing
24 | };
25 | }
26 | return animation;
27 | };
28 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Animation/Functions/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./easing";
2 | export * from "./spring";
3 | export * from "./createProc";
4 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Animation/Runner/Functions/__tests__/interpolateColor.spec.ts:
--------------------------------------------------------------------------------
1 | // @ts-ignore
2 | import { AnimationNode } from "react-native-fluid-animations";
3 | import { interpolateColor } from "../interpolateColor";
4 |
5 | describe("interpolateColor", () => {
6 | it("should return 0xff000000", () => {
7 | const valueToTest = interpolateColor(1, 0, 1, 0x00000000, 0xff000000);
8 | expect((valueToTest as AnimationNode).evaluate()).toBe(0xff000000);
9 | });
10 | it("should return 0x00ff0000", () => {
11 | const valueToTest = interpolateColor(1, 0, 1, 0xff000000, 0x00ff0000);
12 | expect((valueToTest as AnimationNode).evaluate()).toBe(0x00ff0000);
13 | });
14 | it("should return 0x00aa0000", () => {
15 | const valueToTest = interpolateColor(1, 0, 1, 0xff000000, 0x00aa0000);
16 | expect((valueToTest as AnimationNode).evaluate()).toBe(0x00aa0000);
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Animation/Runner/Functions/getExtrapolationValue.ts:
--------------------------------------------------------------------------------
1 | import { Extrapolate } from "./interpolate";
2 | import { ExtrapolateType } from "react-native-fluid-animations";
3 |
4 | export const getExtrapolationValue = (
5 | extrapolate: ExtrapolateType
6 | ): Extrapolate => {
7 | switch (extrapolate) {
8 | case "clamp":
9 | return Extrapolate.Clamp;
10 | case "extend":
11 | return Extrapolate.Extend;
12 | case "identity":
13 | return Extrapolate.Identity;
14 | }
15 | };
16 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Animation/Runner/Functions/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./interpolate";
2 | export * from "./lifecycle";
3 | export * from "./createAnimationNode";
4 | export * from "./normalize";
5 | export * from "./setAnimationValue";
6 | export * from "./interpolateColor";
7 | export * from "./interpolateValue";
8 | export * from "./getExtrapolationValue";
9 | export * from "./createInterpolationNode";
10 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Animation/Runner/Functions/interpolateValue.ts:
--------------------------------------------------------------------------------
1 | import {
2 | IAnimationNode,
3 | AnimationProvider
4 | } from "react-native-fluid-animations";
5 | import { createProc } from "../../Functions/createProc";
6 |
7 | const { proc, add, multiply, divide, sub } = AnimationProvider.Animated;
8 |
9 | const interpolateValueProc = createProc("interpolateValue", () =>
10 | proc(
11 | "interpolateValue",
12 | (inputValue, inputMin, inputMax, outputMin, outputMax) =>
13 | add(
14 | outputMin,
15 | multiply(
16 | divide(sub(inputValue, inputMin), sub(inputMax, inputMin)),
17 | sub(outputMax, outputMin)
18 | )
19 | )
20 | )
21 | );
22 |
23 | export const interpolateValue = (
24 | input: IAnimationNode,
25 | inputMin: any,
26 | inputMax: any,
27 | outputMin: any,
28 | outputMax: any
29 | ) => {
30 | return interpolateValueProc(input, inputMin, inputMax, outputMin, outputMax);
31 | };
32 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Animation/Runner/Functions/normalize.ts:
--------------------------------------------------------------------------------
1 | import { createProc } from "../../Functions/createProc";
2 | import { AnimationProvider } from "react-native-fluid-animations";
3 |
4 | const { proc, greaterThan, divide, sub, cond } = AnimationProvider.Animated;
5 |
6 | export const normalize = createProc("normalize", () =>
7 | proc("normalize", (source, offset, duration) =>
8 | cond(
9 | greaterThan(divide(sub(source, offset), duration), 1.0),
10 | // Greater than 1.0 - return 1.0
11 | 1.0,
12 | // Return value
13 | divide(sub(source, offset), duration)
14 | )
15 | )
16 | );
17 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Animation/Runner/Functions/setAnimationValue.ts:
--------------------------------------------------------------------------------
1 | import { getInterpolatorFunction } from "./interpolate";
2 | import { normalize } from "./normalize";
3 | import {
4 | InterpolateFunction,
5 | AnimationProvider,
6 | IAnimationValue,
7 | } from "react-native-fluid-animations";
8 | import { createProc } from "../../Functions/createProc";
9 | import { EasingFunction } from "../../../Components/Types";
10 | const { cond, set, eq, proc } = AnimationProvider.Animated;
11 |
12 | export const getSetAnimationValue = (
13 | interpolateInternal: InterpolateFunction,
14 | key: string,
15 | easingFunction: EasingFunction,
16 | easingKey: string,
17 | ) => {
18 | const interpolate = getInterpolatorFunction(
19 | interpolateInternal,
20 | key,
21 | easingFunction,
22 | easingKey,
23 | );
24 |
25 | return createProc(`setAnimationValue_${easingKey}-${key}`, () =>
26 | proc(
27 | `setAnimationValue_${easingKey}-${key}`,
28 | (
29 | source,
30 | offset,
31 | duration,
32 | target,
33 | inputMin,
34 | inputMax,
35 | outputMin,
36 | outputMax,
37 | extrapolateLeft,
38 | extrapolateRight,
39 | outputStart,
40 | ) =>
41 | // Copy start output range - this is needed since it might be
42 | // the tracker itself
43 | cond(
44 | eq(outputStart, Number.MIN_VALUE),
45 | // if outputStart is Minvalue then
46 | set(outputStart as IAnimationValue, outputMin),
47 | // else Interpolate
48 | interpolate(
49 | normalize(source, offset, duration),
50 | inputMin,
51 | inputMax,
52 | outputStart,
53 | outputMax,
54 | extrapolateLeft,
55 | extrapolateRight,
56 | target,
57 | ),
58 | ),
59 | ),
60 | );
61 | };
62 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Animation/Runner/Functions/setInterpolationValue.ts:
--------------------------------------------------------------------------------
1 | import { getInterpolatorFunction } from "./interpolate";
2 | import {
3 | InterpolateFunction,
4 | AnimationProvider,
5 | IAnimationValue,
6 | } from "react-native-fluid-animations";
7 | import { createProc } from "../../Functions/createProc";
8 | const { proc, block, cond, eq, set } = AnimationProvider.Animated;
9 |
10 | export const getSetInterpolationValue = (
11 | interpolateInternal: InterpolateFunction,
12 | key: string,
13 | ) => {
14 | const interpolate = getInterpolatorFunction(interpolateInternal, key);
15 |
16 | return createProc(`setInterpolationValue_${key}`, () =>
17 | proc(
18 | `setInterpolationValue_${key}`,
19 | (
20 | source,
21 | target,
22 | inputMin,
23 | inputMax,
24 | outputMin,
25 | outputMax,
26 | extrapolateLeft,
27 | extrapolateRight,
28 | isStarted,
29 | removePreviousStatement,
30 | ) =>
31 | block([
32 | cond(eq(isStarted, 0), [
33 | set(isStarted as IAnimationValue, 1),
34 | removePreviousStatement,
35 | ]),
36 | interpolate(
37 | source,
38 | inputMin,
39 | inputMax,
40 | outputMin,
41 | outputMax,
42 | extrapolateLeft,
43 | extrapolateRight,
44 | target,
45 | ),
46 | ]),
47 | ),
48 | );
49 | };
50 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Animation/Runner/addAnimations.ts:
--------------------------------------------------------------------------------
1 | import { createAnimationNode } from "./Functions";
2 | import { AnimationInfo } from "../../Components/Types/AnimationInfo";
3 | import { Easings, DriverContextType } from "../../Components/Types";
4 | import { IAnimationNode } from "react-native-fluid-animations";
5 |
6 | export const addAnimations = (
7 | source: IAnimationNode,
8 | driverContext: DriverContextType | undefined,
9 | animations: AnimationInfo[],
10 | ) => {
11 | // Skip tracking?
12 | if (animations.length === 0) return;
13 |
14 | // Populate with all interpolations from the tracker list
15 | animations.forEach(animation => {
16 | const {
17 | animationId,
18 | key,
19 | ownerId,
20 | inputRange,
21 | easing,
22 | easingKey,
23 | extrapolate,
24 | extrapolateLeft,
25 | extrapolateRight,
26 | outputRange,
27 | duration,
28 | target,
29 | offset,
30 | onBegin,
31 | onEnd,
32 | interpolate,
33 | } = animation;
34 | // Get easing
35 | const easingFunction = easing || Easings.linear;
36 | // Create node
37 | createAnimationNode(
38 | source,
39 | target,
40 | animationId,
41 | key,
42 | ownerId,
43 | offset,
44 | duration,
45 | easingFunction,
46 | easingKey || "linear",
47 | inputRange,
48 | outputRange,
49 | extrapolate,
50 | extrapolateLeft,
51 | extrapolateRight,
52 | onBegin,
53 | onEnd,
54 | interpolate,
55 | driverContext ? driverContext.isActive : () => false,
56 | );
57 | });
58 | };
59 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Animation/Runner/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./addAnimations";
2 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Animation/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./commitAnimations";
2 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Animation/types.ts:
--------------------------------------------------------------------------------
1 | import { InterpolationInfo } from "../Components/Types";
2 | import { IAnimationNode } from "react-native-fluid-animations";
3 |
4 | export type Interpolations = Array<{
5 | interpolator: IAnimationNode;
6 | interpolationInfo: InterpolationInfo;
7 | }>;
8 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Components/FluidTransitions/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./useConfiguration";
2 | export * from "./useTransitionItems";
3 | export * from "./useInterpolatorContext";
4 | export * from "./useAnimationContext";
5 | export * from "./useTouchable";
6 | export * from "./useSharedInterpolation";
7 | export * from "./useMountUpdate";
8 | export * from "./useLayout";
9 | export * from "./useValueInterpolation";
10 | export * from "./useStyleContext";
11 | export * from "./useStateChanges";
12 | export * from "./useOnConfig";
13 | export * from "./useWhenConfig";
14 | export * from "./useInitialStyle";
15 | export * from "./useInterpolatorConfig";
16 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Components/FluidTransitions/useInterpolatorConfig.ts:
--------------------------------------------------------------------------------
1 | import {
2 | TransitionItem,
3 | ValueContextType,
4 | InterpolatorContextType,
5 | } from "../Types";
6 | import { fluidException } from "../../Types";
7 | import { SafeStateConfigType } from "../../Configuration";
8 |
9 | export const useInterpolatorConfig = (
10 | _transitionItem: TransitionItem,
11 | styleContext: ValueContextType,
12 | _propContext: ValueContextType,
13 | interpolatorContext: InterpolatorContextType,
14 | configuration: SafeStateConfigType,
15 | isMounted: boolean,
16 | ) => {
17 | const interpolations = configuration.interpolation;
18 |
19 | interpolations.forEach(interpolation => {
20 | if (!interpolation.value) {
21 | throw fluidException(
22 | "A configuration interpolation needs an interpolator.",
23 | );
24 | }
25 | const { ownerLabel, valueName } = interpolation.value;
26 | const interpolator = interpolatorContext.getInterpolator(
27 | ownerLabel,
28 | valueName,
29 | );
30 | if (!interpolator) {
31 | if (isMounted) {
32 | // TODO: Better explanation?
33 | throw fluidException(
34 | "Could not find interpolator " +
35 | valueName +
36 | " in item with label " +
37 | ownerLabel +
38 | ".",
39 | );
40 | } else {
41 | return;
42 | }
43 | }
44 |
45 | const {
46 | styleKey,
47 | inputRange,
48 | outputRange,
49 | extrapolate,
50 | extrapolateLeft,
51 | extrapolateRight,
52 | } = interpolation;
53 |
54 | // Set up styles with interpolations
55 | styleContext.addInterpolation(
56 | interpolator,
57 | styleKey,
58 | inputRange,
59 | outputRange,
60 | extrapolate,
61 | extrapolateLeft,
62 | extrapolateRight,
63 | );
64 | });
65 | };
66 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Components/FluidTransitions/usePropContext.ts:
--------------------------------------------------------------------------------
1 | import { useRef } from "react";
2 | import { TransitionItem, AnimationContextType, Values } from "../Types";
3 | import { ValueDescriptorsType } from "../../Types";
4 | import { useValueContext } from "./useValueContext";
5 | import { getAnimatedProps } from "../../Props";
6 | import { IAnimationNode } from "react-native-fluid-animations";
7 |
8 | export const usePropContext = (
9 | transitionItem: TransitionItem,
10 | animationContext: AnimationContextType,
11 | props: T,
12 | valueDescriptors: ValueDescriptorsType
13 | ) => {
14 | // Contains previous prop values for descriptors
15 | const previousPropsRef = useRef();
16 |
17 | // Current animated props
18 | const animatedPropsRef = useRef<{ [key: string]: IAnimationNode }>();
19 |
20 | if (previousPropsRef.current !== props) {
21 | // Update
22 | previousPropsRef.current = props;
23 | }
24 |
25 | const nextKeys = Object.keys(props);
26 | const nextValues: Values = {};
27 | nextKeys.forEach(key => (nextValues[key] = props[key]));
28 |
29 | // Create value context
30 | const valueContext = useValueContext(
31 | transitionItem,
32 | animationContext,
33 | valueDescriptors,
34 | nextKeys,
35 | nextValues
36 | );
37 |
38 | if (valueContext.isChanged) {
39 | // Reset props
40 | animatedPropsRef.current = undefined;
41 | }
42 |
43 | const getAnimatedPropsInternal = () => {
44 | if (!animatedPropsRef.current) {
45 | animatedPropsRef.current = getAnimatedProps(valueContext.current());
46 | }
47 | return animatedPropsRef.current;
48 | };
49 |
50 | return {
51 | getAnimatedProps: getAnimatedPropsInternal,
52 | propContext: valueContext
53 | };
54 | };
55 |
--------------------------------------------------------------------------------
/src/packages/transitions/src/Components/FluidTransitions/useStyleContext.ts:
--------------------------------------------------------------------------------
1 | import { useRef } from "react";
2 | import { StyleSheet } from "react-native";
3 | import {
4 | Style,
5 | TransitionItem,
6 | AnimationContextType,
7 | AnimatedStyleKeys
8 | } from "../Types";
9 | import { getCalulatedStyles } from "../../Styles/getCalculatedStyle";
10 | import { useValueContext } from "./useValueContext";
11 | import { getStyleInfo } from "../../Styles/getStyleInfo";
12 |
13 | /**
14 | *
15 | * @description Builds a hash table of styles that is when interpolating
16 | */
17 | export const useStyleContext = (
18 | transitionItem: TransitionItem,
19 | animationContext: AnimationContextType,
20 | currentStyle: Style[] | Style | number | undefined
21 | ) => {
22 | // Contains the last calculated style
23 | const calculatedStyleRef = useRef