@pyreon/router 0.12.14 → 0.13.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.
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
5386
5386
  </script>
5387
5387
  <script>
5388
5388
  /*<!--*/
5389
- const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"d7a354cf-1","name":"loader.ts"},{"uid":"d7a354cf-3","name":"match.ts"},{"uid":"d7a354cf-5","name":"scroll.ts"},{"uid":"d7a354cf-7","name":"types.ts"},{"uid":"d7a354cf-9","name":"router.ts"},{"uid":"d7a354cf-11","name":"components.tsx"},{"uid":"d7a354cf-13","name":"index.ts"}]}]}],"isRoot":true},"nodeParts":{"d7a354cf-1":{"renderedLength":2855,"gzipLength":1243,"brotliLength":0,"metaUid":"d7a354cf-0"},"d7a354cf-3":{"renderedLength":12203,"gzipLength":3691,"brotliLength":0,"metaUid":"d7a354cf-2"},"d7a354cf-5":{"renderedLength":1906,"gzipLength":781,"brotliLength":0,"metaUid":"d7a354cf-4"},"d7a354cf-7":{"renderedLength":385,"gzipLength":246,"brotliLength":0,"metaUid":"d7a354cf-6"},"d7a354cf-9":{"renderedLength":23190,"gzipLength":6358,"brotliLength":0,"metaUid":"d7a354cf-8"},"d7a354cf-11":{"renderedLength":7106,"gzipLength":2622,"brotliLength":0,"metaUid":"d7a354cf-10"},"d7a354cf-13":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"d7a354cf-12"}},"nodeMetas":{"d7a354cf-0":{"id":"/src/loader.ts","moduleParts":{"index.js":"d7a354cf-1"},"imported":[{"uid":"d7a354cf-14"}],"importedBy":[{"uid":"d7a354cf-12"},{"uid":"d7a354cf-10"}]},"d7a354cf-2":{"id":"/src/match.ts","moduleParts":{"index.js":"d7a354cf-3"},"imported":[],"importedBy":[{"uid":"d7a354cf-12"},{"uid":"d7a354cf-8"}]},"d7a354cf-4":{"id":"/src/scroll.ts","moduleParts":{"index.js":"d7a354cf-5"},"imported":[],"importedBy":[{"uid":"d7a354cf-8"}]},"d7a354cf-6":{"id":"/src/types.ts","moduleParts":{"index.js":"d7a354cf-7"},"imported":[],"importedBy":[{"uid":"d7a354cf-12"},{"uid":"d7a354cf-8"}]},"d7a354cf-8":{"id":"/src/router.ts","moduleParts":{"index.js":"d7a354cf-9"},"imported":[{"uid":"d7a354cf-14"},{"uid":"d7a354cf-15"},{"uid":"d7a354cf-2"},{"uid":"d7a354cf-4"},{"uid":"d7a354cf-6"}],"importedBy":[{"uid":"d7a354cf-12"},{"uid":"d7a354cf-10"}]},"d7a354cf-10":{"id":"/src/components.tsx","moduleParts":{"index.js":"d7a354cf-11"},"imported":[{"uid":"d7a354cf-14"},{"uid":"d7a354cf-0"},{"uid":"d7a354cf-8"}],"importedBy":[{"uid":"d7a354cf-12"}]},"d7a354cf-12":{"id":"/src/index.ts","moduleParts":{"index.js":"d7a354cf-13"},"imported":[{"uid":"d7a354cf-10"},{"uid":"d7a354cf-0"},{"uid":"d7a354cf-2"},{"uid":"d7a354cf-8"},{"uid":"d7a354cf-6"}],"importedBy":[],"isEntry":true},"d7a354cf-14":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"d7a354cf-10"},{"uid":"d7a354cf-0"},{"uid":"d7a354cf-8"}]},"d7a354cf-15":{"id":"@pyreon/reactivity","moduleParts":{},"imported":[],"importedBy":[{"uid":"d7a354cf-8"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5389
+ const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"aa1c31e3-1","name":"loader.ts"},{"uid":"aa1c31e3-3","name":"match.ts"},{"uid":"aa1c31e3-5","name":"scroll.ts"},{"uid":"aa1c31e3-7","name":"types.ts"},{"uid":"aa1c31e3-9","name":"router.ts"},{"uid":"aa1c31e3-11","name":"components.tsx"},{"uid":"aa1c31e3-13","name":"index.ts"}]}]}],"isRoot":true},"nodeParts":{"aa1c31e3-1":{"renderedLength":2824,"gzipLength":1233,"brotliLength":0,"metaUid":"aa1c31e3-0"},"aa1c31e3-3":{"renderedLength":12203,"gzipLength":3691,"brotliLength":0,"metaUid":"aa1c31e3-2"},"aa1c31e3-5":{"renderedLength":2194,"gzipLength":899,"brotliLength":0,"metaUid":"aa1c31e3-4"},"aa1c31e3-7":{"renderedLength":385,"gzipLength":246,"brotliLength":0,"metaUid":"aa1c31e3-6"},"aa1c31e3-9":{"renderedLength":23568,"gzipLength":6469,"brotliLength":0,"metaUid":"aa1c31e3-8"},"aa1c31e3-11":{"renderedLength":7151,"gzipLength":2635,"brotliLength":0,"metaUid":"aa1c31e3-10"},"aa1c31e3-13":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"aa1c31e3-12"}},"nodeMetas":{"aa1c31e3-0":{"id":"/src/loader.ts","moduleParts":{"index.js":"aa1c31e3-1"},"imported":[{"uid":"aa1c31e3-14"}],"importedBy":[{"uid":"aa1c31e3-12"},{"uid":"aa1c31e3-10"}]},"aa1c31e3-2":{"id":"/src/match.ts","moduleParts":{"index.js":"aa1c31e3-3"},"imported":[],"importedBy":[{"uid":"aa1c31e3-12"},{"uid":"aa1c31e3-8"}]},"aa1c31e3-4":{"id":"/src/scroll.ts","moduleParts":{"index.js":"aa1c31e3-5"},"imported":[],"importedBy":[{"uid":"aa1c31e3-8"}]},"aa1c31e3-6":{"id":"/src/types.ts","moduleParts":{"index.js":"aa1c31e3-7"},"imported":[],"importedBy":[{"uid":"aa1c31e3-12"},{"uid":"aa1c31e3-8"}]},"aa1c31e3-8":{"id":"/src/router.ts","moduleParts":{"index.js":"aa1c31e3-9"},"imported":[{"uid":"aa1c31e3-14"},{"uid":"aa1c31e3-15"},{"uid":"aa1c31e3-2"},{"uid":"aa1c31e3-4"},{"uid":"aa1c31e3-6"}],"importedBy":[{"uid":"aa1c31e3-12"},{"uid":"aa1c31e3-10"}]},"aa1c31e3-10":{"id":"/src/components.tsx","moduleParts":{"index.js":"aa1c31e3-11"},"imported":[{"uid":"aa1c31e3-14"},{"uid":"aa1c31e3-0"},{"uid":"aa1c31e3-8"}],"importedBy":[{"uid":"aa1c31e3-12"}]},"aa1c31e3-12":{"id":"/src/index.ts","moduleParts":{"index.js":"aa1c31e3-13"},"imported":[{"uid":"aa1c31e3-10"},{"uid":"aa1c31e3-0"},{"uid":"aa1c31e3-2"},{"uid":"aa1c31e3-8"},{"uid":"aa1c31e3-6"}],"importedBy":[],"isEntry":true},"aa1c31e3-14":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"aa1c31e3-10"},{"uid":"aa1c31e3-0"},{"uid":"aa1c31e3-8"}]},"aa1c31e3-15":{"id":"@pyreon/reactivity","moduleParts":{},"imported":[],"importedBy":[{"uid":"aa1c31e3-8"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5390
5390
 
5391
5391
  const run = () => {
5392
5392
  const width = window.innerWidth;
package/lib/index.js CHANGED
@@ -34,7 +34,6 @@ function useLoaderData() {
34
34
  async function prefetchLoaderData(router, path) {
35
35
  const route = router._resolve(path);
36
36
  const ac = new AbortController();
37
- router._abortController = ac;
38
37
  await Promise.all(route.matched.filter((r) => r.loader).map(async (r) => {
39
38
  const data = await r.loader?.({
40
39
  params: route.params,
@@ -498,6 +497,7 @@ function buildNameIndex(routes) {
498
497
  * Saves scroll position before each navigation and restores it when
499
498
  * navigating back to a previously visited path.
500
499
  */
500
+ const MAX_SCROLL_POSITIONS = 100;
501
501
  var ScrollManager = class {
502
502
  _positions = /* @__PURE__ */ new Map();
503
503
  _behavior;
@@ -507,7 +507,13 @@ var ScrollManager = class {
507
507
  /** Call before navigating away — saves current scroll position for `fromPath` */
508
508
  save(fromPath) {
509
509
  if (typeof window === "undefined") return;
510
+ if (this._positions.has(fromPath)) this._positions.delete(fromPath);
510
511
  this._positions.set(fromPath, window.scrollY);
512
+ while (this._positions.size > MAX_SCROLL_POSITIONS) {
513
+ const oldest = this._positions.keys().next().value;
514
+ if (oldest === void 0) break;
515
+ this._positions.delete(oldest);
516
+ }
511
517
  }
512
518
  /** Call after navigation is committed — applies scroll behavior */
513
519
  restore(to, from) {
@@ -656,17 +662,31 @@ function onBeforeRouteUpdate(guard) {
656
662
  * })
657
663
  * // later: blocker.remove()
658
664
  */
665
+ let _beforeUnloadRefCount = 0;
666
+ const _beforeUnloadHandler = (e) => {
667
+ e.preventDefault();
668
+ };
669
+ function retainBeforeUnload() {
670
+ if (!_isBrowser) return;
671
+ if (_beforeUnloadRefCount === 0) window.addEventListener("beforeunload", _beforeUnloadHandler);
672
+ _beforeUnloadRefCount++;
673
+ }
674
+ function releaseBeforeUnload() {
675
+ if (!_isBrowser) return;
676
+ _beforeUnloadRefCount--;
677
+ if (_beforeUnloadRefCount <= 0) {
678
+ _beforeUnloadRefCount = 0;
679
+ window.removeEventListener("beforeunload", _beforeUnloadHandler);
680
+ }
681
+ }
659
682
  function useBlocker(fn) {
660
683
  const router = useContext(RouterContext) ?? _activeRouter;
661
684
  if (!router) throw new Error("[Pyreon] No router installed. Wrap your app in <RouterProvider router={router}>.");
662
685
  router._blockers.add(fn);
663
- const beforeUnloadHandler = _isBrowser ? (e) => {
664
- e.preventDefault();
665
- } : null;
666
- if (beforeUnloadHandler) window.addEventListener("beforeunload", beforeUnloadHandler);
686
+ retainBeforeUnload();
667
687
  const remove = () => {
668
688
  router._blockers.delete(fn);
669
- if (beforeUnloadHandler) window.removeEventListener("beforeunload", beforeUnloadHandler);
689
+ releaseBeforeUnload();
670
690
  };
671
691
  onUnmount(() => remove());
672
692
  return { remove };
@@ -1152,7 +1172,6 @@ function createRouter(options) {
1152
1172
  componentCache.set(record, comp);
1153
1173
  }));
1154
1174
  const ac = new AbortController();
1155
- router._abortController = ac;
1156
1175
  await Promise.all(resolved.matched.filter((r) => r.loader).map(async (r) => {
1157
1176
  const data = await r.loader?.({
1158
1177
  params: resolved.params,
@@ -1167,11 +1186,13 @@ function createRouter(options) {
1167
1186
  if (_hashchangeHandler) window.removeEventListener("hashchange", _hashchangeHandler);
1168
1187
  guards.length = 0;
1169
1188
  afterHooks.length = 0;
1189
+ for (let i = router._blockers.size; i > 0; i--) releaseBeforeUnload();
1170
1190
  router._blockers.clear();
1171
1191
  componentCache.clear();
1172
1192
  router._loaderData.clear();
1173
1193
  router._abortController?.abort();
1174
1194
  router._abortController = null;
1195
+ if (_activeRouter === router) _activeRouter = null;
1175
1196
  },
1176
1197
  _resolve: (rawPath) => resolveRoute(rawPath, routes)
1177
1198
  };
@@ -1326,6 +1347,7 @@ const RouterLink = (props) => {
1326
1347
  if (!router) return "";
1327
1348
  const current = router.currentRoute().path;
1328
1349
  const target = props.to;
1350
+ if (typeof target !== "string") return "";
1329
1351
  const isExact = current === target;
1330
1352
  const isActive = isExact || !props.exact && isSegmentPrefix(current, target);
1331
1353
  const classes = [];