8000 redesign encoding of dsl element with phantom types by malladinagarjuna2 · Pull Request #467 · armanbilge/calico · GitHub
[go: up one dir, main page]

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ThisBuild / tlBaseVersion := "0.2"
ThisBuild / tlBaseVersion := "0.3"

ThisBuild / organization := "com.armanbilge"
ThisBuild / organizationName := "Arman Bilge"
Expand Down
27 changes: 19 additions & 8 deletions calico/src/main/scala/calico/html/Html.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ sealed class Html[F[_]](using F: Async[F])
DocumentEventProps[F],
WindowEventProps[F],
HtmlAttrs[F],
GeneratedValidInstances[F],
PropModifiers[F],
EventPropModifiers[F],
ClassPropModifiers[F],
Expand All @@ -44,24 +45,34 @@ sealed class Html[F[_]](using F: Async[F])

given Dom[F] = Dom.forAsync

inline given validAttr_rel: ValidAttr["rel", fs2.dom.HtmlElement[F]] = ValidAttr.instance
inline given validAttr_role: ValidAttr["role", fs2.dom.HtmlElement[F]] = ValidAttr.instance
inline given validAttr_style: ValidAttr["style", fs2.dom.HtmlElement[F]] = ValidAttr.instance
inline given validAttr_value: ValidAttr["value", fs2.dom.HtmlElement[F]] = ValidAttr.instance
inline given validAttr_data: ValidAttr[Any, fs2.dom.HtmlElement[F]] = ValidAttr.instance
inline given validProp_className: ValidProp["className", fs2.dom.HtmlElement[F]] =
ValidProp.instance

def aria: Aria[F] = Aria[F]

def cls: ClassProp[F] = ClassProp[F]

def rel: HtmlAttr[F, List[String]] = HtmlAttr("rel", encoders.whitespaceSeparatedStrings)
def rel: HtmlAttr[F, "rel", List[String]] =
new HtmlAttr("rel", encoders.whitespaceSeparatedStrings)

def role: HtmlAttr[F, List[String]] = HtmlAttr("role", encoders.whitespaceSeparatedStrings)
def role: HtmlAttr[F, "role", List[String]] =
new HtmlAttr("role", encoders.whitespaceSeparatedStrings)

def dataAttr(suffix: String): HtmlAttr[F, String] =
HtmlAttr("data-" + suffix, encoders.identity)
def dataAttr(suffix: String): HtmlAttr[F, Any, String] =
new HtmlAttr("data-" + suffix, encoders.identity)

def children: Children[F] = Children[F]

def children[K](f: K => Resource[F, fs2.dom.Node[F]]): KeyedChildren[F, K] =
KeyedChildren[F, K](f)

def styleAttr: HtmlAttr[F, String] =
HtmlAttr("style", encoders.identity)
def styleAttr: HtmlAttr[F, "style", String] =
new HtmlAttr("style", encoders.identity)

def valueAttr: HtmlAttr[F, String] =
HtmlAttr("value", encoders.identity)
def valueAttr: HtmlAttr[F, "value", String] =
new HtmlAttr("value", encoders.identity)
105 changes: 57 additions & 48 deletions calico/src/main/scala/calico/html/HtmlAttr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,119 +23,128 @@ import cats.effect.kernel.Resource
import fs2.concurrent.Signal
import org.scalajs.dom

sealed class HtmlAttr[F[_], V] private[calico] (key: String, encode: V => String):
sealed class HtmlAttr[F[_], A, V] private[calico] (key: String, encode: V => String):
import HtmlAttr.*

@inline def :=(v: V): ConstantModifier[V] =
@inline def :=(v: V): ConstantModifier[A, V] =
ConstantModifier(key, encode, v)

@inline def <--(vs: Signal[F, V]): SignalModifier[F, V] =
@inline def <--(vs: Signal[F, V]): SignalModifier[A, F, V] =
SignalModifier(key, encode, vs)

@inline def <--(vs: Resource[F, Signal[F, V]]): SignalResourceModifier[F, V] =
@inline def <--(vs: Resource[F, Signal[F, V]]): SignalResourceModifier[A, F, V] =
SignalResourceModifier(key, encode, vs)

@inline def <--(vs: Signal[F, Option[V]]): OptionSignalModifier[F, V] =
@inline def <--(vs: Signal[F, Option[V]]): OptionSignalModifier[A, F, V] =
OptionSignalModifier(key, encode, vs)

@inline def <--(vs: Resource[F, Signal[F, Option[V]]]): OptionSignalResourceModifier[F, V] =
@inline def <--(
vs: Resource[F, Signal[F, Option[V]]]): OptionSignalResourceModifier[A, F, V] =
OptionSignalResourceModifier(key, encode, vs)

@inline def contramap[U](f: U => V): HtmlAttr[F, U] =
@inline def contramap[U](f: U => V): HtmlAttr[F, A, U] =
new HtmlAttr(key, f.andThen(encode))

object HtmlAttr:
inline given [F[_]]: Contravariant[HtmlAttr[F, _]] =
_contravariant.asInstanceOf[Contravariant[HtmlAttr[F, _]]]
private val _contravariant: Contravariant[HtmlAttr[Id, _]] = new:
def contramap[A, B](fa: HtmlAttr[Id, A])(f: B => A): HtmlAttr[Id, B] =
inline given [F[_], A]: Contravariant[HtmlAttr[F, A, _]] =
_contravariant.asInstanceOf[Contravariant[HtmlAttr[F, A, _]]]
private val _contravariant: Contravariant[HtmlAttr[Id, Any, _]] = new:
def contramap[X, Y](fa: HtmlAttr[Id, Any, X])(f: Y => X): HtmlAttr[Id, Any, Y] =
fa.contramap(f)

final class ConstantModifier[V] private[calico] (
final class ConstantModifier[A, V] private[calico] (
private[calico] val key: String,
private[calico] val encode: V => String,
private[calico] val value: V
)

final class SignalModifier[F[_], V] private[calico] (
final class SignalModifier[A, F[_], V] private[calico] (
private[calico] val key: String,
private[calico] val encode: V => String,
private[calico] val values: Signal[F, V]
)

final class SignalResourceModifier[F[_], V] private[calico] (
final class SignalResourceModifier[A, F[_], V] private[calico] (
private[calico] val key: String,
private[calico] val encode: V => String,
private[calico] val values: Resource[F, Signal[F, V]]
)

final class OptionSignalModifier[F[_], V] private[calico] (
final class OptionSignalModifier[A, F[_], V] private[calico] (
private[calico] val key: String,
private[calico] val encode: V => String,
private[calico] val values: Signal[F, Option[V]]
)

final class OptionSignalResourceModifier[F[_], V] private[calico] (
final class OptionSignalResourceModifier[A, F[_], V] private[calico] (
private[calico] val key: String,
private[calico] val encode: V => String,
private[calico] val values: Resource[F, Signal[F, Option[V]]]
)

private trait HtmlAttrModifiers[F[_]](using F: Async[F]):
private[calico] trait HtmlAttrModifiers[F[_]](using F: Async[F]):
import HtmlAttr.*

inline given forConstantHtmlAttr[E <: fs2.dom.Element[F], V]
: Modifier[F, E, ConstantModifier[V]] =
_forConstantHtmlAttr.asInstanceOf[Modifier[F, E, ConstantModifier[V]]]
inline given forConstantHtmlAttr[A, E <: fs2.dom.HtmlElement[F], V](
using ValidAttr[A, E]
): Modifier[F, E, ConstantModifier[A, V]] =
_forConstantHtmlAttr.asInstanceOf[Modifier[F, E, ConstantModifier[A, V]]]

private val _forConstantHtmlAttr: Modifier[F, dom.Element, ConstantModifier[Any]] =
private val _forConstantHtmlAttr: Modifier[F, dom.Element, ConstantModifier[Any, Any]] =
(m, e) => Resource.eval(F.delay(e.setAttribute(m.key, m.encode(m.value))))

inline given forSignalHtmlAttr[E <: fs2.dom.Element[F], V]
: Modifier[F, E, SignalModifier[F, V]] =
_forSignalHtmlAttr.asInstanceOf[Modifier[F, E, SignalModifier[F, V]]]
inline given forSignalHtmlAttr[A, E <: fs2.dom.HtmlElement[F], V](
using ValidAttr[A, E]
): Modifier[F, E, SignalModifier[A, F, V]] =
_forSignalHtmlAttr.as 8000 InstanceOf[Modifier[F, E, SignalModifier[A, F, V]]]

private val _forSignalHtmlAttr =
Modifier.forSignal[F, dom.Element, SignalModifier[F, Any], Any](_.values) { (m, e) => v =>
F.delay(e.setAttribute(m.key, m.encode(v)))
Modifier.forSignal[F, dom.Element, SignalModifier[Any, F, Any], Any](_.values) {
(m, e) => v => F.delay(e.setAttribute(m.key, m.encode(v)))
}

inline given forSignalResourceHtmlAttr[E <: fs2.dom.Element[F], V]
: Modifier[F, E, SignalResourceModifier[F, V]] =
_forSignalResourceHtmlAttr.asInstanceOf[Modifier[F, E, SignalResourceModifier[F, V]]]
inline given forSignalResourceHtmlAttr[A, E <: fs2.dom.HtmlElement[F], V](
using ValidAttr[A, E]
): Modifier[F, E, SignalResourceModifier[A, F, V]] =
_forSignalResourceHtmlAttr.asInstanceOf[Modifier[F, E, SignalResourceModifier[A, F, V]]]

private val _forSignalResourceHtmlAttr =
Modifier.forSignalResource[F, dom.Element, SignalResourceModifier[F, Any], Any](_.values) {
(m, e) => v => F.delay(e.setAttribute(m.key, m.encode(v)))
}
Modifier.forSignalResource[F, dom.Element, SignalResourceModifier[Any, F, Any], Any](
_.values) { (m, e) => v => F.delay(e.setAttribute(m.key, m.encode(v))) }

inline given forOptionSignalHtmlAttr[E <: fs2.dom.Element[F], V]
: Modifier[F, E, OptionSignalModifier[F, V]] =
_forOptionSignalHtmlAttr.asInstanceOf[Modifier[F, E, OptionSignalModifier[F, V]]]
inline given forOptionSignalHtmlAttr[A, E <: fs2.dom.HtmlElement[F], V](
using ValidAttr[A, E]
): Modifier[F, E, OptionSignalModifier[A, F, V]] =
_forOptionSignalHtmlAttr.asInstanceOf[Modifier[F, E, OptionSignalModifier[A, F, V]]]

private val _forOptionSignalHtmlAttr =
Modifier.forSignal[F, dom.Element, OptionSignalModifier[F, Any], Option[Any]](_.values) {
(m, e) => v =>
F.delay(v.fold(e.removeAttribute(m.key))(v => e.setAttribute(m.key, m.encode(v))))
Modifier.forSignal[F, dom.Element, OptionSignalModifier[Any, F, Any], Option[Any]](
_.values) { (m, e) => v =>
F.delay(v.fold(e.removeAttribute(m.key))(v => e.setAttribute(m.key, m.encode(v))))
}

inline given forOptionSignalResourceHtmlAttr[E <: fs2.dom.Element[F], V]
: Modifier[F, E, OptionSignalResourceModifier[F, V]] =
inline given forOptionSignalResourceHtmlAttr[A, E <: fs2.dom.HtmlElement[F], V](
using ValidAttr[A, E]
): Modifier[F, E, OptionSignalResourceModifier[A, F, V]] =
_forOptionSignalResourceHtmlAttr
.asInstanceOf[Modifier[F, E, OptionSignalResourceModifier[F, V]]]
.asInstanceOf[Modifier[F, E, OptionSignalResourceModifier[A, F, V]]]

private val _forOptionSignalResourceHtmlAttr =
Modifier
.forSignalResource[F, dom.Element, OptionSignalResourceModifier[F, Any], Option[Any]](
_.values) { (m, e) => v =>
F.delay(v.fold(e.removeAttribute(m.key))(v => e.setAttribute(m.key, m.encode(v))))
}
Modifier.forSignalResource[
F,
dom.Element,
OptionSignalResourceModifier[Any, F, Any],
Option[
Any
]](_.values) { (m, e) => v =>
F.delay(v.fold(e.removeAttribute(m.key))(v => e.setAttribute(m.key, m.encode(v))))
}

final class Aria[F[_]] private extends AriaAttrs[F]

private object Aria:
inline def apply[F[_]]: Aria[F] = instance.asInstanceOf[Aria[F]]
private val instance: Aria[cats.Id] = new Aria[cats.Id]

final class AriaAttr[F[_], V] private[calico] (suffix: String, encode: V => String)
extends HtmlAttr[F, V]("aria-" + suffix, encode)
final class AriaAttr[F[_], A, V] private[calico] (suffix: String, encode: V => String)
extends HtmlAttr[F, A, V]("aria-" + suffix, encode)
Loading
Loading
0