├── ios ├── android ├── index.js ├── e2e ├── mocha.opts ├── firstTest.spec.js └── init.js ├── playground ├── app.json ├── .babelrc-IGNORE ├── babel.config.js ├── assets │ ├── icon-up.png │ ├── map-bg.jpg │ ├── icon-menu.png │ ├── card-photo.jpg │ ├── icon-check.png │ ├── icon-clock.png │ ├── icon-trash.png │ ├── tinder-photo.jpg │ ├── airport-photo.jpg │ ├── calendar-body.png │ ├── calendar-header.png │ ├── chatheads-delete.png │ ├── chatheads-face1.jpg │ └── chatheads-face2.jpg ├── android │ ├── app │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── values │ │ │ │ │ │ ├── strings.xml │ │ │ │ │ │ └── styles.xml │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ └── mipmap-xxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── java │ │ │ │ │ └── com │ │ │ │ │ │ └── playground │ │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ │ └── MainApplication.java │ │ │ │ └── AndroidManifest.xml │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ └── androidTest │ │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── playground │ │ │ │ └── DetoxTest.java │ │ ├── build_defs.bzl │ │ ├── BUCK │ │ └── proguard-rules.pro │ ├── playground.keystore │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── settings.gradle │ ├── gradle.properties │ ├── build.gradle │ └── gradlew.bat ├── ios │ ├── playground │ │ ├── Images.xcassets │ │ │ ├── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── AppDelegate.h │ │ ├── main.m │ │ ├── AppDelegate.m │ │ ├── Info.plist │ │ └── Base.lproj │ │ │ └── LaunchScreen.xib │ ├── playground.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── PlaygroundTests │ │ ├── Info.plist │ │ └── PlaygroundTests.m │ ├── Playground-tvOSTests │ │ └── Info.plist │ ├── Playground-tvOS │ │ └── Info.plist │ ├── Podfile │ └── playground.xcodeproj │ │ └── xcshareddata │ │ └── xcschemes │ │ └── playground.xcscheme ├── .buckconfig ├── index.js ├── metro.config.js ├── src │ ├── examples │ │ ├── ChatHeads.js │ │ ├── SwipeableCard.js │ │ ├── HandleRelayout.js │ │ ├── SnapTo.js │ │ ├── CollapsingHeader.js │ │ ├── HandleTouches.js │ │ ├── TouchesInsideStatic.js │ │ ├── ChangePosition.js │ │ ├── TouchesInside.js │ │ ├── AlertAreas.js │ │ ├── MoreDrawers.js │ │ ├── CollapsingHeaderWithScroll.js │ │ ├── IconDrawer.js │ │ └── SideMenu.js │ └── real-life-examples │ │ ├── Documentation.js │ │ ├── UxInspirations.js │ │ ├── TinderCard.js │ │ ├── MapPanel.js │ │ ├── NowCard.js │ │ ├── CollapsibleCalendar.js │ │ └── NotifPanel.js └── .flowconfig ├── scripts ├── ci.ios.sh └── ci.android.sh ├── logos ├── circle-notitle.png ├── circle-title.png ├── square-notitle.png └── square-title.png ├── rn-cli.config.js ├── lib ├── index.js ├── android │ ├── src │ │ ├── main │ │ │ ├── res │ │ │ │ └── values │ │ │ │ │ ├── strings.xml │ │ │ │ │ ├── colors.xml │ │ │ │ │ └── styles.xml │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── wix │ │ │ │ └── interactable │ │ │ │ ├── InteractableSpring.java │ │ │ │ ├── physics │ │ │ │ ├── PhysicsArea.java │ │ │ │ ├── PhysicsObject.java │ │ │ │ ├── PhysicsAnchorBehavior.java │ │ │ │ ├── PhysicsFrictionBehavior.java │ │ │ │ ├── PhysicsSpringBehavior.java │ │ │ │ ├── PhysicsGravityWellBehavior.java │ │ │ │ ├── PhysicsBehavior.java │ │ │ │ └── PhysicsBounceBehavior.java │ │ │ │ ├── Interactable.java │ │ │ │ ├── InteractableArea.java │ │ │ │ ├── InteractablePoint.java │ │ │ │ ├── RNConvert │ │ │ │ └── RNConvert.java │ │ │ │ └── Events.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── wix │ │ │ └── interactable │ │ │ └── ExampleUnitTest.java │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── .gitignore │ ├── proguard-rules.pro │ ├── gradle.properties │ ├── build.gradle │ └── gradlew.bat ├── ios │ ├── Interactable │ │ ├── PhysicsAnchorBehavior.h │ │ ├── InteractableViewManager.h │ │ ├── PhysicsFrictionBehavior.h │ │ ├── InteractableSpring.m │ │ ├── PhysicsSpringBehavior.h │ │ ├── PhysicsObject.h │ │ ├── InteractableSpring.h │ │ ├── RCTConvert+Interactable.h │ │ ├── PhysicsObject.m │ │ ├── PhysicsGravityWellBehavior.h │ │ ├── PhysicsArea.h │ │ ├── PhysicsBounceBehavior.h │ │ ├── InteractableArea.h │ │ ├── InteractableArea.m │ │ ├── PhysicsArea.m │ │ ├── PhysicsFrictionBehavior.m │ │ ├── PhysicsAnchorBehavior.m │ │ ├── PhysicsBehavior.h │ │ ├── PhysicsSpringBehavior.m │ │ ├── InteractablePoint.h │ │ ├── PhysicsAnimator.h │ │ ├── PhysicsGravityWellBehavior.m │ │ ├── InteractablePoint.m │ │ ├── PhysicsBounceBehavior.m │ │ ├── InteractableView.h │ │ ├── RCTConvert+Interactable.m │ │ ├── PhysicsBehavior.m │ │ └── InteractableViewManager.m │ ├── Interactable.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── InteractableTests │ │ ├── Info.plist │ │ └── InteractableTests.m │ ├── Interactable-tvOSTests │ │ └── Info.plist │ ├── Interactable-tvOS │ │ └── Info.plist │ └── Interactable.xcodeproj │ │ └── xcshareddata │ │ └── xcschemes │ │ └── Interactable.xcscheme └── src │ └── InteractableView.js ├── SUPPORT.md ├── Interactable.podspec ├── .ghp └── wix.json ├── .gitignore ├── LICENSE ├── UX-INSPIRATIONS.md ├── typings └── react-native-interactable.d.ts ├── package.json └── .npmignore /ios: -------------------------------------------------------------------------------- 1 | lib/ios -------------------------------------------------------------------------------- /android: -------------------------------------------------------------------------------- 1 | lib/android -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require('./playground/index.js'); -------------------------------------------------------------------------------- /e2e/mocha.opts: -------------------------------------------------------------------------------- 1 | --recursive --timeout 120000 --bail -------------------------------------------------------------------------------- /playground/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "playground", 3 | "displayName": "playground" 4 | } -------------------------------------------------------------------------------- /playground/.babelrc-IGNORE: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["module:metro-react-native-babel-preset"] 3 | } 4 | -------------------------------------------------------------------------------- /scripts/ci.ios.sh: -------------------------------------------------------------------------------- 1 | npm install 2 | # npm run podinstall 3 | # npm run build:ios 4 | # npm run e2e:ios 5 | -------------------------------------------------------------------------------- /playground/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /logos/circle-notitle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/logos/circle-notitle.png -------------------------------------------------------------------------------- /logos/circle-title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/logos/circle-title.png -------------------------------------------------------------------------------- /logos/square-notitle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/logos/square-notitle.png -------------------------------------------------------------------------------- /logos/square-title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/logos/square-title.png -------------------------------------------------------------------------------- /scripts/ci.android.sh: -------------------------------------------------------------------------------- 1 | yes | $ANDROID_HOME/tools/bin/sdkmanager --licenses 2 | 3 | npm install 4 | # npm run e2e:android:ci 5 | -------------------------------------------------------------------------------- /playground/assets/icon-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/assets/icon-up.png -------------------------------------------------------------------------------- /playground/assets/map-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/assets/map-bg.jpg -------------------------------------------------------------------------------- /rn-cli.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | getProjectRoots() { 3 | return [__dirname, `${__dirname}/playground`]; 4 | } 5 | }; -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | import InteractableView from './src/InteractableView'; 2 | 3 | module.exports = { 4 | View: InteractableView 5 | }; 6 | -------------------------------------------------------------------------------- /playground/assets/icon-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/assets/icon-menu.png -------------------------------------------------------------------------------- /lib/android/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | react-native-interactable 3 | 4 | -------------------------------------------------------------------------------- /playground/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | playground 3 | 4 | -------------------------------------------------------------------------------- /playground/assets/card-photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/assets/card-photo.jpg -------------------------------------------------------------------------------- /playground/assets/icon-check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/assets/icon-check.png -------------------------------------------------------------------------------- /playground/assets/icon-clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/assets/icon-clock.png -------------------------------------------------------------------------------- /playground/assets/icon-trash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/assets/icon-trash.png -------------------------------------------------------------------------------- /playground/assets/tinder-photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/assets/tinder-photo.jpg -------------------------------------------------------------------------------- /playground/ios/playground/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /playground/assets/airport-photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/assets/airport-photo.jpg -------------------------------------------------------------------------------- /playground/assets/calendar-body.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/assets/calendar-body.png -------------------------------------------------------------------------------- /playground/android/playground.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/android/playground.keystore -------------------------------------------------------------------------------- /playground/assets/calendar-header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/assets/calendar-header.png -------------------------------------------------------------------------------- /playground/assets/chatheads-delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/assets/chatheads-delete.png -------------------------------------------------------------------------------- /playground/assets/chatheads-face1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/assets/chatheads-face1.jpg -------------------------------------------------------------------------------- /playground/assets/chatheads-face2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/assets/chatheads-face2.jpg -------------------------------------------------------------------------------- /playground/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /lib/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/lib/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /playground/index.js: -------------------------------------------------------------------------------- 1 | import { AppRegistry } from 'react-native'; 2 | import App from './src/app'; 3 | 4 | AppRegistry.registerComponent('playground', () => App); 5 | -------------------------------------------------------------------------------- /playground/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /lib/android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /playground/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /playground/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /playground/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /playground/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wix-incubator/react-native-interactable/HEAD/playground/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /lib/android/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /playground/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /lib/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Mar 27 14:06:33 IDT 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-all.zip 7 | -------------------------------------------------------------------------------- /lib/ios/Interactable/PhysicsAnchorBehavior.h: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsAnchorBehavior.h 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 2/9/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import "PhysicsBehavior.h" 10 | 11 | @interface PhysicsAnchorBehavior : PhysicsBehavior 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /lib/ios/Interactable.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /lib/ios/Interactable.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /playground/ios/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /playground/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /playground/ios/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | ### Issues 4 | 5 | If you have any issues with the app please open an issue [here](https://github.com/wix/react-native-interactable/issues) 6 | 7 | ### Twitter 8 | 9 | Contact the developer via twitter at `@koltal` 10 | 11 | ### Contact 12 | 13 | http://www.wix.engineering 14 | 15 | or via email academy@wix.com 16 | -------------------------------------------------------------------------------- /playground/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'playground' 2 | include ':app' 3 | 4 | include ':react-native-interactable' 5 | project(':react-native-interactable').projectDir = new File(rootProject.projectDir, '../../lib/android') 6 | 7 | include ':detox' 8 | project(':detox').projectDir = new File(rootProject.projectDir, '../../`node_modules/detox/android/detox') -------------------------------------------------------------------------------- /lib/ios/Interactable/InteractableViewManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // InteractableViewManager.h 3 | // InteractableViewManager 4 | // 5 | // Created by Tal Kol on 1/27/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface InteractableViewManager : RCTViewManager 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /lib/ios/Interactable/PhysicsFrictionBehavior.h: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsFrictionBehavior.h 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 2/9/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import "PhysicsBehavior.h" 10 | 11 | @interface PhysicsFrictionBehavior : PhysicsBehavior 12 | 13 | @property (nonatomic, assign) CGFloat friction; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /lib/ios/Interactable/InteractableSpring.m: -------------------------------------------------------------------------------- 1 | // 2 | // InteractableSpring.m 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 2/9/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import "InteractableSpring.h" 10 | 11 | @implementation InteractableSpring 12 | 13 | - (id)copyWithZone:(__unused NSZone *)zone 14 | { 15 | return self; 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /lib/android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /e2e/firstTest.spec.js: -------------------------------------------------------------------------------- 1 | describe('Example', () => { 2 | beforeEach(async () => { 3 | await device.reloadReactNative(); 4 | }); 5 | 6 | it('should show Overview screen', async () => { 7 | await expect(element(by.id('Overview'))).toBeVisible(); 8 | }); 9 | 10 | it('Chat Heads is clickable', async () => { 11 | await element(by.text('Chat Heads')).tap(); 12 | }); 13 | 14 | }) 15 | -------------------------------------------------------------------------------- /playground/metro.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Metro configuration for React Native 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | */ 7 | 8 | module.exports = { 9 | transformer: { 10 | getTransformOptions: async () => ({ 11 | transform: { 12 | experimentalImportSupport: false, 13 | inlineRequires: false, 14 | }, 15 | }), 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /lib/ios/Interactable/PhysicsSpringBehavior.h: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsSnapBehavior.h 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 2/4/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "PhysicsBehavior.h" 11 | 12 | @interface PhysicsSpringBehavior : PhysicsBehavior 13 | 14 | @property (nonatomic, assign) CGFloat tension; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/wix/interactable/InteractableSpring.java: -------------------------------------------------------------------------------- 1 | package com.wix.interactable; 2 | 3 | /** 4 | * Created by zachik on 12/02/2017. 5 | */ 6 | 7 | public class InteractableSpring { 8 | float tension; 9 | float damping; 10 | 11 | 12 | public InteractableSpring(float tension, float damping) { 13 | this.tension = tension; 14 | this.damping = damping; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lib/ios/Interactable/PhysicsObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsTarget.h 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 2/4/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface PhysicsObject : NSObject 13 | 14 | @property (nonatomic, assign) CGPoint velocity; 15 | @property (nonatomic, assign) CGFloat mass; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /playground/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /lib/ios/Interactable/InteractableSpring.h: -------------------------------------------------------------------------------- 1 | // 2 | // InteractableSpring.h 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 2/9/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface InteractableSpring : NSObject 13 | 14 | @property (nonatomic, assign) CGFloat tension; 15 | @property (nonatomic, assign) CGFloat damping; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /lib/ios/Interactable/RCTConvert+Interactable.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCTConvert+Interactable.h 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 1/27/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @class InteractablePoint; 13 | 14 | @interface RCTConvert (Interactable) 15 | 16 | + (NSArray *)InteractablePointArray:(id)json; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /lib/android/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /e2e/init.js: -------------------------------------------------------------------------------- 1 | const detox = require('detox'); 2 | const config = require('../package.json').detox; 3 | const adapter = require('detox/runners/mocha/adapter'); 4 | 5 | before(async () => { 6 | await detox.init(config); 7 | }); 8 | 9 | beforeEach(async function () { 10 | await adapter.beforeEach(this); 11 | }); 12 | 13 | afterEach(async function () { 14 | await adapter.afterEach(this); 15 | }); 16 | 17 | after(async () => { 18 | await detox.cleanup(); 19 | }); 20 | -------------------------------------------------------------------------------- /lib/ios/Interactable/PhysicsObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsObject.m 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 2/4/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import "PhysicsObject.h" 10 | 11 | @implementation PhysicsObject 12 | 13 | - (instancetype)init 14 | { 15 | if ((self = [super init])) 16 | { 17 | self.velocity = CGPointZero; 18 | self.mass = 1.0; 19 | } 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /lib/ios/Interactable/PhysicsGravityWellBehavior.h: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsGravityWellBehavior.h 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 2/4/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "PhysicsBehavior.h" 11 | 12 | @interface PhysicsGravityWellBehavior : PhysicsBehavior 13 | 14 | @property (nonatomic, assign) CGFloat strength; 15 | @property (nonatomic, assign) CGFloat falloff; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /playground/android/app/src/main/java/com/playground/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.playground; 2 | 3 | import com.facebook.react.ReactActivity; 4 | 5 | public class MainActivity extends ReactActivity { 6 | 7 | /** 8 | * Returns the name of the main component registered from JavaScript. 9 | * This is used to schedule rendering of the component. 10 | */ 11 | @Override 12 | protected String getMainComponentName() { 13 | return "playground"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/wix/interactable/physics/PhysicsArea.java: -------------------------------------------------------------------------------- 1 | package com.wix.interactable.physics; 2 | 3 | import android.graphics.Point; 4 | import android.graphics.PointF; 5 | 6 | /** 7 | * Created by zachik on 12/02/2017. 8 | */ 9 | 10 | public class PhysicsArea { 11 | PointF minPoint; 12 | PointF maxPoint; 13 | 14 | public PhysicsArea(PointF minPoint, PointF maxPoint) { 15 | this.minPoint = minPoint; 16 | this.maxPoint = maxPoint; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/android/src/test/java/com/wix/interactable/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.wix.interactable; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /lib/ios/Interactable/PhysicsArea.h: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsArea.h 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 2/11/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface PhysicsArea : NSObject 13 | 14 | @property (nonatomic, assign) CGPoint minPoint; 15 | @property (nonatomic, assign) CGPoint maxPoint; 16 | 17 | - (instancetype)initWithMinPoint:(CGPoint)minPoint maxPoint:(CGPoint)maxPoint; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /playground/ios/playground/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | #import 12 | 13 | @interface AppDelegate : UIResponder 14 | 15 | @property (nonatomic, strong) UIWindow *window; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /playground/ios/playground/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | #import "AppDelegate.h" 13 | 14 | int main(int argc, char * argv[]) { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/wix/interactable/physics/PhysicsObject.java: -------------------------------------------------------------------------------- 1 | package com.wix.interactable.physics; 2 | 3 | import android.graphics.Point; 4 | import android.graphics.PointF; 5 | 6 | /** 7 | * Created by rotemm on 09/02/2017. 8 | */ 9 | 10 | public class PhysicsObject { 11 | 12 | PointF velocity; 13 | float mass; 14 | 15 | public PhysicsObject() { 16 | this.velocity = new PointF(0,0); 17 | this.mass = 1.0f; 18 | } 19 | 20 | public PhysicsObject(PointF velocity, float mass) { 21 | this.velocity = velocity; 22 | this.mass = mass; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/ios/Interactable/PhysicsBounceBehavior.h: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsBounceBehavior.h 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 2/8/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "PhysicsBehavior.h" 11 | 12 | @interface PhysicsBounceBehavior : PhysicsBehavior 13 | 14 | @property (nonatomic, assign) CGPoint minPoint; 15 | @property (nonatomic, assign) CGPoint maxPoint; 16 | @property (nonatomic, assign) CGFloat bounce; 17 | 18 | - (instancetype)initWithTarget:(UIView*)target minPoint:(CGPoint)minPoint maxPoint:(CGPoint)maxPoint; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Interactable.podspec: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) 4 | 5 | Pod::Spec.new do |s| 6 | s.name = "Interactable" 7 | s.version = package["version"] 8 | s.summary = package["description"] 9 | 10 | s.homepage = "https://github.com/wix/react-native-interactable" 11 | 12 | s.license = "MIT" 13 | s.authors = package["author"] 14 | s.platform = :ios, "7.0" 15 | 16 | s.source = { :git => "https://github.com/wix/react-native-interactable.git" } 17 | s.source_files = "lib/ios/Interactable/*.{h,m}" 18 | 19 | s.dependency 'React' 20 | end 21 | -------------------------------------------------------------------------------- /playground/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 | ) -------------------------------------------------------------------------------- /lib/ios/Interactable/InteractableArea.h: -------------------------------------------------------------------------------- 1 | // 2 | // InteractableArea.h 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 2/6/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface InteractableArea : NSObject 13 | 14 | @property (nonatomic, assign) CGFloat top; 15 | @property (nonatomic, assign) CGFloat left; 16 | @property (nonatomic, assign) CGFloat bottom; 17 | @property (nonatomic, assign) CGFloat right; 18 | @property (nonatomic, assign) CGFloat bounce; 19 | @property (nonatomic, assign) BOOL haptics; 20 | 21 | - (BOOL)pointInside:(CGPoint)point withOrigin:(CGPoint)origin; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /playground/android/app/src/androidTest/java/com/playground/DetoxTest.java: -------------------------------------------------------------------------------- 1 | package com.playground; 2 | 3 | import com.wix.detox.Detox; 4 | 5 | import org.junit.Rule; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | 9 | import androidx.test.ext.junit.runners.AndroidJUnit4; 10 | import androidx.test.filters.LargeTest; 11 | import androidx.test.rule.ActivityTestRule; 12 | 13 | @RunWith(AndroidJUnit4.class) 14 | @LargeTest 15 | public class DetoxTest { 16 | 17 | @Rule 18 | public ActivityTestRule mActivityRule = new ActivityTestRule<>(MainActivity.class, false, false); 19 | 20 | @Test 21 | public void runDetoxTests() { 22 | Detox.runTests(mActivityRule); 23 | } 24 | } -------------------------------------------------------------------------------- /lib/android/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 /Users/rotemm/Library/Android/sdk/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 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /lib/ios/Interactable/InteractableArea.m: -------------------------------------------------------------------------------- 1 | // 2 | // InteractableArea.m 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 2/6/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import "InteractableArea.h" 10 | 11 | @implementation InteractableArea 12 | 13 | - (id)copyWithZone:(__unused NSZone *)zone 14 | { 15 | return self; 16 | } 17 | 18 | - (BOOL)pointInside:(CGPoint)point withOrigin:(CGPoint)origin 19 | { 20 | CGFloat cx = point.x - origin.x; 21 | CGFloat cy = point.y - origin.y; 22 | 23 | if (cx < self.left) return NO; 24 | if (cx > self.right) return NO; 25 | 26 | if (cy < self.top) return NO; 27 | if (cy > self.bottom) return NO; 28 | 29 | return YES; 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /lib/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 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | -------------------------------------------------------------------------------- /lib/ios/InteractableTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /playground/ios/PlaygroundTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /lib/ios/Interactable/PhysicsArea.m: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsArea.m 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 2/11/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import "PhysicsArea.h" 10 | 11 | @implementation PhysicsArea 12 | 13 | - (instancetype)init 14 | { 15 | if ((self = [super init])) 16 | { 17 | self.minPoint = CGPointMake(-CGFLOAT_MAX, -CGFLOAT_MAX); 18 | self.maxPoint = CGPointMake(CGFLOAT_MAX, CGFLOAT_MAX); 19 | } 20 | return self; 21 | } 22 | 23 | - (instancetype)initWithMinPoint:(CGPoint)minPoint maxPoint:(CGPoint)maxPoint 24 | { 25 | if ((self = [super init])) 26 | { 27 | self.minPoint = minPoint; 28 | self.maxPoint = maxPoint; 29 | } 30 | return self; 31 | } 32 | 33 | - (id)copyWithZone:(__unused NSZone *)zone 34 | { 35 | return self; 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /lib/ios/Interactable-tvOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /playground/ios/Playground-tvOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /.ghp/wix.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-interactable", 3 | "description": "Declarative API for handling fluid user interactions with views at 60 FPS in React Native", 4 | "title": "React Native Interactable", 5 | "github": "https://github.com/wix/react-native-interactable", 6 | "AndroidVideoUrl": "https://github.com/wix/react-native/blob/master/src/videos/react-interactable-android.mp4?raw=true", 7 | "IOSVideoUrl": "https://github.com/wix/react-native/blob/master/src/videos/react-iphone-interactable.mp4?raw=true", 8 | "IOSDemoAppLink": "https://itunes.apple.com/us/app/react-native-interactions/id1209875831?mt=8", 9 | "image": "", 10 | "poster": "https://github.com/wix/react-native/blob/master/src/img/react-native-interactable-poster.jpg?raw=true", 11 | "size" : "normal", 12 | "AndroidDemoAppLink": "https://play.google.com/store/apps/details?id=com.wix.interactions&hl=en" 13 | } 14 | -------------------------------------------------------------------------------- /lib/ios/Interactable/PhysicsFrictionBehavior.m: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsFrictionBehavior.m 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 2/9/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import "PhysicsFrictionBehavior.h" 10 | 11 | @implementation PhysicsFrictionBehavior 12 | 13 | - (instancetype)initWithTarget:(UIView*)target 14 | { 15 | if ((self = [super initWithTarget:target])) 16 | { 17 | self.priority = 2; 18 | self.friction = 0.7; 19 | } 20 | return self; 21 | } 22 | 23 | - (void)executeFrameWithDeltaTime:(CFTimeInterval)deltaTime onObject:(PhysicsObject*)object 24 | { 25 | if (![self isWithinInfluence]) return; 26 | 27 | CGFloat vx = pow(self.friction, 60.0 * deltaTime) * object.velocity.x; 28 | CGFloat vy = pow(self.friction, 60.0 * deltaTime) * object.velocity.y; 29 | 30 | object.velocity = CGPointMake(vx, vy); 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /.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/IJ 26 | # 27 | *.iml 28 | .idea 29 | .gradle 30 | local.properties 31 | android/.settings/* 32 | android/.project 33 | lib/android/.project 34 | playground/android/app/.project 35 | playground/android/.project 36 | 37 | # node.js 38 | # 39 | node_modules/ 40 | npm-debug.log 41 | 42 | # npm 43 | package-lock.json 44 | 45 | # yarn 46 | yarn.lock 47 | yarn-error.log 48 | 49 | # BUCK 50 | buck-out/ 51 | \.buckd/ 52 | android/app/libs 53 | *.keystore 54 | !debug.keystore 55 | 56 | # Bundle artifact 57 | *.jsbundle 58 | 59 | # CocoaPods 60 | playground/ios/Pods 61 | -------------------------------------------------------------------------------- /lib/ios/Interactable/PhysicsAnchorBehavior.m: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsAnchorBehavior.m 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 2/9/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import "PhysicsAnchorBehavior.h" 10 | 11 | @implementation PhysicsAnchorBehavior 12 | 13 | - (instancetype)initWithTarget:(UIView*)target anchorPoint:(CGPoint)anchorPoint 14 | { 15 | if ((self = [super initWithTarget:target anchorPoint:anchorPoint])) 16 | { 17 | self.priority = 3; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)executeFrameWithDeltaTime:(CFTimeInterval)deltaTime onObject:(PhysicsObject*)object 23 | { 24 | if (deltaTime == 0.0) return; 25 | 26 | CGFloat dx = self.anchorPoint.x - self.target.center.x; 27 | CGFloat vx = dx / deltaTime; 28 | 29 | CGFloat dy = self.anchorPoint.y - self.target.center.y; 30 | CGFloat vy = dy / deltaTime; 31 | 32 | object.velocity = CGPointMake(vx, vy); 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /playground/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 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/wix/interactable/Interactable.java: -------------------------------------------------------------------------------- 1 | package com.wix.interactable; 2 | 3 | import com.facebook.react.ReactPackage; 4 | import com.facebook.react.bridge.JavaScriptModule; 5 | import com.facebook.react.bridge.NativeModule; 6 | import com.facebook.react.bridge.ReactApplicationContext; 7 | import com.facebook.react.uimanager.ViewManager; 8 | 9 | import java.util.Collections; 10 | import java.util.List; 11 | 12 | public class Interactable implements ReactPackage { 13 | 14 | @Override 15 | public List createNativeModules(ReactApplicationContext reactContext) { 16 | return Collections.emptyList(); 17 | } 18 | 19 | // Deprecated RN 0.47 20 | public List> createJSModules() { 21 | return Collections.emptyList(); 22 | } 23 | 24 | @Override 25 | public List createViewManagers(ReactApplicationContext reactContext) { 26 | return Collections.singletonList(new InteractableViewManager()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /playground/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 12 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/wix/interactable/physics/PhysicsAnchorBehavior.java: -------------------------------------------------------------------------------- 1 | package com.wix.interactable.physics; 2 | 3 | import android.graphics.PointF; 4 | import android.util.Log; 5 | import android.view.View; 6 | 7 | /** 8 | * Created by zachik on 12/02/2017. 9 | */ 10 | 11 | public class PhysicsAnchorBehavior extends PhysicsBehavior { 12 | 13 | 14 | public PhysicsAnchorBehavior(View target,PointF anchorPoint) { 15 | super(target, anchorPoint); 16 | } 17 | 18 | @Override 19 | public void executeFrameWithDeltaTime(float deltaTime, PhysicsObject physicsObject) { 20 | if (deltaTime == 0.0) return; 21 | 22 | // Log.d("InteractableView"," PhysicsAnchorBehavior executeFrameWithDeltaTime: " + deltaTime); 23 | 24 | float dx = this.anchorPoint.x - this.target.getTranslationX(); 25 | float vx = dx / deltaTime; 26 | 27 | float dy = this.anchorPoint.y - this.target.getTranslationY(); 28 | float vy = dy / deltaTime; 29 | 30 | physicsObject.velocity = new PointF(vx, vy); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/ios/Interactable/PhysicsBehavior.h: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsBehavior.h 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 2/4/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "PhysicsObject.h" 12 | #import "PhysicsArea.h" 13 | 14 | @interface PhysicsBehavior : NSObject 15 | 16 | @property (nonatomic) UIView *target; 17 | @property (nonatomic, assign) int priority; // priority 1 is handled first, 2 handled 2nd 18 | @property (nonatomic, assign) BOOL temp; 19 | @property (nonatomic, assign) CGPoint anchorPoint; 20 | @property (nonatomic, copy) PhysicsArea *influence; 21 | @property (nonatomic, assign) BOOL haptics; 22 | 23 | - (instancetype)initWithTarget:(UIView*)target; 24 | - (instancetype)initWithTarget:(UIView*)target anchorPoint:(CGPoint)anchorPoint; 25 | - (void)executeFrameWithDeltaTime:(CFTimeInterval)deltaTime onObject:(PhysicsObject*)object; 26 | - (NSUInteger)findSortIndexInArray:(NSArray*)array; 27 | - (BOOL)isWithinInfluence; 28 | - (void)doHaptics; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Wix.com 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 | -------------------------------------------------------------------------------- /playground/ios/playground/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "size" : "1024x1024", 46 | "scale" : "1x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } -------------------------------------------------------------------------------- /lib/ios/Interactable/PhysicsSpringBehavior.m: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsSnapBehavior.m 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 2/4/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import "PhysicsSpringBehavior.h" 10 | 11 | @implementation PhysicsSpringBehavior 12 | 13 | - (instancetype)initWithTarget:(UIView*)target anchorPoint:(CGPoint)anchorPoint 14 | { 15 | if ((self = [super initWithTarget:target anchorPoint:anchorPoint])) 16 | { 17 | self.tension = 300.0; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)executeFrameWithDeltaTime:(CFTimeInterval)deltaTime onObject:(PhysicsObject*)object 23 | { 24 | if (![self isWithinInfluence]) return; 25 | 26 | CGFloat dx = self.target.center.x - self.anchorPoint.x; 27 | CGFloat ax = (-self.tension * dx) / object.mass; 28 | CGFloat vx = object.velocity.x + deltaTime * ax; 29 | 30 | CGFloat dy = self.target.center.y - self.anchorPoint.y; 31 | CGFloat ay = (-self.tension * dy) / object.mass; 32 | CGFloat vy = object.velocity.y + deltaTime * ay; 33 | 34 | object.velocity = CGPointMake(vx, vy); 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /lib/ios/Interactable/InteractablePoint.h: -------------------------------------------------------------------------------- 1 | // 2 | // InteractablePoint.h 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 1/27/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "InteractableArea.h" 12 | 13 | @interface InteractablePoint : NSObject 14 | 15 | @property (nonatomic, assign) CGFloat x; 16 | @property (nonatomic, assign) CGFloat y; 17 | @property (nonatomic, assign) CGFloat damping; 18 | @property (nonatomic, assign) CGFloat tension; 19 | @property (nonatomic, assign) CGFloat strength; 20 | @property (nonatomic, assign) CGFloat falloff; 21 | @property (nonatomic, copy) id id; 22 | @property (nonatomic, copy) InteractableArea *influenceArea; 23 | @property (nonatomic, assign) BOOL haptics; 24 | 25 | - (CGPoint)positionWithOrigin:(CGPoint)origin; 26 | - (CGFloat)distanceFromPoint:(CGPoint)point withOrigin:(CGPoint)origin; 27 | + (CGPoint)deltaBetweenPoint:(CGPoint)point andOrigin:(CGPoint)origin; 28 | + (InteractablePoint*)findClosestPoint:(NSArray*)points toPoint:(CGPoint)relativeToPoint withOrigin:(CGPoint)origin; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /lib/ios/Interactable/PhysicsAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsAnimator.h 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 2/4/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "PhysicsSpringBehavior.h" 12 | #import "PhysicsBounceBehavior.h" 13 | #import "PhysicsFrictionBehavior.h" 14 | #import "PhysicsAnchorBehavior.h" 15 | #import "PhysicsGravityWellBehavior.h" 16 | 17 | @protocol PhysicsAnimatorDelegate; 18 | 19 | @interface PhysicsAnimator : NSObject 20 | 21 | @property (nonatomic, assign) id delegate; 22 | 23 | - (void)addBehavior:(PhysicsBehavior*)behavior; 24 | - (void)addTempBehavior:(PhysicsBehavior*)behavior; 25 | - (void)removeAllBehaviors; 26 | - (void)removeTempBehaviors; 27 | - (void)ensureRunning; 28 | - (void)stopRunning; 29 | - (void)setTarget:(UIView*)target mass:(CGFloat)mass; 30 | - (void)setTarget:(UIView*)target velocity:(CGPoint)velocity; 31 | - (CGPoint)getTargetVelocity:(UIView*)target; 32 | 33 | @end 34 | 35 | @protocol PhysicsAnimatorDelegate 36 | 37 | - (void)physicsAnimatorDidPause:(PhysicsAnimator *)animator; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /playground/src/examples/ChatHeads.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { StyleSheet, View } from 'react-native'; 3 | import Interactable from 'react-native-interactable'; 4 | 5 | export default class ChatHeads extends Component { 6 | render() { 7 | return ( 8 | 9 | 23 | 24 | 25 | 26 | ); 27 | } 28 | } 29 | 30 | const styles = StyleSheet.create({ 31 | container: { 32 | flex: 1, 33 | justifyContent: 'center', 34 | alignItems: 'center', 35 | backgroundColor: 'white', 36 | } 37 | }); 38 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/wix/interactable/physics/PhysicsFrictionBehavior.java: -------------------------------------------------------------------------------- 1 | package com.wix.interactable.physics; 2 | 3 | import android.graphics.PointF; 4 | import android.util.Log; 5 | import android.view.View; 6 | 7 | /** 8 | * Created by zachik on 12/02/2017. 9 | */ 10 | 11 | public class PhysicsFrictionBehavior extends PhysicsBehavior { 12 | 13 | private float friction; 14 | public PhysicsFrictionBehavior(View target, float friction) { 15 | super(target, false); 16 | this.friction = friction; 17 | this.priority = 2; 18 | } 19 | 20 | @Override 21 | public void executeFrameWithDeltaTime(float deltaTime, PhysicsObject physicsObject) { 22 | // Log.d("InteractableView"," PhysicsFrictionBehavior executeFrameWithDeltaTime friction = " + friction); 23 | if (!isWithinInfluence()) { 24 | return; 25 | } 26 | 27 | float vx = (float) (Math.pow(this.friction, 60.0 * deltaTime) * physicsObject.velocity.x); 28 | float vy = (float) (Math.pow(this.friction, 60.0 * deltaTime) * physicsObject.velocity.y); 29 | 30 | // Log.d("InteractableView"," vx = " + vx + " cur vx = " + physicsObject.velocity.x); 31 | 32 | physicsObject.velocity = new PointF(vx,vy); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /playground/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 = 18 7 | compileSdkVersion = 28 8 | targetSdkVersion = 28 9 | supportLibVersion = "28.0.0" 10 | kotlinVersion = '1.3.31' 11 | } 12 | repositories { 13 | google() 14 | mavenLocal() 15 | jcenter() 16 | } 17 | dependencies { 18 | classpath('com.android.tools.build:gradle:3.4.2') 19 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" 20 | 21 | // NOTE: Do not place your application dependencies here; they belong 22 | // in the individual module build.gradle files 23 | } 24 | } 25 | 26 | allprojects { 27 | repositories { 28 | mavenLocal() 29 | maven { 30 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 31 | url "$rootDir/../../node_modules/react-native/android" 32 | } 33 | maven { 34 | // Android JSC is installed from npm 35 | url("$rootDir/../../node_modules/jsc-android/dist") 36 | } 37 | jcenter() 38 | google() 39 | maven { url 'https://jitpack.io' } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/wix/interactable/physics/PhysicsSpringBehavior.java: -------------------------------------------------------------------------------- 1 | package com.wix.interactable.physics; 2 | 3 | import android.graphics.Point; 4 | import android.graphics.PointF; 5 | import android.util.Log; 6 | import android.view.View; 7 | 8 | /** 9 | * Created by zachik on 12/02/2017. 10 | */ 11 | 12 | public class PhysicsSpringBehavior extends PhysicsBehavior { 13 | public float tension = 300f; 14 | public PhysicsSpringBehavior(View target, PointF anchorPoint) { 15 | super(target, anchorPoint); 16 | } 17 | 18 | @Override 19 | public void executeFrameWithDeltaTime(float deltaTime, PhysicsObject physicsObject) { 20 | if (!isWithinInfluence()) { 21 | return; 22 | } 23 | 24 | float dx = this.target.getTranslationX() - this.anchorPoint.x; 25 | float ax = (-this.tension * dx) / physicsObject.mass; 26 | float vx = physicsObject.velocity.x + deltaTime * ax; 27 | 28 | float dy = this.target.getTranslationY() - this.anchorPoint.y; 29 | float ay = (-this.tension * dy) / physicsObject.mass; 30 | float vy = physicsObject.velocity.y + deltaTime * ay; 31 | 32 | // Log.d("InteractableView"," PhysicsSpringBehavior executeFrameWithDeltaTime cur Vx = " + physicsObject.velocity.x + " vx = " + vx); 33 | 34 | physicsObject.velocity = new PointF(vx, vy); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /playground/src/real-life-examples/Documentation.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { StyleSheet, View, WebView, ActivityIndicator } from 'react-native'; 3 | 4 | const injectedJs = 5 | '[].forEach.call(document.querySelectorAll("img"),function(e){e.parentNode.removeChild(e);});' + 6 | '[].forEach.call(document.querySelectorAll("div.breadcrumb"),function(e){e.parentNode.removeChild(e);});' + 7 | '[].forEach.call(document.querySelectorAll("div.reponav-wrapper"),function(e){e.parentNode.removeChild(e);});' + 8 | '[].forEach.call(document.querySelectorAll("footer"),function(e){e.parentNode.removeChild(e);});' + 9 | '[].forEach.call(document.querySelectorAll("button.header-button"),function(e){e.parentNode.removeChild(e);});'; 10 | 11 | export default class Documentation extends Component { 12 | render() { 13 | return ( 14 | 21 | ); 22 | } 23 | renderLoading() { 24 | return ( 25 | 30 | ); 31 | } 32 | } 33 | 34 | const styles = StyleSheet.create({ 35 | container: { 36 | flex: 1 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /playground/src/real-life-examples/UxInspirations.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { StyleSheet, View, WebView, ActivityIndicator } from 'react-native'; 3 | 4 | const injectedJs = 5 | '[].forEach.call(document.querySelectorAll("img"),function(e){e.parentNode.removeChild(e);});' + 6 | '[].forEach.call(document.querySelectorAll("div.breadcrumb"),function(e){e.parentNode.removeChild(e);});' + 7 | '[].forEach.call(document.querySelectorAll("div.reponav-wrapper"),function(e){e.parentNode.removeChild(e);});' + 8 | '[].forEach.call(document.querySelectorAll("footer"),function(e){e.parentNode.removeChild(e);});' + 9 | '[].forEach.call(document.querySelectorAll("button.header-button"),function(e){e.parentNode.removeChild(e);});'; 10 | 11 | export default class UxInspirations extends Component { 12 | render() { 13 | return ( 14 | 21 | ); 22 | } 23 | renderLoading() { 24 | return ( 25 | 30 | ); 31 | } 32 | } 33 | 34 | const styles = StyleSheet.create({ 35 | container: { 36 | flex: 1 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /playground/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.playground", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.playground", 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 | -------------------------------------------------------------------------------- /playground/src/examples/SwipeableCard.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { StyleSheet, View } from 'react-native'; 3 | import Interactable from 'react-native-interactable'; 4 | 5 | export default class SwipeableCard extends Component { 6 | render() { 7 | return ( 8 | 9 | 10 | 18 | 19 | 20 | 21 | 29 | 30 | 31 | 32 | 40 | 41 | 42 | 43 | 44 | ); 45 | } 46 | } 47 | 48 | const styles = StyleSheet.create({ 49 | container: { 50 | flex: 1, 51 | justifyContent: 'center', 52 | alignItems: 'center', 53 | backgroundColor: 'white', 54 | }, 55 | card : { 56 | width: 300, 57 | height: 180, 58 | backgroundColor: '#32B76C', 59 | borderRadius: 8, 60 | marginVertical: 6 61 | } 62 | }); 63 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/wix/interactable/InteractableArea.java: -------------------------------------------------------------------------------- 1 | package com.wix.interactable; 2 | import android.graphics.PointF; 3 | 4 | public class InteractableArea { 5 | private float top; 6 | private float left; 7 | private float bottom; 8 | private float right; 9 | private float bounce; 10 | private boolean haptics; 11 | 12 | public InteractableArea(float top, float left, float bottom, float right, float bounce, boolean haptics) { 13 | this.top = top; 14 | this.left = left; 15 | this.bottom = bottom; 16 | this.right = right; 17 | this.bounce = bounce; 18 | this.haptics = haptics; 19 | } 20 | 21 | public boolean pointInside(PointF point) { 22 | float cx = point.x; 23 | float cy = point.y; 24 | 25 | if (cx < this.left) return false; 26 | if (cx > this.right) return false; 27 | 28 | if (cy < this.top) return false; 29 | if (cy > this.bottom) return false; 30 | 31 | return true; 32 | } 33 | 34 | public boolean pointInsideWithOrigin(PointF point, PointF origin) { 35 | return this.pointInside(new PointF(point.x - origin.x, point.y - origin.y)); 36 | } 37 | 38 | 39 | public float getTop() { 40 | return top; 41 | } 42 | 43 | public float getLeft() { 44 | return left; 45 | } 46 | 47 | public float getBottom() { 48 | return bottom; 49 | } 50 | 51 | public float getRight() { 52 | return right; 53 | } 54 | 55 | public float getBounce() { 56 | return bounce; 57 | } 58 | 59 | public boolean isHaptic() { 60 | return haptics; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /playground/src/examples/HandleRelayout.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { StyleSheet, View, TouchableOpacity, Text } from 'react-native'; 3 | import Interactable from 'react-native-interactable'; 4 | 5 | export default class HandleRelayout extends Component { 6 | constructor() { 7 | super(); 8 | this.state = { 9 | collapsed: false 10 | }; 11 | } 12 | render() { 13 | return ( 14 | 15 | 16 | 17 | 22 | Tap to {this.state.collapsed ? 'expand' : 'collapse'} 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | ); 34 | } 35 | onChangeLayoutPress() { 36 | this.setState({ 37 | collapsed: !this.state.collapsed 38 | }) 39 | } 40 | } 41 | 42 | const styles = StyleSheet.create({ 43 | container: { 44 | flex: 1, 45 | justifyContent: 'center', 46 | alignItems: 'center', 47 | backgroundColor: 'white', 48 | }, 49 | card: { 50 | width: 300, 51 | height: 180, 52 | backgroundColor: '#542790', 53 | borderRadius: 8, 54 | marginVertical: 6 55 | }, 56 | label: { 57 | textAlign: 'center', 58 | fontSize: 24 59 | } 60 | }); 61 | -------------------------------------------------------------------------------- /lib/ios/Interactable/PhysicsGravityWellBehavior.m: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsGravityWellBehavior.m 3 | // Interactable 4 | // 5 | // Created by Tal Kol on 2/4/17. 6 | // Copyright © 2017 Wix. All rights reserved. 7 | // 8 | 9 | #import "PhysicsGravityWellBehavior.h" 10 | 11 | @implementation PhysicsGravityWellBehavior 12 | 13 | - (instancetype)initWithTarget:(UIView*)target anchorPoint:(CGPoint)anchorPoint 14 | { 15 | if ((self = [super initWithTarget:target anchorPoint:anchorPoint])) 16 | { 17 | self.strength = 400.0; 18 | self.falloff = 40.0; 19 | } 20 | return self; 21 | } 22 | 23 | // regular gravitational force is proportional to 1/r^2 which is instable when r -> 0 24 | // instead, we're using a potential that looks like an inverted gaussian which behaves much better 25 | // its deriviative (the force) looks like this: 26 | // https://www.wolframalpha.com/input/?i=max+-5%2F(7)*sqrt(e)x*e%5E(-1%2F2%2F7%5E2*x%5E2) 27 | 28 | - (void)executeFrameWithDeltaTime:(CFTimeInterval)deltaTime onObject:(PhysicsObject*)object 29 | { 30 | if (![self isWithinInfluence]) return; 31 | 32 | CGFloat dx = self.target.center.x - self.anchorPoint.x; 33 | CGFloat dy = self.target.center.y - self.anchorPoint.y; 34 | CGFloat dr = sqrt(dx*dx + dy*dy); 35 | if (dr == 0.0) return; 36 | 37 | CGFloat a = (-self.strength * dr * exp(-0.5 * dr * dr / self.falloff / self.falloff)) / object.mass; 38 | 39 | CGFloat ax = dx / dr * a; 40 | CGFloat vx = object.velocity.x + deltaTime * ax; 41 | 42 | 43 | CGFloat ay = dy / dr * a; 44 | CGFloat vy = object.velocity.y + deltaTime * ay; 45 | 46 | object.velocity = CGPointMake(vx, vy); 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /lib/ios/Interactable-tvOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSExceptionDomains 28 | 29 | localhost 30 | 31 | NSExceptionAllowsInsecureHTTPLoads 32 | 33 | 34 | 35 | 36 | NSLocationWhenInUseUsageDescription 37 | 38 | UILaunchStoryboardName 39 | LaunchScreen 40 | UIRequiredDeviceCapabilities 41 | 42 | armv7 43 | 44 | UISupportedInterfaceOrientations 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | UIViewControllerBasedStatusBarAppearance 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /playground/ios/playground/AppDelegate.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import "AppDelegate.h" 11 | 12 | #import 13 | #import 14 | #import 15 | 16 | @implementation AppDelegate 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 19 | { 20 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; 21 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge 22 | moduleName:@"playground" 23 | initialProperties:nil]; 24 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; 25 | 26 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 27 | UIViewController *rootViewController = [UIViewController new]; 28 | rootViewController.view = rootView; 29 | self.window.rootViewController = rootViewController; 30 | [self.window makeKeyAndVisible]; 31 | return YES; 32 | } 33 | 34 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 35 | { 36 | #if DEBUG 37 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; 38 | #else 39 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 40 | #endif 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /playground/ios/Playground-tvOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSExceptionDomains 28 | 29 | localhost 30 | 31 | NSExceptionAllowsInsecureHTTPLoads 32 | 33 | 34 | 35 | 36 | NSLocationWhenInUseUsageDescription 37 | 38 | UILaunchStoryboardName 39 | LaunchScreen 40 | UIRequiredDeviceCapabilities 41 | 42 | armv7 43 | 44 | UISupportedInterfaceOrientations 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | UIViewControllerBasedStatusBarAppearance 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /playground/src/examples/SnapTo.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { StyleSheet, View, Button } from 'react-native'; 3 | import Interactable from 'react-native-interactable'; 4 | 5 | export default class SnapTo extends Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | snapToIndex: 0 10 | }; 11 | } 12 | render() { 13 | return ( 14 | 15 | 30 | 31 | 32 | 33 |