@studiolambda/router 0.1.1 → 2.0.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/dist/matcher-C4dv_pr6.cjs +2 -0
- package/dist/{matcher-CTRKcf7I.cjs.map → matcher-C4dv_pr6.cjs.map} +1 -1
- package/dist/{matcher-ehhvtyaT.js → matcher-CQObVRFk.js} +2 -1
- package/dist/{matcher-ehhvtyaT.js.map → matcher-CQObVRFk.js.map} +1 -1
- package/dist/router.cjs +1 -1
- package/dist/router.js +1 -1
- package/dist/router_react.cjs +2 -2
- package/dist/router_react.cjs.map +1 -1
- package/dist/router_react.js +233 -154
- package/dist/router_react.js.map +1 -1
- package/dist/src/react/components/NotFound.d.ts +5 -2
- package/dist/src/react/components/Router.d.ts +1 -1
- package/dist/src/react/context/NavigationContext.d.ts +1 -1
- package/dist/src/react/context/NavigationSignalContext.d.ts +6 -1
- package/dist/src/react/context/NavigationTypeContext.d.ts +6 -1
- package/dist/src/react/context/ParamsContext.d.ts +10 -0
- package/dist/src/react/context/PathnameContext.d.ts +5 -4
- package/dist/src/react/context/TransitionContext.d.ts +0 -6
- package/dist/src/react/context/UrlContext.d.ts +12 -0
- package/dist/src/react/createRouter.d.ts +5 -0
- package/dist/src/react/extractPathname.d.ts +1 -2
- package/dist/src/react/hooks/useBack.d.ts +7 -1
- package/dist/src/react/hooks/useForward.d.ts +8 -1
- package/dist/src/react/hooks/useNavigate.d.ts +15 -0
- package/dist/src/react/hooks/useNavigation.d.ts +10 -0
- package/dist/src/react/hooks/useNavigationEvents.d.ts +18 -0
- package/dist/src/react/hooks/useNavigationHandlers.d.ts +9 -0
- package/dist/src/react/hooks/useNavigationSignal.d.ts +15 -0
- package/dist/src/react/hooks/useNavigationType.d.ts +18 -0
- package/dist/src/react/hooks/useNextMatch.d.ts +11 -0
- package/dist/src/react/hooks/useParams.d.ts +1 -0
- package/dist/src/react/hooks/usePathname.d.ts +1 -0
- package/dist/src/react/hooks/usePrefetch.d.ts +57 -0
- package/dist/src/react/hooks/useSearchParams.d.ts +9 -5
- package/dist/src/react/index.d.ts +2 -1
- package/dist/src/react/navigation/createMemoryNavigation.d.ts +5 -1
- package/package.json +1 -1
- package/dist/matcher-CTRKcf7I.cjs +0 -2
- package/dist/src/react/context/PropsContext.d.ts +0 -10
|
@@ -153,12 +153,17 @@ export type RouteFactory = (path?: string) => RouteBuilder;
|
|
|
153
153
|
* chaining, nested groups with path prefixing, redirects,
|
|
154
154
|
* and all handler options (scroll, focusReset, formHandler).
|
|
155
155
|
*
|
|
156
|
+
* After all routes are registered, static redirect targets
|
|
157
|
+
* are checked for cycles. Self-redirects and multi-hop loops
|
|
158
|
+
* throw an error at registration time.
|
|
159
|
+
*
|
|
156
160
|
* Returns a `Matcher<Handler>` that plugs directly into the
|
|
157
161
|
* `<Router matcher={...}>` component.
|
|
158
162
|
*
|
|
159
163
|
* @param callback - A function that defines routes using the
|
|
160
164
|
* provided `route` factory.
|
|
161
165
|
* @returns A populated matcher ready for the Router.
|
|
166
|
+
* @throws When a static redirect cycle is detected.
|
|
162
167
|
*
|
|
163
168
|
* @example
|
|
164
169
|
* ```tsx
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Extracts the pathname portion from a URL string. Uses a
|
|
3
3
|
* dummy base URL to handle both absolute and relative paths
|
|
4
|
-
* correctly. Returns `'/'` when the input is null
|
|
5
|
-
* or an empty string.
|
|
4
|
+
* correctly. Returns `'/'` when the input is null or undefined.
|
|
6
5
|
*
|
|
7
6
|
* Used by the Router (to extract pathname from navigation
|
|
8
7
|
* destination URLs), Link (for active link comparison), and
|
|
@@ -17,7 +17,8 @@ export interface UseBackResult {
|
|
|
17
17
|
/**
|
|
18
18
|
* Whether backward navigation is possible. Mirrors
|
|
19
19
|
* `navigation.canGoBack` from the Navigation API.
|
|
20
|
-
*
|
|
20
|
+
* Reactively updates when navigations change the
|
|
21
|
+
* history stack. When false, calling `back()` will throw.
|
|
21
22
|
*/
|
|
22
23
|
readonly canGoBack: boolean;
|
|
23
24
|
}
|
|
@@ -27,6 +28,11 @@ export interface UseBackResult {
|
|
|
27
28
|
* `canGoBack` boolean that reflects whether the history
|
|
28
29
|
* stack has a previous entry to traverse to.
|
|
29
30
|
*
|
|
31
|
+
* The `canGoBack` value is kept in React state and
|
|
32
|
+
* updated via the `currententrychange` event, ensuring
|
|
33
|
+
* it stays reactive across navigations — including those
|
|
34
|
+
* triggered outside of React (e.g. browser back button).
|
|
35
|
+
*
|
|
30
36
|
* Must be used inside a `<Router>` component tree.
|
|
31
37
|
*
|
|
32
38
|
* @returns An object with `back` and `canGoBack`.
|
|
@@ -17,7 +17,9 @@ export interface UseForwardResult {
|
|
|
17
17
|
/**
|
|
18
18
|
* Whether forward navigation is possible. Mirrors
|
|
19
19
|
* `navigation.canGoForward` from the Navigation API.
|
|
20
|
-
*
|
|
20
|
+
* Reactively updates when navigations change the
|
|
21
|
+
* history stack. When false, calling `forward()` will
|
|
22
|
+
* throw.
|
|
21
23
|
*/
|
|
22
24
|
readonly canGoForward: boolean;
|
|
23
25
|
}
|
|
@@ -27,6 +29,11 @@ export interface UseForwardResult {
|
|
|
27
29
|
* `canGoForward` boolean that reflects whether the history
|
|
28
30
|
* stack has a next entry to traverse to.
|
|
29
31
|
*
|
|
32
|
+
* The `canGoForward` value is kept in React state and
|
|
33
|
+
* updated via the `currententrychange` event, ensuring
|
|
34
|
+
* it stays reactive across navigations — including those
|
|
35
|
+
* triggered outside of React (e.g. browser forward button).
|
|
36
|
+
*
|
|
30
37
|
* Must be used inside a `<Router>` component tree.
|
|
31
38
|
*
|
|
32
39
|
* @returns An object with `forward` and `canGoForward`.
|
|
@@ -6,5 +6,20 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @returns A navigate function that accepts a URL string and
|
|
8
8
|
* optional `NavigationNavigateOptions`.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* function LogoutButton() {
|
|
13
|
+
* const navigate = useNavigate()
|
|
14
|
+
*
|
|
15
|
+
* return (
|
|
16
|
+
* <button onClick={function () {
|
|
17
|
+
* navigate('/login', { history: 'replace' })
|
|
18
|
+
* }}>
|
|
19
|
+
* Log Out
|
|
20
|
+
* </button>
|
|
21
|
+
* )
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
9
24
|
*/
|
|
10
25
|
export declare function useNavigate(): (url: string, options?: NavigationNavigateOptions) => NavigationResult;
|
|
@@ -9,5 +9,15 @@
|
|
|
9
9
|
*
|
|
10
10
|
* @returns The Navigation object from the nearest provider.
|
|
11
11
|
* @throws When used outside a NavigationContext provider.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* function HistoryDebug() {
|
|
16
|
+
* const navigation = useNavigation()
|
|
17
|
+
* const entries = navigation.entries()
|
|
18
|
+
*
|
|
19
|
+
* return <pre>{JSON.stringify(entries.map(e => e.url))}</pre>
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
12
22
|
*/
|
|
13
23
|
export declare function useNavigation(): Navigation;
|
|
@@ -39,5 +39,23 @@ export interface NavigationEventHandlers {
|
|
|
39
39
|
* @param navigation - The Navigation object to subscribe to.
|
|
40
40
|
* @param handlers - Callbacks for each navigation lifecycle
|
|
41
41
|
* event. All are optional.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```tsx
|
|
45
|
+
* function NavigationLogger() {
|
|
46
|
+
* const navigation = useNavigation()
|
|
47
|
+
*
|
|
48
|
+
* useNavigationEvents(navigation, {
|
|
49
|
+
* onNavigateSuccess() {
|
|
50
|
+
* console.log('navigation completed')
|
|
51
|
+
* },
|
|
52
|
+
* onNavigateError(error) {
|
|
53
|
+
* console.error('navigation failed', error)
|
|
54
|
+
* },
|
|
55
|
+
* })
|
|
56
|
+
*
|
|
57
|
+
* return null
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
42
60
|
*/
|
|
43
61
|
export declare function useNavigationEvents(navigation: Navigation, handlers: NavigationEventHandlers): void;
|
|
@@ -40,6 +40,15 @@ export interface PrecommitHandlerOptions {
|
|
|
40
40
|
* provides TransitionContext.
|
|
41
41
|
* @throws When no transition tuple is provided and the
|
|
42
42
|
* hook is used outside a TransitionContext provider.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```tsx
|
|
46
|
+
* function CustomRouter() {
|
|
47
|
+
* const transition = useTransition()
|
|
48
|
+
* const { createHandler } = useNavigationHandlers(transition)
|
|
49
|
+
* // use createHandler to build intercept handlers
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
43
52
|
*/
|
|
44
53
|
export declare function useNavigationHandlers(transition?: ReturnType<typeof useTransition>): {
|
|
45
54
|
createPrecommitHandler: (options: PrecommitHandlerOptions) => ((controller: NavigationPrecommitController) => Promise<void>) | undefined;
|
|
@@ -8,6 +8,21 @@
|
|
|
8
8
|
* Returns `null` before any navigation event has occurred
|
|
9
9
|
* (i.e. on the initial render).
|
|
10
10
|
*
|
|
11
|
+
* Must be used inside a `<Router>` component tree.
|
|
12
|
+
*
|
|
11
13
|
* @returns The current AbortSignal or null.
|
|
14
|
+
* @throws When used outside a Router or NavigationSignalContext
|
|
15
|
+
* provider.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* function UserProfile({ id }: { id: string }) {
|
|
20
|
+
* const signal = useNavigationSignal()
|
|
21
|
+
*
|
|
22
|
+
* useEffect(function () {
|
|
23
|
+
* fetch(`/api/user/${id}`, { signal })
|
|
24
|
+
* }, [id, signal])
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
12
27
|
*/
|
|
13
28
|
export declare function useNavigationSignal(): AbortSignal | null;
|
|
@@ -7,6 +7,24 @@
|
|
|
7
7
|
* Returns `null` before any navigation event has occurred
|
|
8
8
|
* (i.e. on the initial render).
|
|
9
9
|
*
|
|
10
|
+
* Must be used inside a `<Router>` component tree.
|
|
11
|
+
*
|
|
10
12
|
* @returns The current NavigationType or null.
|
|
13
|
+
* @throws When used outside a Router or NavigationTypeContext
|
|
14
|
+
* provider.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* function PageTransition({ children }: { children: ReactNode }) {
|
|
19
|
+
* const type = useNavigationType()
|
|
20
|
+
* const isTraversal = type === 'traverse'
|
|
21
|
+
*
|
|
22
|
+
* return (
|
|
23
|
+
* <div className={isTraversal ? 'slide' : 'fade'}>
|
|
24
|
+
* {children}
|
|
25
|
+
* </div>
|
|
26
|
+
* )
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
11
29
|
*/
|
|
12
30
|
export declare function useNavigationType(): NavigationType | null;
|
|
@@ -22,5 +22,16 @@ export interface NextMatchOptions {
|
|
|
22
22
|
* @param options - Optional matcher override.
|
|
23
23
|
* @returns A resolver function that takes a destination URL
|
|
24
24
|
* and a not-found component, returning the resolved match.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```tsx
|
|
28
|
+
* function CustomRouter() {
|
|
29
|
+
* const resolve = useNextMatch()
|
|
30
|
+
* const match = resolve(window.location.href, NotFound)
|
|
31
|
+
* const Component = match.handler.component
|
|
32
|
+
*
|
|
33
|
+
* return <Component />
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
25
36
|
*/
|
|
26
37
|
export declare function useNextMatch(options?: NextMatchOptions): (destination: string | null, notFound: ComponentType) => Resolved<Handler>;
|
|
@@ -10,12 +10,53 @@ export interface PrefetchOptions {
|
|
|
10
10
|
*/
|
|
11
11
|
matcher?: Matcher<Handler>;
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Clears the prefetch deduplication cache for a specific
|
|
15
|
+
* matcher instance. After clearing, subsequent calls to the
|
|
16
|
+
* prefetch function will re-execute handlers for pathnames
|
|
17
|
+
* that were previously skipped.
|
|
18
|
+
*
|
|
19
|
+
* Useful when cached data becomes stale — for example after
|
|
20
|
+
* a user logs out, a form submission invalidates server
|
|
21
|
+
* state, or a known data expiry occurs.
|
|
22
|
+
*
|
|
23
|
+
* When called without a matcher argument, has no effect.
|
|
24
|
+
* The cache is automatically garbage-collected when the
|
|
25
|
+
* matcher instance is no longer referenced, so explicit
|
|
26
|
+
* clearing is only needed for long-lived matchers.
|
|
27
|
+
*
|
|
28
|
+
* @param matcher - The matcher whose prefetch cache should
|
|
29
|
+
* be cleared.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* function LogoutButton() {
|
|
34
|
+
* const navigate = useNavigate()
|
|
35
|
+
* const matcher = use(MatcherContext)
|
|
36
|
+
*
|
|
37
|
+
* return (
|
|
38
|
+
* <button onClick={function () {
|
|
39
|
+
* clearPrefetchCache(matcher)
|
|
40
|
+
* navigate('/login', { history: 'replace' })
|
|
41
|
+
* }}>
|
|
42
|
+
* Log Out
|
|
43
|
+
* </button>
|
|
44
|
+
* )
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function clearPrefetchCache(matcher: Matcher<Handler>): void;
|
|
13
49
|
/**
|
|
14
50
|
* Returns a function that triggers the prefetch logic for a
|
|
15
51
|
* given URL by resolving it against the matcher and calling
|
|
16
52
|
* the route's prefetch function. Used by the Link component
|
|
17
53
|
* for hover and viewport prefetch strategies.
|
|
18
54
|
*
|
|
55
|
+
* Each pathname is prefetched at most once per matcher
|
|
56
|
+
* instance per page session. Subsequent calls with the same
|
|
57
|
+
* pathname are no-ops, preventing thundering-herd problems
|
|
58
|
+
* when many Links point to the same destination.
|
|
59
|
+
*
|
|
19
60
|
* Since prefetch triggered from Link happens outside of a
|
|
20
61
|
* navigation event, a stub NavigationPrecommitController is
|
|
21
62
|
* passed (the redirect capability is not meaningful here).
|
|
@@ -23,5 +64,21 @@ export interface PrefetchOptions {
|
|
|
23
64
|
* @param options - Optional matcher override.
|
|
24
65
|
* @returns A function that accepts a URL string and invokes
|
|
25
66
|
* the matched route's prefetch handler, if any.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```tsx
|
|
70
|
+
* function PrefetchOnHover({ href, children }: Props) {
|
|
71
|
+
* const prefetch = usePrefetch()
|
|
72
|
+
*
|
|
73
|
+
* return (
|
|
74
|
+
* <a
|
|
75
|
+
* href={href}
|
|
76
|
+
* onMouseEnter={function () { prefetch(href) }}
|
|
77
|
+
* >
|
|
78
|
+
* {children}
|
|
79
|
+
* </a>
|
|
80
|
+
* )
|
|
81
|
+
* }
|
|
82
|
+
* ```
|
|
26
83
|
*/
|
|
27
84
|
export declare function usePrefetch(options?: PrefetchOptions): (url: string) => void | Promise<void>;
|
|
@@ -22,11 +22,15 @@ export interface SetSearchParamsOptions {
|
|
|
22
22
|
* `URLSearchParams` instance and a setter function to
|
|
23
23
|
* update them via navigation.
|
|
24
24
|
*
|
|
25
|
-
* The getter
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
25
|
+
* The getter derives search params from `UrlContext` —
|
|
26
|
+
* React state managed by the Router — rather than reading
|
|
27
|
+
* the mutable `navigation.currentEntry` during render.
|
|
28
|
+
* This prevents subscription tearing in concurrent mode
|
|
29
|
+
* where two components could otherwise see different
|
|
30
|
+
* search params if a navigation fires mid-render.
|
|
31
|
+
*
|
|
32
|
+
* The setter preserves the existing hash fragment when
|
|
33
|
+
* updating search parameters.
|
|
30
34
|
*
|
|
31
35
|
* The React Compiler handles memoization of the setter,
|
|
32
36
|
* so no manual `useCallback` is needed.
|
|
@@ -4,11 +4,12 @@ export * from './components/NotFound';
|
|
|
4
4
|
export * from './components/Link';
|
|
5
5
|
export * from './context/MatcherContext';
|
|
6
6
|
export * from './context/TransitionContext';
|
|
7
|
-
export * from './context/
|
|
7
|
+
export * from './context/ParamsContext';
|
|
8
8
|
export * from './context/NavigationContext';
|
|
9
9
|
export * from './context/NavigationSignalContext';
|
|
10
10
|
export * from './context/NavigationTypeContext';
|
|
11
11
|
export * from './context/PathnameContext';
|
|
12
|
+
export * from './context/UrlContext';
|
|
12
13
|
export * from './hooks/useNavigation';
|
|
13
14
|
export * from './hooks/useNavigate';
|
|
14
15
|
export * from './hooks/useNavigationSignal';
|
|
@@ -17,13 +17,17 @@ export interface MemoryNavigationOptions {
|
|
|
17
17
|
* browser Navigation API is unavailable.
|
|
18
18
|
*
|
|
19
19
|
* The returned object satisfies the subset of the `Navigation`
|
|
20
|
-
* interface consumed by the Router component:
|
|
20
|
+
* interface consumed by the Router component and hooks:
|
|
21
21
|
*
|
|
22
22
|
* - `currentEntry.url` — returns the initial URL
|
|
23
23
|
* - `addEventListener` / `removeEventListener` — no-ops
|
|
24
24
|
* (no events fire in a memory environment)
|
|
25
25
|
* - `navigate()` — no-op that returns a NavigationResult
|
|
26
26
|
* with immediately-resolved promises
|
|
27
|
+
* - `back()` / `forward()` — no-ops that return a
|
|
28
|
+
* NavigationResult with immediately-resolved promises
|
|
29
|
+
* - `traverseTo()` — no-op that returns a NavigationResult
|
|
30
|
+
* - `updateCurrentEntry()` — no-op
|
|
27
31
|
* - `canGoBack` / `canGoForward` — always false
|
|
28
32
|
* - `entries()` — returns a single-entry array
|
|
29
33
|
*
|
package/package.json
CHANGED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
function e(e){let t=e?.root??{children:new Map};function n(e,n){let r=e.split(`/`).filter(Boolean),i=t;for(let t of r){if(t.startsWith(`*`)){let n=t.length>1?t.slice(1):`*`;if(!i.wildcard)i.wildcard={children:new Map,name:n};else if(i.wildcard.name!==n)throw Error(`conflicting wildcard param name at "${e}": existing "*${i.wildcard.name}" vs new "*${n}"`);i=i.wildcard;continue}if(t.startsWith(`:`)){let n=t.slice(1);if(!i.child)i.child={children:new Map,name:n};else if(i.child.name!==n)throw Error(`conflicting dynamic param name at "${e}": existing ":${i.child.name}" vs new ":${n}"`);i=i.child;continue}let n=i.children.get(t);n||(n={children:new Map},i.children.set(t,n)),i=n}i.handler=n}function r(e){let n=e.split(`/`).filter(Boolean);function r(e,t,i){if(t===n.length)return e.handler===void 0?null:{handler:e.handler,params:i};let a=n[t],o=e.children.get(a);if(o){let e=r(o,t+1,i);if(e)return e}if(e.child&&e.child.name){let n=r(e.child,t+1,{...i,[e.child.name]:a});if(n)return n}if(e.wildcard&&e.wildcard.name&&e.wildcard.handler!==void 0){let r=n.slice(t).join(`/`);return{handler:e.wildcard.handler,params:{...i,[e.wildcard.name]:r}}}return null}return r(t,0,{})}return{register:n,match:r}}Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return e}});
|
|
2
|
-
//# sourceMappingURL=matcher-CTRKcf7I.cjs.map
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Provides the route parameters extracted from the matched URL
|
|
3
|
-
* pattern as a string-keyed record. Defaults to an empty object
|
|
4
|
-
* when no route has been matched yet.
|
|
5
|
-
*
|
|
6
|
-
* Consumed via the `useParams` hook. The Router component
|
|
7
|
-
* updates this context on every successful navigation with
|
|
8
|
-
* the newly extracted parameters.
|
|
9
|
-
*/
|
|
10
|
-
export declare const ParamsContext: import('react').Context<Record<string, string>>;
|