mobx-wouter
Version:
<img src="assets/logo.png" align="right" height="156" alt="logo" />
124 lines (123 loc) • 4.18 kB
JavaScript
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);