├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── core └── src │ └── main │ └── scala │ └── chandu0101 │ └── scalajs │ └── rn │ ├── ReactNative.scala │ ├── ReactNativeComponentB.scala │ ├── apis │ ├── ActionSheetIOS.scala │ ├── AlertIOS.scala │ ├── AppRegistry.scala │ ├── AppStateIOS.scala │ ├── AsyncStorage.scala │ ├── CameraRoll.scala │ ├── Fetch.scala │ ├── InteractionManager.scala │ ├── LinkingIOS.scala │ ├── NetInfo.scala │ ├── PanResponder.scala │ ├── PixelRatio.scala │ ├── PushNotificationIOS.scala │ ├── StyleSheet.scala │ └── VibrationIOS.scala │ ├── components │ ├── ActivityIndicatorIOS.scala │ ├── DatePickerIOS.scala │ ├── DocumentSelectionState.scala │ ├── EdgeInsets.scala │ ├── Image.scala │ ├── ImageSource.scala │ ├── ListView.scala │ ├── ListViewDataSource.scala │ ├── MapView.scala │ ├── Navigator.scala │ ├── NavigatorIOS.scala │ ├── PickerIOS.scala │ ├── PointProp.scala │ ├── ScrollView.scala │ ├── SegmentedControlIOS.scala │ ├── SliderIOS.scala │ ├── SwitchIOS.scala │ ├── TabBarIOS.scala │ ├── Text.scala │ ├── TextInput.scala │ ├── TouchableHighlight.scala │ ├── TouchableOpacity.scala │ ├── TouchableWithoutFeedback.scala │ ├── View.scala │ └── WebView.scala │ ├── extras │ └── OnUnmountNative.scala │ ├── mixins │ └── TimerMixinNative.scala │ ├── package.scala │ └── thirdparty │ └── MapboxGLMap.scala ├── doc └── CHANGELOG_0.2.0.md ├── examples ├── ScalaJSReactNative.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── ScalaJSReactNative.xccheckout │ │ └── xcuserdata │ │ │ └── chandrasekharkode.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ ├── xcshareddata │ │ └── xcschemes │ │ │ └── ScalaJSReactNative.xcscheme │ └── xcuserdata │ │ └── chandrasekharkode.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── iOS │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ │ └── LaunchScreen.xib │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ ├── main.jsbundle │ └── main.m ├── images │ └── movies.gif ├── package.json └── src │ └── main │ └── scala │ └── chandu0101 │ └── scalajs │ └── rn │ └── examples │ ├── HelloNative.scala │ ├── NativeApp.scala │ ├── movies │ ├── Movie.scala │ ├── MovieCell.scala │ ├── MovieScreen.scala │ ├── MoviesApp.scala │ ├── MoviesUtil.scala │ └── SearchScreen.scala │ └── uiexplorer │ ├── UIExample.scala │ ├── UIExplorerApp.scala │ ├── UIExplorerBlock.scala │ ├── UIExplorerList.scala │ ├── UIExplorerPage.scala │ ├── apis │ ├── AlertIOSExample.scala │ ├── AppStateIOSExample.scala │ ├── AsyncStorageExample.scala │ ├── CameraRollView.scala │ ├── GeoLocationExample.scala │ ├── LayoutExample.scala │ ├── NetInfoExample.scala │ ├── PushNotificationIOSExample.scala │ └── StatusBarIOSEXample.scala │ └── components │ ├── ActivityIndicatorIOSExample.scala │ ├── DatePickerIOSExample.scala │ ├── ListViewExample.scala │ ├── ListViewPagingExample.scala │ ├── MapViewExample.scala │ ├── PickerIOSExample.scala │ ├── ScrollViewExample.scala │ ├── SegmentedControlExample.scala │ ├── SliderIOSExample.scala │ ├── SwitchIOSExample.scala │ ├── TabBarIOSExample.scala │ ├── TextInputExample.scala │ ├── TouchableExample.scala │ ├── ViewExample.scala │ ├── WebViewExample.scala │ └── navigator │ ├── BreadCrumbNavigationBarSample.scala │ ├── JumpingNavSample.scala │ ├── NavigationBarSample.scala │ └── NavigatorExample.scala ├── project ├── Build.scala ├── Dependencies.scala ├── build.properties └── plugins.sbt └── styles └── src └── main └── scala └── chandu0101 └── scalajs └── rn └── styles ├── NativeAttrs.scala └── NativeStyleSheet.scala /.gitattributes: -------------------------------------------------------------------------------- 1 | examples/iOS/* linguist-vendored 2 | examples/ScalaJSReactNative.xcodeproj/* linguist-vendored 3 | examples/node_modules/* linguist-vendored 4 | examples/index.ios.js linguist-vendored -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.log 3 | 4 | # sbt specific 5 | .cache/ 6 | .history/ 7 | .lib/ 8 | dist/* 9 | target/ 10 | lib_managed/ 11 | src_managed/ 12 | project/boot/ 13 | project/plugins/project/ 14 | 15 | # Scala-IDE specific 16 | .scala_dependencies 17 | .worksheet 18 | 19 | #Intellij 20 | .idea 21 | *.iml 22 | 23 | #mac 24 | .DS_Store 25 | 26 | #project 27 | examples/js/ 28 | 29 | #node 30 | 31 | node_modules/ 32 | npm-debug.log 33 | 34 | 35 | #ios 36 | index.ios.js -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Please check https://github.com/chandu0101/sri (this is where future work is going to take place) 3 | 4 | # scalajs-react-native 5 | ScalaJS wrapper for [react-native](https://facebook.github.io/react-native/) .This project depends on [scalajs-react](https://github.com/japgolly/scalajs-react) , so you must be familiar with scalajs-react in order to use this library. 6 | 7 | ![movies](examples/images/movies.gif) 8 | 9 | 10 | # Index 11 | 12 | - [Setup](#setup) 13 | - [Styles](#styles) 14 | - [Examples](#examples) 15 | - [Project Template](#template) 16 | 17 | # Setup 18 | 19 | add this to your sbt build file 20 | 21 | ```scala 22 | 23 | libraryDependencies += "com.github.chandu0101.scalajs-react-native" %%% "core" % "0.2.0" 24 | 25 | ``` 26 | 27 | imports 28 | 29 | ```scala 30 | import chandu0101.scalajs.rn._ // to import core builderReactNativeComponentB etc 31 | import chandu0101.scalajs.rn.components._ // for all native components 32 | import chandu0101.scalajs.rn.apis._ // for native API calls 33 | 34 | 35 | ``` 36 | 37 | scalajs-react-native comes with ReactNativeComponentB (its clone of scalajs-react ReactComponentB with native dependencies and extra helper methods ). 38 | 39 | #### Defining Components : 40 | 41 | to define components just follow ReactComponentB guide lines 42 | 43 | example : 44 | 45 | ```scala 46 | val HelloNative = ReactNativeComponentB[Unit]("HelloNative") 47 | .render(P => { 48 | View(style = styles.container)( 49 | Text(style = styles.text)("Welcome to Scala-JS ReactNative"), 50 | Text(style = styles.text)("To get started, edit HelloNative.scala ") 51 | ) 52 | }).buildU 53 | 54 | ``` 55 | 56 | #### Defining Root Component : 57 | 58 | to define root component use buildNative method from builder . 59 | 60 | example : 61 | 62 | ```scala 63 | 64 | val ScalaJSReactNative = ReactNativeComponentB[Unit]("ScalaJSReactNative") 65 | .render((P) => { 66 | HelloNative() 67 | }).buildNative //If your component is going to be render by other third party component then use buildNative 68 | 69 | ReactNative.AppRegistry.registerComponent("ScalaJSReactNative", () => ScalaJSReactNative) 70 | 71 | ``` 72 | 73 | 74 | # Styles 75 | 76 | React Native doesn't implement CSS but instead relies on JavaScript to let you style your application. You can define styles in dynamic/typesafe way 77 | 78 | ##### Dynamic Way : 79 | 80 | Use js.Dynamic.literal to define js styles 81 | 82 | Example : 83 | 84 | ```scala 85 | import scala.scalajs.js.Dynamic.{literal => json} 86 | val styles = ReactNative.StyleSheet.create( 87 | json( 88 | container = json(flex = 1, 89 | backgroundColor = "#F5FCFF"), 90 | textCenter = json(textAlign = "center",marginTop = 10) 91 | ) 92 | ) 93 | 94 | //access styles 95 | View(style = styles.container)(..) 96 | ``` 97 | 98 | ###### TypeSafe Way : 99 | 100 | In order to define styles in type safe manner you need styles module 101 | 102 | ```scala 103 | libraryDependencies += "com.github.chandu0101.scalajs-react-native" %%% "styles" % "0.2.0" 104 | 105 | ``` 106 | 107 | extend ``trait NativeStyleSheet`` to define style sheets . NativeStyleSheet comes with two methods ``style`` (which takes attr value pairs)and ``styleE`` (this is used to extend already defined styles). 108 | 109 | Example : 110 | 111 | ```scala 112 | object styles extends NativeStyleSheet { 113 | val centering = style( 114 | alignItems.center, 115 | justifyContent.center 116 | ) 117 | val gray = style(backgroundColor := "#cccccc") 118 | val horizontal = style(flexDirection.row, justifyContent.center) 119 | val default = styleE(centering, gray)(height := 40) 120 | } 121 | 122 | ``` 123 | 124 | #Examples 125 | 126 | Number of examples can be found in [examples](https://github.com/chandu0101/scalajs-react-native/tree/master/examples) module 127 | 128 | #### How to run examples : 129 | 130 | ```scala 131 | 132 | sbt ~fullOptIOS 133 | 134 | // open new terminal tab/window 135 | cd examples 136 | npm install 137 | npm run start // start react-native package 138 | 139 | Open ScalaJSReactNative.xcodeproj using latest xcode 140 | 141 | Cmd+R - to run project 142 | 143 | Cmd+D - to debug project 144 | 145 | Cmd+B - to build 146 | 147 | Cmd+Shift+K - to cleanup 148 | 149 | ``` 150 | 151 | #Template 152 | 153 | A basic scalajs-react-native skeleton app can be found here 154 | 155 | https://github.com/chandu0101/scalajs-react-native-template 156 | 157 | 158 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/ReactNative.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn 2 | 3 | import chandu0101.scalajs.rn.apis._ 4 | import japgolly.scalajs.react._ 5 | 6 | import scala.scalajs.js 7 | import scala.scalajs.js.Object 8 | 9 | trait ReactNative extends js.Object { 10 | 11 | 12 | //components 13 | val Text: js.Object = js.native 14 | val View: js.Object = js.native 15 | val TextInput: js.Object = js.native 16 | val TouchableWithoutFeedback: js.Object = js.native 17 | val TouchableHighlight: js.Object = js.native 18 | val TouchableOpacity: js.Object = js.native 19 | val ActivityIndicatorIOS: js.Object = js.native 20 | val DatePickerIOS: js.Object = js.native 21 | val Image: js.Object = js.native 22 | val ScrollView: js.Object = js.native 23 | val ListView: js.Object = js.native 24 | val MapView: js.Object = js.native 25 | val Navigator: js.Object = js.native 26 | val NavigatorIOS: js.Object = js.native 27 | val PickerIOS: js.Object = js.native 28 | val SliderIOS: js.Object = js.native 29 | val SwitchIOS: js.Object = js.native 30 | val TabBarItemIOS: js.Object = js.native 31 | val WebView: js.Object = js.native 32 | val TabBarIOS: js.Object = js.native 33 | val SegmentedControlIOS: js.Object = js.native 34 | 35 | // apis 36 | 37 | val AlertIOS: AlertIOS = js.native 38 | val AppRegistry: AppRegistry = js.native 39 | val StyleSheet: StyleSheet = js.native 40 | val AppStateIOS: AppStateIOS = js.native 41 | val AsyncStorage: AsyncStorageJS = js.native 42 | val CameraRoll: CameraRoll = js.native 43 | val InteractionManager: InteractionManager = js.native 44 | val LinkingIOS: LinkingIOS = js.native 45 | val NetInfo: NetInfo = js.native 46 | val LayoutAnimation: js.Dynamic = js.native 47 | val PixelRatio: PixelRatio = js.native 48 | val PushNotificationIOS: PushNotificationIOS = js.native 49 | val PanResponder: PanResponder = js.native 50 | val StatusBarIOS: js.Dynamic = js.native 51 | val VibrationIOS: VibrationIOS = js.native 52 | val Dimensions: js.Dynamic = js.native 53 | 54 | def createClass[P, S, B, N <: TopNode](spec: ReactComponentSpec[P, S, B, N]): ReactComponentType[P, S, B, N] = js.native 55 | 56 | def createClass(spec: js.Object): js.Dynamic = js.native 57 | 58 | def createFactory[P, S, B, N <: TopNode](t: ReactComponentType[P, S, B, N]): ReactComponentCU[P, S, B, N] = js.native 59 | 60 | def createFactory(c: js.Object): js.Dynamic = js.native 61 | 62 | def createElement[P, S, B, N <: TopNode](t: ReactComponentType[P, S, B, N]): ReactComponentCU[P, S, B, N] = js.native 63 | 64 | def createElement(tag: String, props: Object, children: ReactNode*): ReactDOMElement = js.native 65 | 66 | def createElement(tag: js.Object, props: Object, children: ReactNode*): ReactDOMElement = js.native 67 | 68 | 69 | val addons: js.Dynamic = js.native 70 | 71 | def findNodeHandle(ref : js.Any):js.Object = js.native 72 | } 73 | 74 | 75 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/apis/ActionSheetIOS.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.apis 2 | 3 | import scala.scalajs.js 4 | 5 | trait ActionSheetIOS extends js.Object { 6 | 7 | def showActionSheetWithOptions(options: js.Object, callback: js.Function): Unit = js.native 8 | 9 | def showShareActionSheetWithOptions(options: js.Object, failureCallback: js.Function, successCallback: js.Function): Unit = js.native 10 | 11 | } 12 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/apis/AlertIOS.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.apis 2 | 3 | import scala.scalajs.js 4 | import scala.scalajs.js.Dynamic.{literal => json} 5 | 6 | 7 | trait AlertIOS extends js.Object { 8 | 9 | def alert(title: String = ???, message: String = ???, buttons: js.Array[js.Object] = ???): Unit = js.native 10 | 11 | def prompt(title: String, value: String = ???, buttons: js.Array[js.Object] = ???, callback: js.Function = ???): Unit = js.native 12 | } 13 | 14 | 15 | case class AlertButton(text: String, onPress: js.Function) { 16 | def toJson = json(text = text, onPress = onPress) 17 | } -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/apis/AppRegistry.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.apis 2 | 3 | import japgolly.scalajs.react.ReactComponentType 4 | 5 | import scala.scalajs.js 6 | 7 | 8 | trait AppRegistry extends js.Object { 9 | 10 | def registerConfig(config: js.Array[js.Object]): Unit = js.native 11 | 12 | def registerComponent(appKey: String, getComponentFunc: js.Function): Unit = js.native 13 | 14 | def registerRunnable(appKey: String, getComponentFunc: js.Function): Unit = js.native 15 | 16 | def runApplication(appKey: String, appParameters: js.Any): Unit = js.native 17 | } 18 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/apis/AppStateIOS.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.apis 2 | 3 | import scala.scalajs.js 4 | 5 | 6 | trait AppStateIOS extends js.Object { 7 | 8 | def addEventListener(tpe :String,handler : js.Function1[String,_]):Unit = js.native 9 | def removeEventListener(tpe :String,handler : js.Function1[String,_]):Unit = js.native 10 | def currentState : js.UndefOr[String] = js.native 11 | } 12 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/apis/AsyncStorage.scala: -------------------------------------------------------------------------------- 1 | 2 | package chandu0101.scalajs.rn.apis 3 | 4 | import chandu0101.scalajs.rn._ 5 | 6 | import scala.concurrent.{Future, Promise} 7 | import scala.scalajs.js 8 | import scala.scalajs.js.UndefOr 9 | 10 | case class AsyncStorageException(err: js.Dynamic) extends Exception 11 | 12 | object AsyncStorage { 13 | val SUCCESS: String = "" 14 | 15 | type CALLBACK = js.Function2[UndefOr[js.Dynamic], UndefOr[js.Dynamic], _] 16 | 17 | lazy val AsyncStorageJS = ReactNative.AsyncStorage 18 | 19 | 20 | def getItem(key: String): Future[String] = { 21 | val promise = Promise[String]() 22 | AsyncStorageJS.getItem(key, (err: UndefOr[js.Dynamic], resp: UndefOr[String]) => { 23 | if (js.isUndefined(err) || err == null) promise.success(resp.get) 24 | else promise.failure(AsyncStorageException(err.get)) 25 | }) 26 | promise.future 27 | } 28 | 29 | def setItem(key: String, value: String): Future[String] = { 30 | val promise = Promise[String]() 31 | AsyncStorageJS.setItem(key, value, (err: UndefOr[js.Dynamic]) => { 32 | if (js.isUndefined(err) || err == null) promise.success(SUCCESS) 33 | else promise.failure(AsyncStorageException(err.get)) 34 | }) 35 | promise.future 36 | } 37 | 38 | 39 | def removeItem(key: String): Future[String] = { 40 | val promise = Promise[String]() 41 | AsyncStorageJS.removeItem(key, (err: UndefOr[js.Dynamic]) => { 42 | if (js.isUndefined(err) || err == null) promise.success(SUCCESS) 43 | else promise.failure(AsyncStorageException(err.get)) 44 | }) 45 | promise.future 46 | } 47 | 48 | def mergeItem(key: String, value: String): Future[String] = { 49 | val promise = Promise[String]() 50 | AsyncStorageJS.mergeItem(key, value, (err: UndefOr[js.Dynamic]) => { 51 | if (js.isUndefined(err) || err == null) promise.success(SUCCESS) 52 | else promise.failure(AsyncStorageException(err.get)) 53 | }) 54 | promise.future 55 | } 56 | 57 | def clear: Future[String] = { 58 | val promise = Promise[String]() 59 | AsyncStorageJS.clear((err: UndefOr[js.Dynamic]) => { 60 | if (js.isUndefined(err) || err == null) promise.success(SUCCESS) 61 | else promise.failure(AsyncStorageException(err.get)) 62 | }) 63 | promise.future 64 | } 65 | 66 | def getAllKeys: Future[js.Array[String]] = { 67 | val promise = Promise[js.Array[String]]() 68 | AsyncStorageJS.getAllKeys((err: UndefOr[js.Dynamic], resp: UndefOr[js.Array[String]]) => { 69 | if (js.isUndefined(err) || err == null) promise.success(resp.get) 70 | else promise.failure(AsyncStorageException(err.get)) 71 | }) 72 | promise.future 73 | } 74 | 75 | def multiGet(keys: js.Array[String]): Future[js.Array[js.Array[String]]] = { 76 | val promise = Promise[js.Array[js.Array[String]]]() 77 | AsyncStorageJS.multiGet(keys, (err: UndefOr[js.Array[js.Dynamic]], resp: UndefOr[js.Array[js.Array[String]]]) => { 78 | if (js.isUndefined(err) || err == null) promise.success(resp.get) 79 | else promise.failure(AsyncStorageException(err.get.asInstanceOf[js.Dynamic])) 80 | }) 81 | promise.future 82 | } 83 | 84 | def multiSet(keyValuePairs: js.Array[js.Array[String]]): Future[String] = { 85 | val promise = Promise[String]() 86 | AsyncStorageJS.multiSet(keyValuePairs, (err: UndefOr[js.Array[js.Dynamic]]) => { 87 | if (js.isUndefined(err) || err == null) promise.success(SUCCESS) 88 | else promise.failure(AsyncStorageException(err.get.asInstanceOf[js.Dynamic])) 89 | }) 90 | promise.future 91 | } 92 | 93 | def multiRemove(keys: js.Array[String]): Future[String] = { 94 | val promise = Promise[String]() 95 | AsyncStorageJS.multiRemove(keys, (err: UndefOr[js.Array[js.Dynamic]]) => { 96 | if (js.isUndefined(err) || err == null) promise.success(SUCCESS) 97 | else promise.failure(AsyncStorageException(err.get.asInstanceOf[js.Dynamic])) 98 | }) 99 | promise.future 100 | } 101 | 102 | def multiMerge(keyValuePairs: js.Array[js.Array[String]]): Future[String] = { 103 | val promise = Promise[String]() 104 | AsyncStorageJS.multiMerge(keyValuePairs, (err: UndefOr[js.Array[js.Dynamic]]) => { 105 | if (js.isUndefined(err) || err == null) promise.success(SUCCESS) 106 | else promise.failure(AsyncStorageException(err.get.asInstanceOf[js.Dynamic])) 107 | }) 108 | promise.future 109 | } 110 | 111 | 112 | } 113 | 114 | trait AsyncStorageJS extends js.Object{ 115 | 116 | def getItem(key : String,callback : js.Function2[UndefOr[js.Dynamic],UndefOr[String],_] = ???):Unit = js.native 117 | def setItem(key : String,value : String,callback : js.Function1[UndefOr[js.Dynamic],_] = ???):Unit = js.native 118 | def mergeItem(key : String,value : String,callback : js.Function1[UndefOr[js.Dynamic],_] = ???):Unit = js.native 119 | def removeItem(key : String,callback : js.Function1[UndefOr[js.Dynamic],_] = ???):Unit = js.native 120 | def clear(callback : js.Function1[UndefOr[js.Dynamic],_] = ???):Unit = js.native 121 | def getAllKeys(callback : js.Function2[UndefOr[js.Dynamic],UndefOr[js.Array[String]],_] = ???):Unit = js.native 122 | def multiGet(keys : js.Array[String], callback : js.Function2[UndefOr[js.Array[js.Dynamic]],UndefOr[js.Array[js.Array[String]]],_] ):Unit = js.native 123 | def multiRemove(keys : js.Array[String], callback : js.Function1[UndefOr[js.Array[js.Dynamic]],_] ):Unit = js.native 124 | def multiSet(keyValuePairs : js.Array[js.Array[String]], callback : js.Function1[UndefOr[js.Array[js.Dynamic]],_]= ??? ):Unit = js.native 125 | def multiMerge(keyValuePairs : js.Array[js.Array[String]], callback : js.Function1[UndefOr[js.Array[js.Dynamic]],_]= ??? ):Unit = js.native 126 | 127 | } 128 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/apis/CameraRoll.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.apis 2 | 3 | import scala.scalajs.js 4 | 5 | trait CameraRoll extends js.Object{ 6 | 7 | def saveImageWithTag(tag :String,successCallback : js.Function,errorCallback : js.Function):Unit = js.native 8 | def getPhotos(params : js.Object,callback : js.Function,errorCallback : js.Function):Unit = js.native 9 | 10 | } 11 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/apis/Fetch.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.apis 2 | 3 | import scala.scalajs.js 4 | 5 | class Fetch extends js.Object { 6 | 7 | // def this(request : js.Object) : Promise[js.Dynamic] = this() 8 | 9 | } 10 | 11 | //object Fetch -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/apis/InteractionManager.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.apis 2 | 3 | import scala.scalajs.js 4 | 5 | 6 | trait InteractionManager extends js.Object { 7 | 8 | def runAfterInteractions(callback: js.Function): Unit = js.native 9 | 10 | def createInteractionHandle(): Unit = js.native 11 | 12 | def clearInteractionHandle(handle: Int): Unit = js.native 13 | 14 | } 15 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/apis/LinkingIOS.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.apis 2 | 3 | import scala.scalajs.js 4 | 5 | 6 | trait LinkingIOS extends js.Object { 7 | 8 | def addEventListener(tpe : String,handler : js.Function):Unit = js.native 9 | def removeEventListener(tpe : String,handler : js.Function):Unit = js.native 10 | def openURL(url : String):Unit = js.native 11 | def popInitialURL():Unit = js.native 12 | def canOpenURL(url : String, callback : js.Function):Unit = js.native 13 | 14 | } 15 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/apis/NetInfo.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.apis 2 | 3 | import scala.scalajs.js 4 | 5 | trait NetInfo extends js.Object{ 6 | 7 | val isConnected : NetInfoIsConnected = js.native 8 | val reachabilityIOS : NetInfoReachabilityIOS = js.native 9 | 10 | 11 | } 12 | 13 | trait NetInfoIsConnected extends js.Object{ 14 | 15 | def addEventListener(eventName : String,handler : (Boolean) => _) : Unit = js.native 16 | def removeEventListener(eventName : String,handler : (Boolean) => _) : Unit = js.native 17 | def fetch() : js.Dynamic = js.native 18 | } 19 | 20 | trait NetInfoReachabilityIOS extends js.Object{ 21 | 22 | def addEventListener(eventName : String,handler : (String) => _) : Unit = js.native 23 | def removeEventListener(eventName : String,handler : (String) => _) : Unit = js.native 24 | def fetch() : js.Dynamic = js.native 25 | } -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/apis/PanResponder.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.apis 2 | 3 | import scala.scalajs.js 4 | 5 | trait PanResponder extends js.Object { 6 | 7 | def create(config : js.Object):Unit = js.native 8 | } 9 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/apis/PixelRatio.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.apis 2 | 3 | import scala.scalajs.js 4 | 5 | 6 | trait PixelRatio extends js.Object { 7 | 8 | def get() : Int = js.native 9 | } 10 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/apis/PushNotificationIOS.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.apis 2 | 3 | import scala.scalajs.js 4 | import scala.scalajs.js.UndefOr 5 | 6 | 7 | trait PushNotificationIOS extends js.Object { 8 | 9 | def setApplicationIconBadgeNumber(number: Int): Unit = js.native 10 | 11 | def getApplicationIconBadgeNumber(callback: js.Function): Unit = js.native 12 | 13 | def addEventListener(tpe: String, handler: js.Function): Unit = js.native 14 | 15 | def removeEventListener(tpe: String, handler: js.Function): Unit = js.native 16 | 17 | def requestPermissions(): Unit = js.native 18 | 19 | def popInitialNotification(): js.Dynamic = js.native 20 | 21 | def checkPermissions(callback: js.Function): Unit = js.native 22 | 23 | def getSound(): UndefOr[String] = js.native 24 | 25 | def getAlert(): UndefOr[js.Dynamic] = js.native 26 | 27 | def getData(): UndefOr[js.Dynamic] = js.native 28 | 29 | def getBadgeCount(): UndefOr[Int] = js.native 30 | 31 | } 32 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/apis/StyleSheet.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.apis 2 | 3 | import scala.scalajs.js 4 | 5 | 6 | trait StyleSheet extends js.Object { 7 | 8 | def create(obj: js.Object): js.Dynamic = js.native 9 | 10 | } -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/apis/VibrationIOS.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.apis 2 | 3 | import scala.scalajs.js 4 | 5 | 6 | trait VibrationIOS extends js.Object { 7 | 8 | def vibrate() : Unit = js.native 9 | } 10 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/ActivityIndicatorIOS.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import chandu0101.scalajs.rn.ReactNative 4 | import japgolly.scalajs.react.ReactComponentU_ 5 | 6 | import scala.scalajs.js 7 | import scala.scalajs.js.{UndefOr, undefined} 8 | 9 | /** 10 | * Created by chandrasekharkode on 3/31/15. 11 | * 12 | * key: PropTypes.string, 13 | ref: PropTypes.string, 14 | style: PropTypes.js.Any, 15 | animating: PropTypes.bool, 16 | color: PropTypes.string, 17 | hidesWhenStopped: PropTypes.bool, 18 | onLayout: PropTypes.func, 19 | size: PropTypes.ActivityIndicatorIOSSize, 20 | */ 21 | 22 | 23 | 24 | 25 | object ActivityIndicatorIOS { 26 | 27 | def apply(size : js.UndefOr[ActivityIndicatorIOSSize] = js.undefined, 28 | hidesWhenStopped : js.UndefOr[Boolean]=js.undefined, 29 | style : js.UndefOr[js.Any] = js.undefined, 30 | onLayout : js.UndefOr[js.Function] = js.undefined , 31 | ref : js.UndefOr[String] = js.undefined, 32 | color : js.UndefOr[String] = js.undefined, 33 | key : js.UndefOr[String] = js.undefined, 34 | animating : js.UndefOr[Boolean]=js.undefined) = { 35 | 36 | val p = js.Dynamic.literal() 37 | size.foreach(v => p.updateDynamic("size")(v.size)) 38 | hidesWhenStopped.foreach(v => p.updateDynamic("hidesWhenStopped")(v)) 39 | style.foreach(v => p.updateDynamic("style")(v)) 40 | onLayout.foreach(v => p.updateDynamic("onLayout")(v)) 41 | ref.foreach(v => p.updateDynamic("ref")(v)) 42 | color.foreach(v => p.updateDynamic("color")(v)) 43 | key.foreach(v => p.updateDynamic("key")(v)) 44 | animating.foreach(v => p.updateDynamic("animating")(v)) 45 | 46 | val f = ReactNative.createFactory(ReactNative.ActivityIndicatorIOS) 47 | f(p).asInstanceOf[ReactComponentU_] 48 | } 49 | 50 | } 51 | 52 | 53 | class ActivityIndicatorIOSSize private(val size: String) extends AnyVal 54 | 55 | object ActivityIndicatorIOSSize { 56 | 57 | val SMALL = new ActivityIndicatorIOSSize("small") 58 | val LARGE = new ActivityIndicatorIOSSize("large") 59 | 60 | def newSize(size: String) = new ActivityIndicatorIOSSize(size) 61 | } 62 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/DatePickerIOS.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import chandu0101.scalajs.rn.ReactNative 4 | import japgolly.scalajs.react.ReactComponentU_ 5 | 6 | import scala.scalajs.js 7 | import scala.scalajs.js.{UndefOr, undefined} 8 | 9 | /** 10 | * Created by chandrasekharkode on 4/1/15. 11 | * 12 | * key: PropTypes.string, 13 | ref: PropTypes.string, 14 | date: PropTypes.Date.isRequired, 15 | onDateChange: PropTypes.js.Date => Unit.isRequired, 16 | maximumDate: PropTypes.Date, 17 | minimumDate: PropTypes.Date, 18 | mode: PropTypes.DatePickerIOSMode, 19 | minuteInterval: PropTypes.MinuteInterval, 20 | timeZoneOffsetInMinutes: PropTypes.number, 21 | */ 22 | 23 | 24 | 25 | object DatePickerIOS { 26 | 27 | def apply(ref : js.UndefOr[String] = js.undefined, 28 | timeZoneOffsetInMinutes : js.UndefOr[Int] = js.undefined, 29 | key : js.UndefOr[String] = js.undefined, 30 | date : js.Date, 31 | minuteInterval : js.UndefOr[MinuteInterval] = js.undefined, 32 | mode : js.UndefOr[DatePickerIOSMode] = js.undefined, 33 | minimumDate : js.UndefOr[js.Date] = js.undefined , 34 | maximumDate : js.UndefOr[js.Date] = js.undefined , 35 | onDateChange : js.Date => Unit) = { 36 | 37 | val p = js.Dynamic.literal() 38 | ref.foreach(v => p.updateDynamic("ref")(v)) 39 | timeZoneOffsetInMinutes.foreach(v => p.updateDynamic("timeZoneOffsetInMinutes")(v)) 40 | key.foreach(v => p.updateDynamic("key")(v)) 41 | p.updateDynamic("date")(date) 42 | minuteInterval.foreach(v => p.updateDynamic("minuteInterval")(v.interval)) 43 | mode.foreach(v => p.updateDynamic("mode")(v.mode)) 44 | minimumDate.foreach(v => p.updateDynamic("minimumDate")(v)) 45 | maximumDate.foreach(v => p.updateDynamic("maximumDate")(v)) 46 | p.updateDynamic("onDateChange")(onDateChange) 47 | 48 | val f = ReactNative.createFactory(ReactNative.DatePickerIOS) 49 | f(p).asInstanceOf[ReactComponentU_] 50 | } 51 | 52 | } 53 | 54 | 55 | class DatePickerIOSMode private(val mode : String) extends AnyVal 56 | 57 | object DatePickerIOSMode { 58 | 59 | val DATE = new DatePickerIOSMode(("date")) 60 | val TIME = new DatePickerIOSMode(("time")) 61 | val DATE_TIME = new DatePickerIOSMode(("datetime")) 62 | 63 | def newMode(mode : String) = new DatePickerIOSMode(mode) 64 | } 65 | 66 | class MinuteInterval private(val interval : Int) extends AnyVal 67 | 68 | 69 | object MinuteInterval { 70 | 71 | val _1 = new MinuteInterval(1) 72 | val _2 = new MinuteInterval(2) 73 | val _3 = new MinuteInterval(3) 74 | val _4 = new MinuteInterval(4) 75 | val _5 = new MinuteInterval(5) 76 | val _6 = new MinuteInterval(6) 77 | val _10 = new MinuteInterval(10) 78 | val _12 = new MinuteInterval(12) 79 | val _15 = new MinuteInterval(15) 80 | val _20 = new MinuteInterval(20) 81 | val _30 = new MinuteInterval(30) 82 | 83 | def newInterval(interval : Int) = new MinuteInterval(interval) 84 | } -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/DocumentSelectionState.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import scala.scalajs.js 4 | 5 | /** 6 | * Created by chandrasekharkode on 4/3/15. 7 | */ 8 | class DocumentSelectionState extends js.Object { 9 | 10 | def this(anchor: Int, focus: Int) = this() 11 | 12 | def update(anchor: Int, focus: Int): Unit = js.native 13 | 14 | def constrainLength(maxLength: Int): Unit = js.native 15 | 16 | def focus(): Unit = js.native 17 | 18 | def blur(): Unit = js.native 19 | 20 | def hasFocus(): Boolean = js.native 21 | 22 | def isCollapsed(): Boolean = js.native 23 | 24 | def isBackward(): Boolean = js.native 25 | 26 | def getAnchorOffset(): js.UndefOr[Double] = js.native 27 | 28 | def getFocusOffset(): js.UndefOr[Double] = js.native 29 | 30 | def getStartOffset(): js.UndefOr[Double] = js.native 31 | 32 | def getEndOffset(): js.UndefOr[Double] = js.native 33 | 34 | def overlaps(start: Double, end: Double): Boolean = js.native 35 | } 36 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/EdgeInsets.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import scala.scalajs.js.Dynamic.{literal => json} 4 | import scala.scalajs.js.{UndefOr, undefined} 5 | 6 | /** 7 | * Created by chandrasekharkode on 4/1/15. 8 | */ 9 | case class EdgeInsets(top : UndefOr[Double] = undefined, 10 | left : UndefOr[Double] = undefined, 11 | bottom : UndefOr[Double] = undefined, 12 | right : UndefOr[Double] = undefined) { 13 | 14 | def toJson = { 15 | val p = json() 16 | top.foreach(v => p.updateDynamic("top")(v)) 17 | left.foreach(v => p.updateDynamic("left")(v)) 18 | bottom.foreach(v => p.updateDynamic("bottom")(v)) 19 | right.foreach(v => p.updateDynamic("right")(v)) 20 | p 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/Image.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import chandu0101.scalajs.rn.ReactNative 4 | import japgolly.scalajs.react.ReactComponentU_ 5 | 6 | import scala.scalajs.js 7 | import scala.scalajs.js.{UndefOr, undefined} 8 | 9 | /** 10 | * Created by chandrasekharkode on 4/1/15. 11 | * 12 | * key: PropTypes.string, 13 | style: PropTypes.js.Any, 14 | ref: PropTypes.String, 15 | accessibilityLabel: PropTypes.string, 16 | accessible: PropTypes.bool, 17 | capInsets: EdgeInsets, 18 | defaultSource: PropTypes.ImageSource, 19 | onLayout: PropTypes.func, 20 | onLoadAbort: PropTypes.func, 21 | onLoadError: PropTypes.js.Dynamic => Unit, 22 | onLoadProgress: PropTypes.js.Dynamic => Unit, 23 | onLoadStart: PropTypes.js.Dynamic => Unit, 24 | onLoaded: PropTypes.bool, 25 | resizeMode:PropTypes.ImageResizeMode 26 | source: PropTypes.ImageSource, 27 | testID: PropTypes.string, 28 | 29 | */ 30 | 31 | 32 | 33 | 34 | object Image { 35 | 36 | def apply(onLoaded : js.UndefOr[Boolean]=js.undefined, 37 | source : js.UndefOr[ImageSource] = js.undefined, 38 | style : js.UndefOr[js.Any] = js.undefined, 39 | onLayout : js.UndefOr[js.Function] = js.undefined , 40 | accessibilityLabel : js.UndefOr[String] = js.undefined, 41 | onLoadError : js.UndefOr[js.Dynamic => Unit] = js.undefined, 42 | ref : js.UndefOr[String] = js.undefined, 43 | onLoadAbort : js.UndefOr[js.Function] = js.undefined , 44 | key : js.UndefOr[String] = js.undefined, 45 | resizeMode : js.UndefOr[ImageResizeMode] = js.undefined, 46 | testID : js.UndefOr[String] = js.undefined, 47 | onLoadStart : js.UndefOr[js.Dynamic => Unit] = js.undefined, 48 | defaultSource : js.UndefOr[ImageSource] = js.undefined, 49 | onLoadProgress : js.UndefOr[js.Dynamic => Unit] = js.undefined, 50 | accessible : js.UndefOr[Boolean]=js.undefined) = { 51 | 52 | val p = js.Dynamic.literal() 53 | onLoaded.foreach(v => p.updateDynamic("onLoaded")(v)) 54 | source.foreach(v => p.updateDynamic("source")(v.toJson)) 55 | style.foreach(v => p.updateDynamic("style")(v)) 56 | onLayout.foreach(v => p.updateDynamic("onLayout")(v)) 57 | accessibilityLabel.foreach(v => p.updateDynamic("accessibilityLabel")(v)) 58 | onLoadError.foreach(v => p.updateDynamic("onLoadError")(v)) 59 | ref.foreach(v => p.updateDynamic("ref")(v)) 60 | onLoadAbort.foreach(v => p.updateDynamic("onLoadAbort")(v)) 61 | key.foreach(v => p.updateDynamic("key")(v)) 62 | resizeMode.foreach(v => p.updateDynamic("resizeMode")(v.mode)) 63 | testID.foreach(v => p.updateDynamic("testID")(v)) 64 | onLoadStart.foreach(v => p.updateDynamic("onLoadStart")(v)) 65 | defaultSource.foreach(v => p.updateDynamic("defaultSource")(v.toJson)) 66 | onLoadProgress.foreach(v => p.updateDynamic("onLoadProgress")(v)) 67 | accessible.foreach(v => p.updateDynamic("accessible")(v)) 68 | 69 | val f = ReactNative.createFactory(ReactNative.Image) 70 | f(p).asInstanceOf[ReactComponentU_] 71 | } 72 | 73 | } 74 | 75 | 76 | 77 | class ImageResizeMode private(val mode: String) extends AnyVal 78 | 79 | 80 | object ImageResizeMode { 81 | 82 | val COVER = new ImageResizeMode("cover") 83 | val CONTAIN = new ImageResizeMode("contain") 84 | val STRETCH = new ImageResizeMode("stretch") 85 | 86 | def newMode(mode : String) = new ImageResizeMode(mode) 87 | 88 | } -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/ImageSource.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import scala.scalajs.js 4 | import scala.scalajs.js.Dynamic.{literal => json} 5 | 6 | /** 7 | * Created by chandrasekharkode on 4/1/15. 8 | */ 9 | case class ImageSource(uri : String,isStatic : js.UndefOr[Boolean] = js.undefined) { 10 | 11 | def toJson = { 12 | val p = json() 13 | p.updateDynamic("uri")(uri) 14 | isStatic.foreach(v => p.updateDynamic("isStatic")(v)) 15 | p 16 | } 17 | } 18 | 19 | object ImageSource { 20 | def fromJson(obj : js.Dynamic) = { 21 | ImageSource(obj.uri.toString,if(js.isUndefined(obj.isStatic)) js.undefined else obj.isStatic.asInstanceOf[Boolean] ) 22 | } 23 | } -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/ListViewDataSource.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import scala.scalajs.js 4 | import scala.scalajs.js.annotation.JSName 5 | import scala.scalajs.js.{Array => JArray, UndefOr} 6 | 7 | /** 8 | * Created by chandrasekharkode on 4/1/15. 9 | */ 10 | @JSName("ListViewDataSource") 11 | class ListViewDataSource[T] extends js.Object { 12 | 13 | def this(params: js.Object) = this() 14 | 15 | def cloneWithRows(dataBlob: JArray[T], rowIdentities: JArray[String] = ???): ListViewDataSource[T] = js.native 16 | 17 | @JSName("cloneWithRows") 18 | def cloneWithRowsWithObject(dataBlob: js.Dictionary[Any], rowIdentities: JArray[String] = ???): ListViewDataSource[T] = js.native 19 | 20 | def cloneWithRowsAndSections(dataBlob: Any, sectionIdentities: JArray[String] = ???, rowIdentities: JArray[JArray[String]] = ???): ListViewDataSource[T] = js.native 21 | 22 | def getRowCount(): Int = js.native 23 | 24 | def rowShouldUpdate(sectionIndex: Int, rowIndex: Int): Boolean = js.native 25 | 26 | def getRowData(sectionIndex: Int, rowIndex: Int): js.Dynamic = js.native 27 | 28 | def getRowIDForFlatIndex(index: Int): UndefOr[String] = js.native 29 | 30 | def getSectionIDForFlatIndex(index: Int): UndefOr[String] = js.native 31 | 32 | def getSectionLengths(): JArray[Int] = js.native 33 | 34 | def sectionHeaderShouldUpdate(sectionIndex: Int): Boolean = js.native 35 | 36 | def getSectionHeaderData(sectionIndex: Int): js.Dynamic = js.native 37 | 38 | } 39 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/MapView.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import chandu0101.scalajs.rn.ReactNative 4 | import japgolly.scalajs.react.ReactComponentU_ 5 | 6 | import scala.scalajs.js 7 | import scala.scalajs.js.Dynamic.{literal => json} 8 | import scala.scalajs.js.JSConverters.genTravConvertible2JSRichGenTrav 9 | import scala.scalajs.js.{UndefOr, undefined} 10 | 11 | /** 12 | * Created by chandrasekharkode on 4/1/15. 13 | * 14 | * 15 | key: PropTypes.string, 16 | style: PropTypes.js.Any, 17 | ref: PropTypes.String, 18 | showsUserLocation: PropTypes.bool, 19 | zoomEnabled: PropTypes.bool, 20 | rotateEnabled: PropTypes.bool, 21 | pitchEnabled: PropTypes.bool, 22 | scrollEnabled: PropTypes.bool, 23 | region:PropTypes.MapViewRegion, 24 | mapType:PropTypes.MapType, 25 | maxDelta: PropTypes.number, 26 | minDelta: PropTypes.number, 27 | legalLabelInsets: PropTypes.EdgeInsets, 28 | onRegionChange: PropTypes.MapViewRegion => Unit, 29 | onAnnotationPress: PropTypes.MapViewAnnotation => Unit, 30 | annotations:PropTypes.Seq[MapViewAnnotation] 31 | onRegionChangeComplete: PropTypes.MapViewRegion => Unit, 32 | */ 33 | 34 | 35 | 36 | object MapView { 37 | 38 | def apply(maxDelta : js.UndefOr[Int] = js.undefined, 39 | pitchEnabled : js.UndefOr[Boolean]=js.undefined, 40 | mapType : js.UndefOr[MapType] = js.undefined, 41 | style : js.UndefOr[js.Any] = js.undefined, 42 | legalLabelInsets : js.UndefOr[EdgeInsets] = js.undefined, 43 | onRegionChange : js.UndefOr[MapViewRegion => Unit] = js.undefined, 44 | ref : js.UndefOr[String] = js.undefined, 45 | minDelta : js.UndefOr[Int] = js.undefined, 46 | key : js.UndefOr[String] = js.undefined, 47 | scrollEnabled : js.UndefOr[Boolean]=js.undefined, 48 | annotations : js.UndefOr[Seq[MapViewAnnotation]] = js.undefined, 49 | rotateEnabled : js.UndefOr[Boolean]=js.undefined, 50 | onRegionChangeComplete : js.UndefOr[MapViewRegion => Unit] = js.undefined, 51 | region : js.UndefOr[MapViewRegion] = js.undefined, 52 | zoomEnabled : js.UndefOr[Boolean]=js.undefined, 53 | showsUserLocation : js.UndefOr[Boolean]=js.undefined, 54 | onAnnotationPress : js.UndefOr[MapViewAnnotation => Unit] = js.undefined) = { 55 | 56 | val p = js.Dynamic.literal() 57 | maxDelta.foreach(v => p.updateDynamic("maxDelta")(v)) 58 | pitchEnabled.foreach(v => p.updateDynamic("pitchEnabled")(v)) 59 | mapType.foreach(v => p.updateDynamic("mapType")(v.tpe)) 60 | style.foreach(v => p.updateDynamic("style")(v)) 61 | legalLabelInsets.foreach(v => p.updateDynamic("legalLabelInsets")(v.toJson)) 62 | onRegionChange.foreach(v => p.updateDynamic("onRegionChange")((r : js.Dynamic) => v(MapViewRegion.fromJson(r)))) 63 | ref.foreach(v => p.updateDynamic("ref")(v)) 64 | minDelta.foreach(v => p.updateDynamic("minDelta")(v)) 65 | key.foreach(v => p.updateDynamic("key")(v)) 66 | scrollEnabled.foreach(v => p.updateDynamic("scrollEnabled")(v)) 67 | annotations.foreach(v => p.updateDynamic("annotations")(v.map(_.toJson).toJSArray)) 68 | rotateEnabled.foreach(v => p.updateDynamic("rotateEnabled")(v)) 69 | onRegionChangeComplete.foreach(v => p.updateDynamic("onRegionChangeComplete")((r : js.Dynamic) => v(MapViewRegion.fromJson(r)))) 70 | region.foreach(v => p.updateDynamic("region")(v.toJson)) 71 | zoomEnabled.foreach(v => p.updateDynamic("zoomEnabled")(v)) 72 | showsUserLocation.foreach(v => p.updateDynamic("showsUserLocation")(v)) 73 | onAnnotationPress.foreach(v => p.updateDynamic("onAnnotationPress")((annotation : js.Dynamic) => v(MapViewAnnotation.fromJson(annotation)))) 74 | 75 | val f = ReactNative.createFactory(ReactNative.MapView) 76 | f(p).asInstanceOf[ReactComponentU_] 77 | } 78 | 79 | } 80 | 81 | 82 | 83 | class MapType private(val tpe: String) 84 | 85 | object MapType { 86 | 87 | val STANDARD = new MapType("standard") 88 | val SATELLITE = new MapType("satellite") 89 | val HYBRID = new MapType("hybrid") 90 | 91 | } 92 | 93 | 94 | case class MapViewRegion(latitude: Double, longitude: Double, latitudeDelta: Double, longitudeDelta: Double) { 95 | def toJson = json("latitude" -> latitude, "longitudeDelta" -> longitudeDelta, "latitudeDelta" -> latitudeDelta, "longitude" -> longitude) 96 | } 97 | 98 | object MapViewRegion { 99 | def fromJson(obj: js.Dynamic) = MapViewRegion(latitude = obj.latitude.asInstanceOf[Double], 100 | longitudeDelta = obj.longitudeDelta.asInstanceOf[Double], 101 | latitudeDelta = obj.latitudeDelta.asInstanceOf[Double], 102 | longitude = obj.longitude.asInstanceOf[Double]) 103 | } 104 | 105 | case class MapViewAnnotation(latitude: Double, longitude: Double, title: UndefOr[String] = undefined, subTitle: UndefOr[String] = undefined) { 106 | def toJson = { 107 | val p = json() 108 | subTitle.foreach(v => p.updateDynamic("subtitle")(v)) 109 | p.updateDynamic("latitude")(latitude) 110 | title.foreach(v => p.updateDynamic("title")(v)) 111 | p.updateDynamic("longitude")(longitude) 112 | p 113 | } 114 | } 115 | 116 | object MapViewAnnotation { 117 | def fromJson(obj: js.Dynamic) = MapViewAnnotation(subTitle = if (js.isUndefined(obj.subtitle)) js.undefined else obj.subtitle.asInstanceOf[String], 118 | latitude = obj.latitude.asInstanceOf[Double], 119 | title = if (js.isUndefined(obj.title)) js.undefined else obj.title.asInstanceOf[String], 120 | longitude = obj.longitude.asInstanceOf[Double]) 121 | } -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/NavigatorIOS.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import chandu0101.scalajs.rn.ReactNative 4 | import japgolly.scalajs.react.ReactComponentU_ 5 | 6 | import scala.scalajs.js 7 | import scala.scalajs.js.Dynamic.{literal => json} 8 | import scala.scalajs.js.{UndefOr, undefined} 9 | 10 | /** 11 | * Created by chandrasekharkode on 4/1/15. 12 | * 13 | * 14 | key: PropTypes.string, 15 | style: PropTypes.js.Any, 16 | ref: PropTypes.String, 17 | itemWrapperStyle: PropTypes.js.Any, 18 | tintColor: PropTypes.string, 19 | barTintColor: PropTypes.string, 20 | titleTextColor: PropTypes.string, 21 | navigationBarHidden: PropTypes.bool, 22 | translucent: PropTypes.bool, 23 | initialRoute:PropTypes.NavigatorIOSRoute.isRequired 24 | 25 | */ 26 | 27 | 28 | object NavigatorIOS { 29 | 30 | def apply(barTintColor: js.UndefOr[String] = js.undefined, 31 | navigationBarHidden: js.UndefOr[Boolean] = js.undefined, 32 | style: js.UndefOr[js.Any] = js.undefined, 33 | ref: js.UndefOr[String] = js.undefined, 34 | titleTextColor: js.UndefOr[String] = js.undefined, 35 | tintColor: js.UndefOr[String] = js.undefined, 36 | key: js.UndefOr[String] = js.undefined, 37 | itemWrapperStyle: js.UndefOr[js.Any] = js.undefined, 38 | translucent: js.UndefOr[Boolean] = js.undefined, 39 | initialRoute: NavigatorIOSRoute) = { 40 | 41 | val p = js.Dynamic.literal() 42 | barTintColor.foreach(v => p.updateDynamic("barTintColor")(v)) 43 | navigationBarHidden.foreach(v => p.updateDynamic("navigationBarHidden")(v)) 44 | style.foreach(v => p.updateDynamic("style")(v)) 45 | ref.foreach(v => p.updateDynamic("ref")(v)) 46 | titleTextColor.foreach(v => p.updateDynamic("titleTextColor")(v)) 47 | tintColor.foreach(v => p.updateDynamic("tintColor")(v)) 48 | key.foreach(v => p.updateDynamic("key")(v)) 49 | itemWrapperStyle.foreach(v => p.updateDynamic("itemWrapperStyle")(v)) 50 | translucent.foreach(v => p.updateDynamic("translucent")(v)) 51 | p.updateDynamic("initialRoute")(initialRoute.toJson) 52 | 53 | val f = ReactNative.createFactory(ReactNative.NavigatorIOS) 54 | f(p).asInstanceOf[ReactComponentU_] 55 | } 56 | 57 | } 58 | 59 | 60 | trait NavigatorIOSM extends js.Object { 61 | 62 | def push(route: NavigatorIOSRoute): Unit = js.native 63 | 64 | } 65 | 66 | 67 | case class NavigatorIOSRoute(onRightButtonPress: UndefOr[js.Function] = undefined, 68 | passProps: UndefOr[js.Any] = undefined, 69 | rightButtonTitle: UndefOr[String] = undefined, 70 | wrapperStyle: UndefOr[js.Any] = undefined, 71 | backButtonTitle: UndefOr[String] = undefined, 72 | leftButtonTitle: UndefOr[String] = undefined, 73 | backButtonIcon: UndefOr[ImageSource] = undefined, 74 | leftButtonIcon: UndefOr[ImageSource] = undefined, 75 | rightButtonIcon: UndefOr[ImageSource] = undefined, 76 | onLeftButtonPress: UndefOr[js.Function] = undefined, 77 | title: String, 78 | component: js.Object) { 79 | def toJson = { 80 | val p = json("component" -> component) 81 | leftButtonIcon.foreach(v => p.updateDynamic("leftButtonIcon")(v.toJson)) 82 | backButtonIcon.foreach(v => p.updateDynamic("backButtonIcon")(v.toJson)) 83 | backButtonTitle.foreach(v => p.updateDynamic("backButtonTitle")(v)) 84 | rightButtonTitle.foreach(v => p.updateDynamic("rightButtonTitle")(v)) 85 | wrapperStyle.foreach(v => p.updateDynamic("wrapperStyle")(v)) 86 | p.updateDynamic("title")(title) 87 | onLeftButtonPress.foreach(v => p.updateDynamic("onLeftButtonPress")(v)) 88 | passProps.foreach(v => p.updateDynamic("passProps")(v)) 89 | onRightButtonPress.foreach(v => p.updateDynamic("onRightButtonPress")(v)) 90 | rightButtonIcon.foreach(v => p.updateDynamic("rightButtonIcon")(v.toJson)) 91 | leftButtonTitle.foreach(v => p.updateDynamic("leftButtonTitle")(v)) 92 | p 93 | } 94 | } 95 | 96 | object NavigatorIOSRoute { 97 | def fromJson(obj: js.Dynamic) = NavigatorIOSRoute(leftButtonIcon = if (js.isUndefined(obj.leftButtonIcon)) js.undefined else obj.leftButtonIcon.asInstanceOf[ImageSource], backButtonIcon = if (js.isUndefined(obj.backButtonIcon)) js.undefined else obj.backButtonIcon.asInstanceOf[ImageSource], backButtonTitle = if (js.isUndefined(obj.backButtonTitle)) js.undefined else obj.backButtonTitle.asInstanceOf[String], rightButtonTitle = if (js.isUndefined(obj.rightButtonTitle)) js.undefined else obj.rightButtonTitle.asInstanceOf[String], component = obj.component.asInstanceOf[js.Object], wrapperStyle = if (js.isUndefined(obj.wrapperStyle)) js.undefined else obj.wrapperStyle.asInstanceOf[js.Any], title = obj.title.toString, onLeftButtonPress = if (js.isUndefined(obj.onLeftButtonPress)) js.undefined else obj.onLeftButtonPress.asInstanceOf[js.Function], passProps = if (js.isUndefined(obj.passProps)) js.undefined else obj.passProps.asInstanceOf[js.Any], onRightButtonPress = if (js.isUndefined(obj.onRightButtonPress)) js.undefined else obj.onRightButtonPress.asInstanceOf[js.Function], rightButtonIcon = if (js.isUndefined(obj.rightButtonIcon)) js.undefined else obj.rightButtonIcon.asInstanceOf[ImageSource], leftButtonTitle = if (js.isUndefined(obj.leftButtonTitle)) js.undefined else obj.leftButtonTitle.asInstanceOf[String]) 98 | } 99 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/PickerIOS.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import chandu0101.scalajs.rn.ReactNative 4 | import japgolly.scalajs.react.{ReactComponentU_, ReactNode} 5 | 6 | import scala.scalajs.js 7 | import scala.scalajs.js.{UndefOr, undefined} 8 | 9 | /** 10 | * Created by chandrasekharkode on 4/2/15. 11 | * 12 | * key: PropTypes.string, 13 | style: PropTypes.js.Any, 14 | ref: PropTypes.String, 15 | onValueChange: PropTypes.(T) => Unit, 16 | selectedValue: PropTypes.T, 17 | 18 | */ 19 | 20 | 21 | 22 | 23 | case class PickerIOS[T](style : js.UndefOr[js.Any] = js.undefined, 24 | ref : js.UndefOr[String] = js.undefined, 25 | key : js.UndefOr[String] = js.undefined, 26 | onValueChange : js.UndefOr[(T) => Unit] = js.undefined, 27 | selectedValue : js.UndefOr[T] = js.undefined) { 28 | def toJS = { 29 | val p = js.Dynamic.literal() 30 | style.foreach(v => p.updateDynamic("style")(v)) 31 | ref.foreach(v => p.updateDynamic("ref")(v)) 32 | key.foreach(v => p.updateDynamic("key")(v)) 33 | onValueChange.foreach(v => p.updateDynamic("onValueChange")(v)) 34 | selectedValue.foreach(v => p.updateDynamic("selectedValue")(v.asInstanceOf[js.Any])) 35 | p 36 | } 37 | 38 | def apply(children : ReactNode*) = { 39 | val f = ReactNative.createFactory(ReactNative.PickerIOS) 40 | f(toJS,children.toJsArray).asInstanceOf[ReactComponentU_] 41 | } 42 | } 43 | 44 | 45 | /** 46 | *key: PropTypes.string, 47 | style: PropTypes.js.Any, 48 | ref: PropTypes.String, 49 | value:PropTypes.T, 50 | label:PropTypes.string 51 | 52 | */ 53 | object PickerItemIOS { 54 | 55 | def apply[T](style : js.UndefOr[js.Any] = js.undefined, 56 | label : js.UndefOr[String] = js.undefined, 57 | ref : js.UndefOr[String] = js.undefined, 58 | key : js.UndefOr[String] = js.undefined, 59 | value : js.UndefOr[T] = js.undefined) = { 60 | 61 | val p = js.Dynamic.literal() 62 | style.foreach(v => p.updateDynamic("style")(v)) 63 | label.foreach(v => p.updateDynamic("label")(v)) 64 | ref.foreach(v => p.updateDynamic("ref")(v)) 65 | key.foreach(v => p.updateDynamic("key")(v)) 66 | value.foreach(v => p.updateDynamic("value")(v.asInstanceOf[js.Any])) 67 | 68 | val f = ReactNative.createFactory(ReactNative.PickerIOS.asInstanceOf[js.Dynamic].Item.asInstanceOf[js.Object]) 69 | f(p).asInstanceOf[ReactComponentU_] 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/PointProp.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import scala.scalajs.js.Dynamic.{literal => json} 4 | 5 | /** 6 | * Created by chandrasekharkode on 4/1/15. 7 | */ 8 | case class PointProp(x : Double,y : Double) { 9 | def toJson = json( "y" -> y , "x" -> x ) 10 | } 11 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/SegmentedControlIOS.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import chandu0101.scalajs.rn._ 4 | import japgolly.scalajs.react._ 5 | 6 | import scala.scalajs.js 7 | 8 | 9 | /** 10 | * key: PropTypes.string, 11 | style: PropTypes.js.Any, 12 | ref: PropTypes.String, 13 | enabled:PropTypes.bool, 14 | momentary:PropTypes.bool, 15 | onChange: PropTypes.js.Dynamic => Unit, 16 | onValueChange : PropTypes.string => Unit, 17 | selectedIndex: PropTypes.Int, 18 | tintColor: PropTypes.string, 19 | values: PropTypes.Seq[String] 20 | 21 | */ 22 | 23 | object SegmentedControlIOS { 24 | 25 | def apply(momentary: js.UndefOr[Boolean] = js.undefined, 26 | style: js.UndefOr[js.Any] = js.undefined, 27 | onChange: js.UndefOr[js.Dynamic => Unit] = js.undefined, 28 | enabled: js.UndefOr[Boolean] = js.undefined, 29 | ref: js.UndefOr[String] = js.undefined, 30 | tintColor: js.UndefOr[String] = js.undefined, 31 | key: js.UndefOr[String] = js.undefined, 32 | onValueChange: js.UndefOr[String => Unit] = js.undefined, 33 | values: js.UndefOr[Seq[String]] = js.undefined, 34 | selectedIndex: js.UndefOr[Int] = js.undefined) = { 35 | 36 | val p = js.Dynamic.literal() 37 | momentary.foreach(v => p.updateDynamic("momentary")(v)) 38 | style.foreach(v => p.updateDynamic("style")(v)) 39 | onChange.foreach(v => p.updateDynamic("onChange")(v)) 40 | enabled.foreach(v => p.updateDynamic("enabled")(v)) 41 | ref.foreach(v => p.updateDynamic("ref")(v)) 42 | tintColor.foreach(v => p.updateDynamic("tintColor")(v)) 43 | key.foreach(v => p.updateDynamic("key")(v)) 44 | onValueChange.foreach(v => p.updateDynamic("onValueChange")(v)) 45 | values.foreach(v => p.updateDynamic("values")(v.toJsArray)) 46 | selectedIndex.foreach(v => p.updateDynamic("selectedIndex")(v)) 47 | 48 | val f = ReactNative.createFactory(ReactNative.SegmentedControlIOS) 49 | f(p).asInstanceOf[ReactComponentU_] 50 | } 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/SliderIOS.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import chandu0101.scalajs.rn.ReactNative 4 | import japgolly.scalajs.react.ReactComponentU_ 5 | 6 | import scala.scalajs.js 7 | import scala.scalajs.js.{UndefOr, undefined} 8 | 9 | /** 10 | * 11 | * 12 | * key: PropTypes.string, 13 | style: PropTypes.js.Any, 14 | ref: PropTypes.String, 15 | maximumTrackTintColor: PropTypes.string, 16 | maximumValue: PropTypes.Double, 17 | minimumTrackTintColor: PropTypes.string, 18 | minimumValue: PropTypes.Double, 19 | onSlidingComplete: PropTypes.Double => Unit, 20 | onValueChange: PropTypes.Double => Unit, 21 | value: PropTypes.Double, 22 | */ 23 | 24 | 25 | 26 | 27 | object SliderIOS { 28 | 29 | def apply(style : js.UndefOr[js.Any] = js.undefined, 30 | minimumTrackTintColor : js.UndefOr[String] = js.undefined, 31 | minimumValue : js.UndefOr[Double] = js.undefined, 32 | onSlidingComplete : js.UndefOr[Double => Unit] = js.undefined, 33 | ref : js.UndefOr[String] = js.undefined, 34 | maximumTrackTintColor : js.UndefOr[String] = js.undefined, 35 | key : js.UndefOr[String] = js.undefined, 36 | onValueChange : js.UndefOr[Double => Unit] = js.undefined, 37 | value : js.UndefOr[Double] = js.undefined, 38 | maximumValue : js.UndefOr[Double] = js.undefined) = { 39 | 40 | val p = js.Dynamic.literal() 41 | style.foreach(v => p.updateDynamic("style")(v)) 42 | minimumTrackTintColor.foreach(v => p.updateDynamic("minimumTrackTintColor")(v)) 43 | minimumValue.foreach(v => p.updateDynamic("minimumValue")(v)) 44 | onSlidingComplete.foreach(v => p.updateDynamic("onSlidingComplete")(v)) 45 | ref.foreach(v => p.updateDynamic("ref")(v)) 46 | maximumTrackTintColor.foreach(v => p.updateDynamic("maximumTrackTintColor")(v)) 47 | key.foreach(v => p.updateDynamic("key")(v)) 48 | onValueChange.foreach(v => p.updateDynamic("onValueChange")(v)) 49 | value.foreach(v => p.updateDynamic("value")(v)) 50 | maximumValue.foreach(v => p.updateDynamic("maximumValue")(v)) 51 | 52 | val f = ReactNative.createFactory(ReactNative.SliderIOS) 53 | f(p).asInstanceOf[ReactComponentU_] 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/SwitchIOS.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import chandu0101.scalajs.rn.ReactNative 4 | import japgolly.scalajs.react.ReactComponentU_ 5 | 6 | import scala.scalajs.js 7 | 8 | /** 9 | * Created by chandrasekharkode on 4/1/15. 10 | * key: PropTypes.string, 11 | style: PropTypes.js.Any, 12 | ref: PropTypes.String, 13 | disabled: PropTypes.bool, 14 | onTintColor: PropTypes.string, 15 | onValueChange: PropTypes.Boolean => Unit, 16 | thumbTintColor: PropTypes.string, 17 | tintColor: PropTypes.string, 18 | value: PropTypes.bool, 19 | 20 | */ 21 | 22 | 23 | object SwitchIOS { 24 | 25 | def apply(style: js.UndefOr[js.Any] = js.undefined, 26 | ref: js.UndefOr[String] = js.undefined, 27 | tintColor: js.UndefOr[String] = js.undefined, 28 | key: js.UndefOr[String] = js.undefined, 29 | thumbTintColor: js.UndefOr[String] = js.undefined, 30 | onValueChange: js.UndefOr[Boolean => Unit] = js.undefined, 31 | onTintColor: js.UndefOr[String] = js.undefined, 32 | disabled: js.UndefOr[Boolean] = js.undefined, 33 | value: js.UndefOr[Boolean] = js.undefined) = { 34 | 35 | val p = js.Dynamic.literal() 36 | style.foreach(v => p.updateDynamic("style")(v)) 37 | ref.foreach(v => p.updateDynamic("ref")(v)) 38 | tintColor.foreach(v => p.updateDynamic("tintColor")(v)) 39 | key.foreach(v => p.updateDynamic("key")(v)) 40 | thumbTintColor.foreach(v => p.updateDynamic("thumbTintColor")(v)) 41 | onValueChange.foreach(v => p.updateDynamic("onValueChange")(v)) 42 | onTintColor.foreach(v => p.updateDynamic("onTintColor")(v)) 43 | disabled.foreach(v => p.updateDynamic("disabled")(v)) 44 | value.foreach(v => p.updateDynamic("value")(v)) 45 | 46 | val f = ReactNative.createFactory(ReactNative.SwitchIOS) 47 | f(p).asInstanceOf[ReactComponentU_] 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/TabBarIOS.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import chandu0101.scalajs.rn._ 4 | import japgolly.scalajs.react.{ReactComponentU_, ReactNode} 5 | 6 | import scala.scalajs.js 7 | /** 8 | * Created by chandrasekharkode on 4/1/15. 9 | * 10 | * key: PropTypes.string, 11 | style: PropTypes.js.Any, 12 | ref: PropTypes.String, 13 | barTintColor: PropTypes.string, 14 | tintColor: PropTypes.string, 15 | translucent: PropTypes.bool, 16 | 17 | */ 18 | 19 | 20 | 21 | case class TabBarIOS(barTintColor : js.UndefOr[String] = js.undefined, 22 | style : js.UndefOr[js.Any] = js.undefined, 23 | ref : js.UndefOr[String] = js.undefined, 24 | tintColor : js.UndefOr[String] = js.undefined, 25 | key : js.UndefOr[String] = js.undefined, 26 | translucent : js.UndefOr[Boolean]=js.undefined) { 27 | def toJS = { 28 | val p = js.Dynamic.literal() 29 | barTintColor.foreach(v => p.updateDynamic("barTintColor")(v)) 30 | style.foreach(v => p.updateDynamic("style")(v)) 31 | ref.foreach(v => p.updateDynamic("ref")(v)) 32 | tintColor.foreach(v => p.updateDynamic("tintColor")(v)) 33 | key.foreach(v => p.updateDynamic("key")(v)) 34 | translucent.foreach(v => p.updateDynamic("translucent")(v)) 35 | p 36 | } 37 | 38 | def apply(children : ReactNode*) = { 39 | val f = ReactNative.createFactory(ReactNative.TabBarIOS) 40 | f(toJS,children.toJsArray).asInstanceOf[ReactComponentU_] 41 | } 42 | } 43 | 44 | 45 | /** 46 | * key: PropTypes.string, 47 | style: PropTypes.js.Any, 48 | ref: PropTypes.String, 49 | badge: PropTypes.string, 50 | icon: PropTypes.ImageSource.isRequired, 51 | onPress: PropTypes. => Unit.isRequired, 52 | selected: PropTypes.bool.isRequired, 53 | selectedIcon: PropTypes.ImageSource, 54 | systemIcon: PropTypes.SystemIcon, 55 | title: PropTypes.string, 56 | */ 57 | 58 | case class TabBarItemIOS(systemIcon : js.UndefOr[SystemIcon] = js.undefined, 59 | selectedIcon : js.UndefOr[ImageSource] = js.undefined, 60 | onPress : () => Unit, 61 | style : js.UndefOr[js.Any] = js.undefined, 62 | icon : ImageSource, 63 | ref : js.UndefOr[String] = js.undefined, 64 | selected : Boolean, 65 | key : js.UndefOr[String] = js.undefined, 66 | badge : js.UndefOr[String] = js.undefined, 67 | title : js.UndefOr[String] = js.undefined) { 68 | def toJS = { 69 | val p = js.Dynamic.literal() 70 | systemIcon.foreach(v => p.updateDynamic("systemIcon")(v.name)) 71 | selectedIcon.foreach(v => p.updateDynamic("selectedIcon")(v.toJson)) 72 | p.updateDynamic("onPress")(onPress) 73 | style.foreach(v => p.updateDynamic("style")(v)) 74 | p.updateDynamic("icon")(icon.toJson) 75 | ref.foreach(v => p.updateDynamic("ref")(v)) 76 | p.updateDynamic("selected")(selected) 77 | key.foreach(v => p.updateDynamic("key")(v)) 78 | badge.foreach(v => p.updateDynamic("badge")(v)) 79 | title.foreach(v => p.updateDynamic("title")(v)) 80 | p 81 | } 82 | 83 | def apply(children : ReactNode) = { 84 | val f = ReactNative.createFactory(ReactNative.TabBarIOS.asInstanceOf[js.Dynamic].Item.asInstanceOf[js.Object]) 85 | f(toJS,children).asInstanceOf[ReactComponentU_] 86 | } 87 | } 88 | 89 | 90 | 91 | class SystemIcon private(val name : String) extends AnyVal 92 | 93 | object SystemIcon { 94 | 95 | val BOOKMARKS = new SystemIcon("bookmarks") 96 | val CONTACTS = new SystemIcon("contacts") 97 | val DOWNLOADS = new SystemIcon("downloads") 98 | val FAVORITES = new SystemIcon("favorites") 99 | val FEATURED = new SystemIcon("featured") 100 | val HISTORY = new SystemIcon("history") 101 | val MORE = new SystemIcon("more") 102 | val MOST_RECENT = new SystemIcon("most-recent") 103 | val MOST_VIEWED = new SystemIcon("most-viewed") 104 | val RECENTS = new SystemIcon("recents") 105 | val SEARCH = new SystemIcon("search") 106 | val TOP_RATED = new SystemIcon("top-rated") 107 | 108 | def newIcon(name : String) = new SystemIcon(name) 109 | } -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/Text.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import chandu0101.scalajs.rn._ 4 | import japgolly.scalajs.react.{ReactComponentU_, ReactNode} 5 | 6 | import scala.scalajs.js 7 | import scala.scalajs.js.Dynamic.{global => g} 8 | import scala.scalajs.js.{UndefOr, undefined} 9 | 10 | /** 11 | * Created by chandrasekharkode on 3/31/15. 12 | * 13 | * key: PropTypes.string, 14 | style: PropTypes.js.Any, 15 | ref: PropTypes.String, 16 | numberOfLines: PropTypes.number, 17 | onLayout:PropTypes.func 18 | onPress: PropTypes.() => Unit, 19 | suppressHighlighting: PropTypes.bool, 20 | testID: PropTypes.string, 21 | 22 | */ 23 | 24 | 25 | case class Text(suppressHighlighting : js.UndefOr[Boolean]=js.undefined, 26 | onPress : js.UndefOr[() => Unit] = js.undefined, 27 | style : js.UndefOr[js.Any] = js.undefined, 28 | onLayout : js.UndefOr[js.Function] = js.undefined , 29 | numberOfLines : js.UndefOr[Int] = js.undefined, 30 | ref : js.UndefOr[String] = js.undefined, 31 | key : js.UndefOr[String] = js.undefined, 32 | testID : js.UndefOr[String] = js.undefined) { 33 | def toJS = { 34 | val p = js.Dynamic.literal() 35 | suppressHighlighting.foreach(v => p.updateDynamic("suppressHighlighting")(v)) 36 | onPress.foreach(v => p.updateDynamic("onPress")(v)) 37 | style.foreach(v => p.updateDynamic("style")(v)) 38 | onLayout.foreach(v => p.updateDynamic("onLayout")(v)) 39 | numberOfLines.foreach(v => p.updateDynamic("numberOfLines")(v)) 40 | ref.foreach(v => p.updateDynamic("ref")(v)) 41 | key.foreach(v => p.updateDynamic("key")(v)) 42 | testID.foreach(v => p.updateDynamic("testID")(v)) 43 | p 44 | } 45 | 46 | def apply(children : ReactNode*) = { 47 | val f = ReactNative.createFactory(ReactNative.Text) 48 | f(toJS,children.toJsArray).asInstanceOf[ReactComponentU_] 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/TouchableHighlight.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import chandu0101.scalajs.rn._ 4 | import japgolly.scalajs.react.{ReactComponentU_, ReactNode} 5 | 6 | import scala.scalajs.js 7 | 8 | /** 9 | * Created by chandrasekharkode on 4/2/15. 10 | * 11 | * props 12 | * 13 | * key: PropTypes.string, 14 | ref: PropTypes.string, 15 | style: PropTypes.js.Any, 16 | accessible:PropTypes.bool, 17 | delayLongPress: PropTypes.number, 18 | delayPressIn: PropTypes.number, 19 | delayPressOut: PropTypes.number, 20 | onLongPress: PropTypes.() => Unit, 21 | onPress: PropTypes.() => Unit, 22 | onPressIn: PropTypes.() => Unit, 23 | onPressOut: PropTypes.() => Unit, 24 | activeOpacity:PropTypes.number, 25 | onHideUnderlay:PropTypes.() => Unit, 26 | onShowUnderlay:PropTypes.() => Unit, 27 | underlayColor: PropTypes.string, 28 | */ 29 | 30 | 31 | case class TouchableHighlight(onPressIn: js.UndefOr[() => Unit] = js.undefined, 32 | onPress: js.UndefOr[() => Unit] = js.undefined, 33 | style: js.UndefOr[js.Any] = js.undefined, 34 | delayPressIn: js.UndefOr[Int] = js.undefined, 35 | onHideUnderlay: js.UndefOr[() => Unit] = js.undefined, 36 | ref: js.UndefOr[String] = js.undefined, 37 | onPressOut: js.UndefOr[() => Unit] = js.undefined, 38 | key: js.UndefOr[String] = js.undefined, 39 | onLongPress: js.UndefOr[() => Unit] = js.undefined, 40 | underlayColor: js.UndefOr[String] = js.undefined, 41 | delayPressOut: js.UndefOr[Int] = js.undefined, 42 | delayLongPress: js.UndefOr[Int] = js.undefined, 43 | onShowUnderlay: js.UndefOr[() => Unit] = js.undefined, 44 | activeOpacity: js.UndefOr[Int] = js.undefined, 45 | accessible: js.UndefOr[Boolean] = js.undefined) { 46 | def toJS = { 47 | val p = js.Dynamic.literal() 48 | onPressIn.foreach(v => p.updateDynamic("onPressIn")(v)) 49 | onPress.foreach(v => p.updateDynamic("onPress")(v)) 50 | style.foreach(v => p.updateDynamic("style")(v)) 51 | delayPressIn.foreach(v => p.updateDynamic("delayPressIn")(v)) 52 | onHideUnderlay.foreach(v => p.updateDynamic("onHideUnderlay")(v)) 53 | ref.foreach(v => p.updateDynamic("ref")(v)) 54 | onPressOut.foreach(v => p.updateDynamic("onPressOut")(v)) 55 | key.foreach(v => p.updateDynamic("key")(v)) 56 | onLongPress.foreach(v => p.updateDynamic("onLongPress")(v)) 57 | underlayColor.foreach(v => p.updateDynamic("underlayColor")(v)) 58 | delayPressOut.foreach(v => p.updateDynamic("delayPressOut")(v)) 59 | delayLongPress.foreach(v => p.updateDynamic("delayLongPress")(v)) 60 | onShowUnderlay.foreach(v => p.updateDynamic("onShowUnderlay")(v)) 61 | activeOpacity.foreach(v => p.updateDynamic("activeOpacity")(v)) 62 | accessible.foreach(v => p.updateDynamic("accessible")(v)) 63 | p 64 | } 65 | 66 | def apply(children: ReactNode) = { 67 | val f = ReactNative.createFactory(ReactNative.TouchableHighlight) 68 | f(toJS, children).asInstanceOf[ReactComponentU_] 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/TouchableOpacity.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import chandu0101.scalajs.rn.ReactNative 4 | import japgolly.scalajs.react.{ReactComponentU_, ReactNode} 5 | 6 | import scala.scalajs.js 7 | import scala.scalajs.js.{UndefOr, undefined} 8 | 9 | /** 10 | * Created by chandrasekharkode on 4/2/15. 11 | * 12 | * key: PropTypes.string, 13 | ref: PropTypes.string, 14 | style: PropTypes.js.Any, 15 | accessible:PropTypes.bool, 16 | delayLongPress: PropTypes.number, 17 | delayPressIn: PropTypes.number, 18 | delayPressOut: PropTypes.number, 19 | onLongPress: PropTypes.() => Unit, 20 | onPress: PropTypes.() => Unit, 21 | onPressIn: PropTypes.() => Unit, 22 | onPressOut: PropTypes.() => Unit, 23 | activeOpacity:PropTypes.number, 24 | */ 25 | 26 | 27 | 28 | case class TouchableOpacity(onPressIn : js.UndefOr[() => Unit] = js.undefined, 29 | onPress : js.UndefOr[() => Unit] = js.undefined, 30 | style : js.UndefOr[js.Any] = js.undefined, 31 | delayPressIn : js.UndefOr[Int] = js.undefined, 32 | ref : js.UndefOr[String] = js.undefined, 33 | onPressOut : js.UndefOr[() => Unit] = js.undefined, 34 | key : js.UndefOr[String] = js.undefined, 35 | onLongPress : js.UndefOr[() => Unit] = js.undefined, 36 | delayPressOut : js.UndefOr[Int] = js.undefined, 37 | delayLongPress : js.UndefOr[Int] = js.undefined, 38 | activeOpacity : js.UndefOr[Int] = js.undefined, 39 | accessible : js.UndefOr[Boolean]=js.undefined) { 40 | def toJS = { 41 | val p = js.Dynamic.literal() 42 | onPressIn.foreach(v => p.updateDynamic("onPressIn")(v)) 43 | onPress.foreach(v => p.updateDynamic("onPress")(v)) 44 | style.foreach(v => p.updateDynamic("style")(v)) 45 | delayPressIn.foreach(v => p.updateDynamic("delayPressIn")(v)) 46 | ref.foreach(v => p.updateDynamic("ref")(v)) 47 | onPressOut.foreach(v => p.updateDynamic("onPressOut")(v)) 48 | key.foreach(v => p.updateDynamic("key")(v)) 49 | onLongPress.foreach(v => p.updateDynamic("onLongPress")(v)) 50 | delayPressOut.foreach(v => p.updateDynamic("delayPressOut")(v)) 51 | delayLongPress.foreach(v => p.updateDynamic("delayLongPress")(v)) 52 | activeOpacity.foreach(v => p.updateDynamic("activeOpacity")(v)) 53 | accessible.foreach(v => p.updateDynamic("accessible")(v)) 54 | p 55 | } 56 | 57 | def apply(children : ReactNode) = { 58 | val f = ReactNative.createFactory(ReactNative.TouchableOpacity) 59 | f(toJS,children).asInstanceOf[ReactComponentU_] 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/TouchableWithoutFeedback.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import chandu0101.scalajs.rn.ReactNative 4 | import japgolly.scalajs.react.{ReactComponentU_, ReactNode} 5 | 6 | import scala.scalajs.js 7 | 8 | /** 9 | * Created by chandrasekharkode on 4/2/15. 10 | * 11 | * key: PropTypes.string, 12 | ref: PropTypes.string, 13 | style: PropTypes.js.Any, 14 | accessible:PropTypes.bool, 15 | delayLongPress: PropTypes.number, 16 | delayPressIn: PropTypes.number, 17 | delayPressOut: PropTypes.number, 18 | onLongPress: PropTypes.() => Unit, 19 | onPress: PropTypes.() => Unit, 20 | onPressIn: PropTypes.() => Unit, 21 | onPressOut: PropTypes.() => Unit, 22 | */ 23 | 24 | 25 | case class TouchableWithoutFeedback(onPressIn : js.UndefOr[() => Unit] = js.undefined, 26 | onPress : js.UndefOr[() => Unit] = js.undefined, 27 | style : js.UndefOr[js.Any] = js.undefined, 28 | delayPressIn : js.UndefOr[Int] = js.undefined, 29 | ref : js.UndefOr[String] = js.undefined, 30 | onPressOut : js.UndefOr[() => Unit] = js.undefined, 31 | key : js.UndefOr[String] = js.undefined, 32 | onLongPress : js.UndefOr[() => Unit] = js.undefined, 33 | delayPressOut : js.UndefOr[Int] = js.undefined, 34 | delayLongPress : js.UndefOr[Int] = js.undefined, 35 | accessible : js.UndefOr[Boolean]=js.undefined) { 36 | def toJS = { 37 | val p = js.Dynamic.literal() 38 | onPressIn.foreach(v => p.updateDynamic("onPressIn")(v)) 39 | onPress.foreach(v => p.updateDynamic("onPress")(v)) 40 | style.foreach(v => p.updateDynamic("style")(v)) 41 | delayPressIn.foreach(v => p.updateDynamic("delayPressIn")(v)) 42 | ref.foreach(v => p.updateDynamic("ref")(v)) 43 | onPressOut.foreach(v => p.updateDynamic("onPressOut")(v)) 44 | key.foreach(v => p.updateDynamic("key")(v)) 45 | onLongPress.foreach(v => p.updateDynamic("onLongPress")(v)) 46 | delayPressOut.foreach(v => p.updateDynamic("delayPressOut")(v)) 47 | delayLongPress.foreach(v => p.updateDynamic("delayLongPress")(v)) 48 | accessible.foreach(v => p.updateDynamic("accessible")(v)) 49 | p 50 | } 51 | 52 | def apply(children : ReactNode*) = { 53 | val f = ReactNative.createFactory(ReactNative.TouchableWithoutFeedback) 54 | f(toJS,children.toJsArray).asInstanceOf[ReactComponentU_] 55 | } 56 | } -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/components/WebView.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.components 2 | 3 | import chandu0101.scalajs.rn.{NEvent, ReactNative} 4 | import japgolly.scalajs.react.ReactComponentU_ 5 | 6 | import scala.scalajs.js 7 | 8 | /** 9 | * 10 | * 11 | * key: PropTypes.string, 12 | ref: PropTypes.string, 13 | style: PropTypes.js.Any, 14 | automaticallyAdjustContentInsets: PropTypes.bool, 15 | bounces: PropTypes.bool, 16 | contentInset: PropTypes.EdgeInsets, 17 | html: PropTypes.string, 18 | injectedJavaScript: PropTypes.string, 19 | javaScriptEnabledAndroid: PropTypes.bool, 20 | onNavigationStateChange: PropTypes.NavigationState => Unit, 21 | renderError: PropTypes.func, 22 | renderLoading: PropTypes.func, 23 | scalesPageToFit: PropTypes.bool, 24 | scrollEnabled: PropTypes.bool, 25 | startInLoadingState: PropTypes.bool, 26 | url: PropTypes.string.isRequired, 27 | 28 | */ 29 | 30 | 31 | object WebView { 32 | 33 | def apply(contentInset: js.UndefOr[EdgeInsets] = js.undefined, 34 | url: String, 35 | style: js.UndefOr[js.Any] = js.undefined, 36 | javaScriptEnabledAndroid: js.UndefOr[Boolean] = js.undefined, 37 | ref: js.UndefOr[String] = js.undefined, 38 | injectedJavaScript: js.UndefOr[String] = js.undefined, 39 | scalesPageToFit: js.UndefOr[Boolean] = js.undefined, 40 | key: js.UndefOr[String] = js.undefined, 41 | scrollEnabled: js.UndefOr[Boolean] = js.undefined, 42 | onNavigationStateChange: js.UndefOr[NavigationState => Unit] = js.undefined, 43 | bounces: js.UndefOr[Boolean] = js.undefined, 44 | renderLoading: js.UndefOr[js.Function] = js.undefined, 45 | automaticallyAdjustContentInsets: js.UndefOr[Boolean] = js.undefined, 46 | renderError: js.UndefOr[js.Function] = js.undefined, 47 | html: js.UndefOr[String] = js.undefined, 48 | startInLoadingState: js.UndefOr[Boolean] = js.undefined) = { 49 | 50 | val p = js.Dynamic.literal() 51 | contentInset.foreach(v => p.updateDynamic("contentInset")(v.toJson)) 52 | p.updateDynamic("url")(url) 53 | style.foreach(v => p.updateDynamic("style")(v)) 54 | javaScriptEnabledAndroid.foreach(v => p.updateDynamic("javaScriptEnabledAndroid")(v)) 55 | ref.foreach(v => p.updateDynamic("ref")(v)) 56 | injectedJavaScript.foreach(v => p.updateDynamic("injectedJavaScript")(v)) 57 | scalesPageToFit.foreach(v => p.updateDynamic("scalesPageToFit")(v)) 58 | key.foreach(v => p.updateDynamic("key")(v)) 59 | scrollEnabled.foreach(v => p.updateDynamic("scrollEnabled")(v)) 60 | onNavigationStateChange.foreach(v => p.updateDynamic("onNavigationStateChange")(v)) 61 | bounces.foreach(v => p.updateDynamic("bounces")(v)) 62 | renderLoading.foreach(v => p.updateDynamic("renderLoading")(v)) 63 | automaticallyAdjustContentInsets.foreach(v => p.updateDynamic("automaticallyAdjustContentInsets")(v)) 64 | renderError.foreach(v => p.updateDynamic("renderError")(v)) 65 | html.foreach(v => p.updateDynamic("html")(v)) 66 | startInLoadingState.foreach(v => p.updateDynamic("startInLoadingState")(v)) 67 | 68 | val f = ReactNative.createFactory(ReactNative.WebView) 69 | f(p).asInstanceOf[ReactComponentU_] 70 | } 71 | 72 | } 73 | 74 | 75 | trait NavigationState extends js.Object { 76 | 77 | def url: String = js.native 78 | 79 | def title: String = js.native 80 | 81 | def loading: Boolean = js.native 82 | 83 | def canGoBack: Boolean = js.native 84 | 85 | def canGoForward: Boolean = js.native 86 | 87 | } 88 | 89 | trait WebViewM extends js.Object { 90 | 91 | def reload(): Unit = js.native 92 | 93 | def updateNavigationState(event: NEvent): NavigationState = js.native 94 | 95 | def getWebWiewHandle(): js.Dynamic = js.native 96 | 97 | def goForward(): Unit = js.native 98 | 99 | def goBack(): Unit = js.native 100 | 101 | def onLoadingStart(event: NEvent): Unit = js.native 102 | 103 | def onLoadingError(event: NEvent): Unit = js.native 104 | 105 | def onLoadingFinish(event: NEvent): Unit = js.native 106 | 107 | } 108 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/extras/OnUnmountNative.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.extras 2 | 3 | import chandu0101.scalajs.rn.ReactNativeComponentB 4 | import japgolly.scalajs.react.TopNode 5 | 6 | /** 7 | * Its copy of scalajs-react OnUnmount 8 | * Accrues procedures to be run automatically when its component unmounts. 9 | * 10 | * Install in `ReactNativeComponentB` via `.configure(OnUnmount.install)`. 11 | */ 12 | trait OnUnmountNative { 13 | private var unmountProcs: List[() => Unit] = Nil 14 | final def runUnmount(): Unit = { 15 | unmountProcs foreach (_()) 16 | unmountProcs = Nil 17 | } 18 | final def onUnmount(f: => Unit): Unit = unmountProcs ::= (() => f) 19 | final def onUnmountF(f: () => Unit): Unit = unmountProcs ::= f 20 | } 21 | 22 | object OnUnmountNative { 23 | def install[P, S, B <: OnUnmountNative,N <: TopNode] = 24 | (_: ReactNativeComponentB[P, S, B,TopNode]).componentWillUnmount(_.backend.runUnmount()) 25 | 26 | /** 27 | * Convenience class for the frequent case that a component needs a backend with `OnUnmount` and nothing else. 28 | */ 29 | final class Backend extends OnUnmountNative 30 | } 31 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/mixins/TimerMixinNative.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.mixins 2 | 3 | import chandu0101.scalajs.rn.extras.OnUnmountNative 4 | import org.scalajs.dom 5 | import scala.scalajs.js 6 | 7 | /** 8 | * make sure u configure(OnUnMountNative.install) 9 | 10 | */ 11 | abstract class TimerMixinNative extends OnUnmountNative { 12 | 13 | var _timeouts: List[Int] = Nil 14 | 15 | def setTimeout(fn: js.Function0[Any], timeout: Double) = { 16 | val x = dom.window.setTimeout(fn, timeout) 17 | _timeouts +:= x 18 | x 19 | } 20 | 21 | def clearTimeout(id: Int) = dom.window.clearTimeout(id) 22 | 23 | def cleanup() = { 24 | _timeouts.map(clearTimeout) 25 | _timeouts = null 26 | 27 | } 28 | 29 | onUnmount(cleanup()) 30 | 31 | } 32 | -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/package.scala: -------------------------------------------------------------------------------- 1 | 2 | package chandu0101.scalajs 3 | 4 | 5 | import chandu0101.scalajs.rn.components.ListViewDataSource 6 | 7 | import scala.scalajs.js 8 | import scala.scalajs.js.Dynamic.{global => g, literal => json} 9 | 10 | 11 | package object rn { 12 | @inline def load[T](lib: String): T = g.require(lib).asInstanceOf[T] 13 | 14 | lazy val ReactNative = load[ReactNative]("react-native") 15 | 16 | lazy val Dimensions = load[js.Dynamic]("Dimensions") 17 | 18 | /** 19 | * http://stackoverflow.com/questions/31097923/cannot-call-a-class-as-a-function-scala-js 20 | * https://github.com/timoxley/to-factory 21 | * https://github.com/babel/babel/issues/798 22 | */ 23 | lazy val toFactory = load[js.Dynamic]("to-factory") 24 | 25 | type NEvent = js.Dynamic 26 | 27 | def createListViewDataSource[T,H](rowHasChanged: (T, T) => Boolean, 28 | sectionHeaderHasChanged: js.UndefOr[(H,H) => Boolean] = js.undefined, 29 | getRowData : js.UndefOr[(_,String,String) => _] = js.undefined, 30 | getSectionHeaderData : js.UndefOr[(_,String) => _] = js.undefined): ListViewDataSource[T] = { 31 | val ListDataSource = toFactory(ReactNative.ListView.asInstanceOf[js.Dynamic].DataSource) 32 | val j = json(rowHasChanged = rowHasChanged) 33 | sectionHeaderHasChanged.foreach(v => j.updateDynamic("sectionHeaderHasChanged")(v)) 34 | getRowData.foreach(v => j.updateDynamic("getRowData")(v)) 35 | getSectionHeaderData.foreach(v => j.updateDynamic("getSectionHeaderData")(v)) 36 | js.Dynamic.newInstance(ListDataSource)(j).asInstanceOf[ListViewDataSource[T]] 37 | } 38 | 39 | 40 | } -------------------------------------------------------------------------------- /core/src/main/scala/chandu0101/scalajs/rn/thirdparty/MapboxGLMap.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.thirdparty 2 | 3 | import chandu0101.scalajs.rn 4 | import chandu0101.scalajs.rn.ReactNative 5 | import chandu0101.scalajs.rn.components._ 6 | import japgolly.scalajs.react.ReactComponentU_ 7 | 8 | import scala.scalajs.js 9 | import scala.scalajs.js.Dynamic.{literal => json} 10 | import scala.scalajs.js.{UndefOr, undefined} 11 | 12 | /** 13 | * follow instructions from https://github.com/bsudekum/react-native-mapbox-gl 14 | * 15 | * key: PropTypes.string, 16 | style: PropTypes.js.Any, 17 | ref: PropTypes.String, 18 | showsUserLocation: PropTypes.bool, 19 | rotateEnabled: PropTypes.bool, 20 | accessToken: PropTypes.string.isRequired, 21 | zoomLevel: PropTypes.number, 22 | direction: PropTypes.number, 23 | styleURL: PropTypes.string, 24 | clipsToBounds: PropTypes.bool, 25 | debugActive: PropTypes.bool, 26 | centerCoordinate:PropTypes.CenterCoordinate, 27 | annotations: PropTypes.MapViewAnnotation, 28 | onRegionChange: PropTypes.js.Object => _, 29 | onOpenAnnotation: PropTypes.MapViewAnnotation => _ 30 | */ 31 | object MapBoxGLMap { 32 | 33 | def apply(style: UndefOr[js.Any] = undefined, 34 | onOpenAnnotation: UndefOr[MapViewAnnotation => _] = undefined, 35 | onRegionChange: UndefOr[js.Object => _] = undefined, 36 | centerCoordinate: UndefOr[CenterCoordinate] = undefined, 37 | zoomLevel: UndefOr[Int] = undefined, 38 | ref: UndefOr[String] = undefined, 39 | direction: UndefOr[Int] = undefined, 40 | debugActive: UndefOr[Boolean] = undefined, 41 | key: UndefOr[String] = undefined, 42 | styleURL: UndefOr[String] = undefined, 43 | annotations: UndefOr[js.Array[MapViewAnnotation]] = undefined, 44 | rotateEnabled: UndefOr[Boolean] = undefined, 45 | clipsToBounds: UndefOr[Boolean] = undefined, 46 | showsUserLocation: UndefOr[Boolean] = undefined, 47 | accessToken: String) = { 48 | 49 | val p = js.Dynamic.literal() 50 | style.foreach(v => p.updateDynamic("style")(v)) 51 | onOpenAnnotation.foreach(v => p.updateDynamic("onOpenAnnotation")(v)) 52 | onRegionChange.foreach(v => p.updateDynamic("onRegionChange")(v)) 53 | centerCoordinate.foreach(v => p.updateDynamic("centerCoordinate")(if (v != null) v.toJson else null)) 54 | zoomLevel.foreach(v => p.updateDynamic("zoomLevel")(v)) 55 | ref.foreach(v => p.updateDynamic("ref")(v)) 56 | direction.foreach(v => p.updateDynamic("direction")(v)) 57 | debugActive.foreach(v => p.updateDynamic("debugActive")(v)) 58 | key.foreach(v => p.updateDynamic("key")(v)) 59 | styleURL.foreach(v => p.updateDynamic("styleURL")(v)) 60 | annotations.foreach(v => p.updateDynamic("annotations")(v.map(a => a.toJson))) 61 | rotateEnabled.foreach(v => p.updateDynamic("rotateEnabled")(v)) 62 | clipsToBounds.foreach(v => p.updateDynamic("clipsToBounds")(v)) 63 | showsUserLocation.foreach(v => p.updateDynamic("showsUserLocation")(v)) 64 | p.updateDynamic("accessToken")(accessToken) 65 | // val MapBox = js.Dynamic.global.require("react-native-mapbox-gl") 66 | val f = ReactNative.createFactory(rn.load[js.Object]("react-native-mapbox-gl")) 67 | f(p).asInstanceOf[ReactComponentU_] 68 | 69 | } 70 | 71 | } 72 | 73 | 74 | case class CenterCoordinate(latitude: Double, longitude: Double) { 75 | def toJson = { 76 | val p = json() 77 | p.updateDynamic("latitude")(latitude) 78 | p.updateDynamic("longitude")(longitude) 79 | p 80 | } 81 | } 82 | 83 | object CenterCoordinate { 84 | def fromJson(obj: js.Dynamic) = CenterCoordinate(latitude = obj.latitude.asInstanceOf[Double], longitude = obj.longitude.asInstanceOf[Double]) 85 | } -------------------------------------------------------------------------------- /doc/CHANGELOG_0.2.0.md: -------------------------------------------------------------------------------- 1 | * Support react-native 0.8 2 | * Added more examples to UI Explorer -------------------------------------------------------------------------------- /examples/ScalaJSReactNative.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/ScalaJSReactNative.xcodeproj/project.xcworkspace/xcshareddata/ScalaJSReactNative.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 9A806A33-2E03-499E-AE7C-239EEF08C06A 9 | IDESourceControlProjectName 10 | ScalaJSReactNative 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | FE5BDDD7A22B1222F2D19F44F4F856D3A3604AFC 14 | https://github.com/chandu0101/scalajs-react-native 15 | 16 | IDESourceControlProjectPath 17 | examples/ScalaJSReactNative.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | FE5BDDD7A22B1222F2D19F44F4F856D3A3604AFC 21 | ../../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/chandu0101/scalajs-react-native 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | FE5BDDD7A22B1222F2D19F44F4F856D3A3604AFC 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | FE5BDDD7A22B1222F2D19F44F4F856D3A3604AFC 36 | IDESourceControlWCCName 37 | scalajs-react-native 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /examples/ScalaJSReactNative.xcodeproj/project.xcworkspace/xcuserdata/chandrasekharkode.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chandu0101/scalajs-react-native/a30bb21f3a49e872e294033ad717de86f761c22c/examples/ScalaJSReactNative.xcodeproj/project.xcworkspace/xcuserdata/chandrasekharkode.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /examples/ScalaJSReactNative.xcodeproj/xcshareddata/xcschemes/ScalaJSReactNative.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /examples/ScalaJSReactNative.xcodeproj/xcuserdata/chandrasekharkode.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ScalaJSReactNative.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 00E356ED1AD99517003FC87E 16 | 17 | primary 18 | 19 | 20 | 13B07F861A680F5B00A75B9A 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /examples/iOS/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 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (nonatomic, strong) UIWindow *window; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /examples/iOS/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 "RCTRootView.h" 13 | 14 | @implementation AppDelegate 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 17 | { 18 | NSURL *jsCodeLocation; 19 | 20 | /** 21 | * Loading JavaScript code - uncomment the one you want. 22 | * 23 | * OPTION 1 24 | * Load from development server. Start the server from the repository root: 25 | * 26 | * $ npm start 27 | * 28 | * To run on device, change `localhost` to the IP address of your computer 29 | * (you can get this by typing `ifconfig` into the terminal and selecting the 30 | * `inet` value under `en0:`) and make sure your computer and iOS device are 31 | * on the same Wi-Fi network. 32 | */ 33 | 34 | jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle"]; 35 | 36 | /** 37 | * OPTION 2 38 | * Load from pre-bundled file on disk. To re-generate the static bundle 39 | * from the root of your project directory, run 40 | * 41 | * $ react-native bundle --minify 42 | * 43 | * see http://facebook.github.io/react-native/docs/runningondevice.html 44 | */ 45 | 46 | // jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 47 | 48 | RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation 49 | moduleName:@"ScalaJSReactNative" 50 | launchOptions:launchOptions]; 51 | 52 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 53 | UIViewController *rootViewController = [[UIViewController alloc] init]; 54 | rootViewController.view = rootView; 55 | self.window.rootViewController = rootViewController; 56 | [self.window makeKeyAndVisible]; 57 | return YES; 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /examples/iOS/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /examples/iOS/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /examples/iOS/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 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UIViewControllerBasedStatusBarAppearance 38 | 39 | NSLocationWhenInUseUsageDescription 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /examples/iOS/main.jsbundle: -------------------------------------------------------------------------------- 1 | // Offline JS 2 | // To re-generate the offline bundle, run this from the root of your project: 3 | // 4 | // $ react-native bundle --minify 5 | // 6 | // See http://facebook.github.io/react-native/docs/runningondevice.html for more details. 7 | 8 | throw new Error('Offline JS file is empty. See iOS/main.jsbundle for instructions'); 9 | -------------------------------------------------------------------------------- /examples/iOS/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 | -------------------------------------------------------------------------------- /examples/images/movies.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chandu0101/scalajs-react-native/a30bb21f3a49e872e294033ad717de86f761c22c/examples/images/movies.gif -------------------------------------------------------------------------------- /examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "scalajs-react-native", 3 | "version": "0.0.2", 4 | "private": true, 5 | "scripts": { 6 | "start": "node_modules/react-native/packager/packager.sh" 7 | }, 8 | "dependencies": { 9 | "react-native": "^0.8.0", 10 | "to-factory": "^1.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/HelloNative.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples 2 | 3 | import chandu0101.scalajs.rn.ReactNativeComponentB 4 | import chandu0101.scalajs.rn.components.{Text, View} 5 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 6 | 7 | import scala.scalajs.js.Dynamic.{literal => json} 8 | 9 | 10 | object HelloNative { 11 | 12 | val component = ReactNativeComponentB[Unit]("HelloNative") 13 | .render(P => { 14 | View(style = Styles.container("red"))( 15 | Text(style = Styles.text)("Welcome to Scala-JS ReactNative"), 16 | Text(style = Styles.text)("To get started, edit HelloNative.scala ") 17 | ) 18 | }).buildU 19 | 20 | 21 | object Styles extends NativeStyleSheet { 22 | def container(color: String) = style(flex := 1, 23 | alignItems.center, 24 | justifyContent.center, 25 | backgroundColor := color) 26 | 27 | val text = style(fontSize := 15, padding := 100, justifyContent.flexEnd) 28 | 29 | val baby = styleE(text, container("d"))(flexDirection.row, justifyContent.spaceAround) 30 | } 31 | 32 | def apply() = component() 33 | } 34 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/NativeApp.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples 2 | 3 | import chandu0101.scalajs.rn._ 4 | import chandu0101.scalajs.rn.examples.movies.MoviesApp 5 | import chandu0101.scalajs.rn.examples.uiexplorer.UIExplorerApp 6 | import chandu0101.scalajs.rn.examples.uiexplorer.components.navigator.NavigationBarSample 7 | 8 | import scala.scalajs.js.Dynamic.{literal => lit} 9 | import scala.scalajs.js.JSApp 10 | 11 | 12 | object NativeApp extends JSApp { 13 | def main() = { 14 | val ScalaJSReactNative = ReactNativeComponentB[Unit]("ScalaJSReactNative") 15 | .render((P) => { 16 | // HelloNative() 17 | // MoviesApp() 18 | UIExplorerApp() 19 | }).buildNative 20 | 21 | ReactNative.AppRegistry.registerComponent("ScalaJSReactNative", () => ScalaJSReactNative) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/movies/Movie.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.movies 2 | 3 | 4 | case class Movie() { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/movies/MovieCell.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.movies 2 | 3 | import chandu0101.scalajs.rn.components.{Image, Text, TouchableHighlight, View} 4 | import chandu0101.scalajs.rn.examples.movies.MoviesUtil._ 5 | import chandu0101.scalajs.rn.{ReactNative, ReactNativeComponentB} 6 | import japgolly.scalajs.react._ 7 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 8 | 9 | import scala.scalajs.js 10 | import scala.scalajs.js.Dynamic.{literal => json} 11 | 12 | 13 | object MovieCell { 14 | 15 | val component = ReactNativeComponentB[Props]("MovieCell") 16 | .render((P) => { 17 | val criticScore = P.movie.ratings.critics_score.asInstanceOf[Int] 18 | View()( 19 | TouchableHighlight(key = "th", onPress = P.onSelect)( 20 | View(key ="pap", style = styles.row)( 21 | Image(key = "is", source = getImageSource(P.movie,"det"),style = styles.cellImage), 22 | View(key = "sv", style = styles.textContainer)( 23 | Text(key = "tt", style = styles.movieTitle)(P.movie.title.toString), 24 | Text(key = "year", style = styles.movieYear,numberOfLines = 1)( 25 | P.movie.year.toString, 26 | Text(key = "hello")( 27 | s"Critcs ${getTextFromScore(criticScore)}" 28 | ) 29 | ) 30 | ) 31 | ) 32 | ), 33 | View(key = "cb", style = styles.cellBorder)() 34 | ) 35 | }) 36 | .build 37 | 38 | 39 | case class Props(movie: js.Dynamic, onSelect: () => Unit) 40 | 41 | object styles extends NativeStyleSheet { 42 | val textContainer = style( 43 | flex := 1 44 | ) 45 | val movieTitle = style( 46 | flex := 1, 47 | fontSize := 16, 48 | fontWeight._500, 49 | marginBottom := 2 50 | ) 51 | val movieYear = style( 52 | color := "#999999", 53 | fontSize := 12 54 | ) 55 | val row = style( 56 | alignItems.center, 57 | backgroundColor := "white", 58 | flexDirection.row, 59 | padding := 5 60 | ) 61 | val cellImage = style( 62 | backgroundColor := "#dddddd", 63 | height := 93, 64 | marginRight := 10, 65 | width := 60 66 | ) 67 | val cellBorder = style( 68 | backgroundColor := "rgba(0, 0, 0, 0.1)", 69 | height := 1.0 / ReactNative.PixelRatio.get(), 70 | marginLeft := 4 71 | ) 72 | } 73 | 74 | def apply(movie: js.Dynamic, onSelect: () => Unit,key : String = "") = component.withKey(key)(new Props(movie, onSelect)) 75 | 76 | } 77 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/movies/MovieScreen.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.movies 2 | 3 | import chandu0101.scalajs.rn.components.{Image, ScrollView, Text, View} 4 | import chandu0101.scalajs.rn.examples.movies.MoviesUtil._ 5 | import chandu0101.scalajs.rn.{ReactNative, ReactNativeComponentB} 6 | import japgolly.scalajs.react._ 7 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 8 | 9 | import scala.scalajs.js 10 | import scala.scalajs.js.Dynamic.{literal => json} 11 | 12 | 13 | object MovieScreen { 14 | 15 | class Backend(t: BackendScope[_, _]) { 16 | 17 | val props = t.propsDynamic 18 | 19 | } 20 | 21 | val Ratings = ReactNativeComponentB[js.Dynamic]("Ratings") 22 | .render(P => { 23 | val criticsScore = P.critics_score.asInstanceOf[Int] 24 | val audienceScore = P.audience_score.asInstanceOf[Int] 25 | View()( 26 | View(style = styles.rating)( 27 | Text(style = styles.ratingTitle)("Critics:"), 28 | Text(style = styles.ratingValue)(getTextFromScore(criticsScore)) 29 | ), 30 | View(style = styles.rating)( 31 | Text(style = styles.ratingTitle)("Audience:"), 32 | Text(style = styles.ratingValue)(getTextFromScore(audienceScore)) 33 | ) 34 | ) 35 | }).build 36 | 37 | val Cast = ReactNativeComponentB[js.Array[js.Dynamic]]("Cast") 38 | .render(P => { 39 | View()( 40 | Text(style = styles.castTitle)("Actors"), 41 | P.map(actor => Text(key = actor.name.toString, style = styles.castActor)(s"${actor.name.toString}")) 42 | ) 43 | }).build 44 | 45 | val component = ReactNativeComponentB[Props]("MovieScreen") 46 | .stateless 47 | .backend(new Backend(_)) 48 | .render((P, S, B) => { 49 | val movie = B.props.route.passProps 50 | ScrollView(contentContainerStyle = styles.contentContainer)( 51 | View()( 52 | View(style = styles.mainSection)( 53 | Image(style = styles.detailsImage, source = getImageSource(movie, "det")), 54 | View(style = styles.rightPane)( 55 | Text()(movie.year.toString), 56 | View(style = styles.mpaaWrapper)( 57 | Text(style = styles.mpaaText)(movie.mpaa_rating.toString) 58 | ), 59 | Ratings(movie.ratings) 60 | ) 61 | ), 62 | View(style = styles.separator)(), 63 | Text()(movie.synopsis.toString), 64 | View(style = styles.separator)(), 65 | Cast(movie.abridged_cast.asInstanceOf[js.Array[js.Dynamic]]) 66 | ) 67 | 68 | ) 69 | }) 70 | .buildNative 71 | 72 | 73 | case class Props(movie: js.Dynamic) 74 | 75 | 76 | object styles extends NativeStyleSheet { 77 | 78 | val contentContainer = style( 79 | padding := 10 80 | ) 81 | val rightPane = style( 82 | justifyContent.spaceBetween, 83 | flex := 1 84 | ) 85 | val movieTitle = style( 86 | flex := 1, 87 | fontSize := 16, 88 | fontWeight._500 89 | ) 90 | val rating = style( 91 | marginTop := 10 92 | ) 93 | val ratingTitle = style( 94 | fontSize := 14 95 | ) 96 | val ratingValue = style( 97 | fontSize := 28, 98 | fontWeight._500 99 | ) 100 | val mpaaWrapper = style( 101 | alignSelf.flexStart, 102 | borderColor := "black", 103 | borderWidth := 1, 104 | paddingHorizontal := 3, 105 | marginVertical := 5 106 | ) 107 | val mpaaText = style( 108 | fontFamily := "Palatino", 109 | fontSize := 13, 110 | fontWeight._500 111 | ) 112 | val mainSection = style( 113 | flexDirection.row 114 | ) 115 | val detailsImage = style( 116 | width := 134, 117 | height := 200, 118 | backgroundColor := "#eaeaea", 119 | marginRight := 10 120 | ) 121 | val separator = style( 122 | backgroundColor := "rgba(0, 0, 0, 0.1)", 123 | height := 1.0 / ReactNative.PixelRatio.get(), 124 | marginVertical := 10 125 | ) 126 | val castTitle = style( 127 | fontWeight._500, 128 | marginBottom := 3 129 | ) 130 | val castActor = style( 131 | marginLeft := 2 132 | ) 133 | } 134 | 135 | 136 | } 137 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/movies/MoviesApp.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.movies 2 | 3 | import chandu0101.scalajs.rn.ReactNativeComponentB 4 | import chandu0101.scalajs.rn.components.{NavigatorIOS, NavigatorIOSRoute} 5 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 6 | 7 | object MoviesApp { 8 | 9 | val component = ReactNativeComponentB[Unit]("MoviesApp") 10 | .render(P => { 11 | NavigatorIOS(style = Styles.container, 12 | initialRoute = NavigatorIOSRoute(title = "Scala-JS Movies", 13 | component = SearchScreen.component)) 14 | }).buildU 15 | 16 | object Styles extends NativeStyleSheet { 17 | 18 | def container = style(flex := 1, backgroundColor := "#F5FCFF") 19 | } 20 | 21 | def apply() = component() 22 | } 23 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/movies/MoviesUtil.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.movies 2 | 3 | import chandu0101.scalajs.rn.components.ImageSource 4 | 5 | import scala.scalajs.js 6 | import scala.scalajs.js.isUndefined 7 | 8 | object MoviesUtil { 9 | 10 | def getImageSource(movie : js.Dynamic, kind : String = "") : ImageSource = { 11 | var uri = if(!isUndefined(movie) && !isUndefined(movie.posters)) movie.posters.thumbnail.toString else "" 12 | if(kind.nonEmpty && uri.nonEmpty) uri = uri.replace("tmb",kind) 13 | ImageSource(uri = uri) 14 | } 15 | 16 | def getTextFromScore(score : Int) : String = { 17 | if(score >0) s"$score%" else "N/A" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/UIExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer 2 | 3 | import scala.scalajs.js 4 | 5 | 6 | trait UIExample { 7 | 8 | def title: String 9 | 10 | def description: String 11 | 12 | def component :js.Object 13 | } 14 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/UIExplorerApp.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer 2 | 3 | import chandu0101.scalajs.rn.ReactNativeComponentB 4 | import chandu0101.scalajs.rn.components.{NavigatorIOS, NavigatorIOSRoute} 5 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 6 | 7 | 8 | object UIExplorerApp { 9 | 10 | val component = ReactNativeComponentB[Unit]("UIExplorerApp") 11 | .render(P => { 12 | NavigatorIOS(style = styles.container, initialRoute = NavigatorIOSRoute(title = "Scala-JS UIExplorer", component = UIExplorerList.component)) 13 | }).buildU 14 | 15 | object styles extends NativeStyleSheet { 16 | val container = style(flex := 1, backgroundColor := "red") 17 | } 18 | 19 | def apply() = component() 20 | } 21 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/UIExplorerBlock.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer 2 | 3 | import chandu0101.scalajs.rn.ReactNativeComponentB 4 | import chandu0101.scalajs.rn.components.{Text, View} 5 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 6 | import japgolly.scalajs.react.ReactNode 7 | 8 | 9 | object UIExplorerBlock { 10 | 11 | 12 | val component = ReactNativeComponentB[String]("UIExplorerBlock") 13 | .render((P,C) => { 14 | View(style = styles.container)( 15 | View(style = styles.titleContainer)( 16 | Text(style = styles.titleText)(P) 17 | ), 18 | View(style = styles.children)( 19 | C 20 | ) 21 | ) 22 | }).build 23 | 24 | object styles extends NativeStyleSheet { 25 | 26 | val container = style( 27 | borderRadius := 3, 28 | borderWidth := 0.5, 29 | borderColor := "#d6d7da", 30 | backgroundColor := "#ffffff", 31 | margin := 10, 32 | marginVertical := 5, 33 | overflow.hidden 34 | ) 35 | 36 | val titleContainer = style( 37 | borderWidth := 0.5, 38 | borderColor := "#d6d7da", 39 | backgroundColor := "#f6f7f8", 40 | paddingHorizontal := 10, 41 | paddingVertical := 5 42 | ) 43 | 44 | val titleText = style(fontSize := 14, fontWeight._500) 45 | 46 | val children = style(padding := 10) 47 | } 48 | 49 | 50 | def apply(title: String)(children: ReactNode*) = component(title, children) 51 | } 52 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/UIExplorerList.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer 2 | 3 | import chandu0101.scalajs.rn 4 | import chandu0101.scalajs.rn.components._ 5 | import chandu0101.scalajs.rn.examples.uiexplorer.apis._ 6 | import chandu0101.scalajs.rn.examples.uiexplorer.components._ 7 | import chandu0101.scalajs.rn.examples.uiexplorer.components.navigator.NavigatorExample 8 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 9 | import chandu0101.scalajs.rn.{ReactNative, ReactNativeComponentB} 10 | import japgolly.scalajs.react.BackendScope 11 | 12 | import scala.scalajs.js 13 | import scala.scalajs.js.Dynamic.{literal => json} 14 | 15 | 16 | object UIExplorerList { 17 | 18 | val COMPONENTS: js.Array[UIExample] = js.Array(TabBarIOSExample, 19 | ViewExample, 20 | WebViewExample, 21 | TouchableExample, 22 | SegmentedControlExample, 23 | SwitchIOSExample, 24 | SliderIOSExample, 25 | ScrollViewExample, 26 | ActivityIndicatorIOSExample, 27 | PickerIOSExample, 28 | DatePickerIOSExample, 29 | MapViewExample, 30 | TextInputExample, 31 | ListViewExample, 32 | ListViewPagingExample, 33 | NavigatorExample) 34 | 35 | val APIS: js.Array[UIExample] = js.Array(AlertIOSExample, 36 | GeoLocationExample, 37 | AppStateIOSExample, 38 | AsyncStorageExample, 39 | NetInfoExample) 40 | 41 | val ds = rn.createListViewDataSource(rowHasChanged = (r1: UIExample, r2: UIExample) => r1 != r2, sectionHeaderHasChanged = (h1: String, h2: String) => h1 != h2) 42 | 43 | case class State(datasource: ListViewDataSource[UIExample] = ds.cloneWithRowsAndSections(json(componenets = COMPONENTS, apis = APIS))) 44 | 45 | class Backend(t: BackendScope[_, State]) { 46 | 47 | def onPressRow(example: UIExample): Unit = { 48 | t.propsDynamic.navigator.push( 49 | NavigatorIOSRoute(title = example.title, component = example.component).toJson 50 | ) 51 | } 52 | 53 | def handleSearchTextChange(text: String): Unit = { 54 | val filter = (e: UIExample) => e.title.toLowerCase.contains(text.toLowerCase.trim) 55 | val filteredComponents = COMPONENTS.filter(filter) 56 | val filteredAPIS = APIS.filter(filter) 57 | t.modState(_.copy(datasource = ds.cloneWithRowsAndSections(json(componenets = filteredComponents, apis = filteredAPIS)))) 58 | } 59 | 60 | def renderRow(example: UIExample, sectionID: String, rowId: String) = { 61 | View(key = example.title)( 62 | TouchableHighlight(onPress = () => onPressRow(example))( 63 | View(style = styles.row)( 64 | Text(style = styles.rowTitleText)( 65 | example.title 66 | ), 67 | Text(style = styles.rowDetailText)( 68 | example.description 69 | ) 70 | ) 71 | ), 72 | View(style = styles.separator)() 73 | ) 74 | } 75 | 76 | def renderSectionHeader(data: js.Dynamic, sectionID: js.Dynamic) = { 77 | View(style = styles.sectionHeader)( 78 | Text(style = styles.sectionHeaderTitle)( 79 | sectionID.toString.toUpperCase 80 | ) 81 | ) 82 | } 83 | } 84 | 85 | val component = ReactNativeComponentB[Any]("UIExplorerList") 86 | .initialState(State()) 87 | .backend(new Backend(_)) 88 | .render((P, S, B) => { 89 | View(style = styles.listContainer)( 90 | View(style = styles.searchRow)( 91 | TextInput(autoCapitalize = AutoCapitalize.NONE, 92 | autoCorrect = false, 93 | clearButtonMode = "always", 94 | onChangeText = B.handleSearchTextChange _, 95 | placeholder = "Search ..", 96 | style = styles.searchTextInput)() 97 | ), 98 | ListView(style = styles.list, 99 | dataSource = S.datasource, 100 | renderRow = B.renderRow, 101 | renderSectionHeader = B.renderSectionHeader _, 102 | automaticallyAdjustContentInsets = false) 103 | ) 104 | }).buildNative 105 | 106 | 107 | object styles extends NativeStyleSheet { 108 | val listContainer = style( 109 | flex := 1 110 | ) 111 | val list = style( 112 | backgroundColor := "#eeeeee" 113 | ) 114 | val sectionHeader = style( 115 | padding := 5 116 | ) 117 | val group = style( 118 | backgroundColor := "white" 119 | ) 120 | val sectionHeaderTitle = style( 121 | fontWeight._500, 122 | fontSize := 11 123 | ) 124 | val row = style( 125 | backgroundColor := "white", 126 | justifyContent.center, 127 | paddingHorizontal := 15, 128 | paddingVertical := 8 129 | ) 130 | val separator = style( 131 | height := 1.0 / ReactNative.PixelRatio.get(), 132 | backgroundColor := "#bbbbbb", 133 | marginLeft := 15 134 | ) 135 | val rowTitleText = style( 136 | fontSize := 17, 137 | fontWeight._500 138 | ) 139 | val rowDetailText = style( 140 | fontSize := 15, 141 | color := "#888888", 142 | lineHeight := 20 143 | ) 144 | val searchRow = style( 145 | backgroundColor := "#eeeeee", 146 | paddingTop := 75, 147 | paddingLeft := 10, 148 | paddingRight := 10, 149 | paddingBottom := 10 150 | ) 151 | val searchTextInput = style( 152 | backgroundColor := "white", 153 | borderColor := "#cccccc", 154 | borderRadius := 3, 155 | borderWidth := 1, 156 | height := 30, 157 | paddingLeft := 8 158 | ) 159 | } 160 | 161 | } 162 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/UIExplorerPage.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer 2 | 3 | import chandu0101.scalajs.rn.ReactNativeComponentB 4 | import chandu0101.scalajs.rn.components.{keyboardDismissMode, ScrollView, View} 5 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 6 | import japgolly.scalajs.react._ 7 | 8 | 9 | object UIExplorerPage { 10 | 11 | val component = ReactNativeComponentB[Unit]("UIExamplePage") 12 | .render((P, C) => { 13 | View(style = styles.container)( 14 | ScrollView(style = styles.wrapper, keyboardShouldPersistTaps = true, 15 | keyboardDismissMode = keyboardDismissMode.INTERACTIVE)( 16 | C 17 | ) 18 | ) 19 | }).buildU 20 | 21 | object styles extends NativeStyleSheet { 22 | 23 | val container = style(backgroundColor := "#e9eaed", 24 | flex := 1) 25 | 26 | val wrapper = style(flex := 1) 27 | } 28 | 29 | def apply(children: ReactNode*) = component(children) 30 | } 31 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/apis/AlertIOSExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.apis 2 | 3 | import chandu0101.scalajs.rn 4 | import chandu0101.scalajs.rn.ReactNativeComponentB 5 | import chandu0101.scalajs.rn.apis.AlertButton 6 | import chandu0101.scalajs.rn.components.{Text, TouchableHighlight, View} 7 | import chandu0101.scalajs.rn.examples.uiexplorer.{UIExample, UIExplorerBlock, UIExplorerPage} 8 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 9 | 10 | import scala.scalajs.js 11 | import scala.scalajs.js.Dynamic.{literal => json} 12 | import scala.scalajs.js.JSConverters.JSRichGenTraversableOnce 13 | 14 | 15 | object AlertIOSExample extends UIExample { 16 | override def title: String = "AlertIOS" 17 | 18 | override def component = ReactNativeComponentB[Unit]("AlertIOSExample") 19 | .render(P => { 20 | val a1 = () => rn.ReactNative.AlertIOS.alert("Foo title", "alert message") 21 | val a2 = () => rn.ReactNative.AlertIOS.alert(buttons = js.Array(AlertButton("Button",() => println("Button Pressed")).toJson)) 22 | val a3 = () => rn.ReactNative.AlertIOS.alert( 23 | title = "Foo Title", 24 | message = "My Alert Msg" , 25 | buttons = js.Array(AlertButton("Foo",() => println("Foo Button Pressed")).toJson, 26 | AlertButton("Bar",() => println("Bar Button Pressed")).toJson)) 27 | val a4 = () => rn.ReactNative.AlertIOS.alert( 28 | title = "Foo Title", 29 | buttons = js.Array(AlertButton("Foo",() => println("Foo Button Pressed")).toJson, 30 | AlertButton("Bar",() => println("Bar Button Pressed")).toJson, 31 | AlertButton("Baz",() => println("Baz Button Pressed")).toJson)) 32 | val a5 = () => rn.ReactNative.AlertIOS.alert(title = "Foo title", 33 | buttons = (1 to 10).map(i => AlertButton(s"Button $i",() => println(s"Button $i pressed")).toJson.asInstanceOf[js.Object]).toJSArray) 34 | 35 | UIExplorerPage( 36 | UIExplorerBlock("Alerts")( 37 | View(style = json(flex = 1))( 38 | TouchableHighlight(style = styles.wrapper, onPress = a1)( 39 | View(style = styles.button)( 40 | Text()("Alert Message with default button") 41 | ) 42 | ), 43 | TouchableHighlight(style = styles.wrapper, onPress = a2)( 44 | View(style = styles.button)( 45 | Text()("Alert with only one button") 46 | ) 47 | ), 48 | TouchableHighlight(style = styles.wrapper, onPress = a3)( 49 | View(style = styles.button)( 50 | Text()("Alert with two buttons") 51 | ) 52 | ), 53 | TouchableHighlight(style = styles.wrapper, onPress = a4)( 54 | View(style = styles.button)( 55 | Text()("Alert with 3 buttons") 56 | ) 57 | ), 58 | TouchableHighlight(style = styles.wrapper, onPress = a5)( 59 | View(style = styles.button)( 60 | Text()("Alert with too many buttons") 61 | ) 62 | ) 63 | ) 64 | ) 65 | ) 66 | }).buildNative 67 | 68 | object styles extends NativeStyleSheet { 69 | val alertsContainer = style(backgroundColor := "white", 70 | padding := 20) 71 | val wrapper = style(borderRadius := 5, marginBottom := 5) 72 | val button = style(backgroundColor := "#eeeeee", padding := 10) 73 | } 74 | 75 | override def description: String = "iOS alerts and action sheets" 76 | } 77 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/apis/AppStateIOSExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.apis 2 | 3 | import chandu0101.scalajs.rn 4 | import chandu0101.scalajs.rn.ReactNativeComponentB 5 | import chandu0101.scalajs.rn.components._ 6 | import chandu0101.scalajs.rn.examples.uiexplorer.{UIExample, UIExplorerBlock, UIExplorerPage} 7 | import japgolly.scalajs.react.BackendScope 8 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 9 | 10 | import scala.scalajs.js 11 | 12 | object AppStateIOSExample extends UIExample { 13 | 14 | val AppSateIOS = rn.ReactNative.AppStateIOS 15 | 16 | case class State(appState : String = AppSateIOS.currentState.get ,previousAppSates : js.Array[String] = js.Array()) 17 | 18 | class Backend(t: BackendScope[_, State]) { 19 | val handleAppStateChange = (appState : String) => { 20 | t.modState(s => s.copy(appState,s.previousAppSates.+:(appState))) 21 | } 22 | } 23 | 24 | val AppStateSubscription = ReactNativeComponentB[Boolean]("AppStateSubscription") 25 | .initialState(State()) 26 | .backend(new Backend(_)) 27 | .render((P,S,B) => { 28 | View()( 29 | if(P) Text()(S.appState) 30 | else Text()(S.previousAppSates.mkString(",")) 31 | ) 32 | }) 33 | .componentDidMount(scope => AppSateIOS.addEventListener("change",scope.backend.handleAppStateChange)) 34 | .componentWillUnmount(scope => AppSateIOS.removeEventListener("change",scope.backend.handleAppStateChange)) 35 | .build 36 | 37 | 38 | val component = ReactNativeComponentB[Unit]("AppStateIOSExample") 39 | .render(P => { 40 | UIExplorerPage( 41 | UIExplorerBlock("AppStateIOS.currentState")( 42 | Text()(AppSateIOS.currentState.get) 43 | ), 44 | UIExplorerBlock("Subscribed AppStateIOS:")( 45 | AppStateSubscription(true) 46 | ), 47 | UIExplorerBlock("Previous states:")( 48 | AppStateSubscription(false) 49 | ) 50 | ) 51 | }).buildNative 52 | 53 | object styles extends NativeStyleSheet { 54 | 55 | 56 | } 57 | 58 | override def title: String = "AppStateIOS" 59 | 60 | override def description: String = "iOS app background status" 61 | } 62 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/apis/AsyncStorageExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.apis 2 | 3 | import chandu0101.scalajs.rn.ReactNativeComponentB 4 | import chandu0101.scalajs.rn.apis.{AsyncStorage, AsyncStorageException} 5 | import chandu0101.scalajs.rn.components._ 6 | import chandu0101.scalajs.rn.examples.uiexplorer.{UIExample, UIExplorerBlock, UIExplorerPage} 7 | import japgolly.scalajs.react.BackendScope 8 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 9 | 10 | import scala.async.Async._ 11 | import scala.concurrent.ExecutionContext.Implicits.global 12 | import scala.scalajs.js 13 | 14 | object AsyncStorageExample extends UIExample { 15 | 16 | val STORAGE_KEY = "@AsyncStorageExample:key" 17 | val COLORS = js.Array("red", "orange", "yellow", "green", "blue") 18 | 19 | case class State(selectedValue: String = COLORS.head, messages: js.Array[String] = js.Array()) 20 | 21 | class Backend(t: BackendScope[_, State]) { 22 | 23 | def appendMessage(message: String) = { 24 | t.modState(s => s.copy(messages = s.messages.+:(message))) 25 | } 26 | 27 | val saveError: PartialFunction[Throwable, _] = { 28 | case (ex: Throwable) => { 29 | appendMessage(s"AsyncStorage Error ${ex.asInstanceOf[AsyncStorageException].err.message.toString}") 30 | } 31 | } 32 | 33 | def onValueChange(selectedValue: String) : Unit = { 34 | t.modState(_.copy(selectedValue = selectedValue)) 35 | async { 36 | val result = await(AsyncStorage.setItem(STORAGE_KEY, selectedValue)) 37 | appendMessage(s"Saved selection to disk ${selectedValue}") 38 | }.recover(saveError) 39 | } 40 | 41 | def removeStorage : Unit = async{ 42 | val result = await(AsyncStorage.removeItem(STORAGE_KEY)) 43 | appendMessage(s"Selection Removed from Disk") 44 | }.recover(saveError) 45 | } 46 | 47 | val component = ReactNativeComponentB[Unit]("AsyncStorageExample") 48 | .initialState(State()) 49 | .backend(new Backend(_)) 50 | .render((P, S, B) => { 51 | UIExplorerPage( 52 | UIExplorerBlock("Basics - getItem, setItem, removeItem")( 53 | View()( 54 | PickerIOS(selectedValue = S.selectedValue,onValueChange = B.onValueChange _)( 55 | COLORS.map(v => PickerItemIOS(key = v , value = v,label = v)) 56 | ), 57 | Text()("Selected : ", 58 | Text(style = styles.getColorStyle(S.selectedValue))(S.selectedValue) 59 | ), 60 | Text()(" "), 61 | Text(onPress = B.removeStorage _)("Press here to remove from storage"), 62 | Text()(" "), 63 | Text()("Messages : "), 64 | S.messages.map(m => Text()(m)) 65 | ) 66 | ) 67 | ) 68 | }).componentDidMount(scope => { 69 | async { 70 | val result = await(AsyncStorage.getItem(STORAGE_KEY)) 71 | if (result != null) { 72 | scope.modState(_.copy(selectedValue = result)) 73 | scope.backend.appendMessage(s"Recovered selection from disk : ${result}") 74 | } else { 75 | scope.backend.appendMessage(s"Initialized with no selection on disk") 76 | } 77 | }.recover(scope.backend.saveError) 78 | }) 79 | .buildNative 80 | 81 | object styles extends NativeStyleSheet { 82 | 83 | def getColorStyle(c : String) = style(color := c) 84 | } 85 | 86 | override def title: String = "AsyncStorage" 87 | 88 | override def description: String = "Asynchronous local disk storage." 89 | } 90 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/apis/CameraRollView.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.apis 2 | 3 | import chandu0101.scalajs.rn._ 4 | import chandu0101.scalajs.rn.components._ 5 | import japgolly.scalajs.react.BackendScope 6 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 7 | 8 | import scala.scalajs.js 9 | import scala.scalajs.js.JSConverters.genTravConvertible2JSRichGenTrav 10 | 11 | 12 | object CameraRollView { 13 | 14 | type CImage = js.Dynamic 15 | 16 | 17 | def renderImage(asset : CImage) = { 18 | Image(source = ImageSource.fromJson(asset.node.image) ,style = styles.image) 19 | } 20 | 21 | def rowHasChanged(r1 : js.Array[CImage] ,r2 : js.Array[CImage]) = { 22 | r1.length != r2.length || r1.zipWithIndex.forall { case (image,index) => r2(index) == image} 23 | } 24 | 25 | case class State(assets : js.Array[CImage] = js.Array(),groupType : String ,lastCursor : String = null,noMore : Boolean = false,loadingMore : Boolean = false, dataSource: ListViewDataSource[js.Array[CImage]] = createListViewDataSource(rowHasChanged = rowHasChanged)) 26 | 27 | class Backend(t: BackendScope[Props, State]) { 28 | 29 | /** 30 | * This should be called when the image renderer is changed to tell the 31 | * component to re-render its assets. 32 | */ 33 | def rendererChanged = { 34 | val ds : ListViewDataSource[js.Array[CImage]] = createListViewDataSource(rowHasChanged = rowHasChanged) 35 | val rows = t.state.assets.grouped(t.props.imagesPerRow).toJSArray 36 | t.modState(_.copy(dataSource = ds.cloneWithRows(rows))) 37 | } 38 | 39 | def appendAssets(data : js.Dynamic) = { 40 | var assets = data.edges.asInstanceOf[js.Array[CImage]] 41 | var noMore : Boolean = false 42 | if(js.isUndefined(data.page_info.has_next_page) || !data.page_info.has_next_page.asInstanceOf[Boolean]) noMore = true 43 | if(assets.length > 0) { 44 | assets ++= t.state.assets 45 | t.modState(s => s.copy( 46 | noMore = noMore, 47 | loadingMore = false, 48 | lastCursor = data.page_info.end_cursor.toString, 49 | assets = assets, 50 | dataSource = s.dataSource.cloneWithRows(assets.grouped(t.props.batchSize).toJSArray) 51 | )) 52 | } else { 53 | t.modState(_.copy(loadingMore = false,noMore = noMore )) 54 | } 55 | 56 | } 57 | } 58 | 59 | val component = ReactNativeComponentB[Props]("CameraRollView") 60 | .render(P => { 61 | View()() 62 | }).build 63 | 64 | 65 | object styles extends NativeStyleSheet { 66 | val row = style(flexDirection.row, 67 | flex := 1) 68 | 69 | val url = style(fontSize := 9, 70 | marginBottom := 14) 71 | 72 | val image = style(margin := 4, 73 | width := 150, 74 | height := 150) 75 | 76 | val info = style(flex := 1) 77 | 78 | val container = style(flex := 1) 79 | 80 | } 81 | 82 | case class Props(groupType :String = "SavedPhotos" ,batchSize : Int = 5,imagesPerRow : Int = 1,renderImage : CImage => _ = renderImage) 83 | 84 | def apply(props : Props ,key : js.Any = {},ref : js.UndefOr[String] = "") = component.set(key,ref)(props) 85 | 86 | 87 | } 88 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/apis/GeoLocationExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.apis 2 | 3 | import chandu0101.scalajs.rn.ReactNativeComponentB 4 | import chandu0101.scalajs.rn.components.{Text, View} 5 | import chandu0101.scalajs.rn.examples.uiexplorer.{UIExample, UIExplorerBlock, UIExplorerPage} 6 | import japgolly.scalajs.react.BackendScope 7 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 8 | import org.scalajs.dom 9 | import org.scalajs.dom.raw.{Position, PositionError} 10 | 11 | import scala.scalajs.js.JSON 12 | 13 | 14 | object GeoLocationExample extends UIExample { 15 | 16 | case class State(initialPoistion : Position = null,lastPosition : Position = null ) 17 | 18 | class Backend(t: BackendScope[_, State]) { 19 | 20 | var watchID : Int = 0 21 | 22 | } 23 | 24 | val component = ReactNativeComponentB[Unit]("GeoLocationExample") 25 | .initialState(State()) 26 | .backend(new Backend(_)) 27 | .render((P,S,B) => { 28 | UIExplorerPage( 29 | UIExplorerBlock("navigator.geolocation")( 30 | View()( 31 | Text()( 32 | Text(style = styles.title)("Initial Position : "), 33 | JSON.stringify(S.initialPoistion) 34 | ), 35 | Text()( 36 | Text(style = styles.title)("Current Position : "), 37 | JSON.stringify(S.lastPosition) 38 | ) 39 | ) 40 | ) 41 | ) 42 | }) 43 | .componentDidMount(scope => { 44 | dom.window.navigator.geolocation.getCurrentPosition((pos : Position) => { 45 | scope.modState(_.copy(initialPoistion = pos)) 46 | },(error : PositionError) => println(s"Error getting geo data ${error}")) 47 | scope.backend.watchID = dom.window.navigator.geolocation.watchPosition( 48 | (pos : Position) => scope.modState(_.copy(lastPosition = pos)) 49 | ) 50 | }) 51 | .componentWillMount(scope => { 52 | dom.window.navigator.geolocation.clearWatch(scope.backend.watchID) 53 | }) 54 | .buildNative 55 | 56 | object styles extends NativeStyleSheet { 57 | val title = style(fontWeight._500) 58 | 59 | } 60 | 61 | override def title: String = "Geolocation" 62 | 63 | override def description: String = "Examples of using the Geolocation API." 64 | } 65 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/apis/LayoutExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.apis 2 | 3 | import chandu0101.scalajs.rn.ReactNativeComponentB 4 | import chandu0101.scalajs.rn.components._ 5 | import chandu0101.scalajs.rn.examples.uiexplorer.UIExample 6 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 7 | 8 | object LayoutExample extends UIExample { 9 | 10 | val component = ReactNativeComponentB[Unit]("LayoutExample") 11 | .render(P => { 12 | View()() 13 | }).buildNative 14 | 15 | object styles extends NativeStyleSheet { 16 | 17 | 18 | } 19 | 20 | override def title: String = "Layout - Flexbox" 21 | 22 | override def description: String = "Examples of using the flexbox API to layout views." 23 | 24 | } 25 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/apis/NetInfoExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.apis 2 | 3 | import chandu0101.scalajs.rn.components._ 4 | import chandu0101.scalajs.rn.examples.uiexplorer.{UIExample, UIExplorerBlock, UIExplorerPage} 5 | import chandu0101.scalajs.rn.{ReactNative, ReactNativeComponentB} 6 | import japgolly.scalajs.react.BackendScope 7 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 8 | 9 | 10 | object NetInfoExample extends UIExample { 11 | 12 | val NetInfo = ReactNative.NetInfo 13 | 14 | case class State1(isConnected: Boolean = false) 15 | 16 | class Backend1(t: BackendScope[_, State1]) { 17 | 18 | val connectivityHandler = (c: Boolean) => { 19 | t.modState(_.copy(isConnected = c)) 20 | } 21 | 22 | 23 | } 24 | 25 | val IsConnected = ReactNativeComponentB[Unit]("IsConnected") 26 | .initialState(State1()) 27 | .backend(new Backend1(_)) 28 | .render((P, S, B) => { 29 | View()( 30 | Text()(if (S.isConnected) "Online " else "Offline") 31 | ) 32 | }) 33 | .componentDidMount(scope => { 34 | NetInfo.isConnected.addEventListener("change", scope.backend.connectivityHandler) 35 | NetInfo.isConnected.fetch().done( 36 | (isConnected: Boolean) => { 37 | scope.modState(_.copy(isConnected = isConnected)) 38 | } 39 | ) 40 | }) 41 | .componentWillUnmount(scope => NetInfo.isConnected.removeEventListener("change", scope.backend.connectivityHandler)) 42 | .buildU 43 | 44 | 45 | val component = ReactNativeComponentB[Unit]("WebViewExample") 46 | .render(P => { 47 | UIExplorerPage( 48 | UIExplorerBlock("Asyncronously load and observe connectivity")( 49 | IsConnected() 50 | ) 51 | ) 52 | }).buildNative 53 | 54 | object styles extends NativeStyleSheet { 55 | 56 | 57 | } 58 | 59 | override def title: String = "NetInfo" 60 | 61 | override def description: String = "Monitor network status" 62 | } 63 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/apis/PushNotificationIOSExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.apis 2 | 3 | import chandu0101.scalajs.rn 4 | import chandu0101.scalajs.rn.ReactNativeComponentB 5 | import chandu0101.scalajs.rn.components._ 6 | import chandu0101.scalajs.rn.examples.uiexplorer.{UIExample, UIExplorerBlock, UIExplorerPage} 7 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 8 | 9 | object PushNotificationIOSExample extends UIExample { 10 | 11 | val PushNotificationIOS = rn.ReactNative.PushNotificationIOS 12 | 13 | val Button = ReactNativeComponentB[ButtonProps]("Button") 14 | .render( P => { 15 | TouchableHighlight(underlayColor = "white", 16 | style = styles.button, 17 | onPress = P.onPress)( 18 | Text(style = styles.buttonLabel)(P.label) 19 | ) 20 | }).build 21 | 22 | case class ButtonProps(label : String,onPress : () => Unit) 23 | 24 | val component = ReactNativeComponentB[Unit]("PushNotificationIOSExample") 25 | .render(P => { 26 | UIExplorerPage( 27 | UIExplorerBlock("Badge Number")( 28 | View()( 29 | Button(ButtonProps("Set app's icon badge to 42",() => PushNotificationIOS.setApplicationIconBadgeNumber(42) )), 30 | Button(ButtonProps("Clear app's icon badge",() => PushNotificationIOS.setApplicationIconBadgeNumber(0) )) 31 | ) 32 | ) 33 | ) 34 | }).buildNative 35 | 36 | object styles extends NativeStyleSheet { 37 | 38 | val button = style(padding := 10, 39 | alignItems.center, 40 | justifyContent.center) 41 | 42 | val buttonLabel = style(color := "blue") 43 | } 44 | 45 | override def title: String = "PushNotificationIOS" 46 | 47 | override def description: String = "Apple PushNotification and badge value" 48 | } 49 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/apis/StatusBarIOSEXample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.apis 2 | 3 | import chandu0101.scalajs.rn.ReactNativeComponentB 4 | import chandu0101.scalajs.rn.components._ 5 | import chandu0101.scalajs.rn.examples.uiexplorer.UIExample 6 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 7 | 8 | 9 | object StatusBarIOSExample extends UIExample { 10 | 11 | val component = ReactNativeComponentB[Unit]("StatusBarIOSExample") 12 | .render(P => { 13 | View()() 14 | }).buildNative 15 | 16 | object styles extends NativeStyleSheet { 17 | val wrapper = style( 18 | borderRadius := 5, 19 | marginBottom := 5 20 | ) 21 | 22 | val button = style( 23 | backgroundColor := "#eeeeee", 24 | padding := 10 25 | ) 26 | 27 | } 28 | override def title: String = "StatusBarIOS" 29 | 30 | override def description: String = "Module for controlling iOS status bar" 31 | } 32 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/components/ActivityIndicatorIOSExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.components 2 | 3 | import chandu0101.scalajs.rn.ReactNativeComponentB 4 | import chandu0101.scalajs.rn.components._ 5 | import chandu0101.scalajs.rn.examples.uiexplorer.{UIExample, UIExplorerBlock, UIExplorerPage} 6 | import chandu0101.scalajs.rn.extras.OnUnmountNative 7 | import chandu0101.scalajs.rn.mixins.TimerMixinNative 8 | import japgolly.scalajs.react.BackendScope 9 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 10 | 11 | object ActivityIndicatorIOSExample extends UIExample { 12 | 13 | case class State(animating: Boolean = true) 14 | 15 | class Backend(t: BackendScope[_, State]) extends TimerMixinNative { 16 | 17 | def setToggleTimeout: Unit = setTimeout(() => { 18 | t.modState(s => s.copy(animating = !s.animating)) 19 | setToggleTimeout 20 | }, 1200) 21 | } 22 | 23 | 24 | val ToggleAnimatingActivityIndicator = ReactNativeComponentB[Unit]("ToggleAnimatingActivityIndicator") 25 | .initialState(State()) 26 | .backend(new Backend(_)) 27 | .render((P, S, B) => { 28 | ActivityIndicatorIOS(animating = S.animating, 29 | style = styles.animating, 30 | size = ActivityIndicatorIOSSize.LARGE) 31 | }) 32 | .componentDidMount(scope => scope.backend.setToggleTimeout) 33 | .configure(OnUnmountNative.install) 34 | .buildU 35 | 36 | val component = ReactNativeComponentB[Unit]("ActivityIndicatorIOSExample") 37 | .render(P => { 38 | UIExplorerPage( 39 | UIExplorerBlock("Default white")( 40 | ActivityIndicatorIOS(style = styles.default, color = "white") 41 | ), 42 | UIExplorerBlock("Gray")( 43 | ActivityIndicatorIOS(style = styles.default) 44 | ), 45 | UIExplorerBlock("Large")( 46 | ActivityIndicatorIOS(style = styles.default, 47 | color = "white", 48 | size = ActivityIndicatorIOSSize.LARGE) 49 | ), 50 | UIExplorerBlock("Large custom colors")( 51 | View(style = styles.horizontal)( 52 | ActivityIndicatorIOS( 53 | key = "3", 54 | color = "#00aa00", 55 | size = ActivityIndicatorIOSSize.LARGE) 56 | ) 57 | ), 58 | UIExplorerBlock("Start/Stop")( 59 | ToggleAnimatingActivityIndicator() 60 | ) 61 | ) 62 | }) 63 | 64 | .buildNative 65 | 66 | object styles extends NativeStyleSheet { 67 | 68 | val centering = style( 69 | alignItems.center, 70 | justifyContent.center 71 | ) 72 | 73 | val gray = style(backgroundColor := "#cccccc") 74 | 75 | val horizontal = style(flexDirection.row, justifyContent.center) 76 | 77 | val default = styleE(centering, gray)(height := 40) 78 | 79 | val animating = styleE(centering)(height := 80) 80 | } 81 | 82 | override def title: String = "ActivityIndicatorIOS" 83 | 84 | override def description: String = "Animated loading indicators." 85 | } 86 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/components/DatePickerIOSExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.components 2 | 3 | import chandu0101.scalajs.rn.components._ 4 | import chandu0101.scalajs.rn.examples.uiexplorer.{UIExample, UIExplorerBlock, UIExplorerPage} 5 | import chandu0101.scalajs.rn.{NEvent, ReactNativeComponentB} 6 | import japgolly.scalajs.react.BackendScope 7 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 8 | 9 | import scala.scalajs.js 10 | import scala.scalajs.js.Date 11 | import scala.util.Try 12 | 13 | object DatePickerIOSExample extends UIExample { 14 | 15 | val Heading = ReactNativeComponentB[String]("Heading") 16 | .render(P => { 17 | View(style = styles.headingContainer)( 18 | Text(style = styles.heading)( 19 | P 20 | ) 21 | ) 22 | }).build 23 | 24 | val WithLabel = ReactNativeComponentB[String]("WithLabel") 25 | .render((P, C) => { 26 | View(style = styles.headingContainer)( 27 | View(style = styles.labelView)( 28 | Text(style = styles.heading)( 29 | P 30 | ), 31 | C 32 | ) 33 | 34 | ) 35 | }).build 36 | 37 | val x = (-1) * (new Date()).getTimezoneOffset() / 60 38 | 39 | case class State(date: js.Date, timeZoneOffsetInHours: Double) 40 | 41 | class Backend(t: BackendScope[_, State]) { 42 | def onDateChange(date: js.Date) = { 43 | t.modState(_.copy(date = date)) 44 | } 45 | 46 | def onTimezoneChange(event: NEvent) = { 47 | val offset = Try(event.nativeEvent.text.toString.toInt).toOption 48 | if (offset.isDefined) t.modState(_.copy(timeZoneOffsetInHours = offset.get)) 49 | } 50 | } 51 | 52 | val DatePickerExample = ReactNativeComponentB[js.Date]("DatePickerExample") 53 | .initialStateP(p => State(p, (-1) * (new Date()).getTimezoneOffset() / 60.0)) 54 | .backend(new Backend(_)) 55 | .render((P, S, B) => { 56 | View()( 57 | WithLabel("Value :", 58 | Text()(s"${S.date.toLocaleDateString()} ${S.date.toLocaleTimeString()}")), 59 | WithLabel("Timezone :", 60 | TextInput(style = styles.textInput, 61 | value = S.timeZoneOffsetInHours.toString, 62 | onChange = B.onTimezoneChange _)()), 63 | Heading("Date + TimePicker"), 64 | DatePickerIOS(date = S.date, 65 | mode = DatePickerIOSMode.DATE_TIME, timeZoneOffsetInMinutes = (S.timeZoneOffsetInHours * 60).toInt, 66 | onDateChange = B.onDateChange _), 67 | Heading("Date Picker"), 68 | DatePickerIOS(date = S.date, 69 | mode = DatePickerIOSMode.DATE, timeZoneOffsetInMinutes = (S.timeZoneOffsetInHours * 60).toInt, 70 | onDateChange = B.onDateChange _), 71 | Heading("Time picker 10-minute interval"), 72 | DatePickerIOS(date = S.date, 73 | mode = DatePickerIOSMode.TIME, 74 | timeZoneOffsetInMinutes = (S.timeZoneOffsetInHours * 60).toInt, 75 | onDateChange = B.onDateChange _, 76 | minuteInterval = MinuteInterval._10) 77 | 78 | ) 79 | }).build 80 | 81 | 82 | val component = ReactNativeComponentB[Unit]("DatePickerIOSExample") 83 | .render(P => { 84 | UIExplorerPage( 85 | UIExplorerBlock("DatePickerIOS")( 86 | DatePickerExample(new Date()) 87 | ) 88 | ) 89 | }).buildNative 90 | 91 | object styles extends NativeStyleSheet { 92 | 93 | val textInput = style(height := 26, 94 | width := 50, 95 | borderWidth := 0.5, 96 | borderColor := "#0f0f0f", 97 | padding := 4, 98 | fontSize := 13) 99 | 100 | val labelContainer = style(flexDirection.row, 101 | alignItems.center, 102 | marginVertical := 2) 103 | 104 | val labelView = style(marginRight := 10, 105 | paddingVertical := 2) 106 | 107 | val label = style(fontWeight._500) 108 | 109 | val headingContainer = style(padding := 4, 110 | backgroundColor := "#f6f7f8") 111 | 112 | val heading = style(fontWeight._500, fontSize := 14) 113 | 114 | } 115 | 116 | override def title: String = "DatePickerIOS" 117 | 118 | override def description: String = "Select dates and times using the native UIDatePicker." 119 | } 120 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/components/ListViewExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.components 2 | 3 | import chandu0101.scalajs.rn._ 4 | import chandu0101.scalajs.rn.components._ 5 | import chandu0101.scalajs.rn.examples.uiexplorer.{UIExplorerPage, UIExample} 6 | import japgolly.scalajs.react.BackendScope 7 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 8 | import scala.collection.mutable.Map 9 | import scala.scalajs.js 10 | 11 | 12 | object ListViewExample extends UIExample { 13 | 14 | val THUMB_URLS = js.Array("https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851549_767334479959628_274486868_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851561_767334496626293_1958532586_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851579_767334503292959_179092627_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851589_767334513292958_1747022277_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851563_767334559959620_1193692107_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851593_767334566626286_1953955109_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851591_767334523292957_797560749_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851567_767334529959623_843148472_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851548_767334489959627_794462220_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851575_767334539959622_441598241_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851573_767334549959621_534583464_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851583_767334573292952_1519550680_n.png") 15 | val LOREM_IPSUM = "Lorem ipsum dolor sit amet, ius ad pertinax oportere accommodare, an vix civibus corrumpit referrentur. Te nam case ludus inciderint, te mea facilisi adipiscing. Sea id integre luptatum. In tota sale consequuntur nec. Erat ocurreret mei ei. Eu paulo sapientem vulputate est, vel an accusam intellegam interesset. Nam eu stet pericula reprimique, ea vim illud modus, putant invidunt reprehendunt ne qui."; 16 | 17 | case class State(datasource : ListViewDataSource[String] = createListViewDataSource[String,js.Object](rowHasChanged = (r1,r2) => r1 != r2)) 18 | 19 | class Backend(t: BackendScope[_, State]) { 20 | 21 | val pressedData = scala.collection.mutable.Map[String,Boolean]().withDefaultValue(false) 22 | 23 | def genRows(pressedData : Map[String,Boolean]) = { 24 | val dataBlob = js.Array[String]() 25 | (1 to 100).toList.zipWithIndex.foreach { 26 | case (i,index) => { 27 | val pressedText = if(pressedData.getOrElse(index.toString,false)) "pressed" else "" 28 | dataBlob += s"Row $i $pressedText" 29 | } 30 | } 31 | dataBlob 32 | } 33 | 34 | 35 | def pressRow(rowID : String) = { 36 | pressedData.updated(rowID,pressedData(rowID)) 37 | t.modState(s => s.copy(s.datasource.cloneWithRows(genRows(pressedData)))) 38 | } 39 | 40 | def hashCode2(str : String) = { 41 | var hash = 15 42 | str.reverse.foreach( c => { 43 | hash = ((hash << 5) - hash) + c.toInt 44 | }) 45 | hash 46 | } 47 | 48 | def renderRow(rowData : String, sectionID : String,rowID : String) = { 49 | val rowHash = Math.abs(hashCode2(rowData)) 50 | val imageSource = ImageSource(uri = THUMB_URLS(rowHash % THUMB_URLS.length)) 51 | TouchableHighlight(onPress = () => pressRow(rowID))( 52 | View()( 53 | View(style = styles.row)( 54 | Image(style = styles.thumb , source = imageSource), 55 | Text(style = styles.text)( 56 | s"$rowData - ${LOREM_IPSUM.substring(0,rowHash % 301 + 10)}" 57 | ), 58 | View(style = styles.separator)() 59 | ) 60 | ) 61 | ) 62 | } 63 | 64 | val propsDynamic = t.propsDynamic 65 | } 66 | val component = ReactNativeComponentB[Unit]("ListViewExample") 67 | .initialState(State()) 68 | .backend(new Backend(_)) 69 | .render((P,S,B) => { 70 | View()( 71 | ListView(dataSource = S.datasource,renderRow = B.renderRow _) 72 | ) 73 | }) 74 | .componentWillMount(scope => scope.modState(s => s.copy(s.datasource.cloneWithRows(scope.backend.genRows(Map()))))) 75 | .buildNative 76 | 77 | object styles extends NativeStyleSheet { 78 | 79 | val row = style( 80 | flexDirection.row, 81 | justifyContent.center, 82 | padding := 10, 83 | backgroundColor := "#F6F6F6" 84 | ) 85 | 86 | val separator = style( 87 | height := 1, 88 | backgroundColor := "#F6F6F6" 89 | ) 90 | 91 | val thumb = style(width := 64, height := 64) 92 | 93 | val text = style(flex := 1) 94 | 95 | } 96 | 97 | override def title: String = "ListView - simple" 98 | 99 | override def description: String = "Performant, scrollable list of data." 100 | 101 | } 102 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/components/MapViewExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.components 2 | 3 | import chandu0101.scalajs.rn.components._ 4 | import chandu0101.scalajs.rn.examples.uiexplorer.{UIExample, UIExplorerBlock, UIExplorerPage} 5 | import chandu0101.scalajs.rn.{NEvent, ReactNativeComponentB} 6 | import japgolly.scalajs.react.BackendScope 7 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 8 | 9 | import scala.scalajs.js 10 | import scala.util.Try 11 | 12 | 13 | object MapViewExample extends UIExample { 14 | 15 | case class StateInput(region: MapViewRegion = MapViewRegion(0.0, 0.0, 0.0, 0.0)) 16 | 17 | class BackendInput(t: BackendScope[InputProps, StateInput]) { 18 | 19 | var region = MapViewRegion(0.0, 0.0, 0.0, 0.0) 20 | 21 | def getDouble(str: String) = { 22 | val doubleOption = Try(str.toDouble).toOption 23 | doubleOption.getOrElse(0.0) 24 | } 25 | 26 | def onChangeLatitude(e: NEvent) = { 27 | region = region.copy(latitude = getDouble(e.nativeEvent.text.toString)) 28 | } 29 | 30 | def onChangeLongitude(e: NEvent) = { 31 | region = region.copy(longitude = getDouble(e.nativeEvent.text.toString)) 32 | } 33 | 34 | def onChangeLatitudeDelta(e: NEvent) = { 35 | region = region.copy(latitudeDelta = getDouble(e.nativeEvent.text.toString)) 36 | } 37 | 38 | def onChangeLongitudeDelta(e: NEvent) = { 39 | region = region.copy(longitudeDelta = getDouble(e.nativeEvent.text.toString)) 40 | } 41 | 42 | def change : Unit = { 43 | t.modState(_.copy(region = region)) 44 | t.props.onChange(t.state.region) 45 | } 46 | } 47 | 48 | val MapRegionInput = ReactNativeComponentB[InputProps]("MapRegionInput") 49 | .initialState(StateInput()) 50 | .backend(new BackendInput(_)) 51 | .render((P, S, B) => { 52 | View()( 53 | View(style = styles.row)( 54 | Text()("Latitude"), 55 | TextInput(value = S.region.latitude.toString, 56 | style = styles.textInput, 57 | onChange = B.onChangeLatitude _, 58 | selectTextOnFocus = true)()), 59 | View(style = styles.row)( 60 | Text()("Longitude"), 61 | TextInput(value = S.region.longitude.toString, 62 | style = styles.textInput, 63 | onChange = B.onChangeLongitude _, 64 | selectTextOnFocus = true)()), 65 | View(style = styles.row)( 66 | Text()("Latitude delta"), 67 | TextInput(value = S.region.latitudeDelta.toString, 68 | style = styles.textInput, 69 | onChange = B.onChangeLatitudeDelta _, 70 | selectTextOnFocus = true)()), 71 | View(style = styles.row)( 72 | Text()("Longitude delta"), 73 | TextInput(value = S.region.longitudeDelta.toString, 74 | style = styles.textInput, 75 | onChange = B.onChangeLongitudeDelta _, 76 | selectTextOnFocus = true)() 77 | ), 78 | View(style = styles.changeButton)( 79 | Text(onPress = B.change _)("Change") 80 | ) 81 | ) 82 | }) 83 | .componentWillReceiveProps((scope, nextProps) => { 84 | val region = if (nextProps.region != null) nextProps.region 85 | else MapViewRegion(0.0, 0.0, 0.0, 0.0) 86 | scope.modState(_.copy(region = region)) 87 | }) 88 | .build 89 | 90 | case class InputProps(region: MapViewRegion, onChange: (MapViewRegion) => _) 91 | 92 | case class StateMap(mapRegion: MapViewRegion = MapViewRegion(0.0, 0.0, 0.0, 0.0), mapRegionInput: MapViewRegion = MapViewRegion(0.0, 0.0, 0.0, 0.0), annotations: Seq[MapViewAnnotation] = Seq(), isFirstLoad: Boolean = true) 93 | 94 | class BackendMap(t: BackendScope[_, StateMap]) { 95 | 96 | def getAnnotations(region: MapViewRegion) = { 97 | Seq(MapViewAnnotation(latitude = region.latitude, longitude = region.longitude, title = "You Are Here")) 98 | } 99 | 100 | def onRegionChange(region: MapViewRegion) = { 101 | t.modState(_.copy(mapRegionInput = region)) 102 | } 103 | 104 | def onRegionChangeComplete(region: MapViewRegion) = { 105 | if (t.state.isFirstLoad) t.modState(_.copy( 106 | mapRegionInput = region, 107 | annotations = getAnnotations(region), 108 | isFirstLoad = false 109 | )) 110 | } 111 | 112 | def onRegionInputChanged(region: MapViewRegion) = { 113 | t.modState(_.copy(mapRegion = region, mapRegionInput = region, annotations = getAnnotations(region))) 114 | } 115 | 116 | } 117 | 118 | val MapExample = ReactNativeComponentB[Unit]("MapExample") 119 | .initialState(StateMap()) 120 | .backend(new BackendMap(_)) 121 | .render((P, S, B) => { 122 | View()( 123 | MapView(style = styles.map, 124 | onRegionChange = B.onRegionChange _, 125 | onRegionChangeComplete = B.onRegionChangeComplete _, 126 | region = S.mapRegion, 127 | annotations = S.annotations 128 | ), 129 | MapRegionInput(InputProps(onChange = B.onRegionInputChanged _, region = S.mapRegionInput)) 130 | ) 131 | }).buildU 132 | 133 | val component = ReactNativeComponentB[Unit]("MapViewExample") 134 | .render(P => { 135 | UIExplorerPage( 136 | UIExplorerBlock("Map")( 137 | MapExample() 138 | ), 139 | UIExplorerBlock("Map shows user location")( 140 | MapView(style = styles.map, showsUserLocation = true) 141 | ) 142 | ) 143 | }).buildNative 144 | 145 | object styles extends NativeStyleSheet { 146 | 147 | val map = style(height := 150, 148 | margin := 10, 149 | borderWidth := 1, 150 | borderColor := "#000000") 151 | 152 | val row = style(flexDirection.row, 153 | justifyContent.spaceBetween) 154 | 155 | val textInput = style(width := 150, 156 | height := 20, 157 | borderWidth := 0.5, 158 | borderColor := "#aaaaaa", 159 | fontSize := 13, 160 | padding := 4) 161 | 162 | val changeButton = style( 163 | alignSelf.center, 164 | marginTop := 5, 165 | padding := 3, 166 | borderWidth := 0.5, 167 | borderColor := "#777777" 168 | ) 169 | 170 | } 171 | 172 | override def title: String = "MapView" 173 | 174 | override def description: String = "Base component to display maps" 175 | } 176 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/components/PickerIOSExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.components 2 | 3 | import chandu0101.scalajs.rn.ReactNativeComponentB 4 | import chandu0101.scalajs.rn.components._ 5 | import chandu0101.scalajs.rn.examples.uiexplorer.{UIExample, UIExplorerBlock, UIExplorerPage} 6 | import japgolly.scalajs.react.BackendScope 7 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 8 | 9 | import scala.scalajs.js 10 | import scala.scalajs.js.Dynamic.{literal => json} 11 | 12 | 13 | object PickerIOSExample extends UIExample { 14 | 15 | case class CarMake(name: String, models: js.Array[String]) 16 | 17 | case class State(carMake: String = "cadillac", modelIndex: Int = 3) 18 | 19 | class Backend(t: BackendScope[_, State]) { 20 | def handleCarMakeChange(carMake: String) = { 21 | t.modState(_.copy(carMake = carMake,modelIndex = 0)) 22 | } 23 | 24 | def handleCarModelChange(modelIndex: Int) = { 25 | t.modState(_.copy(modelIndex = modelIndex)) 26 | } 27 | } 28 | 29 | val component = ReactNativeComponentB[Unit]("PickerIOSExample") 30 | .initialState(State()) 31 | .backend(new Backend(_)) 32 | .render((P, S, B) => { 33 | val make = CAR_MAKES_AND_MODELS.selectDynamic(S.carMake) 34 | val selectionString = s"${make.name.toString} ${make.models.asInstanceOf[js.Array[String]]((S.modelIndex))}" 35 | UIExplorerPage( 36 | UIExplorerBlock("PickerIOS")( 37 | View()( 38 | Text()("Please choose a make for your car :"), 39 | PickerIOS(selectedValue = S.carMake, 40 | onValueChange = B.handleCarMakeChange _)( 41 | js.Object.keys(CAR_MAKES_AND_MODELS.asInstanceOf[js.Object]).map(key => { 42 | PickerItemIOS(key = key, value = key, label = CAR_MAKES_AND_MODELS.selectDynamic(key).name.toString) 43 | }) 44 | ), 45 | Text()(s"Please choose a model of ${make.name.toString} :"), 46 | PickerIOS(key = S.carMake, selectedValue = S.modelIndex, 47 | onValueChange = B.handleCarModelChange _)( 48 | CAR_MAKES_AND_MODELS.selectDynamic(S.carMake).models.asInstanceOf[js.Array[String]].zipWithIndex 49 | .map { 50 | case (modelName, index) => PickerItemIOS( 51 | key = s"${S.carMake}_${index.toString}", 52 | value = index, 53 | label = modelName 54 | ) 55 | } 56 | ), 57 | Text()(s"You selected : ${selectionString}") 58 | ) 59 | ) 60 | ) 61 | }).buildNative 62 | 63 | object styles extends NativeStyleSheet { 64 | 65 | 66 | } 67 | 68 | override def title: String = "PickerIOS" 69 | 70 | override def description: String = "Render lists of selectable options with UIPickerView." 71 | 72 | val CAR_MAKES_AND_MODELS = json( 73 | amc = json( 74 | name = "AMC", 75 | models = js.Array("AMX", "Concord", "Eagle", "Gremlin", "Matador", "Pacer") 76 | ), 77 | alfa = json( 78 | name = "Alfa-Romeo", 79 | models = js.Array("159", "4C", "Alfasud", "Brera", "GTV6", "Giulia", "MiTo", "Spider") 80 | ), 81 | aston = json( 82 | name = "Aston Martin", 83 | models = js.Array("DB5", "DB9", "DBS", "Rapide", "Vanquish", "Vantage") 84 | ), 85 | audi = json( 86 | name = "Audi", 87 | models = js.Array("90", "4000", "5000", "A3", "A4", "A5", "A6", "A7", "A8", "Q5", "Q7") 88 | ), 89 | austin = json( 90 | name = "Austin", 91 | models = js.Array("America", "Maestro", "Maxi", "Mini", "Montego", "Princess") 92 | ), 93 | borgward = json( 94 | name = "Borgward", 95 | models = js.Array("Hansa", "Isabella", "P100") 96 | ), 97 | buick = json( 98 | name = "Buick", 99 | models = js.Array("Electra", "LaCrosse", "LeSabre", "Park Avenue", "Regal", 100 | "Roadmaster", "Skylark") 101 | ), 102 | cadillac = json( 103 | name = "Cadillac", 104 | models = js.Array("Catera", "Cimarron", "Eldorado", "Fleetwood", "Sedan de Ville") 105 | ), 106 | chevrolet = json( 107 | name = "Chevrolet", 108 | models = js.Array("Astro", "Aveo", "Bel Air", "Captiva", "Cavalier", "Chevelle", 109 | "Corvair", "Corvette", "Cruze", "Nova", "SS", "Vega", "Volt") 110 | ) 111 | ) 112 | } 113 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/components/ScrollViewExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.components 2 | 3 | import chandu0101.scalajs.rn.ReactNativeComponentB 4 | import chandu0101.scalajs.rn.components._ 5 | import chandu0101.scalajs.rn.examples.uiexplorer.{UIExample, UIExplorerBlock, UIExplorerPage} 6 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 7 | 8 | import scala.scalajs.js 9 | 10 | object ScrollViewExample extends UIExample { 11 | 12 | val THUMBS = js.Array("https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851549_767334479959628_274486868_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851561_767334496626293_1958532586_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851579_767334503292959_179092627_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851589_767334513292958_1747022277_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851563_767334559959620_1193692107_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851593_767334566626286_1953955109_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851591_767334523292957_797560749_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851567_767334529959623_843148472_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851548_767334489959627_794462220_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851575_767334539959622_441598241_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851573_767334549959621_534583464_n.png", "https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851583_767334573292952_1519550680_n.png") 13 | 14 | val THUMB = ReactNativeComponentB[String]("THUMB") 15 | .render(P => { 16 | View(style = styles.button)( 17 | Image(style = styles.img, source = ImageSource(uri = P)) 18 | ) 19 | }) 20 | .shouldComponentUpdate((_, _, _) => false) 21 | .build 22 | 23 | val component = ReactNativeComponentB[Unit]("ScrollViewExample") 24 | .render(P => { 25 | UIExplorerPage( 26 | UIExplorerBlock("ScrollView Vertical")( 27 | ScrollView(style = styles.scrollView, 28 | contentInset = EdgeInsets(top = -50.0), 29 | scrollEventThrottle = 16, 30 | onScroll = () => println(s"on Scroll!"))( 31 | THUMBS.++(THUMBS).zipWithIndex.map { 32 | case (u, i) => THUMB.withKey(i)(u) 33 | } 34 | ) 35 | ), 36 | UIExplorerBlock("ScrollView horizontal")( 37 | ScrollView(style = styles.horizontalScrollView, 38 | horizontal = true, 39 | scrollEventThrottle = 16, 40 | contentInset = EdgeInsets(top = -50.0), 41 | onScroll = () => println(s"on Scroll!"))( 42 | THUMBS.++(THUMBS).zipWithIndex.map { 43 | case (u, i) => THUMB.withKey(i)(u) 44 | } 45 | ) 46 | ) 47 | ) 48 | }).buildNative 49 | 50 | object styles extends NativeStyleSheet { 51 | 52 | val scrollView = style( 53 | backgroundColor := "#6A85B1", 54 | height := 300 55 | ) 56 | val horizontalScrollView = styleE(scrollView)(height := 120) 57 | val containerPage = style(height := 50, 58 | width := 50, 59 | backgroundColor := "#527FE4", padding := 5) 60 | 61 | val text = style(fontSize := 20, 62 | color := "#888888", 63 | left := 80, 64 | top := 20, 65 | height := 40) 66 | 67 | val button = style(margin := 7, 68 | padding := 5, 69 | alignItems.center, 70 | backgroundColor := "#eaeaea", 71 | borderRadius := 3) 72 | 73 | val buttonContents = style(flexDirection.row, 74 | width := 64, 75 | height := 64) 76 | 77 | val img = style(width := 64, height := 64) 78 | 79 | 80 | } 81 | 82 | override def title: String = "ScrollView" 83 | 84 | override def description: String = "Component that enables scrolling through child components" 85 | } 86 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/components/SegmentedControlExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.components 2 | 3 | import chandu0101.scalajs.rn.components.{SegmentedControlIOS, Text, View} 4 | import chandu0101.scalajs.rn.examples.uiexplorer.{UIExample, UIExplorerBlock, UIExplorerPage} 5 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 6 | import chandu0101.scalajs.rn.{NEvent, ReactNativeComponentB} 7 | import japgolly.scalajs.react._ 8 | 9 | import scala.scalajs.js 10 | import scala.scalajs.js.Dynamic.{literal => json} 11 | import scala.scalajs.js.JSON 12 | 13 | 14 | object SegmentedControlExample extends UIExample { 15 | 16 | val BasicSegmentedControlExample = ReactNativeComponentB[Unit]("BasicSegmentedControlExample") 17 | .render(P => { 18 | View()( 19 | SegmentedControlIOS(values = Seq("One", "Two")) 20 | ) 21 | }).buildU 22 | 23 | val PreSelectedSegmentedControlExample = ReactNativeComponentB[Unit]("PreSelectedSegmentedControlExample") 24 | .render(P => { 25 | View()( 26 | SegmentedControlIOS(values = Seq("One", "Two"), selectedIndex = 0) 27 | ) 28 | }).buildU 29 | 30 | val MomentarySegmentedControlExample = ReactNativeComponentB[Unit]("MomentarySegmentedControlExample") 31 | .render(P => { 32 | View()( 33 | SegmentedControlIOS(values = Seq("One", "Two"), momentary = true) 34 | ) 35 | }).buildU 36 | 37 | val DisabledSegmentedControlExample = ReactNativeComponentB[Unit]("DisabledSegmentedControlExample") 38 | .render(P => { 39 | View()( 40 | SegmentedControlIOS(values = Seq("One", "Two"), enabled = false, selectedIndex = 0) 41 | ) 42 | }).buildU 43 | 44 | val ColorSegmentedControlExample = ReactNativeComponentB[Unit]("ColorSegmentedControlExample") 45 | .render(P => { 46 | View()( 47 | SegmentedControlIOS(values = Seq("One", "Two"), selectedIndex = 0, tintColor = "#ff0000") 48 | ) 49 | }).buildU 50 | 51 | case class State(values : Seq[String] = Seq("One", "Two","Three","Four"), value: String = "One", index: Int = 0) 52 | 53 | class Backend(t: BackendScope[_, State]) { 54 | def onChange(e: js.Dynamic) = { 55 | t.modState(_.copy(index = e.nativeEvent.selectedSegmentIndex.toString.toInt)) 56 | } 57 | 58 | def onValueChange(value: String) = t.modState(_.copy(value = value)) 59 | } 60 | 61 | val EventSegmentedControlExample = ReactNativeComponentB[Unit]("EventSegmentedControlExample") 62 | .initialState(State()) 63 | .backend(new Backend(_)) 64 | .render((P, S, B) => { 65 | View()( 66 | Text(style = styles.text)(s"Value : ${S.value}"), 67 | Text(style = styles.text)(s"Index : ${S.values.indexOf(S.value)}"), 68 | SegmentedControlIOS(values = S.values, selectedIndex = S.index, 69 | tintColor = "#cf00a2", 70 | onChange = B.onChange _, 71 | onValueChange = B.onValueChange _ 72 | ) 73 | ) 74 | }).buildU 75 | 76 | 77 | val component = ReactNativeComponentB[Unit]("SegmentedControlExample") 78 | .render(P => { 79 | UIExplorerPage( 80 | View()( 81 | UIExplorerBlock("Segmented controls can have values")( 82 | BasicSegmentedControlExample() 83 | ), 84 | UIExplorerBlock("Segmented controls can have a pre-selected value")( 85 | PreSelectedSegmentedControlExample() 86 | ), 87 | UIExplorerBlock("Segmented controls can be momentary")( 88 | MomentarySegmentedControlExample() 89 | ), 90 | UIExplorerBlock("Segmented controls can be disabled")( 91 | DisabledSegmentedControlExample() 92 | ), 93 | UIExplorerBlock("Custom colors can be provided")( 94 | ColorSegmentedControlExample() 95 | ), 96 | UIExplorerBlock("Change events can be detected")( 97 | EventSegmentedControlExample() 98 | ) 99 | ) 100 | ) 101 | 102 | }).buildNative 103 | 104 | 105 | object styles extends NativeStyleSheet { 106 | 107 | val text = style(fontSize := 14, 108 | textAlign.center, 109 | fontWeight._500, 110 | margin := 10) 111 | 112 | 113 | } 114 | 115 | 116 | override def title: String = "SegmentedControlIOS" 117 | 118 | override def description: String = "Native segmented control" 119 | } 120 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/components/SliderIOSExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.components 2 | 3 | import chandu0101.scalajs.rn.ReactNativeComponentB 4 | import chandu0101.scalajs.rn.components._ 5 | import chandu0101.scalajs.rn.examples.uiexplorer.{UIExample, UIExplorerBlock, UIExplorerPage} 6 | import japgolly.scalajs.react.BackendScope 7 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 8 | 9 | object SliderIOSExample extends UIExample { 10 | 11 | case class State(value: Double = 0) 12 | 13 | class Backend(t: BackendScope[_, State]) { 14 | def handleValueChnage(value: Double): Unit = { 15 | t.modState(_.copy(value = value)) 16 | } 17 | } 18 | 19 | val component = ReactNativeComponentB[Unit]("SliderIOSExample") 20 | .initialState(State()) 21 | .backend(new Backend(_)) 22 | .render((P,S,B) => { 23 | UIExplorerPage( 24 | UIExplorerBlock("SliderIOS")( 25 | View()( 26 | Text(style = styles.text)( 27 | S.value 28 | ), 29 | SliderIOS(style = styles.slider, 30 | onValueChange = B.handleValueChnage _) 31 | ) 32 | ) 33 | ) 34 | 35 | }).buildNative 36 | 37 | object styles extends NativeStyleSheet { 38 | val slider = style(height := 10, margin := 10) 39 | 40 | val text = style( 41 | fontSize := 14, 42 | textAlign.center, 43 | fontWeight._500, 44 | margin := 10 45 | ) 46 | 47 | } 48 | 49 | override def title: String = "SliderIOS" 50 | 51 | override def description: String = "Slider Example" 52 | } 53 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/components/SwitchIOSExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.components 2 | 3 | import chandu0101.scalajs.rn.ReactNativeComponentB 4 | import chandu0101.scalajs.rn.components._ 5 | import chandu0101.scalajs.rn.examples.uiexplorer.{UIExample, UIExplorerBlock, UIExplorerPage} 6 | import japgolly.scalajs.react.BackendScope 7 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 8 | 9 | object SwitchIOSExample extends UIExample { 10 | 11 | case class BasicState(trueSwitchIsOn: Boolean = true, falseSwitchIsOn: Boolean = false) 12 | 13 | class Backend(t: BackendScope[_, BasicState]) { 14 | 15 | def handleFalseSwitch(value: Boolean) = { 16 | t.modState(_.copy(falseSwitchIsOn = value)) 17 | } 18 | 19 | def handleTrueSwitch(value: Boolean) = { 20 | t.modState(_.copy(trueSwitchIsOn = value)) 21 | } 22 | } 23 | 24 | val BasicSwitchExample = ReactNativeComponentB[Unit]("BasicSwitchExample") 25 | .initialState(BasicState()) 26 | .backend(new Backend(_)) 27 | .render((P, S, B) => { 28 | View()( 29 | SwitchIOS(onValueChange = B.handleFalseSwitch _, 30 | style = styles.basicFalseSwitch, 31 | value = S.falseSwitchIsOn), 32 | SwitchIOS(onValueChange = B.handleTrueSwitch _, 33 | value = S.trueSwitchIsOn) 34 | ) 35 | }).buildU 36 | 37 | 38 | val DisabledSwitchExample = ReactNativeComponentB[Unit]("DisabledSwitchExample") 39 | .render(P => { 40 | View()( 41 | SwitchIOS(disabled = true, style = styles.basicFalseSwitch, value = true), 42 | SwitchIOS(disabled = true, 43 | value = false) 44 | ) 45 | }).buildU 46 | 47 | val ColorSwitchExample = ReactNativeComponentB[Unit]("ColorSwitchExample") 48 | .initialState(BasicState()) 49 | .backend(new Backend(_)) 50 | .render((P, S, B) => { 51 | View()( 52 | SwitchIOS(onValueChange = B.handleFalseSwitch _, 53 | style = styles.basicFalseSwitch, 54 | onTintColor = "#00ff00", 55 | tintColor = "#ff0000", 56 | value = S.falseSwitchIsOn), 57 | SwitchIOS(onValueChange = B.handleTrueSwitch _, 58 | onTintColor = "#00ff00", 59 | tintColor = "#ff0000", 60 | value = S.trueSwitchIsOn) 61 | ) 62 | }).buildU 63 | 64 | case class State(eventSwitchIsOn: Boolean = false, eventSwitchRegressionIsOn: Boolean = true) 65 | 66 | class Backend2(t: BackendScope[_, State]) { 67 | 68 | def handleEventSwitch(value: Boolean) = { 69 | t.modState(_.copy(eventSwitchIsOn = value)) 70 | } 71 | 72 | def handleEventSwitchRegression(value: Boolean) = { 73 | t.modState(_.copy(eventSwitchRegressionIsOn = value)) 74 | } 75 | 76 | } 77 | 78 | val EventSwitchExample = ReactNativeComponentB[Unit]("EventSwitchExample") 79 | .initialState(State()) 80 | .backend(new Backend2(_)) 81 | .render((P, S, B) => { 82 | View(style = styles.eventsContainer)( 83 | View()( 84 | SwitchIOS(onValueChange = B.handleEventSwitch _, 85 | style = styles.basicFalseSwitch, 86 | value = S.eventSwitchIsOn), 87 | SwitchIOS(onValueChange = B.handleEventSwitch _, 88 | style = styles.basicFalseSwitch, 89 | value = S.eventSwitchIsOn), 90 | Text()(if (S.eventSwitchIsOn) "On" else "Off") 91 | ), 92 | View()( 93 | SwitchIOS(onValueChange = B.handleEventSwitchRegression _, 94 | style = styles.basicFalseSwitch, 95 | value = S.eventSwitchRegressionIsOn), 96 | SwitchIOS(onValueChange = B.handleEventSwitchRegression _, 97 | style = styles.basicFalseSwitch, 98 | value = S.eventSwitchRegressionIsOn), 99 | Text()(if (S.eventSwitchRegressionIsOn) "On" else "Off") 100 | ) 101 | ) 102 | }).buildU 103 | 104 | 105 | val component = ReactNativeComponentB[Unit]("WebViewExample") 106 | .render(P => { 107 | UIExplorerPage( 108 | UIExplorerBlock("Basic Switch")( 109 | BasicSwitchExample() 110 | ), 111 | UIExplorerBlock("Disabled Switches")( 112 | DisabledSwitchExample() 113 | ), 114 | UIExplorerBlock("Colored Switches")( 115 | ColorSwitchExample() 116 | ), 117 | UIExplorerBlock("Change events can be detected")( 118 | EventSwitchExample() 119 | ) 120 | ) 121 | }).buildNative 122 | 123 | object styles extends NativeStyleSheet { 124 | 125 | val basicFalseSwitch = style(marginBottom := 10) 126 | 127 | val eventsContainer = style(flexDirection.row, 128 | justifyContent.spaceAround) 129 | } 130 | 131 | override def title: String = "SwitchIOSExample" 132 | 133 | override def description: String = "Native boolean input" 134 | } 135 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/components/TabBarIOSExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.components 2 | 3 | import chandu0101.scalajs.rn.ReactNativeComponentB 4 | import chandu0101.scalajs.rn.components._ 5 | import chandu0101.scalajs.rn.examples.uiexplorer.UIExample 6 | import japgolly.scalajs.react.BackendScope 7 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 8 | 9 | import scala.scalajs.js 10 | import scala.scalajs.js.Dynamic.{literal => json} 11 | 12 | 13 | object TabBarIOSExample extends UIExample{ 14 | 15 | val BLUE_TAB = "blueTab" 16 | val RED_TAB = "redTab" 17 | val GREEN_TAB = "greenTab" 18 | 19 | case class State(selectedTab: String = BLUE_TAB, notifCount: Int = 0, presses: Int = 0) 20 | 21 | class Backend(t: BackendScope[_, State]) { 22 | 23 | def renderContent(color : String,pageText : String) = { 24 | View(style = js.Array(styles.tabContent,json(backgroundColor = color)))( 25 | Text(style = styles.tabText)(pageText), 26 | Text(style = styles.tabText)(s"${t.state.presses} re-renders of this tab") 27 | ) 28 | } 29 | 30 | def getImage(imageUri : String) = ImageSource(uri = imageUri) 31 | def selectTab(name : String) = name match { 32 | case BLUE_TAB => t.modState(_.copy(selectedTab = name)) 33 | case RED_TAB => t.modState(s => s.copy(selectedTab = name,notifCount = s.notifCount + 1)) 34 | case GREEN_TAB => t.modState(s => s.copy(selectedTab = name,presses = s.presses + 1)) 35 | } 36 | } 37 | 38 | override val component = ReactNativeComponentB[Unit]("TabBarExample") 39 | .initialState(State()) 40 | .backend(new Backend(_)) 41 | .render((P,S,B) => { 42 | val badgeValue = if(S.notifCount >0) S.notifCount.toString else null 43 | TabBarIOS()( 44 | TabBarItemIOS(key = BLUE_TAB, icon = B.getImage("favorites"),selected = (S.selectedTab == BLUE_TAB),onPress = () => B.selectTab(BLUE_TAB))( 45 | B.renderContent("#414A8C","Scala-JS Blue Tab") 46 | ), 47 | TabBarItemIOS(key = RED_TAB, badge = badgeValue, icon = B.getImage("history"),selected = (S.selectedTab == RED_TAB),onPress = () => B.selectTab(RED_TAB))( 48 | B.renderContent("#783E33","Scala-JS Red Tab") 49 | ), 50 | TabBarItemIOS(key = GREEN_TAB, icon = B.getImage("favorites"),selected = (S.selectedTab == GREEN_TAB),onPress = () => B.selectTab(GREEN_TAB))( 51 | B.renderContent("#21551C","Scala-JS Green Tab") 52 | ) 53 | ) 54 | }).buildNative 55 | 56 | object styles extends NativeStyleSheet { 57 | 58 | val tabContent = style(flex := 1,alignItems.center) 59 | 60 | val tabText = style(color := "white" , margin := 50) 61 | 62 | } 63 | 64 | 65 | override def title: String = "TabBarIOS" 66 | 67 | 68 | override def description: String = "Tab-based navigation." 69 | } 70 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/components/TextInputExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.components 2 | 3 | import chandu0101.scalajs.rn.components._ 4 | import chandu0101.scalajs.rn.examples.uiexplorer.{UIExample, UIExplorerBlock, UIExplorerPage} 5 | import chandu0101.scalajs.rn.{NEvent, ReactNativeComponentB} 6 | import japgolly.scalajs.react.BackendScope 7 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 8 | 9 | object TextInputExample extends UIExample { 10 | 11 | val WithLabel = ReactNativeComponentB[String]("WithLabel") 12 | .render((P, C) => { 13 | View(style = styles.labelContainer, key = P)( 14 | View(style = styles.label, key = "lab")( 15 | Text(key = "tex")( 16 | P 17 | ) 18 | ), 19 | C 20 | ) 21 | }).build 22 | 23 | case class State(curText: String = "No Event", prevText: String = "No Event") 24 | 25 | class Backend(t: BackendScope[_, State]) { 26 | 27 | def upDateTex(text: String) = { 28 | t.modState(s => s.copy(text, s.curText)) 29 | } 30 | 31 | def handleInputEvent(e: NEvent) = { 32 | 33 | } 34 | } 35 | 36 | val TextEventsExample = ReactNativeComponentB[Unit]("TextEventsExample") 37 | .initialState(State()) 38 | .backend(new Backend(_)) 39 | .render((P, S, B) => { 40 | View()( 41 | TextInput(autoCapitalize = AutoCapitalize.NONE, 42 | placeholder = "Enter text to see events", 43 | autoCorrect = false, 44 | onFocus = (e: NEvent) => B.upDateTex("onFocus"), 45 | onBlur = (e: NEvent) => B.upDateTex("onBlur"), 46 | onChange = (e: NEvent) => B.upDateTex(s"onChange text ${e.nativeEvent.text}"), 47 | onEndEditing = (e: NEvent) => B.upDateTex(s"onEndEditing text ${e.nativeEvent.text}"), 48 | onSubmitEditing = (e: NEvent) => B.upDateTex(s"onSubmitEditing text ${e.nativeEvent.text}"), 49 | style = styles.default 50 | )(), 51 | Text(style = styles.eventLabel)( 52 | S.curText, 53 | s"\n prev : ${S.prevText}" 54 | ) 55 | ) 56 | }).buildU 57 | 58 | 59 | val component = ReactNativeComponentB[Unit]("TextInputExamples") 60 | .render(P => { 61 | UIExplorerPage( 62 | UIExplorerBlock("Auto-focus")( 63 | TextInput(autoFocus = true, style = styles.default)() 64 | ), 65 | UIExplorerBlock("Auto-capitalize")( 66 | View()( 67 | WithLabel("none", TextInput(autoCapitalize = AutoCapitalize.NONE, key = "none", style = styles.default)()), 68 | WithLabel("sentences", TextInput(autoCapitalize = AutoCapitalize.SENTENCES, key = "sentences", style = styles.default)()), 69 | WithLabel("words", TextInput(autoCapitalize = AutoCapitalize.WORDS, key = "words", style = styles.default)()), 70 | WithLabel("characters", TextInput(autoCapitalize = AutoCapitalize.CHARACTERS, key = "chars", style = styles.default)()) 71 | ) 72 | ), 73 | UIExplorerBlock("Event handling")( 74 | TextEventsExample() 75 | ), 76 | UIExplorerBlock("Auto-correct")( 77 | View()( 78 | WithLabel("true", TextInput(autoCorrect = true, key = "none", style = styles.default)()), 79 | WithLabel("false", TextInput(autoCorrect = false, key = "none", style = styles.default)()) 80 | ) 81 | ), 82 | UIExplorerBlock("Clear button mode")( 83 | View()( 84 | WithLabel("never", TextInput(clearButtonMode = "never", key = "never", style = styles.default)()), 85 | WithLabel("while editing", TextInput(clearButtonMode = "while-editing", key = "sentences", style = styles.default)()), 86 | WithLabel("unless editing", TextInput(clearButtonMode = "unless-editing", key = "unless-editing", style = styles.default)()), 87 | WithLabel("always", TextInput(clearButtonMode = "always", key = "chars", style = styles.default)()) 88 | ) 89 | ) 90 | ) 91 | }).buildNative 92 | 93 | 94 | object styles extends NativeStyleSheet { 95 | 96 | val page = style(paddingBottom := 30) 97 | 98 | val default = style(height := 26, 99 | borderWidth := 0.5, 100 | borderColor := "#0f0f0f", 101 | flex := 1, 102 | fontSize := 13) 103 | 104 | val multiline = style(borderWidth := 0.5, 105 | borderColor := "#0f0f0f", 106 | flex := 1, 107 | fontSize := 13, 108 | height := 50) 109 | 110 | val label = style(width := 120, 111 | justifyContent.flexEnd, 112 | flexDirection.row, 113 | marginRight := 10, 114 | paddingTop := 2) 115 | 116 | val eventLabel = style(margin := 3, fontSize := 12) 117 | 118 | val labelContainer = style(flexDirection.row, marginVertical := 2, flex := 1) 119 | 120 | } 121 | 122 | override def title: String = "TextInput" 123 | 124 | override def description: String = "Single line text inputs" 125 | } 126 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/components/TouchableExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.components 2 | 3 | import chandu0101.scalajs.rn 4 | import chandu0101.scalajs.rn.ReactNativeComponentB 5 | import chandu0101.scalajs.rn.components._ 6 | import chandu0101.scalajs.rn.examples.uiexplorer.{UIExample, UIExplorerBlock, UIExplorerPage} 7 | import japgolly.scalajs.react.BackendScope 8 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 9 | 10 | import scala.scalajs.js 11 | 12 | 13 | object TouchableExample extends UIExample { 14 | 15 | val heartImage = ImageSource(uri = "https://pbs.twimg.com/media/BlXBfT3CQAA6cVZ.png:small") 16 | val component = ReactNativeComponentB[Unit]("TouchableExample") 17 | .render(P => { 18 | UIExplorerPage( 19 | UIExplorerBlock(title = "TouchableHighlight")( 20 | View(style = styles.row)( 21 | TouchableHighlight(style = styles.wrapper, onPress = () => println("stock THW image - highlight"))( 22 | Image(source = heartImage, style = styles.image) 23 | ), 24 | TouchableHighlight(style = styles.wrapper, 25 | activeOpacity = 1, 26 | underlayColor = "rgb(210, 230, 255)", 27 | onPress = () => println("custom THW text - hightlight"))( 28 | Text(style = styles.text)( 29 | "Tap Here For Custom Highlight!" 30 | ) 31 | ) 32 | ) 33 | ), 34 | UIExplorerBlock(title = "Touchable feedback events")( 35 | TouchableFeedbackEvents() 36 | ) 37 | ) 38 | }).buildNative 39 | 40 | case class State(eventLog: js.Array[String] = js.Array()) 41 | 42 | class Backend(t: BackendScope[_, State]) { 43 | 44 | def appendEvent(name: String) = { 45 | val eventLog = t.state.eventLog.slice(0, 5) 46 | t.modState(_.copy(eventLog = name +: eventLog)) 47 | } 48 | } 49 | 50 | val TouchableFeedbackEvents = ReactNativeComponentB[Unit]("TouchableFeedbackEvents") 51 | .initialState(State()) 52 | .backend(new Backend(_)) 53 | .render((P, S, B) => { 54 | View()( 55 | View(style = styles.wrapper)( 56 | TouchableOpacity(style = styles.wrapper, 57 | onPress = () => B.appendEvent("press"), 58 | onPressIn = () => B.appendEvent("pressIn"), 59 | onPressOut = () => B.appendEvent("pressOut"), 60 | onLongPress = () => B.appendEvent("longPress"))( 61 | Text(style = styles.button)("Press Me") 62 | ) 63 | ), 64 | View(style = styles.eventLogBox)( 65 | S.eventLog.zipWithIndex.map { 66 | case (e,i) => Text(key = i.toString)(e) 67 | } 68 | ) 69 | ) 70 | }).buildU 71 | 72 | 73 | object styles extends NativeStyleSheet { 74 | 75 | val row = style(justifyContent.center, 76 | flexDirection.row) 77 | 78 | val icon = style(width := 24, 79 | height := 24) 80 | 81 | val image = style(width := 50, 82 | height := 50) 83 | 84 | val text = style(fontSize := 15) 85 | 86 | val button = style(color := "#007AFF") 87 | 88 | val wrapper = style(borderRadius := 8) 89 | 90 | val wrapperCustom = style( 91 | borderRadius := 8, 92 | padding := 6 93 | ) 94 | val logBox = style( 95 | padding := 20, 96 | margin := 10, 97 | borderWidth := 1.0 / rn.ReactNative.PixelRatio.get(), 98 | borderColor := "#f0f0f0", 99 | backgroundColor := "#f9f9f9" 100 | ) 101 | val eventLogBox = style( 102 | padding := 10, 103 | margin := 10, 104 | height := 120, 105 | borderWidth := 1.0 / rn.ReactNative.PixelRatio.get(), 106 | borderColor := "#f0f0f0", 107 | backgroundColor := "#f9f9f9" 108 | ) 109 | 110 | val textBlock = style( 111 | fontWeight._500, 112 | color := "blue" 113 | ) 114 | } 115 | 116 | override def title: String = "Touchable*" 117 | 118 | override def description: String = "TouchableHighlight,TouchableOpacity .." 119 | 120 | } 121 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/components/ViewExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.components 2 | 3 | import chandu0101.scalajs.rn.ReactNativeComponentB 4 | import chandu0101.scalajs.rn.components.{Text, View} 5 | import chandu0101.scalajs.rn.examples.uiexplorer.{UIExample, UIExplorerBlock, UIExplorerPage} 6 | import japgolly.scalajs.react._ 7 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 8 | 9 | import scala.scalajs.js.Dynamic.{literal => json} 10 | 11 | 12 | object ViewExample extends UIExample { 13 | 14 | 15 | val component = ReactNativeComponentB[Unit]("ViewExample") 16 | .render(P => { 17 | UIExplorerPage( 18 | View(style = styles.container)( 19 | UIExplorerBlock("Background Color")( 20 | View(style = styles.bgColorView)( 21 | Text(style = styles.text)("Blue background") 22 | )), 23 | UIExplorerBlock("Border")( 24 | View(style = styles.borderView)( 25 | Text(style = styles.text)("5px blue border") 26 | )), 27 | UIExplorerBlock("Border Radius")( 28 | View(style = styles.borderRadiusView)( 29 | Text(style = styles.text)("Too much use of `borderRadius` (especially large radii) on\n anything which is scrolling may result in dropped frames.\n Use sparingly.") 30 | )), 31 | UIExplorerBlock("Circle with Border Radius")( 32 | View(style = styles.borderRadiusCircle)()) 33 | ) 34 | ) 35 | 36 | }).buildNative 37 | 38 | 39 | object styles extends NativeStyleSheet { 40 | val container = style(flex := 1, 41 | backgroundColor := "#F5FCFF") 42 | 43 | val text = style(fontSize := 11) 44 | 45 | val bgColorView = style(backgroundColor := "#527FE4", 46 | padding := 5) 47 | 48 | val borderView = style(borderColor := "#527FE4", 49 | padding := 10, 50 | borderWidth := 5) 51 | 52 | val borderRadiusView = style(borderRadius := 5, 53 | padding := 5, 54 | borderWidth := 0.5) 55 | 56 | val borderRadiusCircle = style(borderRadius := 10, 57 | borderWidth := 1, 58 | width := 20, 59 | height := 20) 60 | } 61 | 62 | 63 | override def title: String = "View" 64 | 65 | override def description: String = "Basic building block of all UI." 66 | } 67 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/components/WebViewExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.components 2 | 3 | import chandu0101.scalajs.rn.components._ 4 | import chandu0101.scalajs.rn.examples.uiexplorer.{UIExample, UIExplorerBlock, UIExplorerPage} 5 | import chandu0101.scalajs.rn.{NEvent, ReactNativeComponentB} 6 | import japgolly.scalajs.react.{BackendScope, Ref} 7 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 8 | 9 | object WebViewExample extends UIExample { 10 | 11 | val HEADER = "#3b5998" 12 | val BGWASH = "rgba(255,255,255,0.8)" 13 | val DISABLED_WASH = "rgba(255,255,255,0.25)" 14 | val TEXT_INPUT_REF = "urlInput" 15 | val WEBVIEW_REF = "webview" 16 | val DEFAULT_URL = "https://m.facebook.com" 17 | 18 | case class State(url: String = DEFAULT_URL, status: String = " No PageLoaded", backButtonEnabled: Boolean = false, forwardButtonEnabled: Boolean = true, loading: Boolean = true) 19 | 20 | class Backend(t: BackendScope[_, State]) { 21 | 22 | var inputText = "" 23 | 24 | def handleTextInputChange(event: NEvent) = { 25 | inputText = event.nativeEvent.text.toString 26 | } 27 | 28 | def goBack = if (webRefAccess(t).isDefined) webRefAccess(t).get.goBack() 29 | 30 | def goForward = if (webRefAccess(t).isDefined) webRefAccess(t).get.goForward() 31 | 32 | def reload = if (webRefAccess(t).isDefined) webRefAccess(t).get.reload() 33 | 34 | def onNavigationStateChange(navState: NavigationState) = { 35 | t.modState(_.copy(url = navState.url, loading = navState.loading, backButtonEnabled = navState.canGoBack, forwardButtonEnabled = navState.canGoForward, status = navState.title)) 36 | } 37 | 38 | def pressGoButton = { 39 | val url = inputText.toLowerCase 40 | if (url == t.state.url) reload 41 | else t.modState(_.copy(url = url)) 42 | if (inputRefAccess(t).isDefined) inputRefAccess(t).get.blur() 43 | } 44 | 45 | def onSubmitEditing(event: NEvent) = pressGoButton 46 | 47 | } 48 | 49 | lazy val webRefAccess = Ref.toJS[WebViewM](WEBVIEW_REF) 50 | 51 | lazy val inputRefAccess = Ref.toJS[TextInputM](TEXT_INPUT_REF) 52 | 53 | 54 | val component = ReactNativeComponentB[Unit]("WebViewExample") 55 | .initialState(State()) 56 | .backend(new Backend(_)) 57 | .render((P,S,B) => { 58 | B.inputText = S.url 59 | UIExplorerPage( 60 | UIExplorerBlock(title = "WebView")( 61 | View(style = styles.container)( 62 | View(style = styles.addressBarRow)( 63 | TouchableHighlight(onPress = B.goBack _)( 64 | View(style = if(S.backButtonEnabled) styles.navButton else styles.disabledButton)( 65 | Text()("<") 66 | ) 67 | ), 68 | TouchableHighlight(onPress = B.goForward _)( 69 | View(style = if(S.forwardButtonEnabled) styles.navButton else styles.disabledButton)( 70 | Text()(">") 71 | ) 72 | ), 73 | TextInput(ref = TEXT_INPUT_REF,autoCapitalize = AutoCapitalize.NONE,value = S.url,onSubmitEditing = B.onSubmitEditing _, 74 | onChange = B.handleTextInputChange _, 75 | clearButtonMode = "while-editing", 76 | style = styles.addressBarTextInput)(), 77 | TouchableOpacity(onPress = B.pressGoButton _)( 78 | View(style = styles.goButton)( 79 | Text()("Go!") 80 | ) 81 | ) 82 | ), 83 | WebView(ref = WEBVIEW_REF, 84 | automaticallyAdjustContentInsets = false, 85 | style = styles.webView, 86 | url = S.url, 87 | onNavigationStateChange = B.onNavigationStateChange _, 88 | startInLoadingState = true 89 | ), 90 | View(style = styles.statusBar)( 91 | Text(style = styles.statusBarText)(S.status) 92 | ) 93 | ) 94 | ) 95 | ) 96 | 97 | }).buildNative 98 | 99 | object styles extends NativeStyleSheet { 100 | 101 | val container = style(flex := 1, 102 | backgroundColor := HEADER) 103 | 104 | val addressBarRow = style(flexDirection.row, 105 | padding := 8) 106 | 107 | val webView = style( 108 | backgroundColor := BGWASH, 109 | height := 350 110 | ) 111 | 112 | val addressBarTextInput = style( 113 | backgroundColor := BGWASH, 114 | borderColor := "transparent", 115 | borderRadius := 3, 116 | borderWidth := 1, 117 | height := 24, 118 | paddingLeft := 10, 119 | paddingTop := 3, 120 | flex := 1, 121 | fontSize := 14 122 | ) 123 | 124 | def buttonCommon(bg: String) = style( 125 | padding := 3, 126 | alignItems.center, 127 | justifyContent.center, 128 | backgroundColor := bg, 129 | borderColor := "transparent", 130 | borderRadius := 3 131 | ) 132 | 133 | val navButton = styleE(buttonCommon(BGWASH))( 134 | width := 20, 135 | marginRight := 3) 136 | 137 | val disabledButton = styleE(buttonCommon(DISABLED_WASH))( 138 | width := 20, 139 | marginRight := 3) 140 | 141 | val goButton = styleE(buttonCommon(BGWASH))( 142 | height := 24, 143 | marginLeft := 8, 144 | alignSelf.stretch 145 | ) 146 | 147 | val statusBar = style( 148 | flexDirection.row, 149 | alignItems.center, 150 | paddingLeft := 5, 151 | height := 22 152 | ) 153 | 154 | val statusBarText = style( 155 | color := "white", 156 | fontSize := 13 157 | ) 158 | 159 | val spinner = style( 160 | width := 20, 161 | marginRight := 6 162 | ) 163 | 164 | } 165 | 166 | override def title: String = "WebView" 167 | 168 | override def description: String = "Base component to display web content" 169 | } 170 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/components/navigator/BreadCrumbNavigationBarSample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.components.navigator 2 | 3 | import chandu0101.scalajs.rn._ 4 | import chandu0101.scalajs.rn.components._ 5 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 6 | import japgolly.scalajs.react.{BackendScope, ReactElement} 7 | 8 | import scala.scalajs.js 9 | import scala.scalajs.js.Math 10 | 11 | object BreadCrumbNavigationBarSample { 12 | 13 | val NavButton = ReactNativeComponentB[(() => Unit, String)]("NavButton") 14 | .render(P => { 15 | TouchableHighlight( 16 | style = styles.button, 17 | underlayColor = "#B5B5B5", 18 | onPress = P._1 19 | )(Text(style = styles.buttonText)(P._2)) 20 | }).build 21 | 22 | 23 | class Backend(t: BackendScope[NavigatorM, _]) { 24 | 25 | def newRandomRoute() : js.Dynamic = { 26 | NavigatorRoute(title = s"#${Math.ceil(Math.random() * 1000)}",component = null,getProps = null).toJson 27 | } 28 | 29 | def renderScene(route: NavigatorRoute, navigator: NavigatorM) = { 30 | ScrollView(style = styles.scene)( 31 | NavButton((() => navigator.push(newRandomRoute()), "Push")), 32 | NavButton((() => t.props.pop(), "Close breadcrumb Example")) 33 | ) 34 | } 35 | 36 | def rightContentForRoute(route: NavigatorRoute, navigator: NavigatorM): ReactElement = { 37 | null 38 | } 39 | 40 | def titleContentForRoute(route: NavigatorRoute, navigator: NavigatorM): ReactElement = { 41 | TouchableOpacity(onPress = () => navigator.push(newRandomRoute()))( 42 | View()( 43 | Text(style = styles.titleText)(route.title) 44 | ) 45 | ) 46 | } 47 | 48 | def iconForRoute(route: js.Dynamic, navigator: NavigatorM): ReactElement = { 49 | TouchableOpacity(onPress = () => navigator.popToRoute(route))( 50 | View(style = styles.crumbIconPlaceholder)( 51 | ) 52 | ) 53 | } 54 | 55 | def separatorForRoute(route: NavigatorRoute, navigator: NavigatorM): ReactElement = { 56 | TouchableOpacity(onPress = () => navigator.pop())( 57 | View(style = styles.crumbSeparatorPlaceholder)( 58 | ) 59 | ) 60 | } 61 | 62 | } 63 | 64 | 65 | val component = ReactNativeComponentB[NavigatorM]("BreadCrumbNavigationBarSample") 66 | .stateless 67 | .backend(new Backend(_)) 68 | .render((P, S, B) => { 69 | Navigator(style = styles.container, 70 | renderScene = B.renderScene _, 71 | initialRoute = NavigatorRoute.fromJson(B.newRandomRoute()).toJson, 72 | navigationBar = NavigatorBreadcrumbNavigationBar( style = styles.breadCrumbBar, 73 | routeMapper = BreadcrumbNavigationBarRouteMapper(iconForRoute = B.iconForRoute _, 74 | titleContentForRoute = B.titleContentForRoute _, 75 | rightContentForRoute = B.rightContentForRoute _, 76 | separatorForRoute = B.separatorForRoute _)) 77 | ) 78 | 79 | }) 80 | .build 81 | 82 | object styles extends NativeStyleSheet { 83 | 84 | 85 | val titleText = style(fontSize := 18, 86 | color := "#666666", 87 | fontWeight.bold, 88 | textAlign.center, 89 | lineHeight := 32) 90 | 91 | 92 | val button = style(backgroundColor := "white", 93 | padding := 15, 94 | borderBottomWidth := 1.0 / ReactNative.PixelRatio.get(), 95 | borderBottomColor := "#CDCDCD" 96 | ) 97 | 98 | val buttonText = style(fontSize := 17, 99 | fontWeight._500) 100 | 101 | val scene = style(flexOne, 102 | paddingTop := 90) 103 | 104 | val container = style(flexOne, 105 | overflow.hidden, 106 | backgroundColor := "#dddddd") 107 | 108 | val crumbIconPlaceholder = style(flexOne, 109 | backgroundColor := "#666666") 110 | 111 | 112 | val crumbSeparatorPlaceholder = style( 113 | flexOne, 114 | backgroundColor := "#aaaaaa" 115 | ) 116 | val breadCrumbBar = style(marginTop := 70) 117 | 118 | } 119 | 120 | def apply(navigator: NavigatorM) = component(navigator) 121 | 122 | } 123 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/components/navigator/JumpingNavSample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.components.navigator 2 | 3 | import chandu0101.scalajs.rn._ 4 | import chandu0101.scalajs.rn.components._ 5 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 6 | import japgolly.scalajs.react.{Ref, BackendScope, ReactElement} 7 | 8 | import scala.scalajs.js 9 | import scala.scalajs.js.JSConverters.JSRichGenTraversableOnce 10 | import scala.scalajs.js.{JSON, Math} 11 | import scalajs.js.Dynamic.{literal => json} 12 | 13 | object JumpingNavSample { 14 | 15 | val NavButton = ReactNativeComponentB[(() => Unit, String)]("NavButton") 16 | .render(P => { 17 | TouchableHighlight( 18 | style = styles.button, 19 | underlayColor = "#B5B5B5", 20 | onPress = P._1 21 | )(Text(style = styles.buttonText)(P._2)) 22 | }).build 23 | 24 | 25 | 26 | def newRandomRoute(index : Int) : js.Dynamic = { 27 | NavigatorRoute(title = s"#${index}",component = null,getProps = null).toJson 28 | } 29 | 30 | val ROUTE_STACK = js.Array( 31 | newRandomRoute(45), 32 | newRandomRoute(425), 33 | newRandomRoute(435) 34 | ) 35 | 36 | val INIT_ROUTE_INDEX = 1 37 | 38 | 39 | 40 | case class JumpingProps(initTabIndex : Int,routeStack : js.Array[js.Dynamic],onTabIndex : Int => Any) 41 | 42 | case class JumpingState(tabIndex : Int) 43 | 44 | class JumpingBackend(t: BackendScope[JumpingProps,JumpingState]) { 45 | 46 | def onTabPress(index : Int):Unit = { 47 | t.props.onTabIndex(index) 48 | t.modState(_.copy(tabIndex = index)) 49 | } 50 | 51 | } 52 | val JumpingNavBar = ReactNativeComponentB[JumpingProps]("JumpingNavBar") 53 | .initialStateP(p => JumpingState(tabIndex = p.initTabIndex)) 54 | .backend(new JumpingBackend(_)) 55 | .render( (P,S,B) => { 56 | println(s"rendering jumpingnavbar") 57 | View(style = styles.tabs)( 58 | 59 | TabBarIOS()( 60 | TabBarItemIOS(icon = ImageSource(uri = "history"),selected = S.tabIndex == 1,onPress = () => B.onTabPress(1))( 61 | View()() 62 | ), 63 | TabBarItemIOS(icon = ImageSource(uri = "favorites"),selected = S.tabIndex == 2,onPress = () => B.onTabPress(2))( 64 | View()() 65 | ) 66 | ) 67 | 68 | ) 69 | }).build 70 | 71 | 72 | val ROUTE_STACK_CLASS = ROUTE_STACK.map(NavigatorRoute.fromJson(_)) 73 | 74 | class Backend(t: BackendScope[NavigatorM, _]) { 75 | 76 | 77 | def renderScene(route: NavigatorRoute, navigator: NavigatorM) = { 78 | 79 | var backBtn : ReactElement = null 80 | var forwardBtn : ReactElement = null 81 | if(ROUTE_STACK_CLASS.indexOf(route) != 0) { 82 | backBtn = NavButton((() => navigator.jumpBack(),"JumpBack")) 83 | } 84 | if(ROUTE_STACK_CLASS.indexOf(route) != ROUTE_STACK.length - 1) { 85 | forwardBtn = NavButton((() => navigator.jumpForward(),"JumpForward")) 86 | } 87 | 88 | ScrollView(style = styles.scene)( 89 | Text(style = styles.messageText)(route.title), 90 | backBtn, 91 | forwardBtn, 92 | NavButton((() => t.props.pop(),"Exit NavigationBar Example")) 93 | ) 94 | } 95 | 96 | def configureScene(route : NavigatorRoute) = { 97 | 98 | NavigatorS.SceneConfigs.HorizontalSwipeJump 99 | } 100 | 101 | def onTabindex(index : Int) = { 102 | jumpNav(t).get.jumpTo(ROUTE_STACK(index)) 103 | } 104 | 105 | } 106 | 107 | val jumpNav = Ref.toJS[NavigatorM]("jumpnav") 108 | 109 | val component = ReactNativeComponentB[NavigatorM]("JumpingNavSample") 110 | .stateless 111 | .backend(new Backend(_)) 112 | .render((P, S, B) => { 113 | Navigator(style = styles.container, 114 | ref = "jumpnav", 115 | renderScene = B.renderScene _, 116 | initialRoute = ROUTE_STACK(INIT_ROUTE_INDEX) , 117 | initialRouteStack = ROUTE_STACK, 118 | configureScene = B.configureScene _, 119 | navigationBar = JumpingNavBar(JumpingProps(initTabIndex = INIT_ROUTE_INDEX,routeStack = ROUTE_STACK,onTabIndex = B.onTabindex _ )) 120 | ) 121 | 122 | }) 123 | .build 124 | 125 | object styles extends NativeStyleSheet { 126 | 127 | 128 | val messageText = style(fontSize := 17, 129 | fontWeight._500, 130 | padding := 15, 131 | marginTop := 50, 132 | marginLeft := 15) 133 | 134 | 135 | val button = style(backgroundColor := "white", 136 | padding := 15, 137 | borderBottomWidth := 1.0 / ReactNative.PixelRatio.get(), 138 | borderBottomColor := "#CDCDCD" 139 | ) 140 | 141 | val buttonText = style(fontSize := 17, 142 | fontWeight._500) 143 | 144 | val scene = style(flexOne, 145 | paddingTop := 20, 146 | backgroundColor := "#EAEAEA") 147 | 148 | val tabs = style(height := 50) 149 | 150 | val navBar = style(backgroundColor := "white") 151 | 152 | val navBarText = style(fontSize := 16, 153 | marginVertical := 10) 154 | 155 | val navBarTitleText = style(color := "black", 156 | fontWeight._500, 157 | marginVertical := 9) 158 | 159 | val navBarLeftButton = style(paddingLeft := 10) 160 | 161 | val navBarRightButton = style(paddingRight := 10) 162 | 163 | val navBarButtonText = style(color := "blue") 164 | 165 | val container = style(flexOne, 166 | overflow.hidden, 167 | backgroundColor := "#dddddd") 168 | val combinedText = styleE(navBarText,navBarButtonText)() 169 | 170 | } 171 | 172 | def apply(navigator: NavigatorM) = component(navigator) 173 | 174 | } 175 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/components/navigator/NavigationBarSample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.components.navigator 2 | 3 | import chandu0101.scalajs.rn._ 4 | import chandu0101.scalajs.rn.components._ 5 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 6 | import japgolly.scalajs.react.{ReactElement, BackendScope} 7 | 8 | import scala.scalajs.js 9 | import scala.scalajs.js.Math 10 | 11 | object NavigationBarSample { 12 | 13 | val NavButton = ReactNativeComponentB[(() => Unit, String)]("NavButton") 14 | .render(P => { 15 | TouchableHighlight( 16 | style = styles.button, 17 | underlayColor = "#B5B5B5", 18 | onPress = P._1 19 | )(Text(style = styles.buttonText)(P._2)) 20 | }).build 21 | 22 | 23 | class Backend(t: BackendScope[NavigatorM, _]) { 24 | 25 | def newRandomRoute() :js.Dynamic = { 26 | NavigatorRoute(title = s"#${Math.ceil(Math.random()*1000)}",component = null,getProps = null).toJson 27 | } 28 | 29 | def onPress(nav : NavigatorM) = { 30 | () => nav.immediatelyResetRouteStack(js.Array( 31 | newRandomRoute(), 32 | newRandomRoute(), 33 | newRandomRoute() 34 | )) 35 | } 36 | 37 | def renderScene(route: NavigatorRoute, navigator: NavigatorM) = { 38 | ScrollView(style = styles.scene)( 39 | Text(style = styles.messageText)(route.title), 40 | NavButton((onPress(navigator),"Reset w/3 scenes")), 41 | NavButton((() => t.props.pop(),"Exit NavigationBar Example")) 42 | ) 43 | } 44 | 45 | def onLeftButton(route : NavigatorRoute,navigator : NavigatorM,index : Int,navState : NavigationBarNavState):ReactElement = { 46 | if(index > 0) { 47 | val previousRoute = navState.routeStack(index - 1) 48 | TouchableOpacity(onPress = () => navigator.pop())( 49 | View(style = styles.navBarLeftButton)( 50 | Text(style = styles.combinedText)(previousRoute.title) 51 | ) 52 | ) 53 | } else null 54 | 55 | } 56 | def onRightButtonButton(route : NavigatorRoute,navigator : NavigatorM,index : Int,navState : NavigationBarNavState):ReactElement = { 57 | TouchableOpacity(onPress = () => navigator.push(newRandomRoute()))( 58 | View(style = styles.navBarRightButton)( 59 | Text(style = styles.combinedText)("Next") 60 | ) 61 | ) 62 | } 63 | 64 | def onTitle(route : NavigatorRoute,navigator : NavigatorM,index : Int,navState : NavigationBarNavState):ReactElement = { 65 | Text(style = styles.navBarTitleText)( 66 | s"${ route.title}[${index}]" 67 | ) 68 | } 69 | 70 | 71 | } 72 | 73 | 74 | val component = ReactNativeComponentB[NavigatorM]("NavigationBarSample") 75 | .stateless 76 | .backend(new Backend(_)) 77 | .render((P, S, B) => { 78 | Navigator(style = styles.container, 79 | renderScene = B.renderScene _, 80 | initialRoute = NavigatorRoute.fromJson(B.newRandomRoute()).toJson , 81 | navigationBar = NavigatorNavigationBar(style = styles.navBar, 82 | routeMapper = NavigationBarRouteMapper(Title = B.onTitle _, 83 | LeftButton = B.onLeftButton _, 84 | RightButton = B.onRightButtonButton _)) 85 | ) 86 | 87 | }) 88 | .build 89 | 90 | object styles extends NativeStyleSheet { 91 | 92 | 93 | val messageText = style(fontSize := 17, 94 | fontWeight._500, 95 | padding := 15, 96 | marginTop := 50, 97 | marginLeft := 15) 98 | 99 | 100 | val button = style(backgroundColor := "white", 101 | padding := 15, 102 | borderBottomWidth := 1.0 / ReactNative.PixelRatio.get(), 103 | borderBottomColor := "#CDCDCD" 104 | ) 105 | 106 | val buttonText = style(fontSize := 17, 107 | fontWeight._500) 108 | 109 | val scene = style(flexOne, 110 | paddingTop := 20, 111 | backgroundColor := "#EAEAEA") 112 | 113 | val navBar = style(backgroundColor := "white", 114 | height := 64, 115 | paddingBottom := 5, 116 | borderBottomWidth := 1.0 / ReactNative.PixelRatio.get(), 117 | borderBottomColor := "rgba(0, 0, 0, 0.5)", 118 | marginTop := 80) 119 | 120 | val navBarText = style(fontSize := 16, 121 | marginVertical := 10) 122 | 123 | val navBarTitleText = style(color := "black", 124 | fontWeight._500, 125 | marginVertical := 9) 126 | 127 | val navBarLeftButton = style(paddingLeft := 10) 128 | 129 | val navBarRightButton = style(paddingRight := 10) 130 | 131 | val navBarButtonText = style(color := "#5890ff") 132 | 133 | val container = style(flexOne) 134 | 135 | val combinedText = styleE(navBarText,navBarButtonText)() 136 | 137 | 138 | } 139 | 140 | def apply(navigator: NavigatorM) = component(navigator) 141 | 142 | } 143 | -------------------------------------------------------------------------------- /examples/src/main/scala/chandu0101/scalajs/rn/examples/uiexplorer/components/navigator/NavigatorExample.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.examples.uiexplorer.components.navigator 2 | 3 | import chandu0101.scalajs.rn._ 4 | 5 | import scala.scalajs.js.Dynamic.{literal => json} 6 | 7 | //import chandu0101.scalajs.rn.ReactNativeComponentB 8 | 9 | import chandu0101.scalajs.rn.components._ 10 | import chandu0101.scalajs.rn.examples.uiexplorer.UIExample 11 | import chandu0101.scalajs.rn.styles.NativeStyleSheet 12 | import japgolly.scalajs.react.BackendScope 13 | 14 | object NavigatorExample extends UIExample { 15 | 16 | 17 | val NavButton = ReactNativeComponentB[(() => Unit, String)]("NavButton") 18 | .render(P => { 19 | TouchableHighlight( 20 | style = styles.button, 21 | underlayColor = "#B5B5B5", 22 | onPress = P._1 23 | )(Text(style = styles.buttonText)(P._2)) 24 | }).build 25 | 26 | 27 | case class NavMenuProps(message: String, navigator: NavigatorM) 28 | 29 | val NavMenu = ReactNativeComponentB[NavMenuProps]("NavMenu") 30 | .render(P => { 31 | ScrollView(style = styles.scene)( 32 | Text(style = styles.messageText)(P.message), 33 | NavButton((() => P.navigator.push(json(title = "Swipe right to dismiss", 34 | sceneConfig = NavigatorS.SceneConfigs.FloatFromRight)), 35 | "Float in from right")), 36 | NavButton((() => P.navigator.push(json(title = "Swipe down to dismiss", 37 | sceneConfig = NavigatorS.SceneConfigs.FloatFromBottom)), 38 | "Float in from Bottom")), 39 | NavButton((() => P.navigator.pop(), "Pop")), 40 | NavButton((() => P.navigator.popToTop(), "Pop to Top")), 41 | NavButton((() => P.navigator.push(json(id = "navbar")), 42 | "Nav Bar Example")), 43 | NavButton((() => P.navigator.push(json(id = "jumpnav")), 44 | "Jumping Nav Bar Example")), 45 | NavButton((() => P.navigator.push(json(id = "breadcrumbs")), 46 | "Breadcrumb Nav Bar Example")) 47 | ) 48 | }).build 49 | 50 | 51 | class Backend(t: BackendScope[_, _]) { 52 | 53 | def renderScene(route: NavigatorRoute, nav: NavigatorM) = { 54 | if (route.id.isDefined) { 55 | route.id.get match { 56 | case "navbar" => NavigationBarSample(nav) 57 | case "jumpnav" => JumpingNavSample(nav) 58 | case "breadcrumbs" => BreadCrumbNavigationBarSample(nav) 59 | case _ => NavMenu(NavMenuProps(message = route.title, navigator = nav)) 60 | } 61 | } else NavMenu(NavMenuProps(message = route.title, navigator = nav)) 62 | } 63 | 64 | def configureScene(route: NavigatorRoute) = { 65 | if (route.sceneConfig.isDefined) route.sceneConfig.get 66 | else NavigatorS.SceneConfigs.FloatFromRight 67 | } 68 | } 69 | 70 | 71 | val component = ReactNativeComponentB[Unit]("NavigatorExample") 72 | .stateless 73 | .backend(new Backend(_)) 74 | .render((P, S, B) => { 75 | val component = null 76 | Navigator(ref = "navigator", 77 | style = styles.container, 78 | initialRoute = NavigatorRoute(title = "First Scene", getProps = null,component = component).toJson, 79 | renderScene = B.renderScene _, 80 | configureScene = B.configureScene _ 81 | ) 82 | }).buildNative 83 | 84 | 85 | object styles extends NativeStyleSheet { 86 | 87 | 88 | val messageText = style(fontSize := 17, 89 | fontWeight._500, 90 | padding := 15, 91 | marginTop := 50, 92 | marginLeft := 15) 93 | 94 | val container = style(flexOne) 95 | 96 | val button = style(backgroundColor := "white", 97 | padding := 15, 98 | borderBottomWidth := 1.0 / ReactNative.PixelRatio.get(), 99 | borderBottomColor := "#CDCDCD" 100 | ) 101 | 102 | val buttonText = style(fontSize := 17, 103 | fontWeight._500) 104 | 105 | val scene = style(flexOne, 106 | paddingTop := 20, 107 | backgroundColor := "#EAEAEA") 108 | 109 | 110 | } 111 | 112 | override def title: String = "Navigator" 113 | 114 | override def description: String = "JS-implemented navigation" 115 | } 116 | -------------------------------------------------------------------------------- /project/Build.scala: -------------------------------------------------------------------------------- 1 | import com.typesafe.sbt.pgp.PgpKeys._ 2 | import org.scalajs.sbtplugin.ScalaJSPlugin 3 | import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport._ 4 | import sbt.Keys._ 5 | import sbt._ 6 | 7 | object ScalajsReactNative extends Build { 8 | 9 | import Dependencies._ 10 | 11 | val Scala211 = "2.11.7" 12 | 13 | type PE = Project => Project 14 | 15 | def commonSettings: PE = 16 | _.enablePlugins(ScalaJSPlugin) 17 | .settings( 18 | organization := "com.github.chandu0101.scalajs-react-native", 19 | version := "0.2.0", 20 | homepage := Some(url("https://github.com/chandu0101/scalajs-react-native")), 21 | licenses += ("Apache-2.0", url("http://opensource.org/licenses/Apache-2.0")), 22 | scalaVersion := Scala211, 23 | scalacOptions ++= Seq("-deprecation", "-unchecked", "-feature", 24 | "-language:postfixOps", "-language:implicitConversions", 25 | "-language:higherKinds", "-language:existentials")) 26 | 27 | def preventPublication: PE = 28 | _.settings( 29 | publishArtifact := false, 30 | publishLocalSigned := (), // doesn't work 31 | publishSigned := (), // doesn't work 32 | packagedArtifacts := Map.empty) // doesn't work - https://github.com/sbt/sbt-pgp/issues/42 33 | 34 | def publicationSettings: PE = 35 | _.settings( 36 | publishTo := { 37 | val nexus = "https://oss.sonatype.org/" 38 | if (isSnapshot.value) 39 | Some("snapshots" at nexus + "content/repositories/snapshots") 40 | else 41 | Some("releases" at nexus + "service/local/staging/deploy/maven2") 42 | }, 43 | pomExtra := 44 | 45 | scm:git:github.com/chandu0101/scalajs-react-native 46 | scm:git:git@github.com:chandu0101/scalajs-react-native.git 47 | github.com:chandu0101/scalajs-react-native.git 48 | 49 | 50 | 51 | chandu0101 52 | Chandra Sekhar Kode 53 | 54 | ) 55 | .configure(sourceMapsToGithub) 56 | 57 | def sourceMapsToGithub: PE = 58 | p => p.settings( 59 | scalacOptions ++= (if (isSnapshot.value) Seq.empty else Seq({ 60 | val a = p.base.toURI.toString.replaceFirst("[^/]+/?$", "") 61 | val g = "https://raw.githubusercontent.com/chandu0101/scalajs-react-native" 62 | s"-P:scalajs:mapSourceURI:$a->$g/v${version.value}/" 63 | })) 64 | ) 65 | 66 | // ============== react-native tasks ============ // 67 | val fullOptIOS = Def.taskKey[File]("Generate the file given to react native") 68 | 69 | def createLauncher(scope: String = "compile"): PE = 70 | _.settings( 71 | artifactPath in Compile in fullOptIOS := 72 | baseDirectory.value / "index.ios.js", 73 | fullOptIOS in Compile := { 74 | val outFile = (artifactPath in Compile in fullOptIOS).value 75 | 76 | IO.copyFile((fullOptJS in Compile).value.data, outFile) 77 | 78 | val launcher = (scalaJSLauncher in Compile).value.data.content 79 | IO.append(outFile, launcher) 80 | 81 | outFile 82 | } 83 | ) 84 | 85 | def addCommandAliases(m: (String, String)*) = { 86 | val s = m.map(p => addCommandAlias(p._1, p._2)).reduce(_ ++ _) 87 | (_: Project).settings(s: _*) 88 | } 89 | 90 | def extModuleName(mname: String): PE = 91 | _.settings(name := mname) 92 | 93 | // ========================================= Module Definitions ====================== / 94 | lazy val root = Project("root", file(".")) 95 | .aggregate(core,styles, examples) 96 | .configure(commonSettings, preventPublication, addCommandAliases( 97 | "t" -> "; test:compile ; test/test", 98 | "tt" -> ";+test:compile ;+test/test", 99 | "T" -> "; clean ;t", 100 | "TT" -> ";+clean ;tt")) 101 | 102 | lazy val core = project 103 | .configure(commonSettings, publicationSettings) 104 | .settings(name := "core") 105 | .settings(coreModuleDeps :_*) 106 | 107 | lazy val styles = project 108 | .configure(commonSettings, publicationSettings,extModuleName("styles")) 109 | 110 | lazy val examples = project 111 | .dependsOn(core,styles) 112 | .configure(commonSettings,createLauncher(), preventPublication) 113 | .settings(exampleModuleDeps :_*) 114 | 115 | } -------------------------------------------------------------------------------- /project/Dependencies.scala: -------------------------------------------------------------------------------- 1 | import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport._ 2 | import sbt.Keys._ 3 | import sbt._ 4 | 5 | object Dependencies { 6 | 7 | val scalajsReactVersion = "0.9.1" 8 | 9 | val scalaAsyncVersion = "0.9.2" 10 | 11 | val scalaJSReact = libraryDependencies += "com.github.japgolly.scalajs-react" %%% "core" % scalajsReactVersion 12 | 13 | val scalaJSReactExtra = libraryDependencies += "com.github.japgolly.scalajs-react" %%% "extra" % scalajsReactVersion 14 | 15 | val scalaAsync = libraryDependencies += "org.scala-lang.modules" %% "scala-async" % scalaAsyncVersion 16 | 17 | 18 | val coreModuleDeps = Seq(scalaJSReact,scalaJSReactExtra) 19 | 20 | val exampleModuleDeps = Seq(scalaAsync) 21 | 22 | } -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=0.13.8 -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.4") 2 | 3 | addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0") 4 | 5 | -------------------------------------------------------------------------------- /styles/src/main/scala/chandu0101/scalajs/rn/styles/NativeStyleSheet.scala: -------------------------------------------------------------------------------- 1 | package chandu0101.scalajs.rn.styles 2 | 3 | import scala.scalajs.js 4 | import scala.scalajs.js.Dynamic.{literal => json} 5 | import scala.scalajs.js.JSConverters.JSRichGenMap 6 | 7 | 8 | trait NativeStyleSheet extends NativeAttrs{ 9 | /** if duplicate attrs found then last one wins */ 10 | @inline def styleE(maps: js.Dictionary[Any]*)(v: NativeStylePair[_]*) = { 11 | maps.fold(js.Dictionary.empty[Any])((d1, d2) => d1.++(d2).toJSDictionary) 12 | .++(style(v: _*)) 13 | .toJSDictionary 14 | } 15 | 16 | @inline def style(v: NativeStylePair[_]*) : js.Dictionary[Any] = { 17 | val p = js.Dictionary.empty[Any] 18 | v.foreach(t => p.update(t.key, t.value)) 19 | p 20 | } 21 | } 22 | 23 | 24 | case class NativeStyle[T](name : String) { 25 | def := (v :T) = new NativeStylePair[T](name,v) 26 | } 27 | 28 | case class NativeStylePair[T](key : String ,value : T) { 29 | 30 | } 31 | --------------------------------------------------------------------------------