Laminar Waypoint

Sourcecode on Github: https://github.com/raquo/Waypoint

Install dependencies

Update the build.sbt file:

build.sbt
import org.scalajs.linker.interface.ModuleSplitStyle
 
lazy val myapp = project
  .in(file("."))
  .enablePlugins(ScalaJSPlugin)
  .settings(
    scalaVersion := "3.3.3",
    scalaJSUseMainModuleInitializer := true,
    scalaJSLinkerConfig ~= {
      _.withModuleKind(ModuleKind.ESModule)
        .withModuleSplitStyle(
          ModuleSplitStyle.SmallModulesFor(List("myapp"))
        )
    },
    libraryDependencies ++= Seq(
      "org.scala-js" %%% "scalajs-dom" % "2.4.0",
      "com.raquo"    %%% "laminar" % "16.0.0",
      "com.raquo"    %%% "waypoint" % "7.0.0", 
      "io.bullet"    %%% "borer-core" % "1.10.3", 
      "io.bullet"    %%% "borer-derivation" % "1.10.3"
    )
  )

Usage

First, let create a json utility, src/main/scala/myapp/utils/JsonUtils.scala:

JsonUtils.scala
package myapp.utils
 
import io.bullet.borer.*
import io.bullet.borer.Json.DecodingConfig
import java.nio.charset.StandardCharsets
 
object JsonUtils {
  extension (json: Json.type)
    def decodeString(value: String): DecodingSetup.Api[DecodingConfig] = {
      json.decode(value.getBytes(StandardCharsets.UTF_8))
    }
}

Then updating the App.scala file:

App.scala
package myapp
 
import org.scalajs.dom
 
import com.raquo.laminar.api.L.{*, given}
import com.raquo.waypoint.*
import io.bullet.borer.*
import io.bullet.borer.derivation.MapBasedCodecs.*
import java.nio.charset.StandardCharsets
import io.bullet.borer.Json.DecodingConfig
import myapp.utils.JsonUtils.*
 
object pages {
  sealed trait Page(val title: String)
  case object HomePage extends Page("Home")
  case object AboutPage extends Page("About")
  case object NotFoundPage extends Page("Page Not Found")
  given pageCodec: Codec[Page] = deriveAllCodecs
}
 
val routes = List(
  Route.static(pages.HomePage, root / endOfSegments),
  Route.static(pages.AboutPage, root / "about" / endOfSegments)
)
 
object router
    extends Router[pages.Page](
      routes = routes,
      getPageTitle = _.title,
      serializePage = page => Json.encode(page).toUtf8String,
      deserializePage = pageStr =>
        Json.decodeString(pageStr).to[pages.Page].value,
      routeFallback = _ => pages.NotFoundPage
    )(
      popStateEvents = windowEvents(_.onPopState),
      owner = unsafeWindowOwner
    ) {}
 
def renderPage(page: pages.Page): Div = {
  page match {
    case pages.HomePage  => div("home")
    case pages.AboutPage => div("about")
    case _               => div("Page not found")
  }
}
 
val app = div(child <-- router.currentPageSignal.map(renderPage))
 
@main
def MyApp(): Unit =
  lazy val root = dom.document.querySelector("#app")
  renderOnDomContentLoaded(root, app)

Visit: http://localhost:5173/about

Last Update: 08:28 - 26 April 2024

On this page