From e6ce6f18ffd6bf2ee1943d7326e594feff02b8fe Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 17 Apr 2023 03:21:09 +0000 Subject: [PATCH] Enable modifiers to be reified Co-authored-by: =?UTF-8?q?Jakub=20Koz=C5=82owski?= --- .../src/main/scala/calico/html/Modifier.scala | 22 +++++++++++++++++++ .../src/test/scala/calico/SyntaxSuite.scala | 5 ++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/calico/src/main/scala/calico/html/Modifier.scala b/calico/src/main/scala/calico/html/Modifier.scala index 2b98203e..8aa3858a 100644 --- a/calico/src/main/scala/calico/html/Modifier.scala +++ b/calico/src/main/scala/calico/html/Modifier.scala @@ -37,6 +37,28 @@ trait Modifier[F[_], E, A]: inline final def contramap[B](inline f: B => A): Modifier[F, E, B] = (b: B, e: E) => outer.modify(f(b), e) + extension (a: A) + inline final def toMod[E0 <: E]: Mod[F, E0] = + Mod(a)(using this.asInstanceOf[Modifier[F, E0, A]]) + +/** + * A reified modifier + */ +trait Mod[F[_], E]: + protected type M + protected def mod: M + protected def modifier: Modifier[F, E, M] + +object Mod: + def apply[F[_], E, A](a: A)(using Modifier[F, E, A]): Mod[F, E] = + new: + type M = A + def mod = a + def modifier = summon[Modifier[F, E, M]] + + given [F[_], E, E0 <: E]: Modifier[F[_], E0, Mod[F, E]] = (m, e) => + m.modifier.modify(m.mod, e) + object Modifier: inline given forUnit[F[_], E]: Modifier[F, E, Unit] = _forUnit.asInstanceOf[Modifier[F, E, Unit]] diff --git a/calico/src/test/scala/calico/SyntaxSuite.scala b/calico/src/test/scala/calico/SyntaxSuite.scala index 376f36d6..afa95366 100644 --- a/calico/src/test/scala/calico/SyntaxSuite.scala +++ b/calico/src/test/scala/calico/SyntaxSuite.scala @@ -22,6 +22,7 @@ import calico.syntax.* import cats.effect.* import cats.syntax.all.* import fs2.concurrent.* +import fs2.dom.* class SyntaxSuite: @@ -30,10 +31,12 @@ class SyntaxSuite: def nodeSignal: SignallingRef[IO, Resource[IO, fs2.dom.Node[IO]]] = ??? def nodeOptionSignal: SignallingRef[IO, Option[Resource[IO, fs2.dom.Node[IO]]]] = ??? + def mod = (cls := "bar").toMod[Node[IO]] + def signalModifiers = div( stringSignal, stringOptionSignal, nodeSignal, nodeOptionSignal - ).flatTap(_.modify(cls := "foo")) + ).flatTap(_.modify(cls := "foo")).flatTap(_.modify(mod))