Last active
April 12, 2017 16:23
-
-
Save DylanLukes/c12dac25eaa2b99ce805ba124bf42ea4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.emg.slidedeck.js.sui | |
import com.emg.slidedeck.js.macros.ScalaJSDefinedApply | |
import japgolly.scalajs.react.CtorType.ChildArg | |
import japgolly.scalajs.react.{Children, JsFnComponent} | |
import scala.scalajs.js | |
import scala.scalajs.js.{UndefOr, |} | |
import scala.scalajs.js.annotation.{JSImport, ScalaJSDefined} | |
object Grid { | |
val Row = GridRow | |
val Column = GridColumn | |
@JSImport("semantic-ui-react", "Grid") | |
@js.native | |
object Raw extends js.Object | |
@ScalaJSDefined | |
@ScalaJSDefinedApply | |
trait Props extends js.Object { | |
// TODO: Some of these methods could take Enums instead. | |
/** An element type to render as (string or function). */ | |
val as: UndefOr[String | js.Function] = js.undefined | |
/** A grid can have rows divided into cells. */ | |
val celled: UndefOr[Boolean | String] = js.undefined | |
/** A grid can have its columns centered. */ | |
val centered: UndefOr[Boolean] = js.undefined | |
/** Additional classes. */ | |
val className: UndefOr[String] = js.undefined | |
/** Represents column count per row in Grid. */ | |
val columns: UndefOr[String] = js.undefined | |
/** A grid can be combined with a container to use avaiable layout and alignment. */ | |
val container: UndefOr[Boolean] = js.undefined | |
/** A grid can have dividers between its columns. */ | |
val divided: UndefOr[Boolean | String] = js.undefined | |
/** A grid can double its column width on tablet and mobile sizes. */ | |
val doubling: UndefOr[Boolean] = js.undefined | |
/** A grid can preserve its vertical and horizontal gutters on first and last columns. */ | |
val padded: UndefOr[Boolean | String] = js.undefined | |
/** A grid can increase its gutters to allow for more negative space. */ | |
val relaxed: UndefOr[Boolean | String] = js.undefined | |
/** A grid can specify that its columns should reverse order at different device sizes. */ | |
val reversed: UndefOr[String] = js.undefined | |
/** A grid can have its columns stack on-top of each other after reaching mobile breakpoints. */ | |
val stackable: UndefOr[Boolean] = js.undefined | |
/** An can stretch its contents to take up the entire grid height. */ | |
val stretched: UndefOr[Boolean] = js.undefined | |
/** A grid can specify its text alignment. */ | |
val textAlign: UndefOr[String] = js.undefined | |
/** A grid can specify its vertical alignment to have all its columns vertically centered. */ | |
val verticalAlign: UndefOr[String] = js.undefined | |
} | |
private val Component = JsFnComponent[Props, Children.Varargs](Raw) | |
def apply(P: Props = new Props {})(S: ChildArg*) = Component(P)(S: _*) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.emg.slidedeck.js.macros | |
import scala.collection.immutable.Seq | |
import scala.meta._ | |
class ScalaJSDefinedApply extends scala.annotation.StaticAnnotation { | |
inline def apply(defn: Any): Any = meta { | |
def collectFields(trt: Defn.Trait) = { | |
trt.collect { | |
case dv @ Defn.Val(_, pats, Some(tpe), q"js.undefined") => | |
pats.map { case Pat.Var.Term(name) => (name, tpe, q"js.undefined") } | |
case dv @ Defn.Val(_, _, None, q"js.undefined") => | |
abort(s"@ScalaJSDefinedApply: $dv must have explicit type declarations.") | |
case dv @ Defn.Val(_, _, _, _) => | |
abort(s"@ScalaJSDefinedApply: $dv must have = js.undefined.") | |
}.flatten | |
} | |
def genApply(tname: Type.Name, fields: Seq[(Term.Name, Type, Term)]): Defn.Def = { | |
val params = fields.map { case (name, tpe, default) => | |
param"$name: $tpe = $default" | |
} | |
val args = fields.map { case (name, _, _) => | |
arg"(${Lit.String(name.value)}, ${name}.asInstanceOf[js.Any])" | |
} | |
q"def apply(..$params): $tname = js.Dynamic.literal(..$args).asInstanceOf[$tname]" | |
} | |
defn match { | |
// A companion Object already exists in scope. Modify it. | |
case Term.Block(Seq( | |
dt @ Defn.Trait(_, tname, _, _, _), | |
companion: Defn.Object | |
)) => | |
val fields = collectFields(dt) | |
val applyMethod = genApply(tname, fields) | |
Term.Block(Seq(dt, companion.copy( | |
templ = companion.templ.copy( | |
stats = companion.templ.stats.map { applyMethod +: _ } | |
)) | |
)) | |
// A companion Object does not yet exist. | |
case dt @ Defn.Trait(_, tname, _, _, _) => | |
val fields = collectFields(dt) | |
val applyMethod = genApply(tname, fields) | |
val companion = q"object ${Term.Name(tname.value)} { $applyMethod }" | |
// println(companion) | |
Term.Block(Seq(dt, companion)) | |
case _ => | |
abort("@ScalaJSDefinedApply must annotate a trait.") | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment