diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9ed2ddb --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +*.js linguist-vendored + +*.java linguist-vendored + +*.m linguist-vendored \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..49c05a7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +*.class +*.log + +# sbt specific +.cache/ +.history/ +.lib/ +dist/* +target/ +lib_managed/ +src_managed/ +project/boot/ +project/plugins/project/ + +# Scala-IDE specific +.scala_dependencies +.worksheet + +#Intellij +.idea +*.iml + +#mac +.DS_Store + + + +#node + +node_modules/ +npm-debug.log + + +#project diff --git a/.travis.credentials.sh b/.travis.credentials.sh new file mode 100644 index 0000000..935074e --- /dev/null +++ b/.travis.credentials.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -euo pipefail + +mkdir ~/.bintray/ + +cat < $HOME/.bintray/.credentials +realm = Bintray API Realm +host = api.bintray.com +user = $BINTRAY_USER +password = $BINTRAY_PASSWORD +EOF \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..edc87b4 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,39 @@ +language: scala + +scala: +- 2.12.1 +- 2.11.8 + +jdk: +- oraclejdk8 + +install: + - . $HOME/.nvm/nvm.sh + - nvm install stable + - nvm use stable + - npm install + +env: + global: + JSENV=node + +script: + - sbt ++$TRAVIS_SCALA_VERSION test:fastOptJS test:fullOptJS + - sbt ++$TRAVIS_SCALA_VERSION 'set parallelExecution in ThisBuild := false' test + - sbt ++$TRAVIS_SCALA_VERSION 'set parallelExecution in ThisBuild := false' 'set scalaJSStage in ThisBuild := FullOptStage' test + + +deploy: + provider: script + script: + - /bin/bash "$TRAVIS_BUILD_DIR/.travis.credentials.sh" && sbt ++$TRAVIS_SCALA_VERSION publish + on: + tags: true + +env: + global: + # travis encrypt BINTRAY_USER=xxx + - secure: "rLH/tnkhSN36bnvq4Ta7ZZUi39dS+gQLMUA9szPbMxGApikz3sDPDevkmZSnV6/+ND46OMPZwNbxsvnHDXgu0cZstZEUT7Htd2wlJgNbISqSW8yEnZvFzfuuc136nUdFsHa80H48Au2HqxcHizlnvrsuiFrvK/j2VA/LlH1oFTRn6t21Rk9bjEJB5JB80AKwYlzlmrLSLVOYWCCg7Jq1DjxOke8DFcB7z2tTNa+t0VHDs63Bb2ORlViWghjSorqq5qLQoxksIhGgbw9O4V+FtoZZ/IPBa0k3kKVqpUVMmC2VQBPP9Jw9YtyjvEI2bHF+T70vMr3eZEJZT05Usnyygagce4/C7vE8gXoAl4Oo5YS63st9Mgh3wQc4xx524vuMCgmKDg83wTV3rbhCKh0x4GaEf5E4P/HhPZMJaTuoCTeKCYNj1jtq1Hdcoz8nhpzi7G4kVNhmSxOC2OQ42x4N+1MfYslXKMdyJ7qET5zLf4hdezDf1lnwfEAD+bnQpnL5VPQ7N4et14zQfnbeQ+aqN95eTK6sz6Fsilwu7bh7NyJXLQHFgeGWJTjldc3Ra4u0nX17u26VY0UTJVX34zEKaJ3kBI54IWscQQQvjxBcCYETJOmlflcxSrVvRXSytjENvQsEezGX9oirRbji6KbpM3TDJWUeNJkJ1N+kJdwkzuU=" + # travis encrypt BINTRAY_PASSWORD=xxx + - secure: "G1lSWNcgvPzIQh4SwCspS/tCKlZOTrnoAlIIwPy/Z5XiPvet92IJmJ1U1DWqOC5xu0wvgbLasYqFYViKJgdQzsNZN3z1HpqjVlV0zYkGS4bg8wsJQuZZL0AlYzMyXs8i3lldP8PexHzn4uvfIkpDksdd1jIOSnvJnOlOFAIeJ06uLo4lm9ZRg/yBa9wX/tuRQbEMskrhm1xh2gISTt3BCex7JhhfG0i2qIdb4tyY/+AKRJKa0Vwt2GLMTN47az3Jj7hW1gDHDPaSptRTNkPIJm3bZtZZmUWC3uSSRaahMAudPAsWUS843hxdkyKeztDMVcwRY7/bTkAFb4zBrI1Teyn9AjZ8eche5UxY81TsPVMRzncbyHYVAgVo1R9KkvAUtQoYGX5/dwcL6U078F22ljweiODzv0E+BpyNybcobr+fD44lgVEkMAdAHyB8XCZw/cyTt2il/+PWbwprWDjIqVYbM3VEYpJY62bce/doO4nldqQx9KL6lH0OWnUyCuoZMgQ2Po3t87fRG2bkRwKZQ8iOcjCw63cSmSshLkT263ju/YQrDlCZs+6OTeghbvVdVlc80CuSGKk8XI8AEWjPszT2ABCg4nZiVjSgYcZU61IAVMp9Nvx5hbCmx8XVrAks44hLtj7Z4EmMtZIYRPJNIsnk+CUoJO2GmS31vL6rikk=" + diff --git a/LICENCE.md b/LICENCE.md new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/LICENCE.md @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f87f5c1 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# TODO \ No newline at end of file diff --git a/build.sbt b/build.sbt new file mode 100644 index 0000000..72cee4c --- /dev/null +++ b/build.sbt @@ -0,0 +1,44 @@ +name := "navigation" + +//version := "2017.2.0-SNAPSHOT" + +enablePlugins(ScalaJSPlugin) + +val scala211 = "2.11.8" + +val scala212 = "2.12.1" + +scalaVersion := scala211 + +crossScalaVersions := Seq(scala211, scala212) + +scalacOptions ++= Seq( + "-feature", + "-deprecation", + "-unchecked", + "-language:implicitConversions" +) + +//Dependencies + +libraryDependencies += "scalajs-react-interface" %%% "universal" % "2017.3.23-beta" % Provided +libraryDependencies += "scalajs-react-interface" %%% "core" % "2017.3.23-beta" % Provided + +//bintray +resolvers += Resolver.jcenterRepo + +organization := "scalajs-react-interface" + +licenses += ("Apache-2.0", url( + "https://www.apache.org/licenses/LICENSE-2.0.html")) + +bintrayOrganization := Some("scalajs-react-interface") + +bintrayRepository := "maven" + +publishArtifact in Test := false + +//Test +resolvers += Resolver.bintrayRepo("scalajs-react-interface", "maven") +libraryDependencies += "org.scalatest" %%% "scalatest" % "3.0.0" % Test +scalaJSStage in Global := FastOptStage diff --git a/package.json b/package.json new file mode 100644 index 0000000..804817e --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "sr--test", + "version": "0.1.0", + "description": "sri test", + "repository": { + "type": "git", + "url": "" + }, + "scripts": { + "start": "webpack --watch & webpack-dev-server --progress --colors --port 8090", + "build": "webpack --watch" + }, + "devDependencies": { + "jsdom-global": "2.1.1", + "jsdom": "^9.9.1" + }, + "dependencies": { + + } +} diff --git a/project/build.properties b/project/build.properties new file mode 100644 index 0000000..24be09b --- /dev/null +++ b/project/build.properties @@ -0,0 +1,2 @@ +sbt.version=0.13.13 + diff --git a/project/plugins.sbt b/project/plugins.sbt new file mode 100644 index 0000000..93bb5cf --- /dev/null +++ b/project/plugins.sbt @@ -0,0 +1,4 @@ +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.15") +addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0") +addSbtPlugin("com.dwijnand" % "sbt-dynver" % "1.1.1") +addSbtPlugin("me.lessis" % "bintray-sbt" % "0.3.0") diff --git a/src/main/scala/sri/navigation/CreateNavigator.scala b/src/main/scala/sri/navigation/CreateNavigator.scala new file mode 100644 index 0000000..c786396 --- /dev/null +++ b/src/main/scala/sri/navigation/CreateNavigator.scala @@ -0,0 +1,16 @@ +package sri.navigation + +import sri.core.ReactElement +import sri.navigation.navigators.NavigationNavigatorConstructor + +import scala.scalajs.js +import scala.scalajs.js.annotation.JSImport + +@JSImport("react-navigation", "createNavigator") +@js.native +object CreateNavigator extends js.Object { + type NavigatorView = + js.Function1[NavigatorScreenProps[_], ReactElement] + def apply(router: NavigationRouter) + : js.Function1[NavigatorView, NavigationNavigatorConstructor] = js.native +} diff --git a/src/main/scala/sri/navigation/NavigationAwareComponents.scala b/src/main/scala/sri/navigation/NavigationAwareComponents.scala new file mode 100644 index 0000000..44a9f3a --- /dev/null +++ b/src/main/scala/sri/navigation/NavigationAwareComponents.scala @@ -0,0 +1,141 @@ +package sri.navigation + +import sri.core.{ + =:!=, + Component, + ComponentJS, + ComponentNoPS, + ComponentP, + ComponentS, + ReactClass, + ReactJSProps +} + +import scala.language.existentials +import scala.reflect.ClassTag +import scala.scalajs.js +import scala.scalajs.js.ConstructorTag +import scala.scalajs.js.annotation.ScalaJSDefined + +@ScalaJSDefined +trait ScreenClass extends ReactClass { + type ParamsType <: js.Object +} + +@ScalaJSDefined +abstract class NavigationScreenComponentP[P >: Null <: js.Object]( + implicit ev: =:!=[P, Null]) + extends NavigationScreenComponent[P, Null] {} + +@ScalaJSDefined +abstract class NavigationScreenComponentNoPS + extends NavigationScreenComponent[Null, Null] + +@ScalaJSDefined +abstract class NavigationScreenComponentS[S <: AnyRef]( + implicit ev: =:!=[S, Null]) + extends NavigationScreenComponent[Null, S] + +@ScalaJSDefined +abstract class NavigationScreenComponent[Params >: Nothing <: js.Object, +S <: AnyRef](implicit ev: =:!=[Params, Nothing]) + extends ComponentJS[NavigatorScreenProps[Params], S] + with ScreenClass { + + override type ParamsType = Params + + implicit def navigationJS = props.navigation + def navigation = NavigationCtrl + + @inline + def params: js.UndefOr[ParamsType] = props.navigation.state.params + + @inline + def setParams(params: ParamsType) = props.navigation.setParams(params) + +} + +object NavigationCtrl { + + type NV = Navigation[_] + + @inline + def navigate[C <: NavigationScreenComponent[Null, _]: ConstructorTag]( + implicit ctag: ClassTag[C], + navigation: NV) = + navigation.navigate(ctag.runtimeClass.getName) + + @inline + def navigate[C <: ScreenClass: ConstructorTag]( + params: C#ParamsType)(implicit ctag: ClassTag[C], navigation: NV) = + navigation + .navigate(ctag.runtimeClass.getName, params) + @inline + def goBack(routeKey: String)(implicit navigation: NV) = + navigation.goBack(routeKey) + + @inline + def goBack()(implicit navigation: NV) = navigation.goBack() + + @inline + def openDrawer()(implicit navigation: NV) = navigation.navigate(DRAWER_OPEN) + + @inline + def closeDrawer()(implicit navigation: NV) = + navigation.navigate(DRAWER_CLOSE) + +} +@ScalaJSDefined +abstract class NavigationAwareComponent[P >: Null <: AnyRef, + S >: Null <: AnyRef]( + implicit ev: =:!=[P, Null], + ev2: =:!=[S, Null]) + extends Component[P, S] { + + @inline + implicit def navigationJS = context.navigation.asInstanceOf[Navigation[_]] + + @inline + def navigation = NavigationCtrl +} + +@ScalaJSDefined +abstract class NavigationAwareComponentP[P >: Null <: AnyRef]( + implicit ev: =:!=[P, Null]) + extends ComponentP[P] { + + @inline + implicit def navigationJS = context.navigation.asInstanceOf[Navigation[_]] + + @inline + def navigation = NavigationCtrl +} + +@ScalaJSDefined +abstract class NavigationAwareComponentS[S >: Null <: AnyRef]( + implicit ev: =:!=[S, Null]) + extends ComponentS[S] { + + @inline + implicit def navigationJS = context.navigation.asInstanceOf[Navigation[_]] + + @inline + def navigation = NavigationCtrl +} + +@ScalaJSDefined +abstract class NavigationAwareComponentNoPS extends ComponentNoPS { + + @inline + implicit def navigationJS = context.navigation.asInstanceOf[Navigation[_]] + + @inline + def navigation = NavigationCtrl +} + +//object NavigationAwareComponent { +// @JSExportStatic +// val contextTypes = +// js.Dictionary("navigation" -> React.PropTypes.`object`.isRequired) +// +//} diff --git a/src/main/scala/sri/navigation/TypeDefinition.scala b/src/main/scala/sri/navigation/TypeDefinition.scala new file mode 100644 index 0000000..b215a1d --- /dev/null +++ b/src/main/scala/sri/navigation/TypeDefinition.scala @@ -0,0 +1,646 @@ +package sri.navigation + +import sri.core.{ReactClass, ReactElement, ReactJSProps} +import sri.macros.{FunctionObjectMacro, OptDefault, OptionalParam} + +import scala.scalajs.js +import scala.scalajs.js.Dynamic.literal +import scala.scalajs.js.annotation.ScalaJSDefined +import scala.scalajs.js.{undefined, |, UndefOr => U} + +@ScalaJSDefined +trait NavigationState extends js.Object { + val index: Double + val routes: js.Array[NavigationRoute[js.Object]] +} + +@ScalaJSDefined +trait RouteBase extends js.Object { + type ParamsType <: js.Object +} + +@ScalaJSDefined +trait NavigationRoute[Params <: js.Object] extends RouteBase { + override type ParamsType = Params + val key: String + val routeName: String + val path: U[String] = undefined + val params: U[Params] = undefined +} + +object NavigationRoute { + @inline + def apply[Params <: js.Object](key: String, + routeName: String, + path: OptionalParam[String] = OptDefault, + params: OptionalParam[Params] = OptDefault, + index: Double, + routes: js.Array[NavigationRoute[js.Object]]) + : NavigationRoute[Params] = { + val p = FunctionObjectMacro() + p.asInstanceOf[NavigationRoute[Params]] + } +} + +@ScalaJSDefined +trait NavigationRouter extends js.Object { + val getStateForAction: js.Function2[NavigationAction /*action*/, + U[NavigationState] /*lastState*/, + U[NavigationState]] + val getActionForPathAndParams: js.Function2[String /*path*/, + U[NavigationParams] /*params*/, + U[NavigationAction]] + val getPathAndParamsForState: js.Function1[NavigationState /*state*/, + js.Object] + val getComponentForRouteName: js.Function1[String /*routeName*/, + NavigationComponent] + val getComponentForState: js.Function1[NavigationState /*state*/, + NavigationComponent] + val getScreenConfig: js.Function2[ + NavigationScreenProp[NavigationRoute[js.Object]] /*navigation*/, + String /*optionName*/, + U[js.Any]] + +} + +@ScalaJSDefined +trait HeaderConfig extends js.Object { + val title: U[String | ReactElement] = undefined + val visible: U[Boolean] = undefined + val tintColor: U[String] = undefined + val backTitle: U[String] = undefined + val right: U[ReactElement] = undefined + val left: U[ReactElement] = undefined + val style: U[js.Any] = undefined + val titleStyle: U[js.Any] = undefined +} + +object HeaderConfig { + import sri.universal.DangerousUnionToJSAnyImplicit._ + @inline + def apply(title: OptionalParam[String | ReactElement] = OptDefault, + visible: OptionalParam[Boolean] = OptDefault, + tintColor: OptionalParam[String] = OptDefault, + titleStyle: OptionalParam[js.Any] = OptDefault, + backTitle: OptionalParam[String] = OptDefault, + right: OptionalParam[ReactElement] = OptDefault, + left: OptionalParam[ReactElement] = OptDefault, + style: OptionalParam[js.Any] = OptDefault): HeaderConfig = { + val p = FunctionObjectMacro() + p.asInstanceOf[HeaderConfig] + } +} + +@ScalaJSDefined +trait IconOptions extends js.Object { + + val tintColor: String + + val focused: Boolean +} + +object TabBarConfig { + @inline + def apply(icon: OptionalParam[IconOptions => ReactElement] = OptDefault, + label: OptionalParam[String] = OptDefault): TabBarConfig = { + val p = FunctionObjectMacro() + p.asInstanceOf[TabBarConfig] + } +} + +@ScalaJSDefined +trait TabBarConfig extends js.Object { + val icon: U[js.Function1[IconOptions, U[ReactElement]]] = + undefined + val label: U[String] = undefined +} + +object DrawerConfig { + @inline + def apply(icon: OptionalParam[IconOptions => ReactElement] = OptDefault, + label: OptionalParam[String] = OptDefault): DrawerConfig = { + val p = FunctionObjectMacro() + p.asInstanceOf[DrawerConfig] + } +} + +@ScalaJSDefined +trait DrawerConfig extends js.Object { + val icon: U[js.Function1[IconOptions, U[ReactElement]]] = + undefined + val label: U[String] = undefined +} + +object NavigationScreenOptionsImplicits { + implicit def ftoJSF1[T <: js.Object, R]( + in: scala.Function1[NavigationScreenProp[T], R]) + : OptionalParam[NavigationScreenOption[R, T]] = { + in: js.Function1[NavigationScreenProp[T], R] + } + + implicit def ftoJSF12[T <: js.Object, R]( + in: scala.Function2[NavigationScreenProp[T], js.Object, R]) + : OptionalParam[NavigationScreenOption[R, T]] = { + in: js.Function2[NavigationScreenProp[T], js.Object, R] + } + + implicit def ftoJSF123[T <: js.Object, R]( + in: scala.Function3[NavigationScreenProp[T], + js.Object, + U[NavigationRouter], + R]): OptionalParam[NavigationScreenOption[R, T]] = { + in: js.Function3[NavigationScreenProp[T], + js.Object, + U[NavigationRouter], + R] + } +} + +@ScalaJSDefined +trait NavigationScreenOptions extends js.Object { + type Screen <: ScreenClass + val title: U[NavigationScreenOption[String, Screen#ParamsType]] = undefined + val header: U[NavigationScreenOption[HeaderConfig, Screen#ParamsType]] = + undefined + val tabBar: U[NavigationScreenOption[TabBarConfig, Screen#ParamsType]] = + undefined + val drawer: U[NavigationScreenOption[DrawerConfig, Screen#ParamsType]] = + undefined +} + +@ScalaJSDefined +trait GenericScreen extends ScreenClass { + override type ParamsType = js.Object +} + +object NavigationScreenOptions { + import sri.universal.DangerousUnionToJSAnyImplicit._ + + @inline + def apply[S <: ScreenClass]( + title: OptionalParam[NavigationScreenOption[String, S#ParamsType]] = + OptDefault, + header: OptionalParam[NavigationScreenOption[HeaderConfig, S#ParamsType]] = + OptDefault, + tabBar: OptionalParam[NavigationScreenOption[TabBarConfig, S#ParamsType]] = + OptDefault, + drawer: OptionalParam[NavigationScreenOption[DrawerConfig, S#ParamsType]] = + OptDefault): NavigationScreenOptions { type Screen = S } = { + val p = FunctionObjectMacro() + p.asInstanceOf[NavigationScreenOptions { type Screen = S }] + } +} + +@ScalaJSDefined +trait NavigationScreenConfig extends js.Object { + val title: U[String] = undefined + val header: U[HeaderConfig] = undefined + val tabBar: U[TabBarConfig] = undefined + val drawer: U[DrawerConfig] = undefined +} + +object NavigationScreenConfig { + @inline + def apply(title: OptionalParam[String] = OptDefault, + header: OptionalParam[HeaderConfig] = OptDefault, + tabBar: OptionalParam[TabBarConfig] = OptDefault, + drawer: OptionalParam[DrawerConfig] = OptDefault) + : NavigationScreenConfig = { + val p = FunctionObjectMacro() + p.asInstanceOf[NavigationScreenConfig] + } +} + +//@ScalaJSDefined +//trait NavigationScreenComponent[T] extends js.Object {} + +@ScalaJSDefined +trait NavigationNavigator[T] extends js.Object {} + +@ScalaJSDefined +trait NavigationParams extends js.Object + +@ScalaJSDefined +trait NavigationNavigateAction extends js.Object { + var `type`: String + var routeName: String + var params: U[NavigationParams] = undefined + var action: U[NavigationNavigateAction] = undefined +} + +object NavigationNavigateAction { + + def apply(routeName: String, + params: U[NavigationParams] = undefined, + action: U[NavigationNavigateAction] = undefined) = + literal(`type` = "Navigate", + routeName = routeName, + params = params, + action = action).asInstanceOf[NavigationNavigateAction] +} + +@ScalaJSDefined +trait NavigationBackAction extends js.Object { + var `type`: String + var key: U[String] = undefined +} + +object NavigationBackAction { + + def apply(key: U[String] = undefined) = + literal(`type` = "Back", key = key).asInstanceOf[NavigationBackAction] +} + +@ScalaJSDefined +trait NavigationSetParamsAction extends js.Object { + var `type`: String + var key: String + var params: U[NavigationParams] = undefined +} + +object NavigationSetParamsAction { + def apply(key: String, params: U[NavigationParams] = undefined) = + literal(`type` = "SetParams", key = key, params = params) + .asInstanceOf[NavigationSetParamsAction] +} + +@ScalaJSDefined +trait NavigationInitAction extends js.Object { + var `type`: String +} + +object NavigationInitAction { + def apply() = literal(`type` = "Init").asInstanceOf[NavigationInitAction] +} + +@ScalaJSDefined +trait NavigationResetAction extends js.Object { + var `type`: String + var index: Double + var actions: js.Array[NavigationNavigateAction] +} + +object NavigationResetAction { + def apply(index: Double, actions: js.Array[NavigationNavigateAction]) = + literal(`type` = "Reset", index = index, actions = actions) + .asInstanceOf[NavigationResetAction] +} + +@ScalaJSDefined +trait NavigationContainerOptions extends js.Object { + val URIPrefix: U[String] = undefined +} + +object NavigationContainerOptions { + @inline + def apply(URIPrefix: OptionalParam[String] = OptDefault) + : NavigationContainerOptions = { + val p = FunctionObjectMacro() + p.asInstanceOf[NavigationContainerOptions] + } +} + +@ScalaJSDefined +trait NavigationContainerConfig extends js.Object { + val containerOptions: U[NavigationContainerOptions] = undefined +} + +object NavigationContainerConfig { + @inline + def apply( + containerOptions: OptionalParam[NavigationContainerOptions] = OptDefault) + : NavigationContainerConfig = { + val p = FunctionObjectMacro() + p.asInstanceOf[NavigationContainerConfig] + } +} + +@ScalaJSDefined +trait NavigationStackViewConfigMode extends js.Object + +object NavigationStackViewConfigMode { + @inline def CARD = "card".asInstanceOf[NavigationStackViewConfigMode] + @inline def MODAL = "modal".asInstanceOf[NavigationStackViewConfigMode] +} + +@ScalaJSDefined +trait HeaderMode extends js.Object + +object HeaderMode { + @inline def FLOAT = "float".asInstanceOf[HeaderMode] + @inline def SCREEN = "screen".asInstanceOf[HeaderMode] + @inline def NONE = "none".asInstanceOf[HeaderMode] +} + +@ScalaJSDefined +trait NavigationStackViewConfig extends js.Object { + val mode: U[NavigationStackViewConfigMode] = undefined + + val headerMode: U[HeaderMode] = undefined + val cardStyle: U[js.Any] = undefined + val onTransitionStart: U[js.Function0[_]] = undefined + val onTransitionEnd: U[js.Function0[_]] = undefined + val headerComponent: U[js.Object] = undefined +} + +object NavigationStackViewConfig { + @inline + def apply(mode: OptionalParam[NavigationStackViewConfigMode] = OptDefault, + headerMode: OptionalParam[HeaderMode] = OptDefault, + headerComponent: OptionalParam[js.Object] = OptDefault) + : NavigationStackViewConfig = { + val p = FunctionObjectMacro() + p.asInstanceOf[NavigationStackViewConfig] + } +} + +@ScalaJSDefined +trait NavigationStackRouterConfig extends js.Object { + val initialRouteName: U[String] = undefined + val initialRouteParams: U[NavigationParams] = undefined + val paths: U[NavigationPathsConfig] = undefined + val navigationOptions: U[NavigationScreenOptions] = undefined +} + +object NavigationStackRouterConfig { + @inline + def apply(initialRouteName: OptionalParam[String] = OptDefault, + initialRouteParams: OptionalParam[NavigationParams] = OptDefault, + paths: OptionalParam[NavigationPathsConfig] = OptDefault, + navigationOptions: OptionalParam[NavigationScreenOptions] = + OptDefault): NavigationStackRouterConfig = { + val p = FunctionObjectMacro() + p.asInstanceOf[NavigationStackRouterConfig] + } +} + +@ScalaJSDefined +trait NavigationScreenRouteConfig extends js.Object { + var screen: js.Any //TODO fix this + var navigationOptions: U[NavigationScreenOptions] = undefined + var path: U[String] = undefined +} + +object NavigationScreenRouteConfig { + @inline + def apply(screen: js.Any, + path: OptionalParam[String] = OptDefault, + navigationOptions: OptionalParam[NavigationScreenOptions]) + : NavigationScreenRouteConfig = { + val p = FunctionObjectMacro() + p.asInstanceOf[NavigationScreenRouteConfig] + } +} + +@ScalaJSDefined +trait NavigationScreenRouteConfigVal extends js.Object { + val screen: NavigationScreenComponent[_, _] | NavigationNavigator[_] + val navigationOptions: U[NavigationScreenOptions] = undefined + val path: U[String] = undefined +} + +@ScalaJSDefined +trait NavigationLazyScreenRouteConfig extends js.Object { + val getScreen: js.Function0[NavigationScreenComponent[_, _]] | NavigationNavigator[ + _] + val navigationOptions: U[NavigationScreenOptions] = undefined + val path: U[String] = undefined +} + +object NavigationLazyScreenRouteConfig { + import sri.universal.DangerousUnionToJSAnyImplicit._ + @inline + def apply( + getScreen: js.Function0[NavigationScreenComponent[_, _]] | NavigationNavigator[ + _], + navigationOptions: OptionalParam[NavigationScreenOptions] = OptDefault, + path: OptionalParam[String] = OptDefault) + : NavigationLazyScreenRouteConfig = { + val p = FunctionObjectMacro() + p.asInstanceOf[NavigationLazyScreenRouteConfig] + } +} +@ScalaJSDefined +trait NavigationTabRouterConfig extends js.Object { + val initialRouteName: U[String] = undefined + val paths: U[NavigationPathsConfig] = undefined + val navigationOptions: U[NavigationScreenOptions] = undefined + val order: U[js.Array[String]] = undefined +} + +object NavigationTabRouterConfig { + @inline + def apply(initialRouteName: OptionalParam[String] = OptDefault, + paths: OptionalParam[NavigationPathsConfig] = OptDefault, + navigationOptions: OptionalParam[NavigationScreenOptions] = + OptDefault, + order: OptionalParam[js.Array[String]] = OptDefault) + : NavigationTabRouterConfig = { + val p = FunctionObjectMacro() + p.asInstanceOf[NavigationTabRouterConfig] + } +} + +@ScalaJSDefined +trait NavigationProp[S] extends js.Object { + val state: S + val dispatch: NavigationDispatch[NavigationAction] +} + +@js.native +trait NavigatorScreenProps[P <: js.Object] extends ReactJSProps { + val navigation: NavigationScreenProp[P] = js.native +} + +@js.native +trait NavigationScreenProp[P <: js.Object] extends js.Object { + val state: NavigationRoute[P] = js.native + val dispatch: NavigationDispatch[NavigationAction] = js.native + def goBack(routeKey: String = ???): Boolean = + js.native + def navigate(routeName: String, + params: Any = ???, + action: NavigationAction = ???): Boolean = js.native + def setParams(newParams: P): Boolean = js.native +} + +@ScalaJSDefined +trait NavigationNavigatorProps extends js.Object { + val navigation: NavigationProp[NavigationState] + val router: NavigationRouter +} + +@ScalaJSDefined +trait NavigationLayout extends js.Object { + val height: NavigationAnimatedValue + val initHeight: Double + val initWidth: Double + val isMeasured: Boolean + val width: NavigationAnimatedValue +} + +@ScalaJSDefined +trait NavigationScene extends js.Object { + val index: Double + val isActive: Boolean + val isStale: Boolean + val key: String + val route: NavigationRoute[js.Object] +} + +@ScalaJSDefined +trait NavigationTransitionProps extends js.Object { + val layout: NavigationLayout + val navigationState: NavigationState + val position: NavigationAnimatedValue + val progress: NavigationAnimatedValue + val scenes: js.Array[NavigationScene] + val scene: NavigationScene + val index: Double + val gestureResponseDistance: U[Double] = undefined +} + +@ScalaJSDefined +trait NavigationPanHandlers extends js.Object { + val onMoveShouldSetResponder: js.Function0[Unit] + val onMoveShouldSetResponderCapture: js.Function0[Unit] + val onResponderEnd: js.Function0[Unit] + val onResponderGrant: js.Function0[Unit] + val onResponderMove: js.Function0[Unit] + val onResponderReject: js.Function0[Unit] + val onResponderRelease: js.Function0[Unit] + val onResponderStart: js.Function0[Unit] + val onResponderTerminate: js.Function0[Unit] + val onResponderTerminationRequest: js.Function0[Unit] + val onStartShouldSetResponder: js.Function0[Unit] + val onStartShouldSetResponderCapture: js.Function0[Unit] +} + +@ScalaJSDefined +trait NavigationTransitionSpec extends js.Object { + val duration: U[Double] = undefined + val easing: U[js.Function0[js.Any]] = undefined + val timing: U[js.Function2[NavigationAnimatedValue /*value*/, + js.Any /*config*/, + js.Any]] = undefined +} + +object NavigationTransitionSpec { + @inline + def apply( + duration: OptionalParam[Double] = OptDefault, + easing: OptionalParam[js.Function0[js.Any]] = OptDefault, + timing: OptionalParam[ + (NavigationAnimatedValue /*value*/, js.Any /*config*/ ) => js.Any] = + OptDefault): NavigationTransitionSpec = { + val p = FunctionObjectMacro() + p.asInstanceOf[NavigationTransitionSpec] + } +} + +@ScalaJSDefined +trait NavigationGestureDirection extends js.Object + +object NavigationGestureDirection { + @inline def HORIZONTAL = + "horizontal".asInstanceOf[NavigationGestureDirection] + @inline def VERTICAL = "vertical".asInstanceOf[NavigationGestureDirection] + +} + +@ScalaJSDefined +trait TabBarPosition extends js.Object + +object TabBarPosition { + @inline def TOP = "top".asInstanceOf[TabBarPosition] + @inline def BOTTOM = "bottom".asInstanceOf[TabBarPosition] +} + +@ScalaJSDefined +trait TabBarOptions extends js.Object { + val activeTintColor: U[String] = undefined + val showIcon: U[Boolean] = undefined +} + +object TabBarOptions { + @inline + def apply(activeTintColor: OptionalParam[String] = OptDefault, + showIcon: OptionalParam[Boolean] = OptDefault): TabBarOptions = { + val p = FunctionObjectMacro() + p.asInstanceOf[TabBarOptions] + } +} +@ScalaJSDefined +trait TabViewConfig extends js.Object { + val tabBarComponent: U[ReactClass] = undefined + val tabBarPosition: U[TabBarPosition] = undefined + val tabBarOptions: U[js.Object] = undefined + val swipeEnabled: U[Boolean] = undefined + val animationEnabled: U[Boolean] = undefined + val lazyLoad: U[Boolean] = undefined +} + +object TabViewConfig { + @inline + def apply(tabBarComponent: OptionalParam[ReactClass] = OptDefault, + tabBarPosition: OptionalParam[TabBarPosition] = OptDefault, + tabBarOptions: OptionalParam[js.Object] = OptDefault, + swipeEnabled: OptionalParam[Boolean] = OptDefault, + animationEnabled: OptionalParam[Boolean] = OptDefault, + lazyLoad: OptionalParam[Boolean] = OptDefault): TabViewConfig = { + val p = FunctionObjectMacro() + p.asInstanceOf[TabViewConfig] + } +} + +@ScalaJSDefined +trait DrawerPosition extends js.Object + +object DrawerPosition { + + @inline def LEFT = "left".asInstanceOf[DrawerPosition] + @inline def RIGHT = "right".asInstanceOf[DrawerPosition] +} + +@ScalaJSDefined +trait DrawerContentOptions extends js.Object { + val activeTintColor: U[String] = undefined + val activeBackgroundColor: U[String] = undefined + val inactiveTintColor: U[String] = undefined + val inactiveBackgroundColor: U[String] = undefined + val style: U[js.Any] = undefined +} + +object DrawerContentOptions { + @inline + def apply( + activeTintColor: OptionalParam[String] = OptDefault, + activeBackgroundColor: OptionalParam[String] = OptDefault, + inactiveTintColor: OptionalParam[String] = OptDefault, + inactiveBackgroundColor: OptionalParam[String] = OptDefault, + style: OptionalParam[js.Any] = OptDefault): DrawerContentOptions = { + val p = FunctionObjectMacro() + p.asInstanceOf[DrawerContentOptions] + } +} + +@ScalaJSDefined +trait DrawerViewConfig extends js.Object { + val drawerWidth: U[Double] = undefined + val drawerPosition: U[DrawerPosition] = undefined + val contentComponent: U[ReactClass] = undefined + val contentOptions: U[js.Object] = undefined + val style: U[js.Any] = undefined +} + +object DrawerViewConfig { + @inline + def apply(drawerWidth: OptionalParam[Double] = OptDefault, + drawerPosition: OptionalParam[DrawerPosition] = OptDefault, + contentComponent: OptionalParam[ReactClass] = OptDefault, + contentOptions: OptionalParam[js.Object] = OptDefault, + style: OptionalParam[js.Any] = OptDefault): DrawerViewConfig = { + val p = FunctionObjectMacro() + p.asInstanceOf[DrawerViewConfig] + } +} diff --git a/src/main/scala/sri/navigation/Views.scala b/src/main/scala/sri/navigation/Views.scala new file mode 100644 index 0000000..4efc7f1 --- /dev/null +++ b/src/main/scala/sri/navigation/Views.scala @@ -0,0 +1,17 @@ +package sri.navigation + +import sri.core.{CreateElementJS, JSComponent, ReactClass} + +import scala.scalajs.js +import scala.scalajs.js.annotation.JSImport + +@js.native +@JSImport("react-navigation", "DrawerView.Items") +object DrawerViewItemsComponent extends JSComponent[js.Object] + +object DrawerViewItems { + @inline + def apply(props: Navigation[_]) = + CreateElementJS[DrawerViewItemsComponent.type](DrawerViewItemsComponent, + props) +} diff --git a/src/main/scala/sri/navigation/navigators/package.scala b/src/main/scala/sri/navigation/navigators/package.scala new file mode 100644 index 0000000..8ad914e --- /dev/null +++ b/src/main/scala/sri/navigation/navigators/package.scala @@ -0,0 +1,150 @@ +package sri.navigation + +import sri.core.{ComponentConstructor, ReactClass, ReactElement} +import sri.macros.{FunctionObjectMacro, OptDefault, OptionalParam} + +import scala.scalajs.js +import scala.scalajs.js.annotation.{JSImport, ScalaJSDefined} + +package object navigators { + + @ScalaJSDefined + trait NavigationNavigatorConstructor extends ComponentConstructor { + override type PropsType = NavigationNavigatorProps + } + + @ScalaJSDefined + trait StackNavigatorConfig + extends NavigationContainerConfig + with NavigationStackViewConfig + with NavigationStackRouterConfig + + object StackNavigatorConfig { + @inline + def apply(containerOptions: OptionalParam[NavigationContainerOptions] = + OptDefault, + mode: OptionalParam[NavigationStackViewConfigMode] = OptDefault, + headerMode: OptionalParam[HeaderMode] = OptDefault, + cardStyle: OptionalParam[js.Any] = OptDefault, + onTransitionStart: OptionalParam[() => _] = OptDefault, + onTransitionEnd: OptionalParam[() => _] = OptDefault, + headerComponent: OptionalParam[js.Object] = OptDefault, + initialRouteName: OptionalParam[String] = OptDefault, + initialRouteParams: OptionalParam[js.Object] = OptDefault, + paths: OptionalParam[NavigationPathsConfig] = OptDefault, + navigationOptions: OptionalParam[NavigationScreenOptions] = + OptDefault): StackNavigatorConfig = { + val p = FunctionObjectMacro() + p.asInstanceOf[StackNavigatorConfig] + } + } + + @JSImport("react-navigation", "StackNavigator") + @js.native + object StackNavigatorJS extends js.Object { + + def apply(routeConfigMap: NavigationRouteConfigMap, + stackConfig: StackNavigatorConfig = ???) + : NavigationNavigatorConstructor = + js.native + } + + @inline + def StackNavigator(routes: (String, NavigationRouteConfig)*) = + StackNavigatorJS(js.Dictionary(routes: _*)) + + @inline + def StackNavigator(stackConfig: StackNavigatorConfig, + routes: (String, NavigationRouteConfig)*) = + StackNavigatorJS(js.Dictionary(routes: _*), stackConfig) + + @ScalaJSDefined + trait TabNavigatorConfig + extends NavigationTabRouterConfig + with TabViewConfig + with NavigationContainerConfig + + object TabNavigatorConfig { + @inline + def apply( + initialRouteName: OptionalParam[String] = OptDefault, + paths: OptionalParam[NavigationPathsConfig] = OptDefault, + navigationOptions: OptionalParam[NavigationScreenOptions] = OptDefault, + order: OptionalParam[js.Array[String]] = OptDefault, + tabBarComponent: OptionalParam[ReactClass] = OptDefault, + tabBarPosition: OptionalParam[TabBarPosition] = OptDefault, + tabBarOptions: OptionalParam[js.Object] = OptDefault, + swipeEnabled: OptionalParam[Boolean] = OptDefault, + animationEnabled: OptionalParam[Boolean] = OptDefault, + containerOptions: OptionalParam[NavigationContainerOptions] = + OptDefault, + lazyLoad: OptionalParam[Boolean] = OptDefault): TabNavigatorConfig = { + val p = FunctionObjectMacro() + p.asInstanceOf[TabNavigatorConfig] + } + } + + @JSImport("react-navigation", "TabNavigator") + @js.native + object TabNavigatorJS extends js.Object { + + def apply( + routeConfigMap: NavigationRouteConfigMap, + tabConfig: TabNavigatorConfig = ???): NavigationNavigatorConstructor = + js.native + } + + @inline + def TabNavigator(routes: (String, NavigationRouteConfig)*) = + TabNavigatorJS(js.Dictionary(routes: _*)) + + @inline + def TabNavigator(tabConfig: TabNavigatorConfig, + routes: (String, NavigationRouteConfig)*) = + TabNavigatorJS(js.Dictionary(routes: _*), tabConfig) + + @ScalaJSDefined + trait DrawerNavigatorConfig + extends NavigationTabRouterConfig + with DrawerViewConfig + with NavigationContainerConfig + + object DrawerNavigatorConfig { + @inline + def apply(initialRouteName: OptionalParam[String] = OptDefault, + paths: OptionalParam[NavigationPathsConfig] = OptDefault, + navigationOptions: OptionalParam[NavigationScreenOptions] = + OptDefault, + order: OptionalParam[js.Array[String]] = OptDefault, + drawerWidth: OptionalParam[Double] = OptDefault, + drawerPosition: OptionalParam[DrawerPosition] = OptDefault, + contentComponent: OptionalParam[Navigation[_] => ReactElement] = + OptDefault, + contentOptions: OptionalParam[js.Object] = OptDefault, + style: OptionalParam[js.Any] = OptDefault, + containerOptions: OptionalParam[NavigationContainerOptions] = + OptDefault): DrawerNavigatorConfig = { + val p = FunctionObjectMacro() + p.asInstanceOf[DrawerNavigatorConfig] + } + } + + @JSImport("react-navigation", "DrawerNavigator") + @js.native + object DrawerNavigatorJS extends js.Object { + + def apply(routeConfigMap: NavigationRouteConfigMap, + drawerConfig: DrawerNavigatorConfig = ???) + : NavigationNavigatorConstructor = + js.native + } + + @inline + def DrawerNavigator(routes: (String, NavigationRouteConfig)*) = + DrawerNavigatorJS(js.Dictionary(routes: _*)) + + @inline + def DrawerNavigator(tabConfig: DrawerNavigatorConfig, + routes: (String, NavigationRouteConfig)*) = + DrawerNavigatorJS(js.Dictionary(routes: _*), tabConfig) +} diff --git a/src/main/scala/sri/navigation/package.scala b/src/main/scala/sri/navigation/package.scala new file mode 100644 index 0000000..8728bde --- /dev/null +++ b/src/main/scala/sri/navigation/package.scala @@ -0,0 +1,126 @@ +package sri + +import sri.core.{ComponentConstructor, React, ReactElement} +import sri.macros.{OptDefault, OptionalParam} +import sri.navigation.navigators.NavigationNavigatorConstructor +import sri.universal.apis.AnimatedValue + +import scala.reflect.ClassTag +import scala.scalajs.js +import scala.scalajs.js.annotation.{JSImport, ScalaJSDefined} +import scala.scalajs.js.{ConstructorTag, |} + +package object navigation { + + type NavigationAnimatedValue = AnimatedValue + type NavigationSceneRendererProps = NavigationTransitionProps + type NavigationAnimationSetter = + js.Function3[NavigationAnimatedValue /*position*/, + NavigationState /*newState*/, + NavigationState /*lastState*/, + Unit] + type NavigationSceneRenderer = + js.Function1[NavigationSceneRendererProps /*props*/, + js.UndefOr[ReactElement]] + type NavigationStyleInterpolator = + js.Function1[NavigationSceneRendererProps /*props*/, js.Object] + + type NavigationDispatch[A] = js.Function1[A /*action*/, Boolean] + + type NavigationPathsConfig = js.Dictionary[String] + + type NavigationRouteConfigMap = js.Dictionary[NavigationRouteConfig] + + type NavigationComponent = + NavigationScreenComponentConstructor | NavigationNavigatorConstructor + + type NavigationScreenOption[T, P <: js.Object] = + js.Function1[NavigationScreenProp[P], T] | + js.Function2[NavigationScreenProp[P], js.Object, T] | + js.Function3[NavigationScreenProp[P], + js.Object, + js.UndefOr[NavigationRouter], + T] | T + + type NavigationStackAction = + NavigationInitAction | NavigationNavigateAction | NavigationBackAction | NavigationSetParamsAction | NavigationResetAction + + type NavigationTabAction = + NavigationInitAction | NavigationNavigateAction | NavigationBackAction + + type NavigationAction = + NavigationInitAction | NavigationStackAction | NavigationTabAction + + type NavigationRouteConfig = + NavigationScreenRouteConfig | NavigationLazyScreenRouteConfig + + type Navigation[P <: js.Object] = NavigationScreenProp[P] + + @inline + def registerScreen[C <: NavigationScreenComponent[_, _]: ConstructorTag]( + implicit ctag: ClassTag[C]): (String, NavigationRouteConfig) = { + registerRoute(ctag.runtimeClass.getName, js.constructorTag[C].constructor) + } + + @inline + def registerScreen[C <: NavigationScreenComponent[_, _]: ConstructorTag]( + path: OptionalParam[String] = OptDefault, + navigationOptions: OptionalParam[NavigationScreenOptions] = OptDefault)( + implicit ctag: ClassTag[C]): (String, NavigationRouteConfig) = { + registerRoute(ctag.runtimeClass.getName, + js.constructorTag[C].constructor, + path, + navigationOptions) + + } + + @inline + def registerNavigator( + name: String, + navigator: NavigationNavigatorConstructor, + path: OptionalParam[String] = OptDefault, + navigationOptions: OptionalParam[NavigationScreenOptions] = OptDefault) + : (String, NavigationRouteConfig) = + registerRoute(name, + comp = navigator, + path = path, + navigationOptions = navigationOptions) + + @inline + private def registerRoute( + name: String, + comp: js.Any, + path: OptionalParam[String] = OptDefault, + navigationOptions: OptionalParam[NavigationScreenOptions] = OptDefault) + : (String, NavigationRouteConfig) = + name -> NavigationScreenRouteConfig(screen = comp, + path = path, + navigationOptions = navigationOptions) + + @inline + def getScreenName[C <: NavigationScreenComponent[_, _]: ConstructorTag]( + implicit ctag: ClassTag[C]) = ctag.runtimeClass.getName + + @js.native + @JSImport("react-navigation", "NavigationActions") + object NavigationActions extends js.Object { + def reset(payload: js.Object): NavigationResetAction = js.native + def navigate(payload: js.Object): NavigationAction = js.native + } + + @inline def DRAWER_OPEN = "DrawerOpen" + @inline def DRAWER_CLOSE = "DrawerClose" + + @ScalaJSDefined + sealed trait NavigationScreenComponentConstructor + extends ComponentConstructor + + def screenConstructor[C <: ScreenClass: js.ConstructorTag] = + js.constructorTag[C] + .constructor + .asInstanceOf[NavigationScreenComponentConstructor] + + val navigationContextType = + js.Dictionary("navigation" -> React.PropTypes.`object`.isRequired) + +} diff --git a/src/main/scala/sri/navigation/routers/package.scala b/src/main/scala/sri/navigation/routers/package.scala new file mode 100644 index 0000000..141ff76 --- /dev/null +++ b/src/main/scala/sri/navigation/routers/package.scala @@ -0,0 +1,75 @@ +package sri.navigation + +import sri.macros.{FunctionObjectMacro, OptDefault, OptionalParam} + +import scala.scalajs.js +import scala.scalajs.js.annotation.{JSImport, ScalaJSDefined} + +package object routers { + + @ScalaJSDefined + trait StackRouterConfig extends js.Object + + object StackRouterConfig { + @inline + def apply(initialRouteName: OptionalParam[String] = OptDefault, + initialRouteParams: OptionalParam[js.Object] = OptDefault, + paths: OptionalParam[NavigationPathsConfig] = OptDefault, + navigationOptions: OptionalParam[NavigationScreenOptions] = + OptDefault): StackRouterConfig = { + val p = FunctionObjectMacro() + p.asInstanceOf[StackRouterConfig] + } + } + + @JSImport("react-navigation", "StackRouter") + @js.native + object StackRouterJS extends js.Object { + + def apply(routeConfigMap: NavigationRouteConfigMap, + stackConfig: StackRouterConfig = ???): NavigationRouter = + js.native + } + + @inline + def StackRouter(routes: (String, NavigationRouteConfig)*) = + StackRouterJS(js.Dictionary(routes: _*)) + + @inline + def StackRouter(stackConfig: StackRouterConfig, + routes: (String, NavigationRouteConfig)*) = + StackRouterJS(js.Dictionary(routes: _*), stackConfig) + + @ScalaJSDefined + trait TabRouterConfig extends js.Object + + object TabRouterConfig { + @inline + def apply(initialRouteName: OptionalParam[String] = OptDefault, + initialRouteParams: OptionalParam[js.Object] = OptDefault, + backBehavior: OptionalParam[String] = OptDefault, + paths: OptionalParam[NavigationPathsConfig] = OptDefault, + navigationOptions: OptionalParam[NavigationScreenOptions] = + OptDefault): TabRouterConfig = { + val p = FunctionObjectMacro() + p.asInstanceOf[TabRouterConfig] + } + } + + @JSImport("react-navigation", "TabRouter") + @js.native + object TabRouterJS extends js.Object { + + def apply(routeConfigMap: NavigationRouteConfigMap, + tabConfig: TabRouterConfig = ???): NavigationRouter = js.native + } + + @inline + def TabRouter(routes: (String, NavigationRouteConfig)*) = + TabRouterJS(js.Dictionary(routes: _*)) + + @inline + def TabRouter(tabConfig: TabRouterConfig, + routes: (String, NavigationRouteConfig)*) = + TabRouterJS(js.Dictionary(routes: _*), tabConfig) +} diff --git a/src/test/scala/sri/navigation/BaseTest.scala b/src/test/scala/sri/navigation/BaseTest.scala new file mode 100644 index 0000000..c37901a --- /dev/null +++ b/src/test/scala/sri/navigation/BaseTest.scala @@ -0,0 +1,19 @@ +package sri.navigation; + +import org.scalactic.source.Position +import org.scalatest._ + +import scala.scalajs.js.JavaScriptException + +class BaseTest extends FunSuite with BeforeAndAfter{ + + override protected def test(testName: String, testTags: org.scalatest.Tag*)(testFun: => Any)(implicit pos: Position) = { + super.test(testName, testTags: _*)(try testFun catch { + case jse @ JavaScriptException(e) => + println(e) + jse.printStackTrace() + throw jse + }) + } + +}