History
ascent-history is an optional URL session bound to Squawk. The current location (path, query, hash)
is a value-over-time; push / replace are effects; Back writes the Squawk. The already-mounted
tree patches at reactive boundaries. This is not a router: no path matcher, nested layouts, or
data loaders. Matching is hist.location.map(parse) plus when. A later ascent.router may sit
on this primitive; it must not remount AscentApp.
Memory backend
History.memory is the backend for tests, Chekhov / JSEnv, VS Code webviews, and SSR (seed from
the request URL). push of the current URL still records a stack entry; Eq[Location] is what
stops observers firing.
for
hist <- History.memory()
_ <- hist.push("/a")
_ <- hist.push("/b")
_ <- hist.back
here <- hist.location.get
yield here.href/aDerive an ADT
Hash-mode apps can use a real <a href="#/active"> and let hashchange update the Squawk.
Path-mode apps call hist.push("/session/id") from handlers. There is no window-level click
capture (a later Link helper would call History; it must not hijack every <a>).
for hist <- History.memory()
yield
val here = hist.location.map(_.href)
E.div(
E.span(here),
E.button(Events.onClick(_ => hist.push("/next")), "go"),
)Browser backend
On Scala.js, History.browser binds window.history plus popstate / hashchange. Construction
is URIO[Scope, History]; Scope close removes the listeners. ZIOAppDefault.run already has a
Scope.