mirror of
https://github.com/phfroidmont/scalive.git
synced 2025-12-25 05:26:59 +01:00
Add all phx html attributes
This commit is contained in:
parent
42f1729745
commit
763788fb89
6 changed files with 171 additions and 47 deletions
|
|
@ -2,8 +2,8 @@ package scalive
|
|||
|
||||
import scalive.Mod.Attr
|
||||
import scalive.Mod.Content
|
||||
import scalive.codecs.BooleanAsAttrPresenceCodec
|
||||
import scalive.codecs.Codec
|
||||
import scalive.codecs.BooleanAsAttrPresenceEncoder
|
||||
import scalive.codecs.Encoder
|
||||
import zio.json.*
|
||||
|
||||
class HtmlElement(val tag: HtmlTag, val mods: Vector[Mod]):
|
||||
|
|
@ -43,8 +43,8 @@ class HtmlTag(val name: String, val void: Boolean = false):
|
|||
}
|
||||
)
|
||||
|
||||
class HtmlAttr[V](val name: String, val codec: Codec[V, String]):
|
||||
private inline def isBooleanAsAttrPresence = codec == BooleanAsAttrPresenceCodec
|
||||
class HtmlAttr[V](val name: String, val codec: Encoder[V, String]):
|
||||
private inline def isBooleanAsAttrPresence = codec == BooleanAsAttrPresenceEncoder
|
||||
|
||||
def :=(value: V): Mod.Attr =
|
||||
if isBooleanAsAttrPresence then
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
import scalive.codecs.BooleanAsAttrPresenceCodec
|
||||
import scalive.codecs.StringAsIsCodec
|
||||
import scalive.codecs.BooleanAsAttrPresenceEncoder
|
||||
import scalive.codecs.BooleanAsTrueFalseStringEncoder
|
||||
import scalive.codecs.Encoder
|
||||
import scalive.codecs.IntAsStringEncoder
|
||||
import scalive.codecs.StringAsIsEncoder
|
||||
import scalive.defs.attrs.HtmlAttrs
|
||||
import scalive.defs.complex.ComplexHtmlKeys
|
||||
import scalive.defs.tags.HtmlTags
|
||||
|
||||
package object scalive extends HtmlTags with HtmlAttrs with ComplexHtmlKeys:
|
||||
|
||||
lazy val defer = htmlAttr("defer", codecs.BooleanAsAttrPresenceCodec)
|
||||
lazy val defer = htmlAttr("defer", codecs.BooleanAsAttrPresenceEncoder)
|
||||
|
||||
object link:
|
||||
def navigate(path: String, mods: Mod*): HtmlElement =
|
||||
|
|
@ -14,20 +17,76 @@ package object scalive extends HtmlTags with HtmlAttrs with ComplexHtmlKeys:
|
|||
|
||||
object phx:
|
||||
private def phxAttr(suffix: String): HtmlAttr[String] =
|
||||
new HtmlAttr(s"phx-$suffix", StringAsIsCodec)
|
||||
new HtmlAttr(s"phx-$suffix", StringAsIsEncoder)
|
||||
private def phxAttrBool(suffix: String): HtmlAttr[Boolean] =
|
||||
new HtmlAttr(s"phx-$suffix", BooleanAsTrueFalseStringEncoder)
|
||||
private def phxAttrInt(suffix: String): HtmlAttr[Int] =
|
||||
new HtmlAttr(s"phx-$suffix", IntAsStringEncoder)
|
||||
private def phxAttrJson(suffix: String): HtmlAttrJsonValue =
|
||||
new HtmlAttrJsonValue(s"phx-$suffix")
|
||||
private def dataPhxAttr(suffix: String): HtmlAttr[String] =
|
||||
dataAttr(s"phx-$suffix")
|
||||
|
||||
private[scalive] lazy val session = dataPhxAttr("session")
|
||||
private[scalive] lazy val main = htmlAttr("data-phx-main", BooleanAsAttrPresenceCodec)
|
||||
private[scalive] lazy val main = htmlAttr("data-phx-main", BooleanAsAttrPresenceEncoder)
|
||||
private[scalive] lazy val link = dataPhxAttr("link")
|
||||
private[scalive] lazy val linkState = dataPhxAttr("link-state")
|
||||
lazy val click = phxAttrJson("click")
|
||||
def value(key: String) = phxAttr(s"value-$key")
|
||||
lazy val trackStatic = htmlAttr("phx-track-static", BooleanAsAttrPresenceCodec)
|
||||
|
||||
// Click
|
||||
lazy val click = phxAttrJson("click")
|
||||
lazy val clickAway = phxAttrJson("click-away")
|
||||
// Focus
|
||||
lazy val blur = phxAttrJson("blur")
|
||||
lazy val focus = phxAttrJson("focus")
|
||||
lazy val windowBlur = phxAttrJson("window-blur")
|
||||
|
||||
// Keyboard
|
||||
lazy val keydown = phxAttrJson("keydown")
|
||||
lazy val keyup = phxAttrJson("keyup")
|
||||
lazy val windowKeydown = phxAttrJson("window-keydown")
|
||||
lazy val windowKeyup = phxAttrJson("window-keyup")
|
||||
lazy val key = phxAttr("key")
|
||||
|
||||
// Scroll
|
||||
lazy val viewportTop = phxAttrJson("viewport-top")
|
||||
lazy val viewportBottom = phxAttrJson("viewport-bottom")
|
||||
|
||||
// Form
|
||||
lazy val change = phxAttrJson("change")
|
||||
lazy val submit = phxAttrJson("submit")
|
||||
lazy val autoRecover = phxAttrJson("auto-recover")
|
||||
lazy val triggerAction = phxAttrBool("trigger-action")
|
||||
|
||||
// Button
|
||||
lazy val disableWith = phxAttr("disable-with")
|
||||
|
||||
// Socket connection lifecycle
|
||||
lazy val connected = phxAttrJson("connected")
|
||||
lazy val disconnected = phxAttrJson("disconnected")
|
||||
|
||||
// DOM element lifecycle
|
||||
lazy val mounted = phxAttrJson("mounted")
|
||||
lazy val remove = phxAttrJson("remove")
|
||||
lazy val update = new HtmlAttr["update" | "stream" | "ignore"](s"phx-update", Encoder(identity))
|
||||
|
||||
// Client hooks
|
||||
lazy val hook = phxAttr("hook")
|
||||
|
||||
// Rate limiting
|
||||
lazy val debounce = new HtmlAttr["blur" | Int](
|
||||
s"phx-debounce",
|
||||
Encoder {
|
||||
case _: "blur" => "blur"
|
||||
case value: Int => value.toString
|
||||
}
|
||||
)
|
||||
lazy val throttle = phxAttrInt("throttle")
|
||||
|
||||
def value(key: String) = phxAttr(s"value-$key")
|
||||
lazy val trackStatic = htmlAttr("phx-track-static", BooleanAsAttrPresenceEncoder)
|
||||
end phx
|
||||
|
||||
implicit def stringToMod(v: String): Mod = Mod.Content.Text(v)
|
||||
implicit def htmlElementToMod(el: HtmlElement): Mod = Mod.Content.Tag(el)
|
||||
implicit def dynStringToMod(d: Dyn[String]): Mod = Mod.Content.DynText(d)
|
||||
end scalive
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
package scalive.codecs
|
||||
|
||||
class Codec[ScalaType, DomType](val encode: ScalaType => DomType, val decode: DomType => ScalaType)
|
||||
|
||||
def AsIsCodec[V](): Codec[V, V] = Codec(identity, identity)
|
||||
|
||||
val StringAsIsCodec: Codec[String, String] = AsIsCodec()
|
||||
|
||||
val IntAsIsCodec: Codec[Int, Int] = AsIsCodec()
|
||||
|
||||
lazy val IntAsStringCodec: Codec[Int, String] = Codec[Int, String](_.toString, _.toInt)
|
||||
|
||||
lazy val DoubleAsIsCodec: Codec[Double, Double] = AsIsCodec()
|
||||
|
||||
lazy val DoubleAsStringCodec: Codec[Double, String] = Codec[Double, String](_.toString, _.toDouble)
|
||||
|
||||
val BooleanAsIsCodec: Codec[Boolean, Boolean] = AsIsCodec()
|
||||
|
||||
lazy val BooleanAsAttrPresenceCodec: Codec[Boolean, String] =
|
||||
Codec[Boolean, String](if _ then "" else null, _ != null)
|
||||
|
||||
lazy val BooleanAsTrueFalseStringCodec: Codec[Boolean, String] =
|
||||
Codec[Boolean, String](if _ then "true" else "false", _ == "true")
|
||||
|
||||
lazy val BooleanAsYesNoStringCodec: Codec[Boolean, String] =
|
||||
Codec[Boolean, String](if _ then "yes" else "no", _ == "yes")
|
||||
|
||||
lazy val BooleanAsOnOffStringCodec: Codec[Boolean, String] =
|
||||
Codec[Boolean, String](if _ then "on" else "off", _ == "on")
|
||||
30
core/src/scalive/codecs/Encoder.scala
Normal file
30
core/src/scalive/codecs/Encoder.scala
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
package scalive.codecs
|
||||
|
||||
class Encoder[ScalaType, DomType](val encode: ScalaType => DomType)
|
||||
|
||||
def AsIsEncoder[V](): Encoder[V, V] = Encoder(identity)
|
||||
|
||||
val StringAsIsEncoder: Encoder[String, String] = AsIsEncoder()
|
||||
|
||||
val IntAsIsEncoder: Encoder[Int, Int] = AsIsEncoder()
|
||||
|
||||
lazy val IntAsStringEncoder: Encoder[Int, String] = Encoder[Int, String](_.toString)
|
||||
|
||||
lazy val DoubleAsIsEncoder: Encoder[Double, Double] = AsIsEncoder()
|
||||
|
||||
lazy val DoubleAsStringEncoder: Encoder[Double, String] =
|
||||
Encoder[Double, String](_.toString)
|
||||
|
||||
val BooleanAsIsEncoder: Encoder[Boolean, Boolean] = AsIsEncoder()
|
||||
|
||||
lazy val BooleanAsAttrPresenceEncoder: Encoder[Boolean, String] =
|
||||
Encoder[Boolean, String](if _ then "" else null)
|
||||
|
||||
lazy val BooleanAsTrueFalseStringEncoder: Encoder[Boolean, String] =
|
||||
Encoder[Boolean, String](if _ then "true" else "false")
|
||||
|
||||
lazy val BooleanAsYesNoStringEncoder: Encoder[Boolean, String] =
|
||||
Encoder[Boolean, String](if _ then "yes" else "no")
|
||||
|
||||
lazy val BooleanAsOnOffStringEncoder: Encoder[Boolean, String] =
|
||||
Encoder[Boolean, String](if _ then "on" else "off")
|
||||
|
|
@ -12,7 +12,7 @@ trait ComplexHtmlKeys:
|
|||
* select and access specific elements via the class selectors or functions like the DOM method
|
||||
* document.getElementsByClassName
|
||||
*/
|
||||
val className: HtmlAttr[String] = new HtmlAttr("class", StringAsIsCodec)
|
||||
val className: HtmlAttr[String] = new HtmlAttr("class", StringAsIsEncoder)
|
||||
|
||||
val cls: HtmlAttr[String] = className
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ trait ComplexHtmlKeys:
|
|||
* stylesheet, and the href attribute is set to the URL of an external style sheet to format the
|
||||
* page.
|
||||
*/
|
||||
lazy val rel: HtmlAttr[String] = new HtmlAttr("rel", StringAsIsCodec)
|
||||
lazy val rel: HtmlAttr[String] = new HtmlAttr("rel", StringAsIsEncoder)
|
||||
|
||||
/** The attribute describes the role(s) the current element plays in the context of the document.
|
||||
* This can be used, for example, by applications and assistive technologies to determine the
|
||||
|
|
@ -35,7 +35,7 @@ trait ComplexHtmlKeys:
|
|||
*
|
||||
* See: [[http://www.w3.org/TR/role-attribute/#s_role_module_attributes]]
|
||||
*/
|
||||
lazy val role: HtmlAttr[String] = new HtmlAttr("role", StringAsIsCodec)
|
||||
lazy val role: HtmlAttr[String] = new HtmlAttr("role", StringAsIsEncoder)
|
||||
|
||||
/** This class of attributes, called custom data attributes, allows proprietary information to be
|
||||
* exchanged between the HTML and its DOM representation that may be used by scripts. All such
|
||||
|
|
@ -51,13 +51,13 @@ trait ComplexHtmlKeys:
|
|||
* attribute data-test-value will be accessible via HTMLElement.dataset.testValue as any dash
|
||||
* (U+002D) is replaced by the capitalization of the next letter (camelcase).
|
||||
*/
|
||||
def dataAttr(suffix: String): HtmlAttr[String] = new HtmlAttr(s"data-$suffix", StringAsIsCodec)
|
||||
def dataAttr(suffix: String): HtmlAttr[String] = new HtmlAttr(s"data-$suffix", StringAsIsEncoder)
|
||||
|
||||
/** This attribute contains CSS styling declarations to be applied to the element. Note that it is
|
||||
* recommended for styles to be defined in a separate file or files. This attribute and the style
|
||||
* element have mainly the purpose of allowing for quick styling, for example for testing
|
||||
* purposes.
|
||||
*/
|
||||
lazy val styleAttr: HtmlAttr[String] = new HtmlAttr("style", StringAsIsCodec)
|
||||
lazy val styleAttr: HtmlAttr[String] = new HtmlAttr("style", StringAsIsEncoder)
|
||||
|
||||
end ComplexHtmlKeys
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue