Counter

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.*

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))
          )
        )
      )
  }

val app: Resource[IO, HtmlDivElement[IO]] = div(
  h1("Let's count!"),
  Counter("Sheep", initialStep = 3)
)

app.renderInto(node.asInstanceOf[fs2.dom.Node[IO]]).useForever.unsafeRunAndForget()