StackedRouter: new router simulates app behaviour #45

Merged
Rubicon merged 18 commits from stacky into master 2024-11-18 10:35:30 +00:00
Showing only changes of commit 32dffaaa3d - Show all commits

View file

@ -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<RouterProps, "url">;
@ -24,7 +25,6 @@ export type StackFrame = {
path: string;
rootId: string;
state: unknown;
beforeShow?: (element: HTMLElement) => void;
};
export type NewFrameOptions<T> = (T extends undefined
@ -141,10 +141,21 @@ const StackedRouter: Component<StackedRouterProps> = (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<StackedRouterProps> = (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<StackedRouterProps> = (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(() => {