UNPKG

@virtualstate/app-history

Version:

Native JavaScript [app-history](https://github.com/WICG/app-history) implementation

187 lines (126 loc) 5.02 kB
# `@virtualstate/app-history` Native JavaScript [app-history](https://github.com/WICG/app-history) implementation [//]: # (badges) ### Support ![Node.js supported](https://img.shields.io/badge/node-%3E%3D16.0.0-blue) ![Deno supported](https://img.shields.io/badge/deno-%3E%3D1.17.0-blue) ![Chromium supported](https://img.shields.io/badge/chromium-%3E%3D98.0.4695.0-blue) ![Webkit supported](https://img.shields.io/badge/webkit-%3E%3D15.4-blue) ![Firefox supported](https://img.shields.io/badge/firefox-%3E%3D94.0.1-blue) ### Test Coverage ![Web Platform Tests 115/158](https://img.shields.io/badge/Web%20Platform%20Tests-115%2F158-brightgreen) ![93.54%25 lines covered](https://img.shields.io/badge/lines-93.54%25-brightgreen) ![93.54%25 statements covered](https://img.shields.io/badge/statements-93.54%25-brightgreen) ![85.14%25 functions covered](https://img.shields.io/badge/functions-85.14%25-brightgreen) ![83.88%25 branches covered](https://img.shields.io/badge/branches-83.88%25-brightgreen) [//]: # (badges) ## Install ### Skypack - [Package Registry Link - Skypack](https://www.skypack.dev/view/@virtualstate/app-history) ```typescript const { AppHistory } = await import("https://cdn.skypack.dev/@virtualstate/app-history"); ``` _Or_ ```typescript import { AppHistory } from "https://cdn.skypack.dev/@virtualstate/app-history"; ``` ### npm / yarn / GitHub - [Package Registry Link - GitHub](https://github.com/virtualstate/app-history/packages) - [Package Registry Link - npm](https://www.npmjs.com/package/@virtualstate/app-history) ``` npm i --save @virtualstate/app-history ``` _Or_ ``` yarn add @virtualstate/app-history ``` Then ```typescript import { AppHistory } from "@virtualstate/app-history"; ``` ## Navigation ```typescript import { AppHistory } from "@virtualstate/app-history"; const appHistory = new AppHistory(); // Set initial url appHistory.navigate("/"); appHistory.navigate("/skipped"); // Use .finished to wait for the transition to complete await appHistory.navigate("/awaited").finished; ``` ## Waiting for events ```typescript import { AppHistory } from "@virtualstate/app-history"; const appHistory = new AppHistory(); appHistory.addEventListener("navigate", async ({ destination }) => { if (destination.url === "/disallow") { throw new Error("No!"); } }); await appHistory.navigate("/allowed").finished; // Resolves await appHistory.navigate("/disallow").finished; // Rejects ``` ## Transitions ```typescript import { AppHistory } from "@virtualstate/app-history"; import { loadPhotoIntoCache } from "./cache"; const appHistory = new AppHistory(); appHistory.addEventListener("navigate", async ({ destination, transitionWhile }) => { transitionWhile(loadPhotoIntoCache(destination.url)); }); ``` ## URLPattern You can match `destination.url` using [`URLPattern`](https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API) ```typescript import {AppHistory} from "@virtualstate/app-history"; import {URLPattern} from "urlpattern-polyfill"; const appHistory = new AppHistory(); appHistory.addEventListener("navigate", async ({destination, transitionWhile}) => { const pattern = new URLPattern({ pathname: "/books/:id" }); const match = pattern.exec(destination.url); if (match) { transitionWhile(transition()); } async function transition() { console.log("load book", match.pathname.groups.id) } }); appHistory.navigate("/book/1"); ``` ## State ```typescript import { AppHistory } from "@virtualstate/app-history"; const appHistory = new AppHistory(); appHistory.addEventListener("currentchange", () => { console.log({ updatedState: appHistory.current?.getState() }); }); await appHistory.updateCurrent({ state: { items: [ "first", "second" ], index: 0 } }).finished; await appHistory.updateCurrent({ state: { ...appHistory.current.getState(), index: 1 } }).finished; ``` ## Updating browser url > This is a pending development task. > The below code will help visually update the window This can be achieved various ways, but if your application completely utilises the app history interface, then you can directly use `pushState` to immediately update the window's url. This does not take into account the browser's native back/forward functionality, which would need to be investigated further. ```typescript import { AppHistory } from "@virtualstate/app-history"; const appHistory = new AppHistory(); const origin = typeof location === "undefined" ? "https://example.com" : location.origin; appHistory.addEventListener("currentchange", () => { const { current } = appHistory; if (!current || !current.sameDocument) return; const state = current.getState() ?? {}; const { pathname } = new URL(current.url, origin); if (typeof window !== "undefined" && window.history) { window.history.pushState(state, state.title, origin) } }) ```