StackedRouter: intergrated with web history API
This commit is contained in:
		
							parent
							
								
									5be56bb80e
								
							
						
					
					
						commit
						32dffaaa3d
					
				
					 1 changed files with 25 additions and 10 deletions
				
			
		| 
						 | 
				
			
			@ -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(() => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue