Calico

I did this to prove to myself, that it was possible, and to learn something about calico. Calico worked great, I'm not 100% sure about my integration with it - YMMW, but it follows (as closely as I could tell ) a reactive model which also works nicely with vegas event streams.


import viz.extensions.RawIterables.*
import viz.vega.plots.{BarChart, given}
import calico.*
import calico.html.io.{*, given}
import calico.unsafe.given
import calico.syntax.*
import cats.effect.*
import cats.effect.std.Random
import fs2.*
import fs2.concurrent.*
import fs2.dom.*
import viz.vega.facades.EmbedOptions

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

def calicoChart: Resource[IO, HtmlElement[IO]] =
  SignallingRef[IO]
    .of(List(2.4, 3.4, 5.1, -2.3))
    .product(Channel.unbounded[IO, Int])
    .toResource
    .flatMap { (data: SignallingRef[cats.effect.IO, List[Double]], _) =>
      div(
        p("We want to make it as easy as possible, to build a chart"),
        span("Here's a random data set: "),
        data.map(in => p(in.mkString("[", ",", "]"))),
        button(
          "Add a random number",
          onClick --> (
            _.evalMap(_ =>
              Random.scalaUtilRandom[IO].toResource.use(r => r.nextDouble.map(_ * 5))
            ).foreach(newD =>
              IO.println(newD) >>
                data.update(_ :+ newD).void
            )
          )
        ),
        p(""),
        data.map { data =>
          val barChart: BarChart = data.plotBarChart(
            List(
              viz.Utils.fillDiv,
              viz.Utils.removeYAxis
            )
          )
          val chartDiv = div("")
          chartDiv.flatMap{ d =>
            // To my astonishment, this doesn't work...
            /* val dCheat = d.asInstanceOf[org.scalajs.dom.html.Div]
            dCheat.style.height = "40vmin"
            dCheat.style.width = "40vmin" */
            // end yuck

            // I had to set the div size down in here. Then it worked.
            viz.CalicoViz.viewEmbed(barChart, Some(chartDiv), Some(EmbedOptions())).map(_._1)
          }
        }
      )
    }