@solidjs/router 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.jsx ADDED
@@ -0,0 +1,4 @@
1
+ export * from "./components";
2
+ export * from "./integration";
3
+ export { useRouteData, useHref, useIsRouting, useLocation, useMatch, useNavigate, useParams, useResolvedPath, useSearchParams } from "./routing";
4
+ export { mergeSearchString as _mergeSearchString } from "./utils";
@@ -0,0 +1,6 @@
1
+ import type { LocationChange, LocationChangeSignal, RouterIntegration, RouterUtils } from "./types";
2
+ export declare function createIntegration(get: () => string | LocationChange, set: (next: LocationChange) => void, init?: (notify: (value?: string | LocationChange) => void) => () => void, utils?: Partial<RouterUtils>): RouterIntegration;
3
+ export declare function normalizeIntegration(integration: RouterIntegration | LocationChangeSignal | undefined): RouterIntegration;
4
+ export declare function staticIntegration(obj: LocationChange): RouterIntegration;
5
+ export declare function pathIntegration(): RouterIntegration;
6
+ export declare function hashIntegration(): RouterIntegration;
@@ -0,0 +1,105 @@
1
+ import { createSignal, onCleanup } from "solid-js";
2
+ function bindEvent(target, type, handler) {
3
+ target.addEventListener(type, handler);
4
+ return () => target.removeEventListener(type, handler);
5
+ }
6
+ function intercept([value, setValue], get, set) {
7
+ return [get ? () => get(value()) : value, set ? (v) => setValue(set(v)) : setValue];
8
+ }
9
+ function querySelector(selector) {
10
+ // Guard against selector being an invalid CSS selector
11
+ try {
12
+ return document.querySelector(selector);
13
+ }
14
+ catch (e) {
15
+ return null;
16
+ }
17
+ }
18
+ function scrollToHash(hash, fallbackTop) {
19
+ const el = querySelector(`#${hash}`);
20
+ if (el) {
21
+ el.scrollIntoView();
22
+ }
23
+ else if (fallbackTop) {
24
+ window.scrollTo(0, 0);
25
+ }
26
+ }
27
+ export function createIntegration(get, set, init, utils) {
28
+ let ignore = false;
29
+ const wrap = (value) => (typeof value === "string" ? { value } : value);
30
+ const signal = intercept(createSignal(wrap(get()), { equals: (a, b) => a.value === b.value }), undefined, next => {
31
+ !ignore && set(next);
32
+ return next;
33
+ });
34
+ init &&
35
+ onCleanup(init((value = get()) => {
36
+ ignore = true;
37
+ signal[1](wrap(value));
38
+ ignore = false;
39
+ }));
40
+ return {
41
+ signal,
42
+ utils
43
+ };
44
+ }
45
+ export function normalizeIntegration(integration) {
46
+ if (!integration) {
47
+ return {
48
+ signal: createSignal({ value: "" })
49
+ };
50
+ }
51
+ else if (Array.isArray(integration)) {
52
+ return {
53
+ signal: integration
54
+ };
55
+ }
56
+ return integration;
57
+ }
58
+ export function staticIntegration(obj) {
59
+ return {
60
+ signal: [() => obj, next => Object.assign(obj, next)]
61
+ };
62
+ }
63
+ export function pathIntegration() {
64
+ return createIntegration(() => ({
65
+ value: window.location.pathname + window.location.search + window.location.hash,
66
+ state: history.state
67
+ }), ({ value, replace, scroll, state }) => {
68
+ if (replace) {
69
+ window.history.replaceState(state, "", value);
70
+ }
71
+ else {
72
+ window.history.pushState(state, "", value);
73
+ }
74
+ scrollToHash(window.location.hash.slice(1), scroll);
75
+ }, notify => bindEvent(window, "popstate", () => notify()), {
76
+ go: delta => window.history.go(delta)
77
+ });
78
+ }
79
+ export function hashIntegration() {
80
+ return createIntegration(() => window.location.hash.slice(1), ({ value, replace, scroll, state }) => {
81
+ if (replace) {
82
+ window.history.replaceState(state, "", "#" + value);
83
+ }
84
+ else {
85
+ window.location.hash = value;
86
+ }
87
+ const hashIndex = value.indexOf("#");
88
+ const hash = hashIndex >= 0 ? value.slice(hashIndex + 1) : "";
89
+ scrollToHash(hash, scroll);
90
+ }, notify => bindEvent(window, "hashchange", () => notify()), {
91
+ go: delta => window.history.go(delta),
92
+ renderPath: path => `#${path}`,
93
+ parsePath: str => {
94
+ const to = str.replace(/^.*?#/, "");
95
+ // Hash-only hrefs like `#foo` from plain anchors will come in as `/#foo` whereas a link to
96
+ // `/foo` will be `/#/foo`. Check if the to starts with a `/` and if not append it as a hash
97
+ // to the current path so we can handle these in-page anchors correctly.
98
+ if (!to.startsWith("/")) {
99
+ const [, path = "/"] = window.location.hash.split("#", 2);
100
+ return `${path}#${to}`;
101
+ }
102
+ return to;
103
+ }
104
+ });
105
+ }
@@ -0,0 +1,24 @@
1
+ import type { Component, Accessor } from "solid-js";
2
+ import type { Branch, Location, LocationChangeSignal, NavigateOptions, Navigator, Params, Route, RouteContext, RouteDataFunc, RouteDefinition, RouteMatch, RouterContext, RouterIntegration, SetParams } from "./types";
3
+ export declare const RouterContextObj: import("solid-js").Context<RouterContext | undefined>;
4
+ export declare const RouteContextObj: import("solid-js").Context<RouteContext | undefined>;
5
+ export declare const useRouter: () => RouterContext;
6
+ export declare const useRoute: () => RouteContext;
7
+ export declare const useResolvedPath: (path: () => string) => Accessor<string | undefined>;
8
+ export declare const useHref: (to: () => string | undefined) => Accessor<string | undefined>;
9
+ export declare const useNavigate: () => Navigator;
10
+ export declare const useLocation: <S = unknown>() => Location<S>;
11
+ export declare const useIsRouting: () => () => boolean;
12
+ export declare const useMatch: (path: () => string) => Accessor<import("./types").PathMatch | null>;
13
+ export declare const useParams: <T extends Params>() => T;
14
+ declare type MaybeReturnType<T> = T extends (...args: any) => infer R ? R : T;
15
+ export declare const useRouteData: <T>() => MaybeReturnType<T>;
16
+ export declare const useSearchParams: <T extends Params>() => [T, (params: SetParams, options?: Partial<NavigateOptions<unknown>> | undefined) => void];
17
+ export declare function createRoutes(routeDef: RouteDefinition, base?: string, fallback?: Component): Route[];
18
+ export declare function createBranch(routes: Route[], index?: number): Branch;
19
+ export declare function createBranches(routeDef: RouteDefinition | RouteDefinition[], base?: string, fallback?: Component, stack?: Route[], branches?: Branch[]): Branch[];
20
+ export declare function getRouteMatches(branches: Branch[], location: string): RouteMatch[];
21
+ export declare function createLocation(path: Accessor<string>, state: Accessor<any>): Location;
22
+ export declare function createRouterContext(integration?: RouterIntegration | LocationChangeSignal, base?: string, data?: RouteDataFunc, out?: object): RouterContext;
23
+ export declare function createRouteContext(router: RouterContext, parent: RouteContext, child: () => RouteContext, match: () => RouteMatch): RouteContext;
24
+ export {};
@@ -0,0 +1,377 @@
1
+ import { createComponent, createContext, createMemo, createRenderEffect, createSignal, on, onCleanup, untrack, useContext, useTransition, resetErrorBoundaries } from "solid-js";
2
+ import { isServer } from "solid-js/web";
3
+ import { normalizeIntegration } from "./integration";
4
+ import { createMemoObject, extractSearchParams, invariant, resolvePath, createMatcher, joinPaths, scoreRoute, mergeSearchString, urlDecode, expandOptionals } from "./utils";
5
+ const MAX_REDIRECTS = 100;
6
+ export const RouterContextObj = createContext();
7
+ export const RouteContextObj = createContext();
8
+ export const useRouter = () => invariant(useContext(RouterContextObj), "Make sure your app is wrapped in a <Router />");
9
+ let TempRoute;
10
+ export const useRoute = () => TempRoute || useContext(RouteContextObj) || useRouter().base;
11
+ export const useResolvedPath = (path) => {
12
+ const route = useRoute();
13
+ return createMemo(() => route.resolvePath(path()));
14
+ };
15
+ export const useHref = (to) => {
16
+ const router = useRouter();
17
+ return createMemo(() => {
18
+ const to_ = to();
19
+ return to_ !== undefined ? router.renderPath(to_) : to_;
20
+ });
21
+ };
22
+ export const useNavigate = () => useRouter().navigatorFactory();
23
+ export const useLocation = () => useRouter().location;
24
+ export const useIsRouting = () => useRouter().isRouting;
25
+ export const useMatch = (path) => {
26
+ const location = useLocation();
27
+ const matcher = createMemo(() => createMatcher(path()));
28
+ return createMemo(() => matcher()(location.pathname));
29
+ };
30
+ export const useParams = () => useRoute().params;
31
+ export const useRouteData = () => useRoute().data;
32
+ export const useSearchParams = () => {
33
+ const location = useLocation();
34
+ const navigate = useNavigate();
35
+ const setSearchParams = (params, options) => {
36
+ const searchString = untrack(() => mergeSearchString(location.search, params));
37
+ navigate(searchString, { scroll: false, ...options, resolve: true });
38
+ };
39
+ return [location.query, setSearchParams];
40
+ };
41
+ export function createRoutes(routeDef, base = "", fallback) {
42
+ const { component, data, children } = routeDef;
43
+ const isLeaf = !children || (Array.isArray(children) && !children.length);
44
+ const shared = {
45
+ key: routeDef,
46
+ element: component
47
+ ? () => createComponent(component, {})
48
+ : () => {
49
+ const { element } = routeDef;
50
+ return element === undefined && fallback
51
+ ? createComponent(fallback, {})
52
+ : element;
53
+ },
54
+ preload: routeDef.component
55
+ ? component.preload
56
+ : routeDef.preload,
57
+ data
58
+ };
59
+ return asArray(routeDef.path).reduce((acc, path) => {
60
+ for (const originalPath of expandOptionals(path)) {
61
+ const path = joinPaths(base, originalPath);
62
+ const pattern = isLeaf ? path : path.split("/*", 1)[0];
63
+ acc.push({
64
+ ...shared,
65
+ originalPath,
66
+ pattern,
67
+ matcher: createMatcher(pattern, !isLeaf)
68
+ });
69
+ }
70
+ return acc;
71
+ }, []);
72
+ }
73
+ export function createBranch(routes, index = 0) {
74
+ return {
75
+ routes,
76
+ score: scoreRoute(routes[routes.length - 1]) * 10000 - index,
77
+ matcher(location) {
78
+ const matches = [];
79
+ for (let i = routes.length - 1; i >= 0; i--) {
80
+ const route = routes[i];
81
+ const match = route.matcher(location);
82
+ if (!match) {
83
+ return null;
84
+ }
85
+ matches.unshift({
86
+ ...match,
87
+ route
88
+ });
89
+ }
90
+ return matches;
91
+ }
92
+ };
93
+ }
94
+ function asArray(value) {
95
+ return Array.isArray(value) ? value : [value];
96
+ }
97
+ export function createBranches(routeDef, base = "", fallback, stack = [], branches = []) {
98
+ const routeDefs = asArray(routeDef);
99
+ for (let i = 0, len = routeDefs.length; i < len; i++) {
100
+ const def = routeDefs[i];
101
+ if (def && typeof def === "object" && def.hasOwnProperty("path")) {
102
+ const routes = createRoutes(def, base, fallback);
103
+ for (const route of routes) {
104
+ stack.push(route);
105
+ if (def.children) {
106
+ createBranches(def.children, route.pattern, fallback, stack, branches);
107
+ }
108
+ else {
109
+ const branch = createBranch([...stack], branches.length);
110
+ branches.push(branch);
111
+ }
112
+ stack.pop();
113
+ }
114
+ }
115
+ }
116
+ // Stack will be empty on final return
117
+ return stack.length ? branches : branches.sort((a, b) => b.score - a.score);
118
+ }
119
+ export function getRouteMatches(branches, location) {
120
+ for (let i = 0, len = branches.length; i < len; i++) {
121
+ const match = branches[i].matcher(location);
122
+ if (match) {
123
+ return match;
124
+ }
125
+ }
126
+ return [];
127
+ }
128
+ export function createLocation(path, state) {
129
+ const origin = new URL("http://sar");
130
+ const url = createMemo(prev => {
131
+ const path_ = path();
132
+ try {
133
+ return new URL(path_, origin);
134
+ }
135
+ catch (err) {
136
+ console.error(`Invalid path ${path_}`);
137
+ return prev;
138
+ }
139
+ }, origin, {
140
+ equals: (a, b) => a.href === b.href
141
+ });
142
+ const pathname = createMemo(() => urlDecode(url().pathname));
143
+ const search = createMemo(() => urlDecode(url().search, true));
144
+ const hash = createMemo(() => urlDecode(url().hash));
145
+ const key = createMemo(() => "");
146
+ return {
147
+ get pathname() {
148
+ return pathname();
149
+ },
150
+ get search() {
151
+ return search();
152
+ },
153
+ get hash() {
154
+ return hash();
155
+ },
156
+ get state() {
157
+ return state();
158
+ },
159
+ get key() {
160
+ return key();
161
+ },
162
+ query: createMemoObject(on(search, () => extractSearchParams(url())))
163
+ };
164
+ }
165
+ export function createRouterContext(integration, base = "", data, out) {
166
+ const { signal: [source, setSource], utils = {} } = normalizeIntegration(integration);
167
+ const parsePath = utils.parsePath || (p => p);
168
+ const renderPath = utils.renderPath || (p => p);
169
+ const basePath = resolvePath("", base);
170
+ const output = isServer && out
171
+ ? Object.assign(out, {
172
+ matches: [],
173
+ url: undefined
174
+ })
175
+ : undefined;
176
+ if (basePath === undefined) {
177
+ throw new Error(`${basePath} is not a valid base path`);
178
+ }
179
+ else if (basePath && !source().value) {
180
+ setSource({ value: basePath, replace: true, scroll: false });
181
+ }
182
+ const [isRouting, start] = useTransition();
183
+ const [reference, setReference] = createSignal(source().value);
184
+ const [state, setState] = createSignal(source().state);
185
+ const location = createLocation(reference, state);
186
+ const referrers = [];
187
+ const baseRoute = {
188
+ pattern: basePath,
189
+ params: {},
190
+ path: () => basePath,
191
+ outlet: () => null,
192
+ resolvePath(to) {
193
+ return resolvePath(basePath, to);
194
+ }
195
+ };
196
+ if (data) {
197
+ try {
198
+ TempRoute = baseRoute;
199
+ baseRoute.data = data({
200
+ data: undefined,
201
+ params: {},
202
+ location,
203
+ navigate: navigatorFactory(baseRoute)
204
+ });
205
+ }
206
+ finally {
207
+ TempRoute = undefined;
208
+ }
209
+ }
210
+ function navigateFromRoute(route, to, options) {
211
+ // Untrack in case someone navigates in an effect - don't want to track `reference` or route paths
212
+ untrack(() => {
213
+ if (typeof to === "number") {
214
+ if (!to) {
215
+ // A delta of 0 means stay at the current location, so it is ignored
216
+ }
217
+ else if (utils.go) {
218
+ utils.go(to);
219
+ }
220
+ else {
221
+ console.warn("Router integration does not support relative routing");
222
+ }
223
+ return;
224
+ }
225
+ const { replace, resolve, scroll, state: nextState } = {
226
+ replace: false,
227
+ resolve: true,
228
+ scroll: true,
229
+ ...options
230
+ };
231
+ const resolvedTo = resolve ? route.resolvePath(to) : resolvePath("", to);
232
+ if (resolvedTo === undefined) {
233
+ throw new Error(`Path '${to}' is not a routable path`);
234
+ }
235
+ else if (referrers.length >= MAX_REDIRECTS) {
236
+ throw new Error("Too many redirects");
237
+ }
238
+ const current = reference();
239
+ if (resolvedTo !== current || nextState !== state()) {
240
+ if (isServer) {
241
+ if (output) {
242
+ output.url = resolvedTo;
243
+ }
244
+ setSource({ value: resolvedTo, replace, scroll, state: nextState });
245
+ }
246
+ else {
247
+ const len = referrers.push({ value: current, replace, scroll, state: state() });
248
+ start(() => {
249
+ setReference(resolvedTo);
250
+ setState(nextState);
251
+ resetErrorBoundaries();
252
+ }).then(() => {
253
+ if (referrers.length === len) {
254
+ navigateEnd({
255
+ value: resolvedTo,
256
+ state: nextState
257
+ });
258
+ }
259
+ });
260
+ }
261
+ }
262
+ });
263
+ }
264
+ function navigatorFactory(route) {
265
+ // Workaround for vite issue (https://github.com/vitejs/vite/issues/3803)
266
+ route = route || useContext(RouteContextObj) || baseRoute;
267
+ return (to, options) => navigateFromRoute(route, to, options);
268
+ }
269
+ function navigateEnd(next) {
270
+ const first = referrers[0];
271
+ if (first) {
272
+ if (next.value !== first.value || next.state !== first.state) {
273
+ setSource({
274
+ ...next,
275
+ replace: first.replace,
276
+ scroll: first.scroll
277
+ });
278
+ }
279
+ referrers.length = 0;
280
+ }
281
+ }
282
+ createRenderEffect(() => {
283
+ const { value, state } = source();
284
+ // Untrack this whole block so `start` doesn't cause Solid's Listener to be preserved
285
+ untrack(() => {
286
+ if (value !== reference()) {
287
+ start(() => {
288
+ setReference(value);
289
+ setState(state);
290
+ });
291
+ }
292
+ });
293
+ });
294
+ if (!isServer) {
295
+ function isSvg(el) {
296
+ return el.namespaceURI === "http://www.w3.org/2000/svg";
297
+ }
298
+ function handleAnchorClick(evt) {
299
+ if (evt.defaultPrevented ||
300
+ evt.button !== 0 ||
301
+ evt.metaKey ||
302
+ evt.altKey ||
303
+ evt.ctrlKey ||
304
+ evt.shiftKey)
305
+ return;
306
+ const a = evt
307
+ .composedPath()
308
+ .find(el => el instanceof Node && el.nodeName.toUpperCase() === "A");
309
+ if (!a)
310
+ return;
311
+ const svg = isSvg(a);
312
+ const href = svg ? a.href.baseVal : a.href;
313
+ const target = svg ? a.target.baseVal : a.target;
314
+ if (target || (!href && !a.hasAttribute("state")))
315
+ return;
316
+ const rel = (a.getAttribute("rel") || "").split(/\s+/);
317
+ if (a.hasAttribute("download") || (rel && rel.includes("external")))
318
+ return;
319
+ const url = svg ? new URL(href, document.baseURI) : new URL(href);
320
+ const pathname = urlDecode(url.pathname);
321
+ if (url.origin !== window.location.origin ||
322
+ (basePath && pathname && !pathname.toLowerCase().startsWith(basePath.toLowerCase())))
323
+ return;
324
+ const to = parsePath(pathname + urlDecode(url.search, true) + urlDecode(url.hash));
325
+ const state = a.getAttribute("state");
326
+ evt.preventDefault();
327
+ navigateFromRoute(baseRoute, to, {
328
+ resolve: false,
329
+ replace: a.hasAttribute("replace"),
330
+ scroll: !a.hasAttribute("noscroll"),
331
+ state: state && JSON.parse(state)
332
+ });
333
+ }
334
+ document.addEventListener("click", handleAnchorClick);
335
+ onCleanup(() => document.removeEventListener("click", handleAnchorClick));
336
+ }
337
+ return {
338
+ base: baseRoute,
339
+ out: output,
340
+ location,
341
+ isRouting,
342
+ renderPath,
343
+ parsePath,
344
+ navigatorFactory
345
+ };
346
+ }
347
+ export function createRouteContext(router, parent, child, match) {
348
+ const { base, location, navigatorFactory } = router;
349
+ const { pattern, element: outlet, preload, data } = match().route;
350
+ const path = createMemo(() => match().path);
351
+ const params = createMemoObject(() => match().params);
352
+ preload && preload();
353
+ const route = {
354
+ parent,
355
+ pattern,
356
+ get child() {
357
+ return child();
358
+ },
359
+ path,
360
+ params,
361
+ data: parent.data,
362
+ outlet,
363
+ resolvePath(to) {
364
+ return resolvePath(base.path(), to, path());
365
+ }
366
+ };
367
+ if (data) {
368
+ try {
369
+ TempRoute = route;
370
+ route.data = data({ data: parent.data, params, location, navigate: navigatorFactory(route) });
371
+ }
372
+ finally {
373
+ TempRoute = undefined;
374
+ }
375
+ }
376
+ return route;
377
+ }
@@ -0,0 +1,115 @@
1
+ import { Component, JSX } from "solid-js";
2
+ export declare type Params = Record<string, string>;
3
+ export declare type SetParams = Record<string, string | number | boolean | null | undefined>;
4
+ export interface Path {
5
+ pathname: string;
6
+ search: string;
7
+ hash: string;
8
+ }
9
+ export interface Location<S = unknown> extends Path {
10
+ query: Params;
11
+ state: Readonly<Partial<S>> | null;
12
+ key: string;
13
+ }
14
+ export interface NavigateOptions<S = unknown> {
15
+ resolve: boolean;
16
+ replace: boolean;
17
+ scroll: boolean;
18
+ state: S;
19
+ }
20
+ export interface Navigator {
21
+ (to: string, options?: Partial<NavigateOptions>): void;
22
+ (delta: number): void;
23
+ }
24
+ export declare type NavigatorFactory = (route?: RouteContext) => Navigator;
25
+ export interface LocationChange<S = unknown> {
26
+ value: string;
27
+ replace?: boolean;
28
+ scroll?: boolean;
29
+ state?: S;
30
+ }
31
+ export declare type LocationChangeSignal = [() => LocationChange, (next: LocationChange) => void];
32
+ export interface RouterIntegration {
33
+ signal: LocationChangeSignal;
34
+ utils?: Partial<RouterUtils>;
35
+ }
36
+ export interface RouteDataFuncArgs {
37
+ data: unknown;
38
+ params: Params;
39
+ location: Location;
40
+ navigate: Navigator;
41
+ }
42
+ export declare type RouteDataFunc<T = unknown> = (args: RouteDataFuncArgs) => T;
43
+ export declare type RouteDefinition = {
44
+ path: string | string[];
45
+ data?: RouteDataFunc;
46
+ children?: RouteDefinition | RouteDefinition[];
47
+ } & ({
48
+ element?: never;
49
+ component: Component;
50
+ } | {
51
+ component?: never;
52
+ element?: JSX.Element;
53
+ preload?: () => void;
54
+ });
55
+ export interface PathMatch {
56
+ params: Params;
57
+ path: string;
58
+ }
59
+ export interface RouteMatch extends PathMatch {
60
+ route: Route;
61
+ }
62
+ export interface OutputMatch {
63
+ originalPath: string;
64
+ pattern: string;
65
+ path: string;
66
+ params: Params;
67
+ }
68
+ export interface Route {
69
+ key: unknown;
70
+ originalPath: string;
71
+ pattern: string;
72
+ element: () => JSX.Element;
73
+ preload?: () => void;
74
+ data?: RouteDataFunc;
75
+ matcher: (location: string) => PathMatch | null;
76
+ }
77
+ export interface Branch {
78
+ routes: Route[];
79
+ score: number;
80
+ matcher: (location: string) => RouteMatch[] | null;
81
+ }
82
+ export interface RouteContext {
83
+ parent?: RouteContext;
84
+ child?: RouteContext;
85
+ data?: unknown;
86
+ pattern: string;
87
+ params: Params;
88
+ path: () => string;
89
+ outlet: () => JSX.Element;
90
+ resolvePath(to: string): string | undefined;
91
+ }
92
+ export interface RouterUtils {
93
+ renderPath(path: string): string;
94
+ parsePath(str: string): string;
95
+ go(delta: number): void;
96
+ }
97
+ export interface OutputMatch {
98
+ originalPath: string;
99
+ pattern: string;
100
+ path: string;
101
+ params: Params;
102
+ }
103
+ export interface RouterOutput {
104
+ url?: string;
105
+ matches: OutputMatch[][];
106
+ }
107
+ export interface RouterContext {
108
+ base: RouteContext;
109
+ out?: RouterOutput;
110
+ location: Location;
111
+ navigatorFactory: NavigatorFactory;
112
+ isRouting: () => boolean;
113
+ renderPath(path: string): string;
114
+ parsePath(str: string): string;
115
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ import type { Params, PathMatch, Route, SetParams } from "./types";
2
+ export declare function resolvePath(base: string, path: string, from?: string): string | undefined;
3
+ export declare function invariant<T>(value: T | null | undefined, message: string): T;
4
+ export declare function joinPaths(from: string, to: string): string;
5
+ export declare function extractSearchParams(url: URL): Params;
6
+ export declare function urlDecode(str: string, isQuery?: boolean): string;
7
+ export declare function createMatcher(path: string, partial?: boolean): (location: string) => PathMatch | null;
8
+ export declare function scoreRoute(route: Route): number;
9
+ export declare function createMemoObject<T extends Record<string | symbol, unknown>>(fn: () => T): T;
10
+ export declare function mergeSearchString(search: string, params: SetParams): string;
11
+ export declare function expandOptionals(pattern: string): string[];