diff --git a/src/platform/StackedRouter.tsx b/src/platform/StackedRouter.tsx index 25dd6e6..7325d7e 100644 --- a/src/platform/StackedRouter.tsx +++ b/src/platform/StackedRouter.tsx @@ -6,17 +6,18 @@ import { createRenderEffect, createUniqueId, Index, - onMount, Show, untrack, useContext, type Accessor, } from "solid-js"; import { createStore, unwrap } from "solid-js/store"; -import { insert, render } from "solid-js/web"; import "./StackedRouter.css"; import { animateSlideInFromRight, animateSlideOutToRight } from "./anim"; import { ANIM_CURVE_DECELERATION, ANIM_CURVE_STD } from "../material/theme"; +import { + makeEventListener, +} from "@solid-primitives/event-listener"; export type StackedRouterProps = Omit; @@ -24,7 +25,6 @@ export type StackFrame = { path: string; rootId: string; state: unknown; - beforeShow?: (element: HTMLElement) => void; }; export type NewFrameOptions = (T extends undefined @@ -141,10 +141,21 @@ const StackedRouter: Component = (oprops) => { state: opts?.state, rootId: createUniqueId(), }; + mutStack(opts?.replace ? stack.length - 1 : stack.length, frame); + if (opts?.replace) { + window.history.replaceState(unwrap(stack), "", path); + } else { + window.history.pushState(unwrap(stack), "", path); + } return frame; }); + const onlyPopFrame = (depth: number) => { + mutStack((o) => o.toSpliced(o.length - depth, depth)); + window.history.go(-depth); + }; + const popFrame = (depth: number = 1) => untrack(() => { if (import.meta.env.DEV) { @@ -157,14 +168,10 @@ const StackedRouter: Component = (oprops) => { const element = document.getElementById(lastFrame.rootId)!; requestAnimationFrame(() => { const animation = animateClose(element); - animation.addEventListener("finish", () => - mutStack((o) => o.toSpliced(o.length - depth, depth)), - ); + animation.addEventListener("finish", () => onlyPopFrame(depth)); }); } else { - mutStack((o) => { - return o.toSpliced(o.length - depth, depth); - }); + onlyPopFrame(depth); } }); @@ -175,10 +182,18 @@ const StackedRouter: Component = (oprops) => { createRenderEffect(() => { if (stack.length === 0) { - pushFrame("/", undefined); + pushFrame(window.location.pathname); } }); + createRenderEffect(() => { + makeEventListener(window, "popstate", (event) => { + if (event.state && stack.length !== event.state.length) { + mutStack(event.state); + } + }); + }); + const onBeforeDialogMount = (element: HTMLDialogElement) => { createEffect(() => { requestAnimationFrame(() => {