@real-router/react 0.8.0 → 0.10.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/README.md +43 -2
- package/dist/cjs/index.d.ts +37 -67
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/legacy.d.ts +74 -3
- package/dist/cjs/metafile-cjs.json +1 -1
- package/dist/esm/index.d.mts +37 -67
- package/dist/esm/index.mjs +1 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/legacy.d.mts +74 -3
- package/dist/esm/metafile-esm.json +1 -1
- package/package.json +3 -3
- package/src/components/modern/RouteView/RouteView.tsx +47 -0
- package/src/components/modern/RouteView/components.tsx +13 -0
- package/src/components/modern/RouteView/helpers.tsx +119 -0
- package/src/components/modern/RouteView/index.ts +7 -0
- package/src/components/modern/RouteView/types.ts +24 -0
- package/src/index.ts +8 -0
package/README.md
CHANGED
|
@@ -252,18 +252,59 @@ import { Link } from "@real-router/react";
|
|
|
252
252
|
</Link>;
|
|
253
253
|
```
|
|
254
254
|
|
|
255
|
+
#### `<RouteView nodeName={string}>`
|
|
256
|
+
|
|
257
|
+
Declarative route matching component. Subscribes to a route node and renders the first matched segment.\
|
|
258
|
+
`nodeName: string` — route node to subscribe to (`""` for root)\
|
|
259
|
+
[Wiki](https://github.com/greydragon888/real-router/wiki/RouteView)
|
|
260
|
+
|
|
261
|
+
> **Note:** `RouteView` is only available from the main entry point (`@real-router/react`). It requires React 19.2+ for `keepAlive` support via `<Activity>`.
|
|
262
|
+
|
|
263
|
+
```tsx
|
|
264
|
+
import { RouteView } from "@real-router/react";
|
|
265
|
+
|
|
266
|
+
<RouteView nodeName="">
|
|
267
|
+
<RouteView.Match segment="users">
|
|
268
|
+
<UsersPage />
|
|
269
|
+
</RouteView.Match>
|
|
270
|
+
<RouteView.Match segment="settings">
|
|
271
|
+
<SettingsPage />
|
|
272
|
+
</RouteView.Match>
|
|
273
|
+
<RouteView.NotFound>
|
|
274
|
+
<NotFoundPage />
|
|
275
|
+
</RouteView.NotFound>
|
|
276
|
+
</RouteView>;
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
##### `keepAlive`
|
|
280
|
+
|
|
281
|
+
`<RouteView.Match>` accepts an optional `keepAlive` prop. When enabled, the matched component's state and DOM are preserved when navigating away, using React 19.2's `<Activity>` API.
|
|
282
|
+
|
|
283
|
+
```tsx
|
|
284
|
+
<RouteView nodeName="">
|
|
285
|
+
<RouteView.Match segment="users" keepAlive>
|
|
286
|
+
<UsersPage /> {/* State preserved when navigating away */}
|
|
287
|
+
</RouteView.Match>
|
|
288
|
+
<RouteView.Match segment="settings">
|
|
289
|
+
<SettingsPage /> {/* Unmounts normally */}
|
|
290
|
+
</RouteView.Match>
|
|
291
|
+
</RouteView>
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
When the user navigates away from a `keepAlive` match, the component is hidden (via `<Activity mode="hidden">`) rather than unmounted. Navigating back restores the previous state instantly without re-mounting.
|
|
295
|
+
|
|
255
296
|
---
|
|
256
297
|
|
|
257
298
|
## Migration from React 18
|
|
258
299
|
|
|
259
|
-
If
|
|
300
|
+
If your app uses React 18 (or < 19.2), use the legacy entry point:
|
|
260
301
|
|
|
261
302
|
```diff
|
|
262
303
|
- import { useRouteNode, Link } from '@real-router/react';
|
|
263
304
|
+ import { useRouteNode, Link } from '@real-router/react/legacy';
|
|
264
305
|
```
|
|
265
306
|
|
|
266
|
-
One import path change.
|
|
307
|
+
One import path change. All hooks and `Link` work identically. The only difference: `RouteView` (which uses React 19.2's `<Activity>` for `keepAlive`) is not available from `/legacy`. Use `useRouteNode` with a switch/case pattern instead.
|
|
267
308
|
|
|
268
309
|
---
|
|
269
310
|
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,76 +1,46 @@
|
|
|
1
|
-
|
|
1
|
+
export { Link, LinkProps, NavigatorContext, RouteContext, RouterContext, RouterProvider, useIsActiveRoute, useNavigator, useRoute, useRouteNode, useRouteUtils, useRouter, useRouterTransition } from './legacy.js';
|
|
2
|
+
import { ReactNode, ReactElement } from 'react';
|
|
2
3
|
export { Navigator } from '@real-router/core';
|
|
3
|
-
import { RouterTransitionSnapshot } from '@real-router/sources';
|
|
4
4
|
export { RouterTransitionSnapshot } from '@real-router/sources';
|
|
5
|
-
import
|
|
6
|
-
import { HTMLAttributes, MouseEventHandler, FC, ReactNode } from 'react';
|
|
7
|
-
import { RouteUtils } from '@real-router/route-utils';
|
|
5
|
+
import '@real-router/route-utils';
|
|
8
6
|
|
|
9
|
-
interface
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
interface RouteViewProps {
|
|
8
|
+
/** Route tree node name to subscribe to. "" for root. */
|
|
9
|
+
readonly nodeName: string;
|
|
10
|
+
/** <RouteView.Match> and <RouteView.NotFound> elements. */
|
|
11
|
+
readonly children: ReactNode;
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
13
|
+
interface MatchProps {
|
|
14
|
+
/** Route segment to match against. */
|
|
15
|
+
readonly segment: string;
|
|
16
|
+
/** Exact match only (no descendants). Defaults to false. */
|
|
17
|
+
readonly exact?: boolean;
|
|
18
|
+
/** Preserve component state when deactivated (React Activity). Defaults to false. */
|
|
19
|
+
readonly keepAlive?: boolean;
|
|
20
|
+
/** Content to render when matched. */
|
|
21
|
+
readonly children: ReactNode;
|
|
22
|
+
}
|
|
23
|
+
interface NotFoundProps {
|
|
24
|
+
/** Content to render on UNKNOWN_ROUTE. */
|
|
25
|
+
readonly children: ReactNode;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
declare
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
declare
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
declare const useRouter: () => Router;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Returns a pre-computed {@link RouteUtils} instance for the current router.
|
|
40
|
-
*
|
|
41
|
-
* Internally retrieves the route tree via `getPluginApi` and delegates
|
|
42
|
-
* to `getRouteUtils`, which caches instances per tree reference (WeakMap).
|
|
43
|
-
*
|
|
44
|
-
* @returns RouteUtils instance with pre-computed chains and siblings
|
|
45
|
-
*
|
|
46
|
-
* @example
|
|
47
|
-
* ```tsx
|
|
48
|
-
* const utils = useRouteUtils();
|
|
49
|
-
*
|
|
50
|
-
* utils.getChain("users.profile");
|
|
51
|
-
* // → ["users", "users.profile"]
|
|
52
|
-
*
|
|
53
|
-
* utils.getSiblings("users");
|
|
54
|
-
* // → ["admin"]
|
|
55
|
-
*
|
|
56
|
-
* utils.isDescendantOf("users.profile", "users");
|
|
57
|
-
* // → true
|
|
58
|
-
* ```
|
|
59
|
-
*/
|
|
60
|
-
declare const useRouteUtils: () => RouteUtils;
|
|
61
|
-
|
|
62
|
-
declare function useIsActiveRoute(routeName: string, params?: Params, strict?: boolean, ignoreQueryParams?: boolean): boolean;
|
|
63
|
-
|
|
64
|
-
declare function useRouterTransition(): RouterTransitionSnapshot;
|
|
65
|
-
|
|
66
|
-
interface RouteProviderProps {
|
|
67
|
-
router: Router;
|
|
68
|
-
children: ReactNode;
|
|
28
|
+
declare function Match(_props: MatchProps): null;
|
|
29
|
+
declare namespace Match {
|
|
30
|
+
var displayName: string;
|
|
31
|
+
}
|
|
32
|
+
declare function NotFound(_props: NotFoundProps): null;
|
|
33
|
+
declare namespace NotFound {
|
|
34
|
+
var displayName: string;
|
|
69
35
|
}
|
|
70
|
-
declare const RouterProvider: FC<RouteProviderProps>;
|
|
71
36
|
|
|
72
|
-
declare
|
|
73
|
-
declare
|
|
74
|
-
|
|
37
|
+
declare function RouteViewRoot({ nodeName, children, }: Readonly<RouteViewProps>): ReactElement | null;
|
|
38
|
+
declare namespace RouteViewRoot {
|
|
39
|
+
var displayName: string;
|
|
40
|
+
}
|
|
41
|
+
declare const RouteView: typeof RouteViewRoot & {
|
|
42
|
+
Match: typeof Match;
|
|
43
|
+
NotFound: typeof NotFound;
|
|
44
|
+
};
|
|
75
45
|
|
|
76
|
-
export {
|
|
46
|
+
export { RouteView, type MatchProps as RouteViewMatchProps, type NotFoundProps as RouteViewNotFoundProps, type RouteViewProps };
|
package/dist/cjs/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=require("react"),t=require("@real-router/sources"),r=require("react/jsx-runtime"),o=require("@real-router/core"),
|
|
1
|
+
var e=require("react"),t=require("@real-router/sources"),r=require("react/jsx-runtime"),o=require("@real-router/core"),n=require("@real-router/route-utils"),u=Object.freeze({}),s=Object.freeze({}),i=e.createContext(null),a=e.createContext(null),c=e.createContext(null),l=()=>{const t=e.use(a);if(!t)throw new Error("useRouter must be used within a RouterProvider");return t};function p(t){const r=JSON.stringify(t);return e.useMemo(()=>t,[r])}function d(r,o,n=!1,u=!0){const s=l(),i=p(o),a=e.useMemo(()=>t.createActiveRouteSource(s,r,i,{strict:n,ignoreQueryParams:u}),[s,r,i,n,u]);return e.useSyncExternalStore(a.subscribe,a.getSnapshot,a.getSnapshot)}var m=e.memo(({routeName:t,routeParams:o=u,routeOptions:n=s,className:i,activeClassName:a="active",activeStrict:c=!1,ignoreQueryParams:m=!0,onClick:h,target:g,children:v,...f})=>{const x=l(),N=p(o),S=p(n),y=d(t,N,c,m),R=e.useMemo(()=>"function"==typeof x.buildUrl?x.buildUrl(t,N):x.buildPath(t,N),[x,t,N]),b=e.useCallback(e=>{h&&(h(e),e.defaultPrevented)||function(e){return!(0!==e.button||e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}(e)&&"_blank"!==g&&(e.preventDefault(),x.navigate(t,N,S).catch(()=>{}))},[h,g,x,t,N,S]),w=e.useMemo(()=>y&&a?i?`${i} ${a}`.trim():a:i??void 0,[y,i,a]);return r.jsx("a",{...f,href:R,className:w,onClick:b,children:v})},function(e,t){return e.routeName===t.routeName&&e.className===t.className&&e.activeClassName===t.activeClassName&&e.activeStrict===t.activeStrict&&e.ignoreQueryParams===t.ignoreQueryParams&&e.onClick===t.onClick&&e.target===t.target&&e.style===t.style&&e.children===t.children&&JSON.stringify(e.routeParams)===JSON.stringify(t.routeParams)&&JSON.stringify(e.routeOptions)===JSON.stringify(t.routeOptions)});function h(e){return null}function g(e){return null}function v(e,t,r){return r?e===t:n.startsWithSegment(e,t)}function f(t,r){for(const o of e.Children.toArray(t))e.isValidElement(o)&&(o.type===h||o.type===g?r.push(o):f(o.props.children,r))}function x(t,o,n,u){return n?r.jsx(e.Activity,{mode:u,children:t},o):r.jsx(e.Fragment,{children:t},o)}function N(r){const n=l(),u=e.useMemo(()=>t.createRouteNodeSource(n,r),[n,r]),{route:s,previousRoute:i}=e.useSyncExternalStore(u.subscribe,u.getSnapshot,u.getSnapshot),a=e.useMemo(()=>o.getNavigator(n),[n]);return e.useMemo(()=>({navigator:a,route:s,previousRoute:i}),[a,s,i])}function S({nodeName:t,children:n}){const{route:u}=N(t),s=e.useRef(new Set);if(!u)return null;const i=[];f(n,i);const{rendered:a}=function(t,n,u,s){let i=null,a=!1;const c=[];for(const e of t){if(e.type===g){i=e.props.children;continue}const{segment:t,exact:r=!1,keepAlive:o=!1}=e.props,l=u?`${u}.${t}`:t;!a&&v(n,l,r)?(a=!0,s.add(l),c.push(x(e.props.children,l,o,"visible"))):o&&s.has(l)&&c.push(x(e.props.children,l,o,"hidden"))}return a||n!==o.UNKNOWN_ROUTE||null===i||c.push(r.jsx(e.Fragment,{children:i},"__route-view-not-found__")),{rendered:c,activeMatchFound:a}}(i,u.name,t,s.current);return a.length>0?r.jsx(r.Fragment,{children:a}):null}m.displayName="Link",h.displayName="RouteView.Match",g.displayName="RouteView.NotFound",S.displayName="RouteView";var y=Object.assign(S,{Match:h,NotFound:g});exports.Link=m,exports.NavigatorContext=c,exports.RouteContext=i,exports.RouteView=y,exports.RouterContext=a,exports.RouterProvider=({router:n,children:u})=>{const s=e.useMemo(()=>o.getNavigator(n),[n]),l=e.useMemo(()=>t.createRouteSource(n),[n]),{route:p,previousRoute:d}=e.useSyncExternalStore(l.subscribe,l.getSnapshot,l.getSnapshot),m=e.useMemo(()=>({navigator:s,route:p,previousRoute:d}),[s,p,d]);return r.jsx(a,{value:n,children:r.jsx(c,{value:s,children:r.jsx(i,{value:m,children:u})})})},exports.useIsActiveRoute=d,exports.useNavigator=()=>{const t=e.use(c);if(!t)throw new Error("useNavigator must be used within a RouterProvider");return t},exports.useRoute=()=>{const t=e.use(i);if(!t)throw new Error("useRoute must be used within a RouteProvider");return t},exports.useRouteNode=N,exports.useRouteUtils=()=>{const e=l();return n.getRouteUtils(o.getPluginApi(e).getTree())},exports.useRouter=l,exports.useRouterTransition=function(){const r=l(),o=e.useMemo(()=>t.createTransitionSource(r),[r]);return e.useSyncExternalStore(o.subscribe,o.getSnapshot,o.getSnapshot)};//# sourceMappingURL=index.js.map
|
package/dist/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/constants.ts","../../src/context.ts","../../src/hooks/useRouter.tsx","../../src/hooks/useStableValue.tsx","../../src/hooks/useIsActiveRoute.tsx","../../src/utils.ts","../../src/components/Link.tsx","../../src/hooks/useRouteNode.tsx","../../src/hooks/useRoute.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/hooks/useRouterTransition.tsx","../../src/RouterProvider.tsx"],"names":["createContext","use","useMemo","createActiveRouteSource","useSyncExternalStore","memo","useCallback","jsx","createRouteNodeSource","getNavigator","getRouteUtils","getPluginApi","createTransitionSource","createRouteSource"],"mappings":"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","file":"index.js","sourcesContent":["// packages/react/modules/constants.ts\n\n/**\n * Stable empty object for default params\n */\nexport const EMPTY_PARAMS = Object.freeze({});\n\n/**\n * Stable empty options object\n */\nexport const EMPTY_OPTIONS = Object.freeze({});\n","// packages/react/modules/context.ts\n\nimport { createContext } from \"react\";\n\nimport type { RouteContext as RouteContextType } from \"./types\";\nimport type { Router, Navigator } from \"@real-router/core\";\n\nexport const RouteContext = createContext<RouteContextType | null>(null);\n\nexport const RouterContext = createContext<Router | null>(null);\n\nexport const NavigatorContext = createContext<Navigator | null>(null);\n","// packages/react/modules/hooks/useRouter.tsx\n\nimport { use } from \"react\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = use(RouterContext);\n\n if (!router) {\n throw new Error(\"useRouter must be used within a RouterProvider\");\n }\n\n return router;\n};\n","// packages/react/modules/hooks/useStableValue.tsx\n\nimport { useMemo } from \"react\";\n\n/**\n * Stabilizes a value reference based on deep equality (via JSON serialization).\n * Returns the same reference until the serialized value changes.\n *\n * Useful for object/array dependencies in hooks like useMemo, useCallback, useEffect\n * to prevent unnecessary re-renders when the value is structurally the same.\n *\n * @example\n * ```tsx\n * const stableParams = useStableValue(routeParams);\n * const href = useMemo(() => {\n * return router.buildUrl(routeName, stableParams);\n * }, [router, routeName, stableParams]);\n * ```\n *\n * @param value - The value to stabilize\n * @returns A stable reference to the value\n */\nexport function useStableValue<T>(value: T): T {\n const serialized = JSON.stringify(value);\n\n // We intentionally use serialized in deps to detect deep changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => value, [serialized]);\n}\n","import { createActiveRouteSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\nimport { useStableValue } from \"./useStableValue\";\n\nimport type { Params } from \"@real-router/core\";\n\nexport function useIsActiveRoute(\n routeName: string,\n params?: Params,\n strict = false,\n ignoreQueryParams = true,\n): boolean {\n const router = useRouter();\n\n // useStableValue: JSON.stringify memoization of params object.\n // Without it, every render with a new params reference (e.g.,\n // <Link routeParams={{ id: '123' }} />) would recreate the store.\n const stableParams = useStableValue(params);\n\n const store = useMemo(\n () =>\n createActiveRouteSource(router, routeName, stableParams, {\n strict,\n ignoreQueryParams,\n }),\n [router, routeName, stableParams, strict, ignoreQueryParams],\n );\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n}\n","import type { MouseEvent } from \"react\";\n\n/**\n * Check if navigation should be handled by router\n */\nexport function shouldNavigate(evt: MouseEvent): boolean {\n return (\n evt.button === 0 && // left click\n !evt.metaKey &&\n !evt.altKey &&\n !evt.ctrlKey &&\n !evt.shiftKey\n );\n}\n","import { memo, useCallback, useMemo } from \"react\";\n\nimport { EMPTY_PARAMS, EMPTY_OPTIONS } from \"../constants\";\nimport { useIsActiveRoute } from \"../hooks/useIsActiveRoute\";\nimport { useRouter } from \"../hooks/useRouter\";\nimport { useStableValue } from \"../hooks/useStableValue\";\nimport { shouldNavigate } from \"../utils\";\n\nimport type { LinkProps } from \"../types\";\nimport type { FC, MouseEvent } from \"react\";\n\nfunction areLinkPropsEqual(\n prev: Readonly<LinkProps>,\n next: Readonly<LinkProps>,\n): boolean {\n return (\n prev.routeName === next.routeName &&\n prev.className === next.className &&\n prev.activeClassName === next.activeClassName &&\n prev.activeStrict === next.activeStrict &&\n prev.ignoreQueryParams === next.ignoreQueryParams &&\n prev.onClick === next.onClick &&\n prev.target === next.target &&\n prev.style === next.style &&\n prev.children === next.children &&\n JSON.stringify(prev.routeParams) === JSON.stringify(next.routeParams) &&\n JSON.stringify(prev.routeOptions) === JSON.stringify(next.routeOptions)\n );\n}\n\nexport const Link: FC<LinkProps> = memo(\n ({\n routeName,\n routeParams = EMPTY_PARAMS,\n routeOptions = EMPTY_OPTIONS,\n className,\n activeClassName = \"active\",\n activeStrict = false,\n ignoreQueryParams = true,\n onClick,\n target,\n children,\n ...props\n }) => {\n const router = useRouter();\n\n const stableParams = useStableValue(routeParams);\n const stableOptions = useStableValue(routeOptions);\n\n const isActive = useIsActiveRoute(\n routeName,\n stableParams,\n activeStrict,\n ignoreQueryParams,\n );\n\n const href = useMemo(() => {\n if (typeof router.buildUrl === \"function\") {\n return router.buildUrl(routeName, stableParams);\n }\n\n return router.buildPath(routeName, stableParams);\n }, [router, routeName, stableParams]);\n\n const handleClick = useCallback(\n (evt: MouseEvent<HTMLAnchorElement>) => {\n if (onClick) {\n onClick(evt);\n\n if (evt.defaultPrevented) {\n return;\n }\n }\n\n if (!shouldNavigate(evt) || target === \"_blank\") {\n return;\n }\n\n evt.preventDefault();\n router.navigate(routeName, stableParams, stableOptions).catch(() => {});\n },\n [onClick, target, router, routeName, stableParams, stableOptions],\n );\n\n const finalClassName = useMemo(() => {\n if (isActive && activeClassName) {\n return className\n ? `${className} ${activeClassName}`.trim()\n : activeClassName;\n }\n\n return className ?? undefined;\n }, [isActive, className, activeClassName]);\n\n return (\n <a\n {...props}\n href={href}\n className={finalClassName}\n onClick={handleClick}\n >\n {children}\n </a>\n );\n },\n areLinkPropsEqual,\n);\n\nLink.displayName = \"Link\";\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteNodeSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteContext } from \"../types\";\n\nexport function useRouteNode(nodeName: string): RouteContext {\n const router = useRouter();\n\n const store = useMemo(\n () => createRouteNodeSource(router, nodeName),\n [router, nodeName],\n );\n\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n return useMemo(\n (): RouteContext => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n}\n","// packages/react/modules/hooks/useRoute.tsx\n\nimport { use } from \"react\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = use(RouteContext);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouteProvider\");\n }\n\n return routeContext;\n};\n","// packages/react/modules/hooks/useNavigator.tsx\n\nimport { use } from \"react\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = use(NavigatorContext);\n\n if (!navigator) {\n throw new Error(\"useNavigator must be used within a RouterProvider\");\n }\n\n return navigator;\n};\n","// packages/react/modules/hooks/useRouteUtils.tsx\n\nimport { getPluginApi } from \"@real-router/core\";\nimport { getRouteUtils } from \"@real-router/route-utils\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteUtils } from \"@real-router/route-utils\";\n\n/**\n * Returns a pre-computed {@link RouteUtils} instance for the current router.\n *\n * Internally retrieves the route tree via `getPluginApi` and delegates\n * to `getRouteUtils`, which caches instances per tree reference (WeakMap).\n *\n * @returns RouteUtils instance with pre-computed chains and siblings\n *\n * @example\n * ```tsx\n * const utils = useRouteUtils();\n *\n * utils.getChain(\"users.profile\");\n * // → [\"users\", \"users.profile\"]\n *\n * utils.getSiblings(\"users\");\n * // → [\"admin\"]\n *\n * utils.isDescendantOf(\"users.profile\", \"users\");\n * // → true\n * ```\n */\nexport const useRouteUtils = (): RouteUtils => {\n const router = useRouter();\n\n return getRouteUtils(getPluginApi(router).getTree());\n};\n","import { createTransitionSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouterTransitionSnapshot } from \"@real-router/sources\";\n\nexport function useRouterTransition(): RouterTransitionSnapshot {\n const router = useRouter();\n\n const store = useMemo(() => createTransitionSource(router), [router]);\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot,\n );\n}\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { NavigatorContext, RouteContext, RouterContext } from \"./context\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { FC, ReactNode } from \"react\";\n\nexport interface RouteProviderProps {\n router: Router;\n children: ReactNode;\n}\n\nexport const RouterProvider: FC<RouteProviderProps> = ({\n router,\n children,\n}) => {\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n // useSyncExternalStore manages the router subscription lifecycle:\n // subscribe connects to router on first listener, unsubscribes on last.\n // This is Strict Mode safe — no useEffect cleanup needed.\n const store = useMemo(() => createRouteSource(router), [router]);\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n\n const routeContextValue = useMemo(\n () => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n\n return (\n <RouterContext value={router}>\n <NavigatorContext value={navigator}>\n <RouteContext value={routeContextValue}>{children}</RouteContext>\n </NavigatorContext>\n </RouterContext>\n );\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/constants.ts","../../src/context.ts","../../src/hooks/useRouter.tsx","../../src/hooks/useStableValue.tsx","../../src/hooks/useIsActiveRoute.tsx","../../src/utils.ts","../../src/components/Link.tsx","../../src/components/modern/RouteView/components.tsx","../../src/components/modern/RouteView/helpers.tsx","../../src/hooks/useRouteNode.tsx","../../src/components/modern/RouteView/RouteView.tsx","../../src/hooks/useRoute.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/hooks/useRouterTransition.tsx","../../src/RouterProvider.tsx"],"names":["createContext","use","useMemo","createActiveRouteSource","useSyncExternalStore","memo","useCallback","jsx","startsWithSegment","Children","isValidElement","Activity","Fragment","UNKNOWN_ROUTE","createRouteNodeSource","getNavigator","useRef","getRouteUtils","getPluginApi","createTransitionSource","createRouteSource"],"mappings":"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","file":"index.js","sourcesContent":["// packages/react/modules/constants.ts\n\n/**\n * Stable empty object for default params\n */\nexport const EMPTY_PARAMS = Object.freeze({});\n\n/**\n * Stable empty options object\n */\nexport const EMPTY_OPTIONS = Object.freeze({});\n","// packages/react/modules/context.ts\n\nimport { createContext } from \"react\";\n\nimport type { RouteContext as RouteContextType } from \"./types\";\nimport type { Router, Navigator } from \"@real-router/core\";\n\nexport const RouteContext = createContext<RouteContextType | null>(null);\n\nexport const RouterContext = createContext<Router | null>(null);\n\nexport const NavigatorContext = createContext<Navigator | null>(null);\n","// packages/react/modules/hooks/useRouter.tsx\n\nimport { use } from \"react\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = use(RouterContext);\n\n if (!router) {\n throw new Error(\"useRouter must be used within a RouterProvider\");\n }\n\n return router;\n};\n","// packages/react/modules/hooks/useStableValue.tsx\n\nimport { useMemo } from \"react\";\n\n/**\n * Stabilizes a value reference based on deep equality (via JSON serialization).\n * Returns the same reference until the serialized value changes.\n *\n * Useful for object/array dependencies in hooks like useMemo, useCallback, useEffect\n * to prevent unnecessary re-renders when the value is structurally the same.\n *\n * @example\n * ```tsx\n * const stableParams = useStableValue(routeParams);\n * const href = useMemo(() => {\n * return router.buildUrl(routeName, stableParams);\n * }, [router, routeName, stableParams]);\n * ```\n *\n * @param value - The value to stabilize\n * @returns A stable reference to the value\n */\nexport function useStableValue<T>(value: T): T {\n const serialized = JSON.stringify(value);\n\n // We intentionally use serialized in deps to detect deep changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => value, [serialized]);\n}\n","import { createActiveRouteSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\nimport { useStableValue } from \"./useStableValue\";\n\nimport type { Params } from \"@real-router/core\";\n\nexport function useIsActiveRoute(\n routeName: string,\n params?: Params,\n strict = false,\n ignoreQueryParams = true,\n): boolean {\n const router = useRouter();\n\n // useStableValue: JSON.stringify memoization of params object.\n // Without it, every render with a new params reference (e.g.,\n // <Link routeParams={{ id: '123' }} />) would recreate the store.\n const stableParams = useStableValue(params);\n\n const store = useMemo(\n () =>\n createActiveRouteSource(router, routeName, stableParams, {\n strict,\n ignoreQueryParams,\n }),\n [router, routeName, stableParams, strict, ignoreQueryParams],\n );\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n}\n","import type { MouseEvent } from \"react\";\n\n/**\n * Check if navigation should be handled by router\n */\nexport function shouldNavigate(evt: MouseEvent): boolean {\n return (\n evt.button === 0 && // left click\n !evt.metaKey &&\n !evt.altKey &&\n !evt.ctrlKey &&\n !evt.shiftKey\n );\n}\n","import { memo, useCallback, useMemo } from \"react\";\n\nimport { EMPTY_PARAMS, EMPTY_OPTIONS } from \"../constants\";\nimport { useIsActiveRoute } from \"../hooks/useIsActiveRoute\";\nimport { useRouter } from \"../hooks/useRouter\";\nimport { useStableValue } from \"../hooks/useStableValue\";\nimport { shouldNavigate } from \"../utils\";\n\nimport type { LinkProps } from \"../types\";\nimport type { FC, MouseEvent } from \"react\";\n\nfunction areLinkPropsEqual(\n prev: Readonly<LinkProps>,\n next: Readonly<LinkProps>,\n): boolean {\n return (\n prev.routeName === next.routeName &&\n prev.className === next.className &&\n prev.activeClassName === next.activeClassName &&\n prev.activeStrict === next.activeStrict &&\n prev.ignoreQueryParams === next.ignoreQueryParams &&\n prev.onClick === next.onClick &&\n prev.target === next.target &&\n prev.style === next.style &&\n prev.children === next.children &&\n JSON.stringify(prev.routeParams) === JSON.stringify(next.routeParams) &&\n JSON.stringify(prev.routeOptions) === JSON.stringify(next.routeOptions)\n );\n}\n\nexport const Link: FC<LinkProps> = memo(\n ({\n routeName,\n routeParams = EMPTY_PARAMS,\n routeOptions = EMPTY_OPTIONS,\n className,\n activeClassName = \"active\",\n activeStrict = false,\n ignoreQueryParams = true,\n onClick,\n target,\n children,\n ...props\n }) => {\n const router = useRouter();\n\n const stableParams = useStableValue(routeParams);\n const stableOptions = useStableValue(routeOptions);\n\n const isActive = useIsActiveRoute(\n routeName,\n stableParams,\n activeStrict,\n ignoreQueryParams,\n );\n\n const href = useMemo(() => {\n if (typeof router.buildUrl === \"function\") {\n return router.buildUrl(routeName, stableParams);\n }\n\n return router.buildPath(routeName, stableParams);\n }, [router, routeName, stableParams]);\n\n const handleClick = useCallback(\n (evt: MouseEvent<HTMLAnchorElement>) => {\n if (onClick) {\n onClick(evt);\n\n if (evt.defaultPrevented) {\n return;\n }\n }\n\n if (!shouldNavigate(evt) || target === \"_blank\") {\n return;\n }\n\n evt.preventDefault();\n router.navigate(routeName, stableParams, stableOptions).catch(() => {});\n },\n [onClick, target, router, routeName, stableParams, stableOptions],\n );\n\n const finalClassName = useMemo(() => {\n if (isActive && activeClassName) {\n return className\n ? `${className} ${activeClassName}`.trim()\n : activeClassName;\n }\n\n return className ?? undefined;\n }, [isActive, className, activeClassName]);\n\n return (\n <a\n {...props}\n href={href}\n className={finalClassName}\n onClick={handleClick}\n >\n {children}\n </a>\n );\n },\n areLinkPropsEqual,\n);\n\nLink.displayName = \"Link\";\n","import type { MatchProps, NotFoundProps } from \"./types\";\n\nexport function Match(_props: MatchProps): null {\n return null;\n}\n\nMatch.displayName = \"RouteView.Match\";\n\nexport function NotFound(_props: NotFoundProps): null {\n return null;\n}\n\nNotFound.displayName = \"RouteView.NotFound\";\n","import { UNKNOWN_ROUTE } from \"@real-router/core\";\nimport { startsWithSegment } from \"@real-router/route-utils\";\nimport { Activity, Children, Fragment, isValidElement } from \"react\";\n\nimport { Match, NotFound } from \"./components\";\n\nimport type { MatchProps, NotFoundProps } from \"./types\";\nimport type { ReactElement, ReactNode } from \"react\";\n\nfunction isSegmentMatch(\n routeName: string,\n fullSegmentName: string,\n exact: boolean,\n): boolean {\n if (exact) {\n return routeName === fullSegmentName;\n }\n\n return startsWithSegment(routeName, fullSegmentName);\n}\n\nexport function collectElements(\n children: ReactNode,\n result: ReactElement[],\n): void {\n // eslint-disable-next-line @eslint-react/no-children-to-array\n for (const child of Children.toArray(children)) {\n if (!isValidElement(child)) {\n continue;\n }\n\n if (child.type === Match || child.type === NotFound) {\n result.push(child);\n } else {\n collectElements(\n (child.props as { readonly children: ReactNode }).children,\n result,\n );\n }\n }\n}\n\nfunction renderMatchElement(\n matchChildren: ReactNode,\n fullSegmentName: string,\n keepAlive: boolean,\n mode: \"visible\" | \"hidden\",\n): ReactElement {\n if (keepAlive) {\n return (\n <Activity mode={mode} key={fullSegmentName}>\n {matchChildren}\n </Activity>\n );\n }\n\n return <Fragment key={fullSegmentName}>{matchChildren}</Fragment>;\n}\n\nexport function buildRenderList(\n elements: ReactElement[],\n routeName: string,\n nodeName: string,\n hasBeenActivated: Set<string>,\n): { rendered: ReactElement[]; activeMatchFound: boolean } {\n let notFoundChildren: ReactNode = null;\n let activeMatchFound = false;\n const rendered: ReactElement[] = [];\n\n for (const child of elements) {\n if (child.type === NotFound) {\n notFoundChildren = (child.props as NotFoundProps).children;\n continue;\n }\n\n const {\n segment,\n exact = false,\n keepAlive = false,\n } = child.props as MatchProps;\n const fullSegmentName = nodeName ? `${nodeName}.${segment}` : segment;\n const isActive =\n !activeMatchFound && isSegmentMatch(routeName, fullSegmentName, exact);\n\n if (isActive) {\n activeMatchFound = true;\n hasBeenActivated.add(fullSegmentName);\n rendered.push(\n renderMatchElement(\n (child.props as MatchProps).children,\n fullSegmentName,\n keepAlive,\n \"visible\",\n ),\n );\n } else if (keepAlive && hasBeenActivated.has(fullSegmentName)) {\n rendered.push(\n renderMatchElement(\n (child.props as MatchProps).children,\n fullSegmentName,\n keepAlive,\n \"hidden\",\n ),\n );\n }\n }\n\n if (\n !activeMatchFound &&\n routeName === UNKNOWN_ROUTE &&\n notFoundChildren !== null\n ) {\n rendered.push(\n <Fragment key=\"__route-view-not-found__\">{notFoundChildren}</Fragment>,\n );\n }\n\n return { rendered, activeMatchFound };\n}\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteNodeSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteContext } from \"../types\";\n\nexport function useRouteNode(nodeName: string): RouteContext {\n const router = useRouter();\n\n const store = useMemo(\n () => createRouteNodeSource(router, nodeName),\n [router, nodeName],\n );\n\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n return useMemo(\n (): RouteContext => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n}\n","import { useRef } from \"react\";\n\nimport { Match, NotFound } from \"./components\";\nimport { buildRenderList, collectElements } from \"./helpers\";\nimport { useRouteNode } from \"../../../hooks/useRouteNode\";\n\nimport type { RouteViewProps } from \"./types\";\nimport type { ReactElement } from \"react\";\n\nfunction RouteViewRoot({\n nodeName,\n children,\n}: Readonly<RouteViewProps>): ReactElement | null {\n const { route } = useRouteNode(nodeName);\n const hasBeenActivatedRef = useRef<Set<string>>(new Set());\n\n if (!route) {\n return null;\n }\n\n const elements: ReactElement[] = [];\n\n collectElements(children, elements);\n\n const { rendered } = buildRenderList(\n elements,\n route.name,\n nodeName,\n hasBeenActivatedRef.current,\n );\n\n if (rendered.length > 0) {\n return <>{rendered}</>;\n }\n\n return null;\n}\n\nRouteViewRoot.displayName = \"RouteView\";\n\nexport const RouteView = Object.assign(RouteViewRoot, { Match, NotFound });\n\nexport type {\n RouteViewProps,\n MatchProps as RouteViewMatchProps,\n NotFoundProps as RouteViewNotFoundProps,\n} from \"./types\";\n","// packages/react/modules/hooks/useRoute.tsx\n\nimport { use } from \"react\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = use(RouteContext);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouteProvider\");\n }\n\n return routeContext;\n};\n","// packages/react/modules/hooks/useNavigator.tsx\n\nimport { use } from \"react\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = use(NavigatorContext);\n\n if (!navigator) {\n throw new Error(\"useNavigator must be used within a RouterProvider\");\n }\n\n return navigator;\n};\n","// packages/react/modules/hooks/useRouteUtils.tsx\n\nimport { getPluginApi } from \"@real-router/core\";\nimport { getRouteUtils } from \"@real-router/route-utils\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteUtils } from \"@real-router/route-utils\";\n\n/**\n * Returns a pre-computed {@link RouteUtils} instance for the current router.\n *\n * Internally retrieves the route tree via `getPluginApi` and delegates\n * to `getRouteUtils`, which caches instances per tree reference (WeakMap).\n *\n * @returns RouteUtils instance with pre-computed chains and siblings\n *\n * @example\n * ```tsx\n * const utils = useRouteUtils();\n *\n * utils.getChain(\"users.profile\");\n * // → [\"users\", \"users.profile\"]\n *\n * utils.getSiblings(\"users\");\n * // → [\"admin\"]\n *\n * utils.isDescendantOf(\"users.profile\", \"users\");\n * // → true\n * ```\n */\nexport const useRouteUtils = (): RouteUtils => {\n const router = useRouter();\n\n return getRouteUtils(getPluginApi(router).getTree());\n};\n","import { createTransitionSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouterTransitionSnapshot } from \"@real-router/sources\";\n\nexport function useRouterTransition(): RouterTransitionSnapshot {\n const router = useRouter();\n\n const store = useMemo(() => createTransitionSource(router), [router]);\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot,\n );\n}\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { NavigatorContext, RouteContext, RouterContext } from \"./context\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { FC, ReactNode } from \"react\";\n\nexport interface RouteProviderProps {\n router: Router;\n children: ReactNode;\n}\n\nexport const RouterProvider: FC<RouteProviderProps> = ({\n router,\n children,\n}) => {\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n // useSyncExternalStore manages the router subscription lifecycle:\n // subscribe connects to router on first listener, unsubscribes on last.\n // This is Strict Mode safe — no useEffect cleanup needed.\n const store = useMemo(() => createRouteSource(router), [router]);\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n\n const routeContextValue = useMemo(\n () => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n\n return (\n <RouterContext value={router}>\n <NavigatorContext value={navigator}>\n <RouteContext value={routeContextValue}>{children}</RouteContext>\n </NavigatorContext>\n </RouterContext>\n );\n};\n"]}
|
package/dist/cjs/legacy.d.ts
CHANGED
|
@@ -1,5 +1,76 @@
|
|
|
1
|
-
|
|
1
|
+
import { Params, NavigationOptions, Navigator, State, Router } from '@real-router/core';
|
|
2
2
|
export { Navigator } from '@real-router/core';
|
|
3
|
+
import * as react from 'react';
|
|
4
|
+
import { HTMLAttributes, MouseEventHandler, FC, ReactNode } from 'react';
|
|
5
|
+
import { RouteUtils } from '@real-router/route-utils';
|
|
6
|
+
import { RouterTransitionSnapshot } from '@real-router/sources';
|
|
3
7
|
export { RouterTransitionSnapshot } from '@real-router/sources';
|
|
4
|
-
|
|
5
|
-
|
|
8
|
+
|
|
9
|
+
interface RouteState<P extends Params = Params, MP extends Params = Params> {
|
|
10
|
+
route: State<P, MP> | undefined;
|
|
11
|
+
previousRoute?: State | undefined;
|
|
12
|
+
}
|
|
13
|
+
type RouteContext$1 = {
|
|
14
|
+
navigator: Navigator;
|
|
15
|
+
} & RouteState;
|
|
16
|
+
interface LinkProps<P extends Params = Params> extends HTMLAttributes<HTMLAnchorElement> {
|
|
17
|
+
routeName: string;
|
|
18
|
+
routeParams?: P;
|
|
19
|
+
routeOptions?: NavigationOptions;
|
|
20
|
+
activeClassName?: string;
|
|
21
|
+
activeStrict?: boolean;
|
|
22
|
+
ignoreQueryParams?: boolean;
|
|
23
|
+
target?: string;
|
|
24
|
+
onClick?: MouseEventHandler<HTMLAnchorElement>;
|
|
25
|
+
onMouseOver?: MouseEventHandler<HTMLAnchorElement>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
declare const Link: FC<LinkProps>;
|
|
29
|
+
|
|
30
|
+
declare function useRouteNode(nodeName: string): RouteContext$1;
|
|
31
|
+
|
|
32
|
+
declare const useRoute: () => RouteContext$1;
|
|
33
|
+
|
|
34
|
+
declare const useNavigator: () => Navigator;
|
|
35
|
+
|
|
36
|
+
declare const useRouter: () => Router;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Returns a pre-computed {@link RouteUtils} instance for the current router.
|
|
40
|
+
*
|
|
41
|
+
* Internally retrieves the route tree via `getPluginApi` and delegates
|
|
42
|
+
* to `getRouteUtils`, which caches instances per tree reference (WeakMap).
|
|
43
|
+
*
|
|
44
|
+
* @returns RouteUtils instance with pre-computed chains and siblings
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```tsx
|
|
48
|
+
* const utils = useRouteUtils();
|
|
49
|
+
*
|
|
50
|
+
* utils.getChain("users.profile");
|
|
51
|
+
* // → ["users", "users.profile"]
|
|
52
|
+
*
|
|
53
|
+
* utils.getSiblings("users");
|
|
54
|
+
* // → ["admin"]
|
|
55
|
+
*
|
|
56
|
+
* utils.isDescendantOf("users.profile", "users");
|
|
57
|
+
* // → true
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
declare const useRouteUtils: () => RouteUtils;
|
|
61
|
+
|
|
62
|
+
declare function useIsActiveRoute(routeName: string, params?: Params, strict?: boolean, ignoreQueryParams?: boolean): boolean;
|
|
63
|
+
|
|
64
|
+
declare function useRouterTransition(): RouterTransitionSnapshot;
|
|
65
|
+
|
|
66
|
+
interface RouteProviderProps {
|
|
67
|
+
router: Router;
|
|
68
|
+
children: ReactNode;
|
|
69
|
+
}
|
|
70
|
+
declare const RouterProvider: FC<RouteProviderProps>;
|
|
71
|
+
|
|
72
|
+
declare const RouteContext: react.Context<RouteContext$1 | null>;
|
|
73
|
+
declare const RouterContext: react.Context<Router<object> | null>;
|
|
74
|
+
declare const NavigatorContext: react.Context<Navigator | null>;
|
|
75
|
+
|
|
76
|
+
export { Link, type LinkProps, NavigatorContext, RouteContext, RouterContext, RouterProvider, useIsActiveRoute, useNavigator, useRoute, useRouteNode, useRouteUtils, useRouter, useRouterTransition };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js":{"bytes":569,"imports":[],"format":"esm"},"src/constants.ts":{"bytes":225,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/context.ts":{"bytes":416,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouter.tsx":{"bytes":364,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useStableValue.tsx":{"bytes":976,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useIsActiveRoute.tsx":{"bytes":1060,"imports":[{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"src/hooks/useStableValue.tsx","kind":"import-statement","original":"./useStableValue"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/utils.ts":{"bytes":293,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/components/Link.tsx":{"bytes":2900,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/constants.ts","kind":"import-statement","original":"../constants"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"../hooks/useIsActiveRoute"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"../hooks/useRouter"},{"path":"src/hooks/useStableValue.tsx","kind":"import-statement","original":"../hooks/useStableValue"},{"path":"src/utils.ts","kind":"import-statement","original":"../utils"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouteNode.tsx":{"bytes":837,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRoute.tsx":{"bytes":403,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useNavigator.tsx":{"bytes":394,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouteUtils.tsx":{"bytes":977,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouterTransition.tsx":{"bytes":508,"imports":[{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/RouterProvider.tsx":{"bytes":1380,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"./context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":805,"imports":[{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"./hooks/useIsActiveRoute"},{"path":"src/hooks/useRouterTransition.tsx","kind":"import-statement","original":"./hooks/useRouterTransition"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"src/context.ts","kind":"import-statement","original":"./context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/legacy.ts":{"bytes":805,"imports":[{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"./hooks/useIsActiveRoute"},{"path":"src/hooks/useRouterTransition.tsx","kind":"import-statement","original":"./hooks/useRouterTransition"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"src/context.ts","kind":"import-statement","original":"./context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"}},"outputs":{"dist/cjs/index.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":16253},"dist/cjs/index.js":{"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"exports":["Link","NavigatorContext","RouteContext","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"entryPoint":"src/index.ts","inputs":{"src/components/Link.tsx":{"bytesInOutput":2409},"src/constants.ts":{"bytesInOutput":77},"src/hooks/useIsActiveRoute.tsx":{"bytesInOutput":671},"src/hooks/useRouter.tsx":{"bytesInOutput":202},"src/context.ts":{"bytesInOutput":164},"src/hooks/useStableValue.tsx":{"bytesInOutput":157},"src/utils.ts":{"bytesInOutput":140},"src/index.ts":{"bytesInOutput":0},"src/hooks/useRouteNode.tsx":{"bytesInOutput":742},"src/hooks/useRoute.tsx":{"bytesInOutput":225},"src/hooks/useNavigator.tsx":{"bytesInOutput":229},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":225},"src/hooks/useRouterTransition.tsx":{"bytesInOutput":397},"src/RouterProvider.tsx":{"bytesInOutput":1001}},"bytes":7303},"dist/cjs/legacy.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":16253},"dist/cjs/legacy.js":{"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"exports":["Link","NavigatorContext","RouteContext","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"entryPoint":"src/legacy.ts","inputs":{"src/components/Link.tsx":{"bytesInOutput":2409},"src/constants.ts":{"bytesInOutput":77},"src/hooks/useIsActiveRoute.tsx":{"bytesInOutput":671},"src/hooks/useRouter.tsx":{"bytesInOutput":202},"src/context.ts":{"bytesInOutput":164},"src/hooks/useStableValue.tsx":{"bytesInOutput":157},"src/utils.ts":{"bytesInOutput":140},"src/legacy.ts":{"bytesInOutput":0},"src/hooks/useRouteNode.tsx":{"bytesInOutput":742},"src/hooks/useRoute.tsx":{"bytesInOutput":225},"src/hooks/useNavigator.tsx":{"bytesInOutput":229},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":225},"src/hooks/useRouterTransition.tsx":{"bytesInOutput":397},"src/RouterProvider.tsx":{"bytesInOutput":1001}},"bytes":7303}}}
|
|
1
|
+
{"inputs":{"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js":{"bytes":569,"imports":[],"format":"esm"},"src/constants.ts":{"bytes":225,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/context.ts":{"bytes":416,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouter.tsx":{"bytes":364,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useStableValue.tsx":{"bytes":976,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useIsActiveRoute.tsx":{"bytes":1060,"imports":[{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"src/hooks/useStableValue.tsx","kind":"import-statement","original":"./useStableValue"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/utils.ts":{"bytes":293,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/components/Link.tsx":{"bytes":2900,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/constants.ts","kind":"import-statement","original":"../constants"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"../hooks/useIsActiveRoute"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"../hooks/useRouter"},{"path":"src/hooks/useStableValue.tsx","kind":"import-statement","original":"../hooks/useStableValue"},{"path":"src/utils.ts","kind":"import-statement","original":"../utils"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/components/modern/RouteView/components.tsx":{"bytes":286,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/components/modern/RouteView/helpers.tsx":{"bytes":2980,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/components/modern/RouteView/components.tsx","kind":"import-statement","original":"./components"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouteNode.tsx":{"bytes":837,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/components/modern/RouteView/RouteView.tsx":{"bytes":1073,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/components/modern/RouteView/components.tsx","kind":"import-statement","original":"./components"},{"path":"src/components/modern/RouteView/helpers.tsx","kind":"import-statement","original":"./helpers"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"../../../hooks/useRouteNode"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/components/modern/RouteView/index.ts":{"bytes":145,"imports":[{"path":"src/components/modern/RouteView/RouteView.tsx","kind":"import-statement","original":"./RouteView"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRoute.tsx":{"bytes":403,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useNavigator.tsx":{"bytes":394,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouteUtils.tsx":{"bytes":977,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouterTransition.tsx":{"bytes":508,"imports":[{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/RouterProvider.tsx":{"bytes":1380,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"./context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":987,"imports":[{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/components/modern/RouteView/index.ts","kind":"import-statement","original":"./components/modern/RouteView"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"./hooks/useIsActiveRoute"},{"path":"src/hooks/useRouterTransition.tsx","kind":"import-statement","original":"./hooks/useRouterTransition"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"src/context.ts","kind":"import-statement","original":"./context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/legacy.ts":{"bytes":805,"imports":[{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"./hooks/useIsActiveRoute"},{"path":"src/hooks/useRouterTransition.tsx","kind":"import-statement","original":"./hooks/useRouterTransition"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"src/context.ts","kind":"import-statement","original":"./context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"}},"outputs":{"dist/cjs/index.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":23036},"dist/cjs/index.js":{"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"exports":["Link","NavigatorContext","RouteContext","RouteView","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"entryPoint":"src/index.ts","inputs":{"src/components/Link.tsx":{"bytesInOutput":2409},"src/constants.ts":{"bytesInOutput":77},"src/hooks/useIsActiveRoute.tsx":{"bytesInOutput":671},"src/hooks/useRouter.tsx":{"bytesInOutput":202},"src/context.ts":{"bytesInOutput":164},"src/hooks/useStableValue.tsx":{"bytesInOutput":157},"src/utils.ts":{"bytesInOutput":140},"src/index.ts":{"bytesInOutput":0},"src/components/modern/RouteView/RouteView.tsx":{"bytesInOutput":712},"src/components/modern/RouteView/components.tsx":{"bytesInOutput":171},"src/components/modern/RouteView/helpers.tsx":{"bytesInOutput":2366},"src/hooks/useRouteNode.tsx":{"bytesInOutput":742},"src/components/modern/RouteView/index.ts":{"bytesInOutput":0},"src/hooks/useRoute.tsx":{"bytesInOutput":225},"src/hooks/useNavigator.tsx":{"bytesInOutput":229},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":225},"src/hooks/useRouterTransition.tsx":{"bytesInOutput":397},"src/RouterProvider.tsx":{"bytesInOutput":1001}},"bytes":10764},"dist/cjs/legacy.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":16253},"dist/cjs/legacy.js":{"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"exports":["Link","NavigatorContext","RouteContext","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"entryPoint":"src/legacy.ts","inputs":{"src/components/Link.tsx":{"bytesInOutput":2409},"src/constants.ts":{"bytesInOutput":77},"src/hooks/useIsActiveRoute.tsx":{"bytesInOutput":671},"src/hooks/useRouter.tsx":{"bytesInOutput":202},"src/context.ts":{"bytesInOutput":164},"src/hooks/useStableValue.tsx":{"bytesInOutput":157},"src/utils.ts":{"bytesInOutput":140},"src/legacy.ts":{"bytesInOutput":0},"src/hooks/useRouteNode.tsx":{"bytesInOutput":742},"src/hooks/useRoute.tsx":{"bytesInOutput":225},"src/hooks/useNavigator.tsx":{"bytesInOutput":229},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":225},"src/hooks/useRouterTransition.tsx":{"bytesInOutput":397},"src/RouterProvider.tsx":{"bytesInOutput":1001}},"bytes":7303}}}
|
package/dist/esm/index.d.mts
CHANGED
|
@@ -1,76 +1,46 @@
|
|
|
1
|
-
|
|
1
|
+
export { Link, LinkProps, NavigatorContext, RouteContext, RouterContext, RouterProvider, useIsActiveRoute, useNavigator, useRoute, useRouteNode, useRouteUtils, useRouter, useRouterTransition } from './legacy.mjs';
|
|
2
|
+
import { ReactNode, ReactElement } from 'react';
|
|
2
3
|
export { Navigator } from '@real-router/core';
|
|
3
|
-
import { RouterTransitionSnapshot } from '@real-router/sources';
|
|
4
4
|
export { RouterTransitionSnapshot } from '@real-router/sources';
|
|
5
|
-
import
|
|
6
|
-
import { HTMLAttributes, MouseEventHandler, FC, ReactNode } from 'react';
|
|
7
|
-
import { RouteUtils } from '@real-router/route-utils';
|
|
5
|
+
import '@real-router/route-utils';
|
|
8
6
|
|
|
9
|
-
interface
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
interface RouteViewProps {
|
|
8
|
+
/** Route tree node name to subscribe to. "" for root. */
|
|
9
|
+
readonly nodeName: string;
|
|
10
|
+
/** <RouteView.Match> and <RouteView.NotFound> elements. */
|
|
11
|
+
readonly children: ReactNode;
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
13
|
+
interface MatchProps {
|
|
14
|
+
/** Route segment to match against. */
|
|
15
|
+
readonly segment: string;
|
|
16
|
+
/** Exact match only (no descendants). Defaults to false. */
|
|
17
|
+
readonly exact?: boolean;
|
|
18
|
+
/** Preserve component state when deactivated (React Activity). Defaults to false. */
|
|
19
|
+
readonly keepAlive?: boolean;
|
|
20
|
+
/** Content to render when matched. */
|
|
21
|
+
readonly children: ReactNode;
|
|
22
|
+
}
|
|
23
|
+
interface NotFoundProps {
|
|
24
|
+
/** Content to render on UNKNOWN_ROUTE. */
|
|
25
|
+
readonly children: ReactNode;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
declare
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
declare
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
declare const useRouter: () => Router;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Returns a pre-computed {@link RouteUtils} instance for the current router.
|
|
40
|
-
*
|
|
41
|
-
* Internally retrieves the route tree via `getPluginApi` and delegates
|
|
42
|
-
* to `getRouteUtils`, which caches instances per tree reference (WeakMap).
|
|
43
|
-
*
|
|
44
|
-
* @returns RouteUtils instance with pre-computed chains and siblings
|
|
45
|
-
*
|
|
46
|
-
* @example
|
|
47
|
-
* ```tsx
|
|
48
|
-
* const utils = useRouteUtils();
|
|
49
|
-
*
|
|
50
|
-
* utils.getChain("users.profile");
|
|
51
|
-
* // → ["users", "users.profile"]
|
|
52
|
-
*
|
|
53
|
-
* utils.getSiblings("users");
|
|
54
|
-
* // → ["admin"]
|
|
55
|
-
*
|
|
56
|
-
* utils.isDescendantOf("users.profile", "users");
|
|
57
|
-
* // → true
|
|
58
|
-
* ```
|
|
59
|
-
*/
|
|
60
|
-
declare const useRouteUtils: () => RouteUtils;
|
|
61
|
-
|
|
62
|
-
declare function useIsActiveRoute(routeName: string, params?: Params, strict?: boolean, ignoreQueryParams?: boolean): boolean;
|
|
63
|
-
|
|
64
|
-
declare function useRouterTransition(): RouterTransitionSnapshot;
|
|
65
|
-
|
|
66
|
-
interface RouteProviderProps {
|
|
67
|
-
router: Router;
|
|
68
|
-
children: ReactNode;
|
|
28
|
+
declare function Match(_props: MatchProps): null;
|
|
29
|
+
declare namespace Match {
|
|
30
|
+
var displayName: string;
|
|
31
|
+
}
|
|
32
|
+
declare function NotFound(_props: NotFoundProps): null;
|
|
33
|
+
declare namespace NotFound {
|
|
34
|
+
var displayName: string;
|
|
69
35
|
}
|
|
70
|
-
declare const RouterProvider: FC<RouteProviderProps>;
|
|
71
36
|
|
|
72
|
-
declare
|
|
73
|
-
declare
|
|
74
|
-
|
|
37
|
+
declare function RouteViewRoot({ nodeName, children, }: Readonly<RouteViewProps>): ReactElement | null;
|
|
38
|
+
declare namespace RouteViewRoot {
|
|
39
|
+
var displayName: string;
|
|
40
|
+
}
|
|
41
|
+
declare const RouteView: typeof RouteViewRoot & {
|
|
42
|
+
Match: typeof Match;
|
|
43
|
+
NotFound: typeof NotFound;
|
|
44
|
+
};
|
|
75
45
|
|
|
76
|
-
export {
|
|
46
|
+
export { RouteView, type MatchProps as RouteViewMatchProps, type NotFoundProps as RouteViewNotFoundProps, type RouteViewProps };
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{Link,NavigatorContext,RouteContext,RouterContext,RouterProvider,useIsActiveRoute,useNavigator,useRoute,useRouteNode,useRouteUtils,useRouter,useRouterTransition}from"./chunk-35HV34W6.mjs";//# sourceMappingURL=index.mjs.map
|
|
1
|
+
import{useRouteNode as e}from"./chunk-35HV34W6.mjs";export{Link,NavigatorContext,RouteContext,RouterContext,RouterProvider,useIsActiveRoute,useNavigator,useRoute,useRouteNode,useRouteUtils,useRouter,useRouterTransition}from"./chunk-35HV34W6.mjs";import{useRef as t,Children as r,isValidElement as o,Fragment as n,Activity as u}from"react";import{UNKNOWN_ROUTE as i}from"@real-router/core";import{startsWithSegment as s}from"@real-router/route-utils";import{jsx as c,Fragment as l}from"react/jsx-runtime";function a(e){return null}function d(e){return null}function p(e,t,r){return r?e===t:s(e,t)}function m(e,t){for(const n of r.toArray(e))o(n)&&(n.type===a||n.type===d?t.push(n):m(n.props.children,t))}function h(e,t,r,o){return r?c(u,{mode:o,children:e},t):c(n,{children:e},t)}function f({nodeName:r,children:o}){const{route:u}=e(r),s=t(new Set);if(!u)return null;const a=[];m(o,a);const{rendered:f}=function(e,t,r,o){let u=null,s=!1;const l=[];for(const n of e){if(n.type===d){u=n.props.children;continue}const{segment:e,exact:i=!1,keepAlive:c=!1}=n.props,a=r?`${r}.${e}`:e;!s&&p(t,a,i)?(s=!0,o.add(a),l.push(h(n.props.children,a,c,"visible"))):c&&o.has(a)&&l.push(h(n.props.children,a,c,"hidden"))}return s||t!==i||null===u||l.push(c(n,{children:u},"__route-view-not-found__")),{rendered:l,activeMatchFound:s}}(a,u.name,r,s.current);return f.length>0?c(l,{children:f}):null}a.displayName="RouteView.Match",d.displayName="RouteView.NotFound",f.displayName="RouteView";var R=Object.assign(f,{Match:a,NotFound:d});export{R as RouteView};//# sourceMappingURL=index.mjs.map
|
package/dist/esm/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.mjs"}
|
|
1
|
+
{"version":3,"sources":["../../src/components/modern/RouteView/components.tsx","../../src/components/modern/RouteView/helpers.tsx","../../src/components/modern/RouteView/RouteView.tsx"],"names":["Fragment","jsx"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { MatchProps, NotFoundProps } from \"./types\";\n\nexport function Match(_props: MatchProps): null {\n return null;\n}\n\nMatch.displayName = \"RouteView.Match\";\n\nexport function NotFound(_props: NotFoundProps): null {\n return null;\n}\n\nNotFound.displayName = \"RouteView.NotFound\";\n","import { UNKNOWN_ROUTE } from \"@real-router/core\";\nimport { startsWithSegment } from \"@real-router/route-utils\";\nimport { Activity, Children, Fragment, isValidElement } from \"react\";\n\nimport { Match, NotFound } from \"./components\";\n\nimport type { MatchProps, NotFoundProps } from \"./types\";\nimport type { ReactElement, ReactNode } from \"react\";\n\nfunction isSegmentMatch(\n routeName: string,\n fullSegmentName: string,\n exact: boolean,\n): boolean {\n if (exact) {\n return routeName === fullSegmentName;\n }\n\n return startsWithSegment(routeName, fullSegmentName);\n}\n\nexport function collectElements(\n children: ReactNode,\n result: ReactElement[],\n): void {\n // eslint-disable-next-line @eslint-react/no-children-to-array\n for (const child of Children.toArray(children)) {\n if (!isValidElement(child)) {\n continue;\n }\n\n if (child.type === Match || child.type === NotFound) {\n result.push(child);\n } else {\n collectElements(\n (child.props as { readonly children: ReactNode }).children,\n result,\n );\n }\n }\n}\n\nfunction renderMatchElement(\n matchChildren: ReactNode,\n fullSegmentName: string,\n keepAlive: boolean,\n mode: \"visible\" | \"hidden\",\n): ReactElement {\n if (keepAlive) {\n return (\n <Activity mode={mode} key={fullSegmentName}>\n {matchChildren}\n </Activity>\n );\n }\n\n return <Fragment key={fullSegmentName}>{matchChildren}</Fragment>;\n}\n\nexport function buildRenderList(\n elements: ReactElement[],\n routeName: string,\n nodeName: string,\n hasBeenActivated: Set<string>,\n): { rendered: ReactElement[]; activeMatchFound: boolean } {\n let notFoundChildren: ReactNode = null;\n let activeMatchFound = false;\n const rendered: ReactElement[] = [];\n\n for (const child of elements) {\n if (child.type === NotFound) {\n notFoundChildren = (child.props as NotFoundProps).children;\n continue;\n }\n\n const {\n segment,\n exact = false,\n keepAlive = false,\n } = child.props as MatchProps;\n const fullSegmentName = nodeName ? `${nodeName}.${segment}` : segment;\n const isActive =\n !activeMatchFound && isSegmentMatch(routeName, fullSegmentName, exact);\n\n if (isActive) {\n activeMatchFound = true;\n hasBeenActivated.add(fullSegmentName);\n rendered.push(\n renderMatchElement(\n (child.props as MatchProps).children,\n fullSegmentName,\n keepAlive,\n \"visible\",\n ),\n );\n } else if (keepAlive && hasBeenActivated.has(fullSegmentName)) {\n rendered.push(\n renderMatchElement(\n (child.props as MatchProps).children,\n fullSegmentName,\n keepAlive,\n \"hidden\",\n ),\n );\n }\n }\n\n if (\n !activeMatchFound &&\n routeName === UNKNOWN_ROUTE &&\n notFoundChildren !== null\n ) {\n rendered.push(\n <Fragment key=\"__route-view-not-found__\">{notFoundChildren}</Fragment>,\n );\n }\n\n return { rendered, activeMatchFound };\n}\n","import { useRef } from \"react\";\n\nimport { Match, NotFound } from \"./components\";\nimport { buildRenderList, collectElements } from \"./helpers\";\nimport { useRouteNode } from \"../../../hooks/useRouteNode\";\n\nimport type { RouteViewProps } from \"./types\";\nimport type { ReactElement } from \"react\";\n\nfunction RouteViewRoot({\n nodeName,\n children,\n}: Readonly<RouteViewProps>): ReactElement | null {\n const { route } = useRouteNode(nodeName);\n const hasBeenActivatedRef = useRef<Set<string>>(new Set());\n\n if (!route) {\n return null;\n }\n\n const elements: ReactElement[] = [];\n\n collectElements(children, elements);\n\n const { rendered } = buildRenderList(\n elements,\n route.name,\n nodeName,\n hasBeenActivatedRef.current,\n );\n\n if (rendered.length > 0) {\n return <>{rendered}</>;\n }\n\n return null;\n}\n\nRouteViewRoot.displayName = \"RouteView\";\n\nexport const RouteView = Object.assign(RouteViewRoot, { Match, NotFound });\n\nexport type {\n RouteViewProps,\n MatchProps as RouteViewMatchProps,\n NotFoundProps as RouteViewNotFoundProps,\n} from \"./types\";\n"]}
|
package/dist/esm/legacy.d.mts
CHANGED
|
@@ -1,5 +1,76 @@
|
|
|
1
|
-
|
|
1
|
+
import { Params, NavigationOptions, Navigator, State, Router } from '@real-router/core';
|
|
2
2
|
export { Navigator } from '@real-router/core';
|
|
3
|
+
import * as react from 'react';
|
|
4
|
+
import { HTMLAttributes, MouseEventHandler, FC, ReactNode } from 'react';
|
|
5
|
+
import { RouteUtils } from '@real-router/route-utils';
|
|
6
|
+
import { RouterTransitionSnapshot } from '@real-router/sources';
|
|
3
7
|
export { RouterTransitionSnapshot } from '@real-router/sources';
|
|
4
|
-
|
|
5
|
-
|
|
8
|
+
|
|
9
|
+
interface RouteState<P extends Params = Params, MP extends Params = Params> {
|
|
10
|
+
route: State<P, MP> | undefined;
|
|
11
|
+
previousRoute?: State | undefined;
|
|
12
|
+
}
|
|
13
|
+
type RouteContext$1 = {
|
|
14
|
+
navigator: Navigator;
|
|
15
|
+
} & RouteState;
|
|
16
|
+
interface LinkProps<P extends Params = Params> extends HTMLAttributes<HTMLAnchorElement> {
|
|
17
|
+
routeName: string;
|
|
18
|
+
routeParams?: P;
|
|
19
|
+
routeOptions?: NavigationOptions;
|
|
20
|
+
activeClassName?: string;
|
|
21
|
+
activeStrict?: boolean;
|
|
22
|
+
ignoreQueryParams?: boolean;
|
|
23
|
+
target?: string;
|
|
24
|
+
onClick?: MouseEventHandler<HTMLAnchorElement>;
|
|
25
|
+
onMouseOver?: MouseEventHandler<HTMLAnchorElement>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
declare const Link: FC<LinkProps>;
|
|
29
|
+
|
|
30
|
+
declare function useRouteNode(nodeName: string): RouteContext$1;
|
|
31
|
+
|
|
32
|
+
declare const useRoute: () => RouteContext$1;
|
|
33
|
+
|
|
34
|
+
declare const useNavigator: () => Navigator;
|
|
35
|
+
|
|
36
|
+
declare const useRouter: () => Router;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Returns a pre-computed {@link RouteUtils} instance for the current router.
|
|
40
|
+
*
|
|
41
|
+
* Internally retrieves the route tree via `getPluginApi` and delegates
|
|
42
|
+
* to `getRouteUtils`, which caches instances per tree reference (WeakMap).
|
|
43
|
+
*
|
|
44
|
+
* @returns RouteUtils instance with pre-computed chains and siblings
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```tsx
|
|
48
|
+
* const utils = useRouteUtils();
|
|
49
|
+
*
|
|
50
|
+
* utils.getChain("users.profile");
|
|
51
|
+
* // → ["users", "users.profile"]
|
|
52
|
+
*
|
|
53
|
+
* utils.getSiblings("users");
|
|
54
|
+
* // → ["admin"]
|
|
55
|
+
*
|
|
56
|
+
* utils.isDescendantOf("users.profile", "users");
|
|
57
|
+
* // → true
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
declare const useRouteUtils: () => RouteUtils;
|
|
61
|
+
|
|
62
|
+
declare function useIsActiveRoute(routeName: string, params?: Params, strict?: boolean, ignoreQueryParams?: boolean): boolean;
|
|
63
|
+
|
|
64
|
+
declare function useRouterTransition(): RouterTransitionSnapshot;
|
|
65
|
+
|
|
66
|
+
interface RouteProviderProps {
|
|
67
|
+
router: Router;
|
|
68
|
+
children: ReactNode;
|
|
69
|
+
}
|
|
70
|
+
declare const RouterProvider: FC<RouteProviderProps>;
|
|
71
|
+
|
|
72
|
+
declare const RouteContext: react.Context<RouteContext$1 | null>;
|
|
73
|
+
declare const RouterContext: react.Context<Router<object> | null>;
|
|
74
|
+
declare const NavigatorContext: react.Context<Navigator | null>;
|
|
75
|
+
|
|
76
|
+
export { Link, type LinkProps, NavigatorContext, RouteContext, RouterContext, RouterProvider, useIsActiveRoute, useNavigator, useRoute, useRouteNode, useRouteUtils, useRouter, useRouterTransition };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"src/constants.ts":{"bytes":225,"imports":[],"format":"esm"},"src/context.ts":{"bytes":416,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouter.tsx":{"bytes":364,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"format":"esm"},"src/hooks/useStableValue.tsx":{"bytes":976,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useIsActiveRoute.tsx":{"bytes":1060,"imports":[{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"src/hooks/useStableValue.tsx","kind":"import-statement","original":"./useStableValue"}],"format":"esm"},"src/utils.ts":{"bytes":293,"imports":[],"format":"esm"},"src/components/Link.tsx":{"bytes":2900,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/constants.ts","kind":"import-statement","original":"../constants"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"../hooks/useIsActiveRoute"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"../hooks/useRouter"},{"path":"src/hooks/useStableValue.tsx","kind":"import-statement","original":"../hooks/useStableValue"},{"path":"src/utils.ts","kind":"import-statement","original":"../utils"},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouteNode.tsx":{"bytes":837,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"}],"format":"esm"},"src/hooks/useRoute.tsx":{"bytes":403,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"format":"esm"},"src/hooks/useNavigator.tsx":{"bytes":394,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"format":"esm"},"src/hooks/useRouteUtils.tsx":{"bytes":977,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"}],"format":"esm"},"src/hooks/useRouterTransition.tsx":{"bytes":508,"imports":[{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"}],"format":"esm"},"src/RouterProvider.tsx":{"bytes":1380,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"./context"},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":805,"imports":[{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"./hooks/useIsActiveRoute"},{"path":"src/hooks/useRouterTransition.tsx","kind":"import-statement","original":"./hooks/useRouterTransition"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"src/context.ts","kind":"import-statement","original":"./context"}],"format":"esm"},"src/legacy.ts":{"bytes":805,"imports":[{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"./hooks/useIsActiveRoute"},{"path":"src/hooks/useRouterTransition.tsx","kind":"import-statement","original":"./hooks/useRouterTransition"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"src/context.ts","kind":"import-statement","original":"./context"}],"format":"esm"}},"outputs":{"dist/esm/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":93},"dist/esm/index.mjs":{"imports":[{"path":"dist/esm/chunk-35HV34W6.mjs","kind":"import-statement"}],"exports":["Link","NavigatorContext","RouteContext","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"entryPoint":"src/index.ts","inputs":{"src/index.ts":{"bytesInOutput":0}},"bytes":442},"dist/esm/legacy.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":93},"dist/esm/legacy.mjs":{"imports":[{"path":"dist/esm/chunk-35HV34W6.mjs","kind":"import-statement"}],"exports":["Link","NavigatorContext","RouteContext","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"entryPoint":"src/legacy.ts","inputs":{"src/legacy.ts":{"bytesInOutput":0}},"bytes":442},"dist/esm/chunk-35HV34W6.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":16251},"dist/esm/chunk-35HV34W6.mjs":{"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"exports":["Link","NavigatorContext","RouteContext","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"inputs":{"src/context.ts":{"bytesInOutput":164},"src/hooks/useRouter.tsx":{"bytesInOutput":202},"src/hooks/useIsActiveRoute.tsx":{"bytesInOutput":671},"src/hooks/useStableValue.tsx":{"bytesInOutput":157},"src/components/Link.tsx":{"bytesInOutput":2409},"src/constants.ts":{"bytesInOutput":77},"src/utils.ts":{"bytesInOutput":140},"src/hooks/useRouteNode.tsx":{"bytesInOutput":742},"src/hooks/useRoute.tsx":{"bytesInOutput":225},"src/hooks/useNavigator.tsx":{"bytesInOutput":229},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":225},"src/hooks/useRouterTransition.tsx":{"bytesInOutput":397},"src/RouterProvider.tsx":{"bytesInOutput":1001}},"bytes":7276}}}
|
|
1
|
+
{"inputs":{"src/constants.ts":{"bytes":225,"imports":[],"format":"esm"},"src/context.ts":{"bytes":416,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouter.tsx":{"bytes":364,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"format":"esm"},"src/hooks/useStableValue.tsx":{"bytes":976,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useIsActiveRoute.tsx":{"bytes":1060,"imports":[{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"src/hooks/useStableValue.tsx","kind":"import-statement","original":"./useStableValue"}],"format":"esm"},"src/utils.ts":{"bytes":293,"imports":[],"format":"esm"},"src/components/Link.tsx":{"bytes":2900,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/constants.ts","kind":"import-statement","original":"../constants"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"../hooks/useIsActiveRoute"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"../hooks/useRouter"},{"path":"src/hooks/useStableValue.tsx","kind":"import-statement","original":"../hooks/useStableValue"},{"path":"src/utils.ts","kind":"import-statement","original":"../utils"},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/components/modern/RouteView/components.tsx":{"bytes":286,"imports":[],"format":"esm"},"src/components/modern/RouteView/helpers.tsx":{"bytes":2980,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/components/modern/RouteView/components.tsx","kind":"import-statement","original":"./components"},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouteNode.tsx":{"bytes":837,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"}],"format":"esm"},"src/components/modern/RouteView/RouteView.tsx":{"bytes":1073,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/components/modern/RouteView/components.tsx","kind":"import-statement","original":"./components"},{"path":"src/components/modern/RouteView/helpers.tsx","kind":"import-statement","original":"./helpers"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"../../../hooks/useRouteNode"},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/components/modern/RouteView/index.ts":{"bytes":145,"imports":[{"path":"src/components/modern/RouteView/RouteView.tsx","kind":"import-statement","original":"./RouteView"}],"format":"esm"},"src/hooks/useRoute.tsx":{"bytes":403,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"format":"esm"},"src/hooks/useNavigator.tsx":{"bytes":394,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"format":"esm"},"src/hooks/useRouteUtils.tsx":{"bytes":977,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"}],"format":"esm"},"src/hooks/useRouterTransition.tsx":{"bytes":508,"imports":[{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"}],"format":"esm"},"src/RouterProvider.tsx":{"bytes":1380,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"./context"},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":987,"imports":[{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/components/modern/RouteView/index.ts","kind":"import-statement","original":"./components/modern/RouteView"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"./hooks/useIsActiveRoute"},{"path":"src/hooks/useRouterTransition.tsx","kind":"import-statement","original":"./hooks/useRouterTransition"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"src/context.ts","kind":"import-statement","original":"./context"}],"format":"esm"},"src/legacy.ts":{"bytes":805,"imports":[{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"./hooks/useIsActiveRoute"},{"path":"src/hooks/useRouterTransition.tsx","kind":"import-statement","original":"./hooks/useRouterTransition"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"src/context.ts","kind":"import-statement","original":"./context"}],"format":"esm"}},"outputs":{"dist/esm/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":6846},"dist/esm/index.mjs":{"imports":[{"path":"dist/esm/chunk-35HV34W6.mjs","kind":"import-statement"},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"exports":["Link","NavigatorContext","RouteContext","RouteView","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"entryPoint":"src/index.ts","inputs":{"src/index.ts":{"bytesInOutput":0},"src/components/modern/RouteView/RouteView.tsx":{"bytesInOutput":712},"src/components/modern/RouteView/components.tsx":{"bytesInOutput":171},"src/components/modern/RouteView/helpers.tsx":{"bytesInOutput":2355},"src/components/modern/RouteView/index.ts":{"bytesInOutput":0}},"bytes":3892},"dist/esm/legacy.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":93},"dist/esm/legacy.mjs":{"imports":[{"path":"dist/esm/chunk-35HV34W6.mjs","kind":"import-statement"}],"exports":["Link","NavigatorContext","RouteContext","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"entryPoint":"src/legacy.ts","inputs":{"src/legacy.ts":{"bytesInOutput":0}},"bytes":442},"dist/esm/chunk-35HV34W6.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":16251},"dist/esm/chunk-35HV34W6.mjs":{"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"exports":["Link","NavigatorContext","RouteContext","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"inputs":{"src/context.ts":{"bytesInOutput":164},"src/hooks/useRouter.tsx":{"bytesInOutput":202},"src/hooks/useIsActiveRoute.tsx":{"bytesInOutput":671},"src/hooks/useStableValue.tsx":{"bytesInOutput":157},"src/components/Link.tsx":{"bytesInOutput":2409},"src/constants.ts":{"bytesInOutput":77},"src/utils.ts":{"bytesInOutput":140},"src/hooks/useRouteNode.tsx":{"bytesInOutput":742},"src/hooks/useRoute.tsx":{"bytesInOutput":225},"src/hooks/useNavigator.tsx":{"bytesInOutput":229},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":225},"src/hooks/useRouterTransition.tsx":{"bytesInOutput":397},"src/RouterProvider.tsx":{"bytesInOutput":1001}},"bytes":7276}}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@real-router/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"type": "commonjs",
|
|
5
5
|
"description": "React integration for Real-Router",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -64,9 +64,9 @@
|
|
|
64
64
|
"license": "MIT",
|
|
65
65
|
"sideEffects": false,
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@real-router/sources": "^0.2.0",
|
|
68
67
|
"@real-router/core": "^0.35.1",
|
|
69
|
-
"@real-router/route-utils": "^0.1.4"
|
|
68
|
+
"@real-router/route-utils": "^0.1.4",
|
|
69
|
+
"@real-router/sources": "^0.2.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@testing-library/dom": "10.4.1",
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useRef } from "react";
|
|
2
|
+
|
|
3
|
+
import { Match, NotFound } from "./components";
|
|
4
|
+
import { buildRenderList, collectElements } from "./helpers";
|
|
5
|
+
import { useRouteNode } from "../../../hooks/useRouteNode";
|
|
6
|
+
|
|
7
|
+
import type { RouteViewProps } from "./types";
|
|
8
|
+
import type { ReactElement } from "react";
|
|
9
|
+
|
|
10
|
+
function RouteViewRoot({
|
|
11
|
+
nodeName,
|
|
12
|
+
children,
|
|
13
|
+
}: Readonly<RouteViewProps>): ReactElement | null {
|
|
14
|
+
const { route } = useRouteNode(nodeName);
|
|
15
|
+
const hasBeenActivatedRef = useRef<Set<string>>(new Set());
|
|
16
|
+
|
|
17
|
+
if (!route) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const elements: ReactElement[] = [];
|
|
22
|
+
|
|
23
|
+
collectElements(children, elements);
|
|
24
|
+
|
|
25
|
+
const { rendered } = buildRenderList(
|
|
26
|
+
elements,
|
|
27
|
+
route.name,
|
|
28
|
+
nodeName,
|
|
29
|
+
hasBeenActivatedRef.current,
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
if (rendered.length > 0) {
|
|
33
|
+
return <>{rendered}</>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
RouteViewRoot.displayName = "RouteView";
|
|
40
|
+
|
|
41
|
+
export const RouteView = Object.assign(RouteViewRoot, { Match, NotFound });
|
|
42
|
+
|
|
43
|
+
export type {
|
|
44
|
+
RouteViewProps,
|
|
45
|
+
MatchProps as RouteViewMatchProps,
|
|
46
|
+
NotFoundProps as RouteViewNotFoundProps,
|
|
47
|
+
} from "./types";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { MatchProps, NotFoundProps } from "./types";
|
|
2
|
+
|
|
3
|
+
export function Match(_props: MatchProps): null {
|
|
4
|
+
return null;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
Match.displayName = "RouteView.Match";
|
|
8
|
+
|
|
9
|
+
export function NotFound(_props: NotFoundProps): null {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
NotFound.displayName = "RouteView.NotFound";
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { UNKNOWN_ROUTE } from "@real-router/core";
|
|
2
|
+
import { startsWithSegment } from "@real-router/route-utils";
|
|
3
|
+
import { Activity, Children, Fragment, isValidElement } from "react";
|
|
4
|
+
|
|
5
|
+
import { Match, NotFound } from "./components";
|
|
6
|
+
|
|
7
|
+
import type { MatchProps, NotFoundProps } from "./types";
|
|
8
|
+
import type { ReactElement, ReactNode } from "react";
|
|
9
|
+
|
|
10
|
+
function isSegmentMatch(
|
|
11
|
+
routeName: string,
|
|
12
|
+
fullSegmentName: string,
|
|
13
|
+
exact: boolean,
|
|
14
|
+
): boolean {
|
|
15
|
+
if (exact) {
|
|
16
|
+
return routeName === fullSegmentName;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return startsWithSegment(routeName, fullSegmentName);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function collectElements(
|
|
23
|
+
children: ReactNode,
|
|
24
|
+
result: ReactElement[],
|
|
25
|
+
): void {
|
|
26
|
+
// eslint-disable-next-line @eslint-react/no-children-to-array
|
|
27
|
+
for (const child of Children.toArray(children)) {
|
|
28
|
+
if (!isValidElement(child)) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (child.type === Match || child.type === NotFound) {
|
|
33
|
+
result.push(child);
|
|
34
|
+
} else {
|
|
35
|
+
collectElements(
|
|
36
|
+
(child.props as { readonly children: ReactNode }).children,
|
|
37
|
+
result,
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function renderMatchElement(
|
|
44
|
+
matchChildren: ReactNode,
|
|
45
|
+
fullSegmentName: string,
|
|
46
|
+
keepAlive: boolean,
|
|
47
|
+
mode: "visible" | "hidden",
|
|
48
|
+
): ReactElement {
|
|
49
|
+
if (keepAlive) {
|
|
50
|
+
return (
|
|
51
|
+
<Activity mode={mode} key={fullSegmentName}>
|
|
52
|
+
{matchChildren}
|
|
53
|
+
</Activity>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return <Fragment key={fullSegmentName}>{matchChildren}</Fragment>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function buildRenderList(
|
|
61
|
+
elements: ReactElement[],
|
|
62
|
+
routeName: string,
|
|
63
|
+
nodeName: string,
|
|
64
|
+
hasBeenActivated: Set<string>,
|
|
65
|
+
): { rendered: ReactElement[]; activeMatchFound: boolean } {
|
|
66
|
+
let notFoundChildren: ReactNode = null;
|
|
67
|
+
let activeMatchFound = false;
|
|
68
|
+
const rendered: ReactElement[] = [];
|
|
69
|
+
|
|
70
|
+
for (const child of elements) {
|
|
71
|
+
if (child.type === NotFound) {
|
|
72
|
+
notFoundChildren = (child.props as NotFoundProps).children;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const {
|
|
77
|
+
segment,
|
|
78
|
+
exact = false,
|
|
79
|
+
keepAlive = false,
|
|
80
|
+
} = child.props as MatchProps;
|
|
81
|
+
const fullSegmentName = nodeName ? `${nodeName}.${segment}` : segment;
|
|
82
|
+
const isActive =
|
|
83
|
+
!activeMatchFound && isSegmentMatch(routeName, fullSegmentName, exact);
|
|
84
|
+
|
|
85
|
+
if (isActive) {
|
|
86
|
+
activeMatchFound = true;
|
|
87
|
+
hasBeenActivated.add(fullSegmentName);
|
|
88
|
+
rendered.push(
|
|
89
|
+
renderMatchElement(
|
|
90
|
+
(child.props as MatchProps).children,
|
|
91
|
+
fullSegmentName,
|
|
92
|
+
keepAlive,
|
|
93
|
+
"visible",
|
|
94
|
+
),
|
|
95
|
+
);
|
|
96
|
+
} else if (keepAlive && hasBeenActivated.has(fullSegmentName)) {
|
|
97
|
+
rendered.push(
|
|
98
|
+
renderMatchElement(
|
|
99
|
+
(child.props as MatchProps).children,
|
|
100
|
+
fullSegmentName,
|
|
101
|
+
keepAlive,
|
|
102
|
+
"hidden",
|
|
103
|
+
),
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (
|
|
109
|
+
!activeMatchFound &&
|
|
110
|
+
routeName === UNKNOWN_ROUTE &&
|
|
111
|
+
notFoundChildren !== null
|
|
112
|
+
) {
|
|
113
|
+
rendered.push(
|
|
114
|
+
<Fragment key="__route-view-not-found__">{notFoundChildren}</Fragment>,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return { rendered, activeMatchFound };
|
|
119
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
export interface RouteViewProps {
|
|
4
|
+
/** Route tree node name to subscribe to. "" for root. */
|
|
5
|
+
readonly nodeName: string;
|
|
6
|
+
/** <RouteView.Match> and <RouteView.NotFound> elements. */
|
|
7
|
+
readonly children: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface MatchProps {
|
|
11
|
+
/** Route segment to match against. */
|
|
12
|
+
readonly segment: string;
|
|
13
|
+
/** Exact match only (no descendants). Defaults to false. */
|
|
14
|
+
readonly exact?: boolean;
|
|
15
|
+
/** Preserve component state when deactivated (React Activity). Defaults to false. */
|
|
16
|
+
readonly keepAlive?: boolean;
|
|
17
|
+
/** Content to render when matched. */
|
|
18
|
+
readonly children: ReactNode;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface NotFoundProps {
|
|
22
|
+
/** Content to render on UNKNOWN_ROUTE. */
|
|
23
|
+
readonly children: ReactNode;
|
|
24
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
// Components
|
|
4
4
|
export { Link } from "./components/Link";
|
|
5
5
|
|
|
6
|
+
export { RouteView } from "./components/modern/RouteView";
|
|
7
|
+
|
|
6
8
|
// Hooks
|
|
7
9
|
export { useRouteNode } from "./hooks/useRouteNode";
|
|
8
10
|
|
|
@@ -26,6 +28,12 @@ export { RouterContext, RouteContext, NavigatorContext } from "./context";
|
|
|
26
28
|
// Types
|
|
27
29
|
export type { LinkProps } from "./types";
|
|
28
30
|
|
|
31
|
+
export type {
|
|
32
|
+
RouteViewProps,
|
|
33
|
+
RouteViewMatchProps,
|
|
34
|
+
RouteViewNotFoundProps,
|
|
35
|
+
} from "./components/modern/RouteView";
|
|
36
|
+
|
|
29
37
|
export type { Navigator } from "@real-router/core";
|
|
30
38
|
|
|
31
39
|
export type { RouterTransitionSnapshot } from "@real-router/sources";
|