README
@virtualstate/app-history
Native JavaScript app-history implementation
Support
Test Coverage
Install
Skypack
const { AppHistory } = await import("https://cdn.skypack.dev/@virtualstate/app-history");
Or
import { AppHistory } from "https://cdn.skypack.dev/@virtualstate/app-history";
npm / yarn / GitHub
npm i --save @virtualstate/app-history
Or
yarn add @virtualstate/app-history
Then
import { AppHistory } from "@virtualstate/app-history";
Navigation
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
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
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
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
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.
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)
}
})