diff --git a/.scalafmt.conf b/.scalafmt.conf
index d21ae24..cd02d3a 100644
--- a/.scalafmt.conf
+++ b/.scalafmt.conf
@@ -1,2 +1,2 @@
version = 3.4.3
-runner.dialect = scala213
+runner.dialect = scala3
diff --git a/build.sbt b/build.sbt
index 4e494a0..0104447 100644
--- a/build.sbt
+++ b/build.sbt
@@ -1,9 +1,9 @@
-enablePlugins(ScalaJSPlugin)
+enablePlugins(ScalaJSPlugin, EsbuildPlugin)
name := "nostr-army-knife"
-scalaVersion := "2.13.7"
+scalaVersion := "3.2.2"
scalaJSUseMainModuleInitializer := true
libraryDependencies += "com.armanbilge" %%% "calico" % "0.2.0-RC2"
-libraryDependencies += "com.fiatjaf" %%% "snow" % "0.2.0-RC2"
+libraryDependencies += "com.fiatjaf" %%% "snow" % "0.0.1-SNAPSHOT"
diff --git a/index.html b/index.html
index 54a4ee1..5073af1 100644
--- a/index.html
+++ b/index.html
@@ -1,6 +1,7 @@
nostr army knife
-
-
-
+
+
+
+
diff --git a/src/main/scala/Main.scala b/src/main/scala/Main.scala
index 8b13789..20f3f9a 100644
--- a/src/main/scala/Main.scala
+++ b/src/main/scala/Main.scala
@@ -1 +1,63 @@
+import calico.*
+import calico.html.io.{*, given}
+import calico.syntax.*
+import calico.unsafe.given
+import cats.effect.*
+import cats.effect.syntax.all.*
+import cats.syntax.all.*
+import fs2.*
+import fs2.concurrent.*
+import fs2.dom.*
+object Main extends IOWebApp {
+ def Counter(
+ label: String,
+ initialStep: Int
+ ): Resource[IO, HtmlDivElement[IO]] =
+ SignallingRef[IO]
+ .of(initialStep)
+ .product(Channel.unbounded[IO, Int])
+ .toResource
+ .flatMap { (step, diff) =>
+ val allowedSteps = List(1, 2, 3, 5, 10)
+
+ div(
+ p(
+ "Step: ",
+ select.withSelf { self =>
+ (
+ allowedSteps
+ .map(step => option(value := step.toString, step.toString)),
+ value <-- step.map(_.toString),
+ onChange --> {
+ _.evalMap(_ => self.value.get)
+ .map(_.toIntOption)
+ .unNone
+ .foreach(step.set)
+ }
+ )
+ }
+ ),
+ p(
+ label + ": ",
+ b(diff.stream.scanMonoid.map(_.toString).holdOptionResource),
+ " ",
+ button(
+ "-",
+ onClick --> {
+ _.evalMap(_ => step.get).map(-1 * _).foreach(diff.send(_).void)
+ }
+ ),
+ button(
+ "+",
+ onClick --> (_.evalMap(_ => step.get).foreach(diff.send(_).void))
+ )
+ )
+ )
+ }
+
+ def render: Resource[IO, HtmlDivElement[IO]] = div(
+ h1("Let's count!"),
+ Counter("Sheep", initialStep = 3)
+ )
+}