@thi.ng/router 4.0.12 → 4.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/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2024-06-29T09:28:36Z
3
+ - **Last updated**: 2024-07-02T12:48:17Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
@@ -9,6 +9,15 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
9
9
  **Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
10
10
  and/or version bumps of transitive dependencies.
11
11
 
12
+ ## [4.1.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/router@4.1.0) (2024-07-02)
13
+
14
+ #### 🚀 Features
15
+
16
+ - update HTMLRouter initial & default route handling ([8ea075e](https://github.com/thi-ng/umbrella/commit/8ea075e))
17
+ - avoid duplicate dispatch (and breaking back button) for missing routes
18
+ - new behavior: HTMLRouter dispatches default route redirect, but does **not** push it to history
19
+ - update initial route handling to use `replaceState()` instead of `pushState()`
20
+
12
21
  ### [4.0.11](https://github.com/thi-ng/umbrella/tree/@thi.ng/router@4.0.11) (2024-06-21)
13
22
 
14
23
  #### ♻️ Refactoring
package/README.md CHANGED
@@ -71,7 +71,7 @@ Browser ESM import:
71
71
 
72
72
  [JSDelivr documentation](https://www.jsdelivr.com/)
73
73
 
74
- Package sizes (brotli'd, pre-treeshake): ESM: 1.94 KB
74
+ Package sizes (brotli'd, pre-treeshake): ESM: 1.93 KB
75
75
 
76
76
  ## Dependencies
77
77
 
@@ -83,12 +83,13 @@ Package sizes (brotli'd, pre-treeshake): ESM: 1.94 KB
83
83
 
84
84
  ## Usage examples
85
85
 
86
- One project in this repo's
86
+ Several projects in this repo's
87
87
  [/examples](https://github.com/thi-ng/umbrella/tree/develop/examples)
88
- directory is using this package:
88
+ directory are using this package:
89
89
 
90
90
  | Screenshot | Description | Live demo | Source |
91
91
  |:---------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------|:----------------------------------------------------|:---------------------------------------------------------------------------------|
92
+ | <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/rdom-router.jpg" width="240"/> | Basic thi.ng/router usage with thi.ng/rdom components | [Demo](https://demo.thi.ng/umbrella/rdom-router/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-router) |
92
93
  | <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/router-basics.jpg" width="240"/> | Complete mini SPA app w/ router & async content loading | [Demo](https://demo.thi.ng/umbrella/router-basics/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/router-basics) |
93
94
 
94
95
  ## API
package/api.d.ts CHANGED
@@ -136,11 +136,19 @@ export interface RouterOpts<T = any> {
136
136
  /**
137
137
  * Fallback route ID (MUST exist in `routes`), used if none of the defined
138
138
  * routes could be matched against user input, e.g. a home or error page.
139
+ *
140
+ * @remarks
141
+ * If using {@link HTMLRouter}, any redirects to this route will **not** be
142
+ * recorded to the browser history.
139
143
  */
140
144
  default: string;
141
145
  /**
142
146
  * Optional initial route to trigger when router starts. If given, this MUST
143
147
  * be a route without params.
148
+ *
149
+ * @remarks
150
+ * If using {@link HTMLRouter}, this route will be applied to the browser
151
+ * history using `replaceState()`.
144
152
  */
145
153
  initial?: string;
146
154
  /**
package/html.d.ts CHANGED
@@ -6,26 +6,24 @@ export declare class HTMLRouter<T = any> extends Router<T> {
6
6
  protected popHandler: Fn<PopStateEvent, void>;
7
7
  protected hashHandler: EventListener;
8
8
  protected useFragment: boolean;
9
- protected ignoreHashChange: boolean;
10
9
  constructor(config: HTMLRouterOpts);
11
10
  start(): void;
12
11
  release(): void;
13
12
  /**
14
- * Like {@link Router.route}, but takes additional arg to control if
15
- * this routing operation should manipulate the browser's `history`.
13
+ * Like {@link Router.route}, but takes additional arg to control if this
14
+ * routing operation should manipulate the browser's `history`.
16
15
  *
17
16
  * @remarks
18
- * If called from userland, this normally is true (also default). However,
19
- * we want to avoid this if called from this router's own event handlers.
17
+ * If called from userland, this normally is set to "push" (also the
18
+ * default). However, we want to adjust this behavior if called internally.
20
19
  *
21
20
  * @param src -
22
21
  * @param ctx -
23
- * @param pushState -
22
+ * @param mode -
24
23
  */
25
- route(src: string, ctx?: T, pushState?: boolean): import("@thi.ng/api").Maybe<import("./api.js").RouteMatch>;
24
+ route(src: string, ctx?: T, mode?: "push" | "replace" | "none"): import("@thi.ng/api").Maybe<import("./api.js").RouteMatch>;
26
25
  routeTo(route: string, ctx?: T): void;
27
26
  protected handlePopChange(): Fn<PopStateEvent, void>;
28
27
  protected handleHashChange(): EventListener;
29
- protected handleRouteFailure(): boolean;
30
28
  }
31
29
  //# sourceMappingURL=html.d.ts.map
package/html.js CHANGED
@@ -5,11 +5,9 @@ class HTMLRouter extends Router {
5
5
  popHandler;
6
6
  hashHandler;
7
7
  useFragment;
8
- ignoreHashChange;
9
8
  constructor(config) {
10
9
  super({ prefix: config.useFragment ? "#/" : "/", ...config });
11
10
  this.useFragment = config.useFragment !== false;
12
- this.ignoreHashChange = false;
13
11
  }
14
12
  start() {
15
13
  window.addEventListener("popstate", this.handlePopChange());
@@ -18,7 +16,7 @@ class HTMLRouter extends Router {
18
16
  }
19
17
  if (this.opts.initial) {
20
18
  const route = this.routeForID(this.opts.initial);
21
- this.route(this.format({ id: route.id }));
19
+ this.route(this.format({ id: route.id }), void 0, "replace");
22
20
  } else {
23
21
  this.route(this.useFragment ? location.hash : location.pathname);
24
22
  }
@@ -30,24 +28,26 @@ class HTMLRouter extends Router {
30
28
  }
31
29
  }
32
30
  /**
33
- * Like {@link Router.route}, but takes additional arg to control if
34
- * this routing operation should manipulate the browser's `history`.
31
+ * Like {@link Router.route}, but takes additional arg to control if this
32
+ * routing operation should manipulate the browser's `history`.
35
33
  *
36
34
  * @remarks
37
- * If called from userland, this normally is true (also default). However,
38
- * we want to avoid this if called from this router's own event handlers.
35
+ * If called from userland, this normally is set to "push" (also the
36
+ * default). However, we want to adjust this behavior if called internally.
39
37
  *
40
38
  * @param src -
41
39
  * @param ctx -
42
- * @param pushState -
40
+ * @param mode -
43
41
  */
44
- route(src, ctx, pushState = true) {
42
+ route(src, ctx, mode = "push") {
45
43
  const old = this.current;
46
44
  const route = super.route(src, ctx);
47
45
  if (route && !equiv(route, old)) {
48
46
  this.currentPath = this.format(route);
49
- if (pushState) {
47
+ if (mode === "push") {
50
48
  history.pushState(this.currentPath, "", this.currentPath);
49
+ } else if (mode === "replace") {
50
+ history.replaceState(this.currentPath, "", this.currentPath);
51
51
  }
52
52
  }
53
53
  return route;
@@ -63,28 +63,20 @@ class HTMLRouter extends Router {
63
63
  this.route(
64
64
  e.state || (this.useFragment ? location.hash : location.pathname),
65
65
  void 0,
66
- false
66
+ "none"
67
67
  );
68
68
  }).bind(this);
69
69
  }
70
70
  handleHashChange() {
71
71
  return this.hashHandler = this.hashHandler || ((e) => {
72
- if (!this.ignoreHashChange) {
72
+ if (!this.current?.redirect) {
73
73
  const hash = e.newURL.substring(e.newURL.indexOf("#"));
74
74
  if (hash !== this.currentPath) {
75
- this.route(hash, void 0, false);
75
+ this.route(hash, void 0, "none");
76
76
  }
77
77
  }
78
78
  }).bind(this);
79
79
  }
80
- handleRouteFailure() {
81
- this.ignoreHashChange = true;
82
- location.hash = this.format({
83
- id: this.routeForID(this.opts.default).id
84
- });
85
- this.ignoreHashChange = false;
86
- return true;
87
- }
88
80
  }
89
81
  export {
90
82
  HTMLRouter
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/router",
3
- "version": "4.0.12",
3
+ "version": "4.1.0",
4
4
  "description": "Generic trie-based router with support for wildcards, route param validation/coercion, auth",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -97,5 +97,5 @@
97
97
  ],
98
98
  "year": 2014
99
99
  },
100
- "gitHead": "7b950c112fba0b2e7c450765b15624c3382f1354\n"
100
+ "gitHead": "4a2f35b6e720cc4ad3e2ff2549b78beb3f80732e\n"
101
101
  }