mirror of
https://github.com/phfroidmont/scalive.git
synced 2025-12-25 05:26:59 +01:00
Initial support for JS commands
This commit is contained in:
parent
d42472061b
commit
6f012b6796
4 changed files with 62 additions and 5 deletions
|
|
@ -64,10 +64,10 @@ class HtmlAttr[V](val name: String, val codec: Codec[V, String]):
|
||||||
|
|
||||||
class HtmlAttrJsonValue(val name: String):
|
class HtmlAttrJsonValue(val name: String):
|
||||||
|
|
||||||
def :=[V: JsonCodec](value: V): Mod.Attr =
|
def :=[V: JsonEncoder](value: V): Mod.Attr =
|
||||||
Mod.Attr.Static(name, value.toJson, isJson = true)
|
Mod.Attr.Static(name, value.toJson, isJson = true)
|
||||||
|
|
||||||
def :=[V: JsonCodec](value: Dyn[V]): Mod.Attr =
|
def :=[V: JsonEncoder](value: Dyn[V]): Mod.Attr =
|
||||||
Mod.Attr.Dyn(name, value(_.toJson), isJson = true)
|
Mod.Attr.Dyn(name, value(_.toJson), isJson = true)
|
||||||
|
|
||||||
sealed trait Mod
|
sealed trait Mod
|
||||||
|
|
|
||||||
53
core/src/scalive/JS.scala
Normal file
53
core/src/scalive/JS.scala
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
package scalive
|
||||||
|
|
||||||
|
import zio.json.*
|
||||||
|
import zio.json.ast.Json
|
||||||
|
|
||||||
|
val JS: JSCommands.JSCommand = JSCommands.empty
|
||||||
|
|
||||||
|
object JSCommands:
|
||||||
|
opaque type JSCommand = List[Json]
|
||||||
|
|
||||||
|
def empty: JSCommand = List.empty
|
||||||
|
|
||||||
|
object JSCommand:
|
||||||
|
given JsonEncoder[JSCommand] =
|
||||||
|
JsonEncoder[Json].contramap(ops => Json.Arr(ops.reverse*))
|
||||||
|
|
||||||
|
private def classNames(names: String) = names.split("\\s+")
|
||||||
|
|
||||||
|
extension (ops: JSCommand)
|
||||||
|
private def addOp[A: JsonEncoder](kind: String, args: A) =
|
||||||
|
(kind, args).toJsonAST.getOrElse(throw new IllegalArgumentException()) :: ops
|
||||||
|
|
||||||
|
def toggleClass(
|
||||||
|
names: String,
|
||||||
|
to: String = "",
|
||||||
|
transition: String | (String, String, String) = "",
|
||||||
|
time: Int = 200,
|
||||||
|
blocking: Boolean = true
|
||||||
|
) =
|
||||||
|
ops.addOp(
|
||||||
|
"toggle_class",
|
||||||
|
Args.ToggleClass(
|
||||||
|
classNames(names),
|
||||||
|
Some(to).filterNot(_.isBlank),
|
||||||
|
transition match
|
||||||
|
case "" => None
|
||||||
|
case names: String => Some(classNames(names))
|
||||||
|
case t: (String, String, String) => Some(t.toList),
|
||||||
|
Some(time).filterNot(_ == 200),
|
||||||
|
Some(blocking).filterNot(_ == true)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
private object Args:
|
||||||
|
final case class ToggleClass(
|
||||||
|
names: Seq[String],
|
||||||
|
to: Option[String],
|
||||||
|
transition: Option[Seq[String]],
|
||||||
|
time: Option[Int],
|
||||||
|
blocking: Option[Boolean])
|
||||||
|
derives JsonEncoder
|
||||||
|
|
||||||
|
end JSCommands
|
||||||
|
|
@ -5,7 +5,7 @@ import zio.stream.ZStream
|
||||||
class HomeLiveView() extends LiveView[String, Unit]:
|
class HomeLiveView() extends LiveView[String, Unit]:
|
||||||
val links = List(
|
val links = List(
|
||||||
"/counter" -> "Counter",
|
"/counter" -> "Counter",
|
||||||
"/list" -> "List"
|
"/list?q=test" -> "List"
|
||||||
)
|
)
|
||||||
|
|
||||||
def init = ZIO.succeed(())
|
def init = ZIO.succeed(())
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,11 @@ class ListLiveView(someParam: String) extends LiveView[Msg, Model]:
|
||||||
phx.click := Msg.IncAge(1),
|
phx.click := Msg.IncAge(1),
|
||||||
"Inc age"
|
"Inc age"
|
||||||
),
|
),
|
||||||
span(cls := "grow")
|
span(cls := "grow"),
|
||||||
|
button(
|
||||||
|
phx.click := JS.toggleClass("bg-red-500 border-5"),
|
||||||
|
"Toggle color"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue