UNPKG

mobx-wouter

Version:

<img src="assets/logo.png" align="right" height="156" alt="logo" />

124 lines (123 loc) 4.18 kB
import { QueryParams, buildSearchString, createBrowserHistory, createHashHistory, } from 'mobx-location-history'; import { startTransition } from 'react'; export class Router { config; history; queryParams; baseUrl; constructor(config) { this.config = config; this.baseUrl = config.baseUrl; this.history = config.history ?? createBrowserHistory(); if (config.history) { this.history = config.history; } else if (config.type === 'hash') { this.history = createHashHistory(); } else { this.history = createBrowserHistory(); } this.queryParams = config.queryParams ?? new QueryParams({ history: this.history }); } createPath(to) { const baseUrl = !this.baseUrl || this.baseUrl === '/' ? '' : this.baseUrl; if (typeof to === 'string') { const [rawPathname, ...searchSegments] = to.split('?'); const [pathname, ...hashSegments] = rawPathname.split('#'); const search = searchSegments.join('?'); const hash = hashSegments.join('#'); return { baseUrl, pathname, search: search ? `?${search}` : '', hash: hash || '', }; } else if ('baseUrl' in to) { return to; } else { return this.createPath(`${to.pathname}${buildSearchString(to.search || {})}`); } } get location() { return this.history.location; } createUrl(to) { const path = this.createPath(to); return [ path.baseUrl, this.config.type === 'hash' ? '#' : '', path.pathname, path.hash && `#${path.hash}`, path.search, ].join(''); } lastViewTransition; wrapInViewTransition(action, useStartViewTransition) { if ((useStartViewTransition || (useStartViewTransition == null && this.config.useStartViewTransition)) && document.startViewTransition) { if (this.lastViewTransition) { this.lastViewTransition.skipTransition(); } this.lastViewTransition = document.startViewTransition(() => { startTransition(action); }); this.lastViewTransition.finished.finally(() => { delete this.lastViewTransition; }); } else { action(); } } hashNavigate(to, options) { const path = this.createPath(to); const url = this.createUrl({ ...path, // This is fixes bug with pathname endings / // If location.pathname is /test-foo then after navigation to /test-foo#bar // navigation back will not work // If location.pathname is /test-foo/ then after navigation to /test-foo/#/bar // navigation back will not work baseUrl: this.location.pathname, }); const state = options?.state ?? null; this.wrapInViewTransition(() => { this.location.hash = `#${path.pathname || '/'}`; this.history.replace(url, state); }, options?.useStartViewTransition); } navigate(to, options) { if (this.config.type === 'hash') { this.hashNavigate(to, options); } else { const path = this.createPath(to); const url = this.createUrl(path); const state = options?.state ?? null; this.wrapInViewTransition(() => { if (options?.replace) { this.history.replace(url, state); } else { this.history.push(url, state); } }, options?.useStartViewTransition); } } back() { this.history.back(); } } /** * @deprecated Use `Router` instead. * This export will be removed in next major release */ export const MobxRouter = Router; export const createRouter = (config) => new Router(config);