compact-router 0.0.0-stage → 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Alexander Tkačenko
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,121 @@
1
- # Temporary Holding Version
1
+ # compact-router
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Vanilla TS/JS routing
4
+
5
+ Contents: [Route](#route) · [Annotated live demos](#annotated-live-demos)
6
+
7
+ ## `Route`
8
+
9
+ `Route` stores the URL and exposes a `window.location`-like API for SPA navigation with a URL matching API.
10
+
11
+ ```js
12
+ import { Route } from "compact-router";
13
+
14
+ const route = new Route();
15
+ ```
16
+
17
+ Navigate to other URLs in a SPA fashion similarly to the browser APIs:
18
+
19
+ ```js
20
+ route.href = "/intro";
21
+ route.assign("/intro");
22
+ route.replace("/intro");
23
+ ```
24
+
25
+ Or in a more fine-grained manner:
26
+
27
+ ```js
28
+ route.navigate({ href: "/intro", history: "replace", scroll: "off" });
29
+ ```
30
+
31
+ Check the current URL value like a regular `string` with `route.href`:
32
+
33
+ ```js
34
+ route.href === "/intro";
35
+ route.href.startsWith("/sections/");
36
+ /^\/sections\/\d+\/?/.test(route.href);
37
+ ```
38
+
39
+ Or, alternatively, with `route.at(url)` returning `true` if the current URL matches `url`, and `false` otherwise:
40
+
41
+ ```js
42
+ route.at("/intro"); // `true` at "/intro", `false` otherwise
43
+ route.at(/^\/sections\//); // `true` at "/sections/*"
44
+ ```
45
+
46
+ Or with the extended form `route.at(url, x, y?)`, which is similar to the ternary conditional operator `atURL ? x : y`:
47
+
48
+ ```js
49
+ document.querySelector("header").className = route.at("/", "full", "compact");
50
+ // at "/" ? then "full" : otherwise "compact"
51
+ ```
52
+
53
+ Use `route.at(url, x, y?)` with dynamic values that require values from the URL pattern's capturing groups:
54
+
55
+ ```js
56
+ document.querySelector("h1").textContent = route.at(
57
+ /^\/sections\/(?<id>\d+)\/?/,
58
+ ({ params }) => `Section ${params.id}`,
59
+ );
60
+ // at "/sections/:id", "Section <id>" (otherwise `undefined`)
61
+ ```
62
+
63
+ Or, alternatively, with a string URL pattern:
64
+
65
+ ```js
66
+ import { url } from "url-shape";
67
+
68
+ document.querySelector("h1").textContent = route.at(
69
+ url("/sections/:id"),
70
+ ({ params }) => `Section ${params.id}`,
71
+ );
72
+ // at "/sections/:id", "Section <id>" (otherwise `undefined`)
73
+ ```
74
+
75
+ Use a URL builder like the one from `url-shape` also in conjunction with a URL schema to set up type-safe routes ([example](https://codesandbox.io/p/sandbox/qg7qg3?file=%2Fsrc%2Findex.ts)).
76
+
77
+ Enable SPA navigation with HTML links inside the specified container (or the entire `document`) without any changes to the HTML:
78
+
79
+ ```js
80
+ route.observe(document);
81
+ ```
82
+
83
+ Tweak the links' navigation behavior by adding a relevant combination of the optional `data-` attributes (corresponding to the `route.navigate()` options):
84
+
85
+ ```html
86
+ <a href="/intro">Intro</a>
87
+ <a href="/intro" data-history="replace">Intro</a>
88
+ <a href="/intro" data-scroll="off">Intro</a>
89
+ <a href="/intro" data-spa="off">Intro</a>
90
+ ```
91
+
92
+ Links covered by `route.observe(container, selector?)` also automatically receive the `data-active="true"` attribute whenever their `href` attribute matches the current URL, which can be used for additional styling. If links are added to the DOM asynchronously, call `route.emit("ready")` when the rendering is complete to mark active links.
93
+
94
+ Define what should be done when the URL changes:
95
+
96
+ ```js
97
+ route.on("navigationcomplete", ({ href }) => {
98
+ renderContent();
99
+ });
100
+ ```
101
+
102
+ Define what should be done before the URL changes (in a way effectively similar to routing middleware):
103
+
104
+ ```js
105
+ route.on("navigationstart", ({ href }) => {
106
+ if (hasUnsavedInput) return false; // Quit the navigation, prevent the current URL change
107
+
108
+ if (href === "/") {
109
+ route.href = "/intro"; // SPA redirection
110
+ return false;
111
+ }
112
+ });
113
+ ```
114
+
115
+ ## Annotated live demos
116
+
117
+ - [URL-based rendering](https://codesandbox.io/p/sandbox/kt6m5l?file=%252Fsrc%252Findex.ts)
118
+ - [Type-safe URL-based rendering](https://codesandbox.io/p/sandbox/qg7qg3?file=%2Fsrc%2Findex.ts)
119
+ - [SPA redirection](https://codesandbox.io/p/sandbox/rpl3gh?file=%252Fsrc%252Findex.ts)
120
+
121
+ Find also the code of these examples in the repo's [`tests`](https://github.com/axtk/compact-router/tree/main/tests) directory.
package/dist/index.cjs ADDED
@@ -0,0 +1,369 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let quasiurl = require("quasiurl");
3
+ let compact_state = require("compact-state");
4
+ // src/URLState.ts
5
+ function isImmediatelyInvokedNavigationEvent(event) {
6
+ return event === "navigationstart" || event === "navigationcomplete";
7
+ }
8
+ function isImmediatelyInvokedEvent(event) {
9
+ return event === "ready";
10
+ }
11
+ var URLState = class extends compact_state.State {
12
+ constructor(href = null, options) {
13
+ super(href ?? "", options);
14
+ }
15
+ _init() {
16
+ super._init();
17
+ if (typeof window === "undefined") return;
18
+ let handleURLChange = () => {
19
+ this.setValue(window.location.href, { source: "popstate" });
20
+ };
21
+ this.on("start", () => {
22
+ window.addEventListener("popstate", handleURLChange);
23
+ this.emit("ready");
24
+ });
25
+ this.on("stop", () => {
26
+ window.removeEventListener("popstate", handleURLChange);
27
+ });
28
+ }
29
+ on(event, callback, invokeImmediately) {
30
+ if (invokeImmediately !== false) {
31
+ if (isImmediatelyInvokedNavigationEvent(event)) this._call(() => {
32
+ callback({ href: this.getValue() });
33
+ });
34
+ else if (isImmediatelyInvokedEvent(event)) this._call(() => {
35
+ callback();
36
+ });
37
+ }
38
+ return super.on(event, callback);
39
+ }
40
+ getValue() {
41
+ return this.toValue(this._value);
42
+ }
43
+ setValue(update, options) {
44
+ if (!this._active) return;
45
+ let href = this.toValue(this._resolveValue(update));
46
+ let extendedOptions = {
47
+ ...options,
48
+ href,
49
+ referrer: this.getValue()
50
+ };
51
+ if (this.emit("navigationstart", extendedOptions) && this._transition(extendedOptions) !== false) {
52
+ this._assignValue(href);
53
+ this.emit("navigation", extendedOptions);
54
+ if (this.emit("navigationcomplete", extendedOptions)) {
55
+ this._complete(extendedOptions);
56
+ this.emit("ready");
57
+ }
58
+ }
59
+ }
60
+ _transition(options) {
61
+ if (typeof window === "undefined" || options?.href === void 0 || options?.source === "popstate") return;
62
+ let { href, target, spa, history } = options;
63
+ if (target && target !== "_self") {
64
+ window.open(href, target);
65
+ return false;
66
+ }
67
+ let url = new quasiurl.QuasiURL(href);
68
+ if (spa === "off" || !window.history || url.origin !== "" && url.origin !== window.location.origin) {
69
+ window.location[history === "replace" ? "replace" : "assign"](href);
70
+ return false;
71
+ }
72
+ window.history[history === "replace" ? "replaceState" : "pushState"]({}, "", href);
73
+ }
74
+ _complete(options) {
75
+ if (typeof window === "undefined" || !options || options.scroll === "off") return;
76
+ let { href, target } = options;
77
+ if (href === void 0 || target && target !== "_self") return;
78
+ let { hash } = new quasiurl.QuasiURL(href);
79
+ requestAnimationFrame(() => {
80
+ let targetElement = hash === "" ? null : document.querySelector(`${hash}, a[name="${hash.slice(1)}"]`);
81
+ if (targetElement) targetElement.scrollIntoView();
82
+ else window.scrollTo(0, 0);
83
+ });
84
+ }
85
+ toValue(x) {
86
+ if (typeof window === "undefined") return x;
87
+ let url = new quasiurl.QuasiURL(x || window.location.href);
88
+ if (url.origin === window.location.origin) url.origin = "";
89
+ return url.href;
90
+ }
91
+ };
92
+ // src/utils/isLocationObject.ts
93
+ function isLocationObject(x) {
94
+ return x !== null && typeof x === "object" && "exec" in x && "compile" in x && "_schema" in x;
95
+ }
96
+ // src/utils/compileURL.ts
97
+ function compileURL(urlPattern, data) {
98
+ if (isLocationObject(urlPattern)) return urlPattern.compile(data);
99
+ let url = new quasiurl.QuasiURL(urlPattern ?? "");
100
+ let query = data?.query;
101
+ if (query) url.search = new URLSearchParams(Object.entries(query).reduce((p, [k, v]) => {
102
+ if (v !== null && v !== void 0) p[k] = typeof v === "string" ? v : JSON.stringify(v);
103
+ return p;
104
+ }, {}));
105
+ return url.href;
106
+ }
107
+ // src/utils/getNavigationOptions.ts
108
+ function getNavigationOptions(element) {
109
+ let { id, spa, history, scroll } = element.dataset;
110
+ return {
111
+ href: element.getAttribute("href"),
112
+ target: element.getAttribute("target"),
113
+ spa,
114
+ history,
115
+ scroll,
116
+ id
117
+ };
118
+ }
119
+ // src/utils/isRouteEvent.ts
120
+ function isRouteEvent(event) {
121
+ return event !== null && typeof event === "object" && (!("button" in event) || event.button === 0) && (!("ctrlKey" in event) || !event.ctrlKey) && (!("shiftKey" in event) || !event.shiftKey) && (!("altKey" in event) || !event.altKey) && (!("metaKey" in event) || !event.metaKey);
122
+ }
123
+ // src/utils/matchURL.ts
124
+ function toObject(x) {
125
+ return x.reduce((p, v, k) => {
126
+ p[String(k)] = v;
127
+ return p;
128
+ }, {});
129
+ }
130
+ function matchPattern(pattern, href) {
131
+ let query = Object.fromEntries(new URLSearchParams(new quasiurl.QuasiURL(href).search));
132
+ if (typeof pattern === "string") return {
133
+ ok: pattern === "*" || pattern === href,
134
+ href,
135
+ params: {},
136
+ query
137
+ };
138
+ if (pattern instanceof RegExp) {
139
+ let matches = pattern.exec(href);
140
+ return {
141
+ ok: matches !== null,
142
+ href,
143
+ params: matches ? {
144
+ ...toObject(Array.from(matches).slice(1)),
145
+ ...matches.groups
146
+ } : {},
147
+ query
148
+ };
149
+ }
150
+ if (isLocationObject(pattern)) {
151
+ let result = pattern.exec(href);
152
+ if (result === null) return {
153
+ ok: false,
154
+ href,
155
+ params: {},
156
+ query: {}
157
+ };
158
+ return {
159
+ ok: true,
160
+ href,
161
+ params: result.params ?? {},
162
+ query: result.query ?? {}
163
+ };
164
+ }
165
+ return {
166
+ ok: false,
167
+ href,
168
+ params: {},
169
+ query: {}
170
+ };
171
+ }
172
+ function matchURL(pattern, href) {
173
+ if (Array.isArray(pattern)) {
174
+ for (let p of pattern) {
175
+ let result = matchPattern(p, href);
176
+ if (result.ok) return result;
177
+ }
178
+ return {
179
+ ok: false,
180
+ href,
181
+ params: {},
182
+ query: {}
183
+ };
184
+ }
185
+ return matchPattern(pattern, href);
186
+ }
187
+ // src/Route.ts
188
+ function isElementCollection(x) {
189
+ return Array.isArray(x) || x instanceof NodeList || x instanceof HTMLCollection;
190
+ }
191
+ function isLinkElement(x) {
192
+ return x instanceof HTMLAnchorElement || x instanceof HTMLAreaElement;
193
+ }
194
+ function toggleActive(element, route) {
195
+ if (!isLinkElement(element)) return;
196
+ if (element.hasAttribute("href") && route.match(route.toValue(element.href)).ok) element.dataset.active = "true";
197
+ else delete element.dataset.active;
198
+ }
199
+ var Route = class extends URLState {
200
+ _observeInited = false;
201
+ constructor(href = null, options) {
202
+ super(String(href ?? ""), options);
203
+ }
204
+ /**
205
+ * Enables SPA navigation with HTML links inside the specified container.
206
+ *
207
+ * @example
208
+ * ```js
209
+ * let route = new Route();
210
+ * route.observe(document);
211
+ * ```
212
+ */
213
+ observe(container, elements = "a, area") {
214
+ if (typeof window === "undefined") return;
215
+ if (!this._observeInited) {
216
+ let handleClick = (event) => {
217
+ this.emit("documentclick", event);
218
+ };
219
+ this.on("start", () => {
220
+ document.addEventListener("click", handleClick);
221
+ });
222
+ this.on("stop", () => {
223
+ document.removeEventListener("click", handleClick);
224
+ });
225
+ if (this.active) document.addEventListener("click", handleClick);
226
+ this._observeInited = true;
227
+ }
228
+ let resolveParams = () => {
229
+ let resolvedContainer = typeof container === "function" ? container() : container;
230
+ if (!resolvedContainer) return;
231
+ return {
232
+ resolvedContainer,
233
+ targetElements: isElementCollection(elements) ? Array.from(elements) : [elements]
234
+ };
235
+ };
236
+ let removeClickHandlers = this.on("documentclick", (event) => {
237
+ if (event.defaultPrevented || !isRouteEvent(event)) return;
238
+ let resolvedParams = resolveParams();
239
+ if (!resolvedParams) return;
240
+ let { resolvedContainer, targetElements } = resolvedParams;
241
+ let element = null;
242
+ for (let targetElement of targetElements) {
243
+ let target = null;
244
+ if (typeof targetElement === "string") target = event.target instanceof HTMLElement ? event.target.closest(targetElement) : null;
245
+ else target = targetElement;
246
+ if (isLinkElement(target) && resolvedContainer.contains(target)) {
247
+ element = target;
248
+ break;
249
+ }
250
+ }
251
+ if (element) {
252
+ event.preventDefault();
253
+ this.navigate(getNavigationOptions(element));
254
+ }
255
+ });
256
+ let removeURLChangeHandlers = this.on("ready", () => {
257
+ let resolvedParams = resolveParams();
258
+ if (!resolvedParams) return;
259
+ let { resolvedContainer, targetElements } = resolvedParams;
260
+ for (let targetElement of targetElements) if (typeof targetElement === "string") {
261
+ let targets = resolvedContainer.querySelectorAll(targetElement);
262
+ for (let element of targets) toggleActive(element, this);
263
+ } else if (resolvedContainer.contains(targetElement)) toggleActive(targetElement, this);
264
+ });
265
+ return () => {
266
+ removeClickHandlers();
267
+ removeURLChangeHandlers();
268
+ };
269
+ }
270
+ /**
271
+ * Navigates to the URL specified with `options.href`.
272
+ *
273
+ * @example
274
+ * ```js
275
+ * let route = new Route();
276
+ * route.navigate({ href: "/intro", history: "replace", scroll: "off" });
277
+ * ```
278
+ */
279
+ navigate(options) {
280
+ if (!options?.href) return;
281
+ let { href, referrer, ...params } = options;
282
+ let transformedOptions = {
283
+ href: String(href),
284
+ referrer: referrer && String(referrer),
285
+ ...params
286
+ };
287
+ this.setValue(transformedOptions.href, transformedOptions);
288
+ }
289
+ assign(url) {
290
+ this.navigate({ href: url });
291
+ }
292
+ replace(url) {
293
+ this.navigate({
294
+ href: url,
295
+ history: "replace"
296
+ });
297
+ }
298
+ reload() {
299
+ this.assign(this.getValue());
300
+ }
301
+ go(delta) {
302
+ if (typeof window !== "undefined" && window.history) window.history.go(delta);
303
+ }
304
+ back() {
305
+ this.go(-1);
306
+ }
307
+ forward() {
308
+ this.go(1);
309
+ }
310
+ get href() {
311
+ return this.getValue();
312
+ }
313
+ set href(value) {
314
+ this.assign(value);
315
+ }
316
+ get pathname() {
317
+ return new quasiurl.QuasiURL(this.href).pathname;
318
+ }
319
+ set pathname(value) {
320
+ let url = new quasiurl.QuasiURL(this.href);
321
+ url.pathname = String(value);
322
+ this.assign(url.href);
323
+ }
324
+ get search() {
325
+ return new quasiurl.QuasiURL(this.href).search;
326
+ }
327
+ set search(value) {
328
+ let url = new quasiurl.QuasiURL(this.href);
329
+ url.search = value;
330
+ this.assign(url.href);
331
+ }
332
+ get hash() {
333
+ return new quasiurl.QuasiURL(this.href).hash;
334
+ }
335
+ set hash(value) {
336
+ let url = new quasiurl.QuasiURL(this.href);
337
+ url.hash = value;
338
+ this.assign(url.href);
339
+ }
340
+ toString() {
341
+ return this.href;
342
+ }
343
+ /**
344
+ * Matches the current location against `urlPattern`.
345
+ */
346
+ match(urlPattern) {
347
+ return matchURL(urlPattern, this.href);
348
+ }
349
+ /**
350
+ * Compiles `urlPattern` to a URL string by filling out the parameters
351
+ * based on `data`.
352
+ */
353
+ compile(urlPattern, data) {
354
+ return compileURL(urlPattern, data);
355
+ }
356
+ at(urlPattern, x, y) {
357
+ let result = this.match(urlPattern);
358
+ if (x === void 0 && y === void 0) return result.ok;
359
+ if (!result.ok) return typeof y === "function" ? y(result) : y;
360
+ return typeof x === "function" ? x(result) : x;
361
+ }
362
+ };
363
+ exports.Route = Route;
364
+ exports.URLState = URLState;
365
+ exports.compileURL = compileURL;
366
+ exports.getNavigationOptions = getNavigationOptions;
367
+ exports.isLocationObject = isLocationObject;
368
+ exports.isRouteEvent = isRouteEvent;
369
+ exports.matchURL = matchURL;
@@ -0,0 +1,149 @@
1
+ import { EventCallback, State, StateOptions, StatePayloadMap, StateUpdate } from "compact-state";
2
+ import { StandardSchemaV1 } from "@standard-schema/spec";
3
+ export type URLComponents = {
4
+ params?: Record<string, unknown> | undefined;
5
+ query?: Record<string, unknown> | undefined;
6
+ };
7
+ export type URLSchema = StandardSchemaV1<URLComponents>;
8
+ export type LocationObject = {
9
+ _schema: URLSchema | undefined;
10
+ exec: (x: string) => URLComponents | null;
11
+ compile: (x: any) => string;
12
+ toString: () => string;
13
+ };
14
+ type URLConfigShape = {
15
+ strict?: boolean;
16
+ };
17
+ export interface URLConfig extends URLConfigShape {}
18
+ export type LocationValue = URLConfig["strict"] extends true ? LocationObject | undefined : string | LocationObject | undefined;
19
+ export type LocationPattern = URLConfig["strict"] extends true ? LocationValue | LocationValue[] : LocationValue | RegExp | (LocationValue | RegExp)[];
20
+ export type MatchState<P extends LocationPattern> = {
21
+ ok: boolean;
22
+ href: string;
23
+ params: P extends {
24
+ _schema: URLSchema;
25
+ } ? StandardSchemaV1.InferOutput<P["_schema"]> extends {
26
+ params?: Record<string, unknown>;
27
+ } ? StandardSchemaV1.InferOutput<P["_schema"]>["params"] : Record<string, never> : Record<string, string | undefined>;
28
+ query: P extends {
29
+ _schema: URLSchema;
30
+ } ? StandardSchemaV1.InferOutput<P["_schema"]> extends {
31
+ query?: Record<string, unknown>;
32
+ } ? StandardSchemaV1.InferOutput<P["_schema"]>["query"] : Record<string, never> : Record<string, string | undefined>;
33
+ };
34
+ export type MatchHandler<P extends LocationPattern, T> = (payload: MatchState<P>) => T;
35
+ export type NavigationOptions<Href = string> = {
36
+ target?: string;
37
+ href?: Href;
38
+ referrer?: Href;
39
+ spa?: "auto" | "off" | undefined;
40
+ history?: "push" | "replace" | undefined;
41
+ scroll?: "auto" | "off" | undefined;
42
+ id?: string;
43
+ source?: "popstate" | undefined;
44
+ };
45
+ export type URLData<T extends LocationValue = LocationValue> = T extends {
46
+ _schema: URLSchema;
47
+ } ? StandardSchemaV1.InferOutput<T["_schema"]> : URLComponents;
48
+ export type URLStatePayloadMap = StatePayloadMap<string> & {
49
+ navigationstart: NavigationOptions;
50
+ navigation: NavigationOptions;
51
+ navigationcomplete: NavigationOptions;
52
+ ready: void;
53
+ };
54
+ export type URLStateOptions = StateOptions;
55
+ export declare class URLState<P extends URLStatePayloadMap = URLStatePayloadMap> extends State<string, P> {
56
+ constructor(href?: string | null, options?: URLStateOptions);
57
+ _init(): void;
58
+ on<E extends string>(event: E, callback: EventCallback<P[E]>, invokeImmediately?: boolean): () => void;
59
+ getValue(): string;
60
+ setValue(update: string | StateUpdate<string>, options?: NavigationOptions): void;
61
+ _transition(options?: NavigationOptions): boolean | void | undefined;
62
+ _complete(options?: NavigationOptions): boolean | void | undefined;
63
+ toValue(x: string): string;
64
+ }
65
+ export type ContainerElement = Document | Element | null | undefined;
66
+ export type ElementCollection = (string | Node)[] | HTMLCollection | NodeList;
67
+ export type ObservedElement = string | Node | (string | Node)[] | HTMLCollection | NodeList;
68
+ export type RoutePayloadMap = URLStatePayloadMap & {
69
+ documentclick: MouseEvent;
70
+ };
71
+ export type RouteOptions = URLStateOptions;
72
+ export declare class Route extends URLState<RoutePayloadMap> {
73
+ _observeInited: boolean;
74
+ constructor(href?: LocationValue | null, options?: RouteOptions);
75
+ /**
76
+ * Enables SPA navigation with HTML links inside the specified container.
77
+ *
78
+ * @example
79
+ * ```js
80
+ * let route = new Route();
81
+ * route.observe(document);
82
+ * ```
83
+ */
84
+ observe(container: ContainerElement | (() => ContainerElement), elements?: ObservedElement): (() => void) | undefined;
85
+ /**
86
+ * Navigates to the URL specified with `options.href`.
87
+ *
88
+ * @example
89
+ * ```js
90
+ * let route = new Route();
91
+ * route.navigate({ href: "/intro", history: "replace", scroll: "off" });
92
+ * ```
93
+ */
94
+ navigate(options?: NavigationOptions<LocationValue>): void;
95
+ assign(url: LocationValue): void;
96
+ replace(url: LocationValue): void;
97
+ reload(): void;
98
+ go(delta: number): void;
99
+ back(): void;
100
+ forward(): void;
101
+ get href(): string;
102
+ set href(value: LocationValue);
103
+ get pathname(): string;
104
+ set pathname(value: LocationValue);
105
+ get search(): string;
106
+ set search(value: string | URLSearchParams);
107
+ get hash(): string;
108
+ set hash(value: string);
109
+ toString(): string;
110
+ /**
111
+ * Matches the current location against `urlPattern`.
112
+ */
113
+ match<P extends LocationPattern>(urlPattern: P): MatchState<P>;
114
+ /**
115
+ * Compiles `urlPattern` to a URL string by filling out the parameters
116
+ * based on `data`.
117
+ */
118
+ compile<T extends LocationValue>(urlPattern: T, data?: URLData<T>): string;
119
+ /**
120
+ * `at(urlPattern)` returns `true` if `urlPattern` matches the current URL,
121
+ * and `false` otherwise.
122
+ *
123
+ * `at(urlPattern, x, y?)` returns either based on `x` if `urlPattern`
124
+ * matches the current URL, or based on `y` otherwise. (It loosely resembles
125
+ * the ternary conditional operator `matchesURLPattern ? x : y`.)
126
+ *
127
+ * If the current location matches `urlPattern`, `at(urlPattern, x, y)`
128
+ * returns:
129
+ * - `x`, if `x` is not a function;
130
+ * - `x({ params })`, if `x` is a function, with `params` extracted from
131
+ * the current URL.
132
+ *
133
+ * If the current location doesn't match `urlPattern`, `at(urlPattern, x, y)`
134
+ * returns:
135
+ * - `y`, if `y` is not a function;
136
+ * - `y({ params })`, if `y` is a function, with `params` extracted from
137
+ * the current URL.
138
+ */
139
+ at<P extends LocationPattern>(urlPattern: P): boolean;
140
+ at<P extends LocationPattern, X>(urlPattern: P, x: X | MatchHandler<P, X>): X | undefined;
141
+ at<P extends LocationPattern, X, Y>(urlPattern: P, x: X | MatchHandler<P, X>, y: Y | MatchHandler<P, Y>): X | Y;
142
+ }
143
+ export type LinkElement = HTMLAnchorElement | HTMLAreaElement;
144
+ export declare function compileURL<T extends LocationValue>(urlPattern: T, data?: URLData<T>): string;
145
+ export declare function getNavigationOptions(element: LinkElement): NavigationOptions;
146
+ export declare function isLocationObject(x: unknown): x is LocationObject;
147
+ export declare function isRouteEvent(event: unknown): boolean;
148
+ export declare function matchURL<P extends LocationPattern>(pattern: P, href: string): MatchState<P>;
149
+ export {};