package com.payalabs.scalajs.react import scala.concurrent.{ExecutionContext, Future} import scala.language.experimental.macros import scala.reflect.ClassTag import scala.scalajs.js import scala.scalajs.js.JSConverters._ import scala.scalajs.js.{Object, |} import japgolly.scalajs.react.component.Js import japgolly.scalajs.react.vdom.{TagMod, VdomElement, VdomNode} import japgolly.scalajs.react.{CallbackTo, Children, CtorType} import japgolly.scalajs.react.vdom.Implicits._ package object bridge extends GeneratedImplicits { def writerFromConversion[A](implicit conv: A => js.Any): JsWriter[A] = JsWriter(x => x) implicit def stringWriter: JsWriter[String] = writerFromConversion[String] implicit def boolWriter: JsWriter[Boolean] = writerFromConversion[Boolean] // Note: Char and Long not supported here, since in Scala.js they map to opaque types, which // may not map well to the underlying components expectations. implicit def byteWriter: JsWriter[Byte] = writerFromConversion[Byte] implicit def shortWriter: JsWriter[Short] = writerFromConversion[Short] implicit def intWriter: JsWriter[Int] = writerFromConversion[Int] implicit def floatWriter: JsWriter[Float] = writerFromConversion[Float] implicit def doubleWriter: JsWriter[Double] = writerFromConversion[Double] implicit def unitWriter: JsWriter[Unit] = writerFromConversion[Unit] implicit def jsAnyWriter[A <: js.Any]: JsWriter[A] = JsWriter(identity) implicit def callbackToWriter[T](implicit writerT: JsWriter[T]): JsWriter[CallbackTo[T]] = JsWriter(value => value.map(writerT.toJs).runNow()) implicit def undefOrWriter[A](implicit writerA: JsWriter[A]): JsWriter[js.UndefOr[A]] = JsWriter(_.map(writerA.toJs)) implicit def optionWriter[A](implicit writerA: JsWriter[A]): JsWriter[Option[A]] = JsWriter(_.map(writerA.toJs).orUndefined) implicit def unionWriter[A, B](implicit A: ClassTag[A], writerA: JsWriter[A], B: ClassTag[B], writerB: JsWriter[B]): JsWriter[A | B] = JsWriter { value => A.unapply(value).map(writerA.toJs) .orElse(B.unapply(value).map(writerB.toJs)) .getOrElse(throw new RuntimeException(s"Value $value of type ($A | $B) matched neither}")) } implicit def enumerationWriter[T <: Enumeration#Value]: JsWriter[T] = JsWriter(_.toString) implicit def baseSeqWriter[T: JsWriter]: JsWriter[scala.collection.Seq[T]] = { val elementWriter = implicitly[JsWriter[T]] JsWriter(_.map(elementWriter.toJs).toJSArray) } implicit def immutableSeqWriter[T : JsWriter]: JsWriter[scala.collection.immutable.Seq[T]] = { val elementWriter = implicitly[JsWriter[T]] JsWriter((value: scala.collection.immutable.Seq[T]) => js.Array(value.map(e => elementWriter.toJs(e)): _*)) } implicit def mapWriter[T : JsWriter]: JsWriter[Map[String, T]] = { val elementWriter = implicitly[JsWriter[T]] JsWriter( (value: Map[String, T]) => { val converted = value.map { case (k, v) => (k, elementWriter.toJs(v)) } js.Dictionary(converted.toSeq: _*) } ) } implicit def futureWriter[A](implicit writeA: JsWriter[A], executionContext: ExecutionContext): JsWriter[Future[A]] = JsWriter(_.map(writeA.toJs).toJSPromise) implicit def vdomElementWriter: JsWriter[VdomElement] = JsWriter(_.rawElement) type JsComponentType = Js.ComponentSimple[Object, CtorType.Summoner.Aux[Object, Children.Varargs, CtorType.PropsAndChildren]#CT, Js.UnmountedWithRawType[Object, Null, Js.RawMounted[Object, Null]]] def extractPropsAndChildren(attrAndChildren: Seq[TagMod]): (js.Object, List[VdomNode]) = { val b = new japgolly.scalajs.react.vdom.Builder.ToJs {} attrAndChildren.toTagMod.applyTo(b) b.addClassNameToProps() b.addStyleToProps() (b.props, b.childrenAsVdomNodes) } }