Skip to content

Commit

Permalink
Merge pull request #172 from armanbilge/pr/events
Browse files Browse the repository at this point in the history
Use `fs2.dom.Event[F]` and friends
  • Loading branch information
armanbilge authored Jan 30, 2023
2 parents 7544c63 + f0c0b1f commit 63d5d5f
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 36 deletions.
33 changes: 17 additions & 16 deletions calico/src/main/scala/calico/html/Prop.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import cats.effect.kernel.Async
import cats.effect.kernel.Resource
import cats.syntax.all.*
import fs2.Pipe
import fs2.Stream
import fs2.concurrent.Signal
import org.scalajs.dom

Expand Down Expand Up @@ -146,37 +147,37 @@ private trait PropModifiers[F[_]](using F: Async[F]):
Modifier.forSignalResource[F, Any, OptionSignalResourceModifier[F, Any, Any], Option[Any]](
_.values) { (m, n) => setPropOption(n, m.name, m.encode) }

final class EventProp[F[_], E, A] private[calico] (key: String, pipe: Pipe[F, E, A]):
final class EventProp[F[_], A] private[calico] (key: String, pipe: Pipe[F, Any, A]):
import EventProp.*

@inline def -->(sink: Pipe[F, A, Nothing]): PipeModifier[F, E] =
@inline def -->(sink: Pipe[F, A, Nothing]): PipeModifier[F] =
PipeModifier(key, pipe.andThen(sink))

@inline private def through[B](pipe: Pipe[F, A, B]): EventProp[F, E, B] =
@inline private def through[B](pipe: Pipe[F, A, B]): EventProp[F, B] =
new EventProp(key, this.pipe.andThen(pipe))

object EventProp:
def apply[F[_], E](key: String): EventProp[F, E, E] =
new EventProp(key, identity(_))
@inline private[html] def apply[F[_], E](key: String, f: Any => E): EventProp[F, E] =
new EventProp(key, _.map(f))

final class PipeModifier[F[_], E] private[calico] (
final class PipeModifier[F[_]] private[calico] (
private[calico] val key: String,
private[calico] val sink: Pipe[F, E, Nothing])
private[calico] val sink: Pipe[F, Any, Nothing])

inline given [F[_], E]: (Functor[EventProp[F, E, _]] & FunctorFilter[EventProp[F, E, _]]) =
_functor.asInstanceOf[Functor[EventProp[F, E, _]] & FunctorFilter[EventProp[F, E, _]]]
private val _functor: Functor[EventProp[Id, Any, _]] & FunctorFilter[EventProp[Id, Any, _]] =
new Functor[EventProp[Id, Any, _]] with FunctorFilter[EventProp[Id, Any, _]]:
def map[A, B](fa: EventProp[Id, Any, A])(f: A => B) = fa.through(_.map(f))
inline given [F[_]]: (Functor[EventProp[F, _]] & FunctorFilter[EventProp[F, _]]) =
_functor.asInstanceOf[Functor[EventProp[F, _]] & FunctorFilter[EventProp[F, _]]]
private val _functor: Functor[EventProp[Id, _]] & FunctorFilter[EventProp[Id, _]] =
new Functor[EventProp[Id, _]] with FunctorFilter[EventProp[Id, _]]:
def map[A, B](fa: EventProp[Id, A])(f: A => B) = fa.through(_.map(f))
def functor = this
def mapFilter[A, B](fa: EventProp[Id, Any, A])(f: A => Option[B]) =
def mapFilter[A, B](fa: EventProp[Id, A])(f: A => Option[B]) =
fa.through(_.mapFilter(f))

private trait EventPropModifiers[F[_]](using F: Async[F]):
import EventProp.*
inline given forPipeEventProp[T <: fs2.dom.Node[F], E]: Modifier[F, T, PipeModifier[F, E]] =
_forPipeEventProp.asInstanceOf[Modifier[F, T, PipeModifier[F, E]]]
private val _forPipeEventProp: Modifier[F, dom.EventTarget, PipeModifier[F, Any]] =
inline given forPipeEventProp[T <: fs2.dom.Node[F]]: Modifier[F, T, PipeModifier[F]] =
_forPipeEventProp.asInstanceOf[Modifier[F, T, PipeModifier[F]]]
private val _forPipeEventProp: Modifier[F, dom.EventTarget, PipeModifier[F]] =
(m, t) => fs2.dom.events(t, m.key).through(m.sink).compile.drain.cedeBackground.void

final class ClassProp[F[_]] private[calico]
Expand Down
29 changes: 16 additions & 13 deletions project/src/main/scala/calico/html/codegen/CalicoGenerator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -245,15 +245,6 @@ private[codegen] class CalicoGenerator(srcManaged: File)
defType: DefType): String = {
val (defs, defGroupComments) = defsAndGroupComments(defSources, printDefGroupComments)

val baseImplDef =
if (outputBaseImpl)
List(
s"@inline private[calico] def ${keyImplName}[Ev <: ${baseScalaJsEventType}](key: String): ${keyKind}[F, Ev, Ev] = ${keyKind}(key)"
)
else {
Nil
}

val headerLines = List(
s"package $eventPropDefsPackagePath",
"",
Expand All @@ -268,17 +259,29 @@ private[codegen] class CalicoGenerator(srcManaged: File)
headerLines = headerLines,
traitCommentLines = traitCommentLines,
traitModifiers = traitModifiers,
traitName = traitName,
traitName = s"${traitName}(using cats.effect.kernel.Async[F])",
traitExtends = traitExtends,
traitThisType = traitThisType,
defType = _ => defType,
keyKind = keyKind,
keyImplName = _ => keyImplName,
baseImplDefComments = baseImplDefComments,
baseImplDef = baseImplDef,
baseImplDefComments = Nil,
baseImplDef = Nil,
outputImplDefs = true,
format = format
).printTrait().getOutput()
) {

override def impl(keyDef: EventPropDef): String = {
List[String](
"EventProp(",
repr(keyDef.domName),
", ",
s"e => fs2.dom.${keyDef.javascriptEventType}(e.asInstanceOf[dom.${keyDef.javascriptEventType}])",
")"
).mkString
}

}.printTrait().getOutput()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,7 @@ object DomDefsGenerator {
(
key,
vals.map(attr =>
attr.copy(scalaJsEventType =
s"F, ${attr.scalaJsEventType}, ${attr.scalaJsEventType}")))
attr.copy(scalaJsEventType = s"F, fs2.${attr.scalaJsEventType}[F]")))
},
printDefGroupComments = true,
traitCommentLines = Nil,
Expand Down Expand Up @@ -313,8 +312,7 @@ object DomDefsGenerator {
(
key,
vals.map(attr =>
attr.copy(scalaJsEventType =
s"F, ${attr.scalaJsEventType}, ${attr.scalaJsEventType}")))
attr.copy(scalaJsEventType = s"F, fs2.${attr.scalaJsEventType}[F]")))
},
printDefGroupComments = true,
traitCommentLines = List(eventPropsDefGroups.head._1),
Expand Down
6 changes: 3 additions & 3 deletions todo-mvc/src/main/scala/todomvc/TodoMvc.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import io.circe.Codec
import io.circe.jawn
import io.circe.syntax.*
import org.http4s.*
import org.scalajs.dom.KeyCode
import org.scalajs.dom.KeyValue

import scala.collection.immutable.SortedMap

Expand Down Expand Up @@ -76,7 +76,7 @@ object TodoMvc extends IOWebApp:
placeholder := "What needs to be done?",
autoFocus := true,
onKeyDown --> {
_.filter(_.keyCode == KeyCode.Enter)
_.filter(_.key == KeyValue.Enter)
.evalMap(_ => self.value.get)
.filterNot(_.isEmpty)
.foreach(store.create(_) *> self.value.set(""))
Expand Down Expand Up @@ -105,7 +105,7 @@ object TodoMvc extends IOWebApp:
cls := "edit",
defaultValue <-- todo.map(_.foldMap(_.text)),
onKeyDown --> {
_.filter(_.keyCode == KeyCode.Enter).foreach(_ => endEdit)
_.filter(_.key == KeyValue.Enter).foreach(_ => endEdit)
},
onBlur --> (_.foreach(_ => endEdit))
)
Expand Down

0 comments on commit 63d5d5f

Please sign in to comment.