@flight-framework/router 0.0.4 → 0.0.5
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.d.ts +25 -2
- package/dist/index.js +113 -15
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -266,9 +266,32 @@ declare function prefetchWhenIdle(page: string, options?: PrefetchOptions): void
|
|
|
266
266
|
* Router Hooks
|
|
267
267
|
*
|
|
268
268
|
* React hooks for accessing router state.
|
|
269
|
-
*
|
|
269
|
+
* Uses useSyncExternalStore for concurrent-safe external state (2026 best practice).
|
|
270
270
|
*/
|
|
271
271
|
|
|
272
|
+
/**
|
|
273
|
+
* Subscribe to pathname changes - for useSyncExternalStore
|
|
274
|
+
*/
|
|
275
|
+
declare function subscribeToPathname(callback: () => void): () => void;
|
|
276
|
+
/**
|
|
277
|
+
* Get current pathname snapshot - for useSyncExternalStore
|
|
278
|
+
*/
|
|
279
|
+
declare function getPathnameSnapshot(): string;
|
|
280
|
+
/**
|
|
281
|
+
* Get server snapshot - for useSyncExternalStore SSR
|
|
282
|
+
*/
|
|
283
|
+
declare function getPathnameServerSnapshot(): string;
|
|
284
|
+
/**
|
|
285
|
+
* Create usePathname hook with provided React instance
|
|
286
|
+
* This pattern ensures proper bundler support for React hooks
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* import { useSyncExternalStore } from 'react';
|
|
290
|
+
* import { createUsePathname } from '@flight-framework/router';
|
|
291
|
+
*
|
|
292
|
+
* const usePathname = createUsePathname(useSyncExternalStore);
|
|
293
|
+
*/
|
|
294
|
+
declare function createUsePathname(useSyncExternalStore: <T>(subscribe: (onStoreChange: () => void) => () => void, getSnapshot: () => T, getServerSnapshot?: () => T) => T): () => string;
|
|
272
295
|
declare let useParams: <T extends RouteParams = RouteParams>() => T;
|
|
273
296
|
declare let useSearchParams: () => [URLSearchParams, (params: SearchParams | URLSearchParams) => void];
|
|
274
297
|
declare let usePathname: () => string;
|
|
@@ -409,4 +432,4 @@ declare function observeForPrefetch(element: Element, href: string): () => void;
|
|
|
409
432
|
*/
|
|
410
433
|
declare function setupIntentPrefetch(element: HTMLElement, href: string): () => void;
|
|
411
434
|
|
|
412
|
-
export { Link, type LinkProps, type LoaderContext, type LoaderFunction, type NavigateOptions, type PrefetchOptions, PrefetchPageLinks, type PrefetchPriority, type PrefetchStrategy, type RouteDefinition, type RouteMatch, type RouteParams, RouterContext, type RouterContextValue, RouterProvider, type RouterProviderProps, type SearchParams, clearPrefetchCache, createLink, findRoute, generatePath, isActive, isPrefetched, matchRoute, navigate, observeForPrefetch, parseParams, prefetch, prefetchAll, prefetchPages, prefetchRoute, prefetchWhenIdle, redirect, setupIntentPrefetch, useLinkProps, useParams, usePathname, useRouter, useSearchParams };
|
|
435
|
+
export { Link, type LinkProps, type LoaderContext, type LoaderFunction, type NavigateOptions, type PrefetchOptions, PrefetchPageLinks, type PrefetchPriority, type PrefetchStrategy, type RouteDefinition, type RouteMatch, type RouteParams, RouterContext, type RouterContextValue, RouterProvider, type RouterProviderProps, type SearchParams, clearPrefetchCache, createLink, createUsePathname, findRoute, generatePath, getPathnameServerSnapshot, getPathnameSnapshot, isActive, isPrefetched, matchRoute, navigate, observeForPrefetch, parseParams, prefetch, prefetchAll, prefetchPages, prefetchRoute, prefetchWhenIdle, redirect, setupIntentPrefetch, subscribeToPathname, useLinkProps, useParams, usePathname, useRouter, useSearchParams };
|
package/dist/index.js
CHANGED
|
@@ -39,6 +39,63 @@ function navigateTo(to, options = {}) {
|
|
|
39
39
|
window.scrollTo({ top: 0, left: 0, behavior: "instant" });
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
+
function initRouter(options = {}) {
|
|
43
|
+
const { initialPath, basePath = "" } = options;
|
|
44
|
+
let path;
|
|
45
|
+
let searchParams;
|
|
46
|
+
if (isBrowser) {
|
|
47
|
+
path = window.location.pathname;
|
|
48
|
+
searchParams = new URLSearchParams(window.location.search);
|
|
49
|
+
} else {
|
|
50
|
+
path = initialPath || "/";
|
|
51
|
+
searchParams = new URLSearchParams();
|
|
52
|
+
}
|
|
53
|
+
if (basePath && path.startsWith(basePath)) {
|
|
54
|
+
path = path.slice(basePath.length) || "/";
|
|
55
|
+
}
|
|
56
|
+
currentContext = {
|
|
57
|
+
path,
|
|
58
|
+
searchParams,
|
|
59
|
+
navigate: navigateTo,
|
|
60
|
+
back: () => isBrowser && window.history.back(),
|
|
61
|
+
forward: () => isBrowser && window.history.forward()
|
|
62
|
+
};
|
|
63
|
+
if (isBrowser) {
|
|
64
|
+
window.addEventListener("popstate", () => {
|
|
65
|
+
updateContext({
|
|
66
|
+
path: window.location.pathname,
|
|
67
|
+
searchParams: new URLSearchParams(window.location.search)
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
const originalPushState = history.pushState.bind(history);
|
|
71
|
+
const originalReplaceState = history.replaceState.bind(history);
|
|
72
|
+
history.pushState = function(state, unused, url) {
|
|
73
|
+
originalPushState(state, unused, url);
|
|
74
|
+
if (url) {
|
|
75
|
+
const newUrl = new URL(url.toString(), window.location.origin);
|
|
76
|
+
updateContext({
|
|
77
|
+
path: newUrl.pathname,
|
|
78
|
+
searchParams: newUrl.searchParams
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
history.replaceState = function(state, unused, url) {
|
|
83
|
+
originalReplaceState(state, unused, url);
|
|
84
|
+
if (url) {
|
|
85
|
+
const newUrl = new URL(url.toString(), window.location.origin);
|
|
86
|
+
updateContext({
|
|
87
|
+
path: newUrl.pathname,
|
|
88
|
+
searchParams: newUrl.searchParams
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
var initialized = false;
|
|
95
|
+
if (isBrowser && !initialized) {
|
|
96
|
+
initialized = true;
|
|
97
|
+
initRouter();
|
|
98
|
+
}
|
|
42
99
|
var RouterContext = null;
|
|
43
100
|
var RouterProvider = null;
|
|
44
101
|
var useRouter = getRouterContext;
|
|
@@ -493,15 +550,65 @@ function prefetchWhenIdle(page, options = {}) {
|
|
|
493
550
|
|
|
494
551
|
// src/hooks.ts
|
|
495
552
|
var isBrowser5 = typeof window !== "undefined";
|
|
553
|
+
var pathSubscribers = /* @__PURE__ */ new Set();
|
|
554
|
+
function notifyPathChange() {
|
|
555
|
+
pathSubscribers.forEach((fn) => fn());
|
|
556
|
+
}
|
|
557
|
+
var historyIntercepted = false;
|
|
558
|
+
function interceptHistory() {
|
|
559
|
+
if (!isBrowser5 || historyIntercepted) return;
|
|
560
|
+
historyIntercepted = true;
|
|
561
|
+
const originalPushState = history.pushState.bind(history);
|
|
562
|
+
const originalReplaceState = history.replaceState.bind(history);
|
|
563
|
+
history.pushState = function(state, unused, url) {
|
|
564
|
+
originalPushState(state, unused, url);
|
|
565
|
+
notifyPathChange();
|
|
566
|
+
};
|
|
567
|
+
history.replaceState = function(state, unused, url) {
|
|
568
|
+
originalReplaceState(state, unused, url);
|
|
569
|
+
notifyPathChange();
|
|
570
|
+
};
|
|
571
|
+
window.addEventListener("popstate", notifyPathChange);
|
|
572
|
+
}
|
|
573
|
+
if (isBrowser5) {
|
|
574
|
+
interceptHistory();
|
|
575
|
+
}
|
|
576
|
+
function subscribeToPathname(callback) {
|
|
577
|
+
pathSubscribers.add(callback);
|
|
578
|
+
return () => pathSubscribers.delete(callback);
|
|
579
|
+
}
|
|
580
|
+
function getPathnameSnapshot() {
|
|
581
|
+
return isBrowser5 ? window.location.pathname : "/";
|
|
582
|
+
}
|
|
583
|
+
function getPathnameServerSnapshot() {
|
|
584
|
+
return "/";
|
|
585
|
+
}
|
|
586
|
+
function createUsePathname(useSyncExternalStore) {
|
|
587
|
+
return function usePathname2() {
|
|
588
|
+
return useSyncExternalStore(
|
|
589
|
+
subscribeToPathname,
|
|
590
|
+
getPathnameSnapshot,
|
|
591
|
+
getPathnameServerSnapshot
|
|
592
|
+
);
|
|
593
|
+
};
|
|
594
|
+
}
|
|
496
595
|
var useParams = () => ({});
|
|
497
596
|
var useSearchParams = () => [new URLSearchParams(), () => {
|
|
498
597
|
}];
|
|
499
|
-
var usePathname = () =>
|
|
598
|
+
var usePathname = () => {
|
|
599
|
+
if (isBrowser5) {
|
|
600
|
+
return window.location.pathname;
|
|
601
|
+
}
|
|
602
|
+
return "/";
|
|
603
|
+
};
|
|
500
604
|
if (typeof globalThis !== "undefined") {
|
|
501
605
|
try {
|
|
502
606
|
const React = globalThis.React;
|
|
607
|
+
if (React?.useSyncExternalStore) {
|
|
608
|
+
usePathname = createUsePathname(React.useSyncExternalStore);
|
|
609
|
+
}
|
|
503
610
|
if (React?.useState) {
|
|
504
|
-
const { useState, useEffect, useCallback
|
|
611
|
+
const { useState, useEffect, useCallback } = React;
|
|
505
612
|
useParams = function useFlightParams() {
|
|
506
613
|
const [params, setParams] = useState({});
|
|
507
614
|
useEffect(() => {
|
|
@@ -545,19 +652,6 @@ if (typeof globalThis !== "undefined") {
|
|
|
545
652
|
}, []);
|
|
546
653
|
return [searchParams, setSearchParams];
|
|
547
654
|
};
|
|
548
|
-
usePathname = function useFlightPathname() {
|
|
549
|
-
const { path } = getRouterContext();
|
|
550
|
-
const [pathname, setPathname] = useState(path);
|
|
551
|
-
useEffect(() => {
|
|
552
|
-
if (!isBrowser5) return;
|
|
553
|
-
const handleChange = () => {
|
|
554
|
-
setPathname(window.location.pathname);
|
|
555
|
-
};
|
|
556
|
-
window.addEventListener("popstate", handleChange);
|
|
557
|
-
return () => window.removeEventListener("popstate", handleChange);
|
|
558
|
-
}, []);
|
|
559
|
-
return pathname;
|
|
560
|
-
};
|
|
561
655
|
}
|
|
562
656
|
} catch {
|
|
563
657
|
}
|
|
@@ -644,8 +738,11 @@ export {
|
|
|
644
738
|
RouterProvider,
|
|
645
739
|
clearPrefetchCache,
|
|
646
740
|
createLink,
|
|
741
|
+
createUsePathname,
|
|
647
742
|
findRoute,
|
|
648
743
|
generatePath,
|
|
744
|
+
getPathnameServerSnapshot,
|
|
745
|
+
getPathnameSnapshot,
|
|
649
746
|
isActive,
|
|
650
747
|
isPrefetched,
|
|
651
748
|
matchRoute,
|
|
@@ -659,6 +756,7 @@ export {
|
|
|
659
756
|
prefetchWhenIdle,
|
|
660
757
|
redirect,
|
|
661
758
|
setupIntentPrefetch,
|
|
759
|
+
subscribeToPathname,
|
|
662
760
|
useLinkProps,
|
|
663
761
|
useParams,
|
|
664
762
|
usePathname,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flight-framework/router",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Agnostic client-side routing primitives for Flight Framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -45,4 +45,4 @@
|
|
|
45
45
|
"optional": true
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
-
}
|
|
48
|
+
}
|