From 0b067aa7e15ff1d53d8fc437f296218582b24593 Mon Sep 17 00:00:00 2001 From: Paul-Henri Froidmont Date: Sat, 13 Sep 2025 01:36:30 +0200 Subject: [PATCH] Add home liveview --- core/src/scalive/HtmlElement.scala | 14 ++++++++++---- example/src/Example.scala | 4 ++++ example/src/HomeLiveView.scala | 29 +++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 example/src/HomeLiveView.scala diff --git a/core/src/scalive/HtmlElement.scala b/core/src/scalive/HtmlElement.scala index b14a243..9ccb1ba 100644 --- a/core/src/scalive/HtmlElement.scala +++ b/core/src/scalive/HtmlElement.scala @@ -35,7 +35,13 @@ class HtmlElement(val tag: HtmlTag, val mods: Vector[Mod]): diff class HtmlTag(val name: String, val void: Boolean = false): - def apply(mods: Mod*): HtmlElement = HtmlElement(this, mods.toVector) + def apply(mods: (Mod | IterableOnce[Mod])*): HtmlElement = HtmlElement( + this, + mods.toVector.flatMap { + case m: Mod => Some(m) + case ms: IterableOnce[Mod] => ms + } + ) class HtmlAttr[V](val name: String, val codec: Codec[V, String]): private inline def isBooleanAsAttrPresence = codec == BooleanAsAttrPresenceCodec @@ -83,9 +89,9 @@ object Mod: case DynText(dyn: Dyn[String]) extends Content with DynamicMod case DynElement(dyn: Dyn[HtmlElement]) extends Content with DynamicMod // TODO support arbitrary collection - case DynOptionElement(dyn: Dyn[Option[HtmlElement]]) extends Content with DynamicMod - case DynElementColl(dyn: Dyn[Iterable[HtmlElement]]) extends Content with DynamicMod - case DynSplit(v: SplitVar[?, HtmlElement, ?]) extends Content with DynamicMod + case DynOptionElement(dyn: Dyn[Option[HtmlElement]]) extends Content with DynamicMod + case DynElementColl(dyn: Dyn[IterableOnce[HtmlElement]]) extends Content with DynamicMod + case DynSplit(v: SplitVar[?, HtmlElement, ?]) extends Content with DynamicMod extension (mod: Mod) private[scalive] def setAllUnchanged(): Unit = diff --git a/example/src/Example.scala b/example/src/Example.scala index a830196..133c113 100644 --- a/example/src/Example.scala +++ b/example/src/Example.scala @@ -25,6 +25,10 @@ object Example extends ZIOAppDefault: LiveRouter( RootLayout(_), List( + LiveRoute( + Root, + (_, _) => HomeLiveView() + ), LiveRoute( Root / "counter", (_, _) => CounterLiveView() diff --git a/example/src/HomeLiveView.scala b/example/src/HomeLiveView.scala new file mode 100644 index 0000000..2ad5e51 --- /dev/null +++ b/example/src/HomeLiveView.scala @@ -0,0 +1,29 @@ +import scalive.* +import zio.* +import zio.stream.ZStream + +class HomeLiveView() extends LiveView[String, Unit]: + val links = List( + "/counter" -> "Counter", + "/list" -> "List" + ) + + def init = ZIO.succeed(()) + + def update(model: Unit) = _ => ZIO.succeed(model) + + def view(model: Dyn[Unit]) = + ul( + cls := "space-y-2", + links.map((path, name) => + li( + a( + href := path, + cls := "block px-4 py-2 rounded-lg text-gray-700 hover:bg-gray-100 hover:text-gray-900 font-medium transition", + name + ) + ) + ) + ) + + def subscriptions(model: Unit) = ZStream.empty